@lsamien/yaovi 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build-info.json +23 -3
- package/desktop/main.mjs +18 -9
- package/dist/assets/{AboutDialog-CBKv505Y.js → AboutDialog-CJ9tCjSs.js} +2 -2
- package/dist/assets/AboutDialog-CJ9tCjSs.js.map +1 -0
- package/dist/assets/{BotAutomationsView-S3aHciek.js → BotAutomationsView-CsoI3js3.js} +2 -2
- package/dist/assets/{BotAutomationsView-S3aHciek.js.map → BotAutomationsView-CsoI3js3.js.map} +1 -1
- package/dist/assets/{BotControlSettingsPanel-DJF4oA6g.js → BotControlSettingsPanel-DIuBZlLu.js} +2 -2
- package/dist/assets/{BotControlSettingsPanel-DJF4oA6g.js.map → BotControlSettingsPanel-DIuBZlLu.js.map} +1 -1
- package/dist/assets/{BotPluginsDialog-BVOQ3DTp.js → BotPluginsDialog-BsGszDMH.js} +2 -2
- package/dist/assets/{BotPluginsDialog-BVOQ3DTp.js.map → BotPluginsDialog-BsGszDMH.js.map} +1 -1
- package/dist/assets/{BotSettingsPanel-CEH3KSAO.js → BotSettingsPanel-j3ThYgt2.js} +3 -3
- package/dist/assets/{BotSettingsPanel-CEH3KSAO.js.map → BotSettingsPanel-j3ThYgt2.js.map} +1 -1
- package/dist/assets/{ComputerPanel-CC-xkAxr.js → ComputerPanel-DdlgOm-B.js} +2 -2
- package/dist/assets/{ComputerPanel-CC-xkAxr.js.map → ComputerPanel-DdlgOm-B.js.map} +1 -1
- package/dist/assets/{ComputerViewerView-CEQrOmy7.js → ComputerViewerView-I3adPI6O.js} +2 -2
- package/dist/assets/{ComputerViewerView-CEQrOmy7.js.map → ComputerViewerView-I3adPI6O.js.map} +1 -1
- package/dist/assets/ConversationsView-CBhzg-9w.css +1 -0
- package/dist/assets/{ConversationsView-CzFWn-79.js → ConversationsView-CxVFk5sQ.js} +73 -73
- package/dist/assets/ConversationsView-CxVFk5sQ.js.map +1 -0
- package/dist/assets/{DevicePairingDialog-ByYk05DC.js → DevicePairingDialog-C307ARt-.js} +2 -2
- package/dist/assets/{DevicePairingDialog-ByYk05DC.js.map → DevicePairingDialog-C307ARt-.js.map} +1 -1
- package/dist/assets/{LocalVmSettingsPanel-DBkqouAU.js → LocalVmSettingsPanel-Zs7CiXdf.js} +2 -2
- package/dist/assets/{LocalVmSettingsPanel-DBkqouAU.js.map → LocalVmSettingsPanel-Zs7CiXdf.js.map} +1 -1
- package/dist/assets/{ProviderLoginDialog-DdPS62uM.js → ProviderLoginDialog-D3mqdAlo.js} +2 -2
- package/dist/assets/{ProviderLoginDialog-DdPS62uM.js.map → ProviderLoginDialog-D3mqdAlo.js.map} +1 -1
- package/dist/assets/{RunnerSettingsPanel-gzA2xzOg.js → RunnerSettingsPanel-DjMGnXGP.js} +2 -2
- package/dist/assets/{RunnerSettingsPanel-gzA2xzOg.js.map → RunnerSettingsPanel-DjMGnXGP.js.map} +1 -1
- package/dist/assets/{StandaloneDialog-B9HCNEFb.js → StandaloneDialog-BXCK22Dx.js} +2 -2
- package/dist/assets/{StandaloneDialog-B9HCNEFb.js.map → StandaloneDialog-BXCK22Dx.js.map} +1 -1
- package/dist/assets/{UpdateCheckDialog-djkXTQgD.js → UpdateCheckDialog-DAY0VEQm.js} +2 -2
- package/dist/assets/{UpdateCheckDialog-djkXTQgD.js.map → UpdateCheckDialog-DAY0VEQm.js.map} +1 -1
- package/dist/assets/{UsageView-DFaWBB40.js → UsageView-DNwG8LAx.js} +2 -2
- package/dist/assets/{UsageView-DFaWBB40.js.map → UsageView-DNwG8LAx.js.map} +1 -1
- package/dist/assets/{WorkspaceKnowledgePanel-In2a_s_z.js → WorkspaceKnowledgePanel-hy_IkIJI.js} +2 -2
- package/dist/assets/{WorkspaceKnowledgePanel-In2a_s_z.js.map → WorkspaceKnowledgePanel-hy_IkIJI.js.map} +1 -1
- package/dist/assets/{WorkspaceRoutinesPanel-zOxFoqML.js → WorkspaceRoutinesPanel-B7PkBP7x.js} +2 -2
- package/dist/assets/{WorkspaceRoutinesPanel-zOxFoqML.js.map → WorkspaceRoutinesPanel-B7PkBP7x.js.map} +1 -1
- package/dist/assets/{WorkstreamsView-HvlivC3b.js → WorkstreamsView-BeE2TRXK.js} +2 -2
- package/dist/assets/{WorkstreamsView-HvlivC3b.js.map → WorkstreamsView-BeE2TRXK.js.map} +1 -1
- package/dist/assets/{index-BPE9bBla.js → index-D11cgXI9.js} +3 -3
- package/dist/assets/{index-BPE9bBla.js.map → index-D11cgXI9.js.map} +1 -1
- package/dist/assets/{pdf-Q2a37aK5.js → pdf-BjTcV6As.js} +2 -2
- package/dist/assets/{pdf-Q2a37aK5.js.map → pdf-BjTcV6As.js.map} +1 -1
- package/dist/index.html +1 -1
- package/dist-server/server/botControl.js +1 -1
- package/dist-server/server/desktopEnvironments.js +10 -9
- package/dist-server/server/desktopHostProtocol.js +1 -1
- package/dist-server/server/workspacePrompt.js +2 -2
- package/dist-server/shared/botEnvironment.js +10 -4
- package/dist-server/shared/fileTransferEndpoint.mjs +5 -5
- package/dist-server/shared/hostPaths.mjs +14 -4
- package/package.json +3 -2
- package/release.json +3 -3
- package/dist/assets/AboutDialog-CBKv505Y.js.map +0 -1
- package/dist/assets/ConversationsView-B6JNGLt_.css +0 -1
- package/dist/assets/ConversationsView-CzFWn-79.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WorkspaceKnowledgePanel-In2a_s_z.js","names":["_hoisted_1","_openBlock","_createElementBlock","_createElementVNode"],"sources":["../../node_modules/@vicons/ionicons5/es/ChevronForwardOutline.js","../../src/client/components/app/ConnectionNetworkPanel.vue","../../src/client/components/app/ConnectionNetworkPanel.vue","../../src/shared/autoRouting.ts","../../src/shared/botModelSettings.ts","../../src/client/components/messages/AutoRouteNotice.vue","../../src/client/components/messages/AutoRouteNotice.vue","../../src/client/components/app/JevAutoPanel.vue","../../src/client/components/app/JevAutoPanel.vue","../../src/client/components/app/JevNetworkPanel.vue","../../src/client/components/app/JevNetworkPanel.vue","../../src/client/components/app/BotModelVisibilityPanel.vue","../../src/client/components/app/BotModelVisibilityPanel.vue","../../src/client/components/app/HermesProvidersPanel.vue","../../src/client/components/app/HermesProvidersPanel.vue","../../src/shared/hermesAuxiliary.ts","../../src/client/components/workspace/MemoryFilesPanel.vue","../../src/client/components/workspace/MemoryFilesPanel.vue","../../src/shared/collaborationPresentation.ts","../../src/shared/collaborationTimeline.ts","../../src/client/components/workspace/WorkspaceKnowledgePanel.vue","../../src/client/components/workspace/WorkspaceKnowledgePanel.vue"],"sourcesContent":["import { createElementVNode as _createElementVNode, openBlock as _openBlock, createElementBlock as _createElementBlock, defineComponent } from 'vue'\nconst _hoisted_1 = {\n xmlns: 'http://www.w3.org/2000/svg',\n 'xmlns:xlink': 'http://www.w3.org/1999/xlink',\n viewBox: '0 0 512 512'\n}\nexport default defineComponent({\n name: 'ChevronForwardOutline',\n render: function render(_ctx, _cache) {\n return (\n _openBlock(),\n _createElementBlock(\n 'svg',\n _hoisted_1,\n _cache[0] ||\n (_cache[0] = [\n _createElementVNode(\n 'path',\n {\n fill: 'none',\n stroke: 'currentColor',\n 'stroke-linecap': 'round',\n 'stroke-linejoin': 'round',\n 'stroke-width': '48',\n d: 'M184 112l144 144l-144 144'\n },\n null,\n -1 /* HOISTED */\n )\n ])\n )\n )\n }\n})\n","<script setup lang=\"ts\">\nimport { computed, onMounted, ref, watch } from 'vue'\nimport AppIcon from '@/components/common/AppIcon.vue'\nimport ModelNetworkChoice from './ModelNetworkChoice.vue'\nimport { modelNetworkApi } from '@/api/modelNetwork'\nimport type { ModelNetworkView, NetworkPolicy } from '@shared/modelNetwork'\nconst props=defineProps<{provider:string;name:string;bot?:string;canLogin?:boolean}>()\nconst emit=defineEmits<{back:[];login:[];changed:[];'dirty-change':[value:boolean];'busy-change':[value:boolean]}>()\nconst view=ref<ModelNetworkView>(),policy=ref<NetworkPolicy>({mode:'inherit'}),busy=ref(false),testing=ref(false),error=ref(''),notice=ref('')\nconst dirty=computed(()=>!!view.value&&JSON.stringify(policy.value)!==JSON.stringify(view.value.connections[props.provider]??{mode:'inherit'}))\nwatch(dirty,v=>emit('dirty-change',v));watch(busy,v=>emit('busy-change',v))\nasync function load(){try{view.value=await modelNetworkApi.get(props.bot);policy.value={...view.value.connections[props.provider]??{mode:'inherit'}}}catch(cause){error.value=cause instanceof Error?cause.message:'读取失败'}}\nfunction back(){if(!busy.value&&(!dirty.value||window.confirm('放弃尚未保存的网络更改?')))emit('back')}\nasync function save(login=false){busy.value=true;error.value='';try{view.value=await modelNetworkApi.save(view.value!.revision,policy.value,props.provider,props.bot);notice.value='网络设置已保存,从下一轮任务或新登录生效。';emit('changed');if(login)emit('login')}catch(cause){error.value=cause instanceof Error?cause.message:'保存失败'}finally{busy.value=false}}\nonMounted(load)\ndefineExpose({reset:()=>{if(view.value)policy.value={...view.value.connections[props.provider]??{mode:'inherit'}};notice.value=''}})\n</script>\n<template>\n <section class=\"connection-network\">\n <button class=\"back\" type=\"button\" :disabled=\"busy\" @click=\"back\"><AppIcon name=\"chevron-left\" :size=\"16\" />返回模型连接</button>\n <div class=\"connection-heading\"><h3>{{ name }}</h3><span>{{ canLogin?'尚未登录':'模型连接' }}</span></div>\n <p class=\"hint\">用于登录、自动续期、模型列表与模型请求。{{ bot?'继承服务器凭据时沿用服务器连接的网络;此处配置用于本 Bot 独立保存的凭据。':'' }}</p>\n <p v-if=\"error\" role=\"alert\">{{ error }}</p><p v-if=\"notice\" role=\"status\">{{ notice }}</p>\n <ModelNetworkChoice v-if=\"view\" v-model=\"policy\" :view=\"view\" :provider=\"provider\" :bot=\"bot\" :disabled=\"busy\" @busy=\"testing=$event\" />\n <footer v-if=\"view\"><button type=\"button\" :disabled=\"busy || !dirty\" @click=\"policy={...view.connections[provider]??{mode:'inherit'}}\">取消更改</button><button class=\"primary\" type=\"button\" :disabled=\"busy || testing || (!dirty && !canLogin) || (policy.mode==='proxy'&&!policy.proxyId)\" @click=\"save(!!canLogin)\">{{ busy?'正在保存…':canLogin?'保存并登录':'保存更改' }}</button></footer>\n </section>\n</template>\n<style scoped>\n.connection-heading{display:flex;align-items:center;gap:16px}.connection-heading span{font-size:12px;background:var(--surface-soft);color:var(--text-secondary);border-radius:20px;padding:4px 12px}.connection-heading h3{margin:0!important}\n.connection-network{display:grid;gap:8px;margin-top:-12px;max-width:100%;font-size:14px;line-height:1.6}.connection-network h3{margin:0 0 6px;font-size:24px;font-weight:600}.connection-network p{margin:0;color:var(--text-secondary)}.connection-network .hint{font-size:13px}.connection-network footer{display:flex;justify-content:space-between;gap:16px;border-top:1px solid var(--line);padding-top:16px}.connection-network button{min-height:44px;border:1px solid var(--line);border-radius:8px;padding:10px 16px;background:var(--surface);color:var(--text-primary);font:inherit;cursor:pointer}.connection-network .back{display:flex;align-items:center;gap:8px;justify-self:start;border:0;padding-left:0;color:var(--text-secondary)}.connection-network .primary{background:var(--accent);color:var(--text-on-solid);border-color:var(--accent)}.connection-network :disabled{opacity:.5}.connection-network [role=alert]{color:var(--danger)}.connection-network :focus-visible{outline:2px solid var(--accent);outline-offset:3px}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, onMounted, ref, watch } from 'vue'\nimport AppIcon from '@/components/common/AppIcon.vue'\nimport ModelNetworkChoice from './ModelNetworkChoice.vue'\nimport { modelNetworkApi } from '@/api/modelNetwork'\nimport type { ModelNetworkView, NetworkPolicy } from '@shared/modelNetwork'\nconst props=defineProps<{provider:string;name:string;bot?:string;canLogin?:boolean}>()\nconst emit=defineEmits<{back:[];login:[];changed:[];'dirty-change':[value:boolean];'busy-change':[value:boolean]}>()\nconst view=ref<ModelNetworkView>(),policy=ref<NetworkPolicy>({mode:'inherit'}),busy=ref(false),testing=ref(false),error=ref(''),notice=ref('')\nconst dirty=computed(()=>!!view.value&&JSON.stringify(policy.value)!==JSON.stringify(view.value.connections[props.provider]??{mode:'inherit'}))\nwatch(dirty,v=>emit('dirty-change',v));watch(busy,v=>emit('busy-change',v))\nasync function load(){try{view.value=await modelNetworkApi.get(props.bot);policy.value={...view.value.connections[props.provider]??{mode:'inherit'}}}catch(cause){error.value=cause instanceof Error?cause.message:'读取失败'}}\nfunction back(){if(!busy.value&&(!dirty.value||window.confirm('放弃尚未保存的网络更改?')))emit('back')}\nasync function save(login=false){busy.value=true;error.value='';try{view.value=await modelNetworkApi.save(view.value!.revision,policy.value,props.provider,props.bot);notice.value='网络设置已保存,从下一轮任务或新登录生效。';emit('changed');if(login)emit('login')}catch(cause){error.value=cause instanceof Error?cause.message:'保存失败'}finally{busy.value=false}}\nonMounted(load)\ndefineExpose({reset:()=>{if(view.value)policy.value={...view.value.connections[props.provider]??{mode:'inherit'}};notice.value=''}})\n</script>\n<template>\n <section class=\"connection-network\">\n <button class=\"back\" type=\"button\" :disabled=\"busy\" @click=\"back\"><AppIcon name=\"chevron-left\" :size=\"16\" />返回模型连接</button>\n <div class=\"connection-heading\"><h3>{{ name }}</h3><span>{{ canLogin?'尚未登录':'模型连接' }}</span></div>\n <p class=\"hint\">用于登录、自动续期、模型列表与模型请求。{{ bot?'继承服务器凭据时沿用服务器连接的网络;此处配置用于本 Bot 独立保存的凭据。':'' }}</p>\n <p v-if=\"error\" role=\"alert\">{{ error }}</p><p v-if=\"notice\" role=\"status\">{{ notice }}</p>\n <ModelNetworkChoice v-if=\"view\" v-model=\"policy\" :view=\"view\" :provider=\"provider\" :bot=\"bot\" :disabled=\"busy\" @busy=\"testing=$event\" />\n <footer v-if=\"view\"><button type=\"button\" :disabled=\"busy || !dirty\" @click=\"policy={...view.connections[provider]??{mode:'inherit'}}\">取消更改</button><button class=\"primary\" type=\"button\" :disabled=\"busy || testing || (!dirty && !canLogin) || (policy.mode==='proxy'&&!policy.proxyId)\" @click=\"save(!!canLogin)\">{{ busy?'正在保存…':canLogin?'保存并登录':'保存更改' }}</button></footer>\n </section>\n</template>\n<style scoped>\n.connection-heading{display:flex;align-items:center;gap:16px}.connection-heading span{font-size:12px;background:var(--surface-soft);color:var(--text-secondary);border-radius:20px;padding:4px 12px}.connection-heading h3{margin:0!important}\n.connection-network{display:grid;gap:8px;margin-top:-12px;max-width:100%;font-size:14px;line-height:1.6}.connection-network h3{margin:0 0 6px;font-size:24px;font-weight:600}.connection-network p{margin:0;color:var(--text-secondary)}.connection-network .hint{font-size:13px}.connection-network footer{display:flex;justify-content:space-between;gap:16px;border-top:1px solid var(--line);padding-top:16px}.connection-network button{min-height:44px;border:1px solid var(--line);border-radius:8px;padding:10px 16px;background:var(--surface);color:var(--text-primary);font:inherit;cursor:pointer}.connection-network .back{display:flex;align-items:center;gap:8px;justify-self:start;border:0;padding-left:0;color:var(--text-secondary)}.connection-network .primary{background:var(--accent);color:var(--text-on-solid);border-color:var(--accent)}.connection-network :disabled{opacity:.5}.connection-network [role=alert]{color:var(--danger)}.connection-network :focus-visible{outline:2px solid var(--accent);outline-offset:3px}\n</style>\n","import type { BotAutoCandidate, BotAutoPool, BotModelOption } from './botModelSettings.js'\n\nexport const autoTiers = ['light', 'standard', 'complex', 'deep'] as const\nexport type AutoTier = typeof autoTiers[number]\nexport const autoTierLabels: Record<AutoTier, string> = { light: '轻量', standard: '常规', complex: '复杂', deep: '深度' }\nexport const autoTierDescriptions: Record<AutoTier, string> = {\n light: '问候、短答、单步查询,以及目标清晰、范围有限的操作。',\n standard: '常规多步任务、一般分析与内容整理。',\n complex: '跨模块修改、复杂排查和有多项约束的工作。',\n deep: '高难推理、系统性研究与架构设计。',\n}\nexport const autoEfforts = ['low', 'medium', 'high', 'xhigh', 'max'] as const\nexport type AutoEffort = typeof autoEfforts[number]\nexport const effortOrder = ['none', 'minimal', ...autoEfforts, 'ultra'] as const\nexport const effortRank = (value: string) => (effortOrder as readonly string[]).indexOf(value)\nexport type AutoContinuity = 'new' | 'continue' | 'correction' | 'unclear'\nexport const autoContinuityLabels: Record<AutoContinuity, string> = { new: '新任务', continue: '继续未完成任务', correction: '纠正原任务', unclear: '上下文不足' }\nexport type AutoTaskRequirement = { tier: AutoTier; reasoningEffort: AutoEffort }\nexport type AutoRouteDecision = {\n provider: string\n model: string\n reasoningEffort: string\n confidence: number\n reason: 'jev' | 'jeff' | 'fallback' | 'single'\n taskTier?: AutoTier\n requestedTier?: AutoTier\n requestedEffort?: string\n continuity?: AutoContinuity\n taskRequirement?: AutoTaskRequirement\n explanation: string\n fallbackReason?: 'low_confidence' | 'invalid_response' | 'request_failed' | 'not_configured'\n probabilities?: Record<string, Record<string, number>>\n previous?: { provider: string; model: string }\n}\n\n/** Editable starting recommendations for existing pools; unknown models remain standard. */\nexport function suggestedAutoTier(model: string): AutoTier {\n if (model === 'gpt-6-luna') return 'light'\n if (model === 'gpt-6.1-sol') return 'complex'\n if (model === 'gpt-6-astra') return 'deep'\n return 'standard'\n}\nexport function candidateTier(candidate: BotAutoCandidate): AutoTier { return candidate.tier ?? suggestedAutoTier(candidate.model) }\nexport function autoPolicy(pool: BotAutoPool) {\n return { preserveTaskAbility: pool.preserveTaskAbility !== false, maxReasoningEffort: pool.maxReasoningEffort ?? 'high' as AutoEffort, fallbackReasoningEffort: pool.fallbackReasoningEffort ?? 'medium' }\n}\n\n/** No inferred effort ladder. Unknown capabilities use the provider default. */\nexport function compatibleAutoEffort(model: Pick<BotModelOption, 'reasoningKnown' | 'reasoningEfforts' | 'defaultReasoningEffort'>, requested: string, maximum: AutoEffort): string | null {\n if (!model.reasoningKnown) return 'default'\n if (!model.reasoningEfforts.length) return 'none'\n const supported = model.reasoningEfforts.filter(e => effortRank(e) >= 0 && effortRank(e) <= effortRank(maximum)).sort((a, b) => effortRank(a) - effortRank(b))\n if (!supported.length) return null\n if (requested === 'default') requested = model.defaultReasoningEffort ?? 'medium'\n if (requested === 'none' && supported.includes('none')) return 'none'\n if (supported.every(e => e === 'none')) return 'none'\n const target = Math.min(Math.max(effortRank(requested), effortRank('low')), effortRank(maximum))\n // Do not disable thinking just because a requested nonzero level is absent.\n const enabled = requested === 'none' ? supported : supported.filter(e => e !== 'none')\n if (!enabled.length) return null\n // A lower supported level cannot satisfy an established task's effort floor.\n return enabled.find(e => effortRank(e) >= target) ?? null\n}\n\nexport function selectAutoCombination(candidates: BotAutoCandidate[], options: BotModelOption[], requirement: AutoTaskRequirement, pool: BotAutoPool, preferred?: {provider: string; model: string}) {\n const policy = autoPolicy(pool)\n const eligible = candidates.flatMap((candidate, index) => {\n const option = options.find(o => o.provider === candidate.provider && o.model === candidate.model)\n if (!option || autoTiers.indexOf(candidateTier(candidate)) < autoTiers.indexOf(requirement.tier)) return []\n const reasoningEffort = compatibleAutoEffort(option, requirement.reasoningEffort, policy.maxReasoningEffort)\n return reasoningEffort === null ? [] : [{ ...candidate, reasoningEffort, index }]\n }).sort((a,b) => autoTiers.indexOf(candidateTier(a)) - autoTiers.indexOf(candidateTier(b)) || a.index - b.index)\n return (preferred && eligible.find(c => c.provider === preferred.provider && c.model === preferred.model)) || eligible[0]\n}\n","import type { HermesAuxiliaryOverrides, HermesFallbackChain } from './hermesAuxiliary.js'\nimport type { BotMediaSettings } from './botMediaSettings.js'\n\nexport type BotFastMode = 'normal' | 'fast' | 'auto' | 'cold'\n\n/** Virtual provider/model pair for TypeSafe Jev Auto routing. */\nexport const BOT_MODEL_AUTO_PROVIDER = 'auto'\nexport const BOT_MODEL_AUTO_MODEL = 'auto'\nexport const JEV_NETWORK_PROVIDER = 'typesafe'\nexport const BOT_AUTO_MIN_CANDIDATES = 2\nexport const BOT_AUTO_DEFAULT_MIN_CONFIDENCE = 0.55\n\nexport interface BotAutoCandidate {\n provider: string\n model: string\n /** Short capability hint for Jev Choice criteria. */\n blurb?: string\n /** User-configurable capability/cost tier; not a provider capability claim. */\n tier?: 'light' | 'standard' | 'complex' | 'deep'\n}\n\nexport interface BotAutoPool {\n candidates: BotAutoCandidate[]\n /** Used when Jev fails or confidence is low. Defaults to candidates[0]. */\n fallback?: { provider: string; model: string }\n minConfidence?: number\n preserveTaskAbility?: boolean\n maxReasoningEffort?: 'low' | 'medium' | 'high' | 'xhigh' | 'max'\n fallbackReasoningEffort?: string\n}\n\nexport interface BotModelPreset {\n provider: string\n model: string\n reasoningEffort: string | null\n fastMode: BotFastMode | null\n}\n\nexport interface BotModelSettings {\n /** Per-model tuning; editing an inactive model never selects it. Omitted PATCH preserves these. */\n modelPresets?: BotModelPreset[] | null\n provider: string | null\n model: string | null\n reasoningEffort: string | null\n fastMode: BotFastMode | null\n /** Hermes `auxiliary.<task>` overlay. Null inherits the system layer; omission in a PATCH preserves it. */\n auxiliary?: HermesAuxiliaryOverrides | null\n /** Hermes `fallback_model` overlay. Null inherits the system layer. */\n fallback?: HermesFallbackChain | null\n /** Null follows system defaults; omitted PATCH fields preserve Bot choices. */\n media?: BotMediaSettings | null\n /** Candidate pool for Auto (`provider`/`model` === `auto`). Omitted PATCH preserves it. */\n autoPool?: BotAutoPool | null\n}\n\nexport function isBotModelAuto(settings: Pick<BotModelSettings, 'provider' | 'model'> | null | undefined): boolean {\n return settings?.provider === BOT_MODEL_AUTO_PROVIDER && settings?.model === BOT_MODEL_AUTO_MODEL\n}\n\nexport function autoCandidateKey(candidate: Pick<BotAutoCandidate, 'provider' | 'model'>): string {\n return `${candidate.provider}::${candidate.model}`\n}\n\nexport function parseAutoCandidateKey(key: string): { provider: string; model: string } | null {\n const sep = key.indexOf('::')\n if (sep <= 0 || sep === key.length - 2) return null\n const provider = key.slice(0, sep), model = key.slice(sep + 2)\n return provider && model ? { provider, model } : null\n}\n\nexport function mergeBotModelSettings<T extends BotModelSettings>(current: BotModelSettings | null | undefined, patch: T | null | undefined) {\n if (!patch) return patch\n const next = { ...patch }\n if (!Object.hasOwn(patch, 'auxiliary') && current?.auxiliary !== undefined) next.auxiliary = current.auxiliary\n if (!Object.hasOwn(patch, 'fallback') && current?.fallback !== undefined) next.fallback = current.fallback\n if (!Object.hasOwn(patch, 'media') && current?.media !== undefined) next.media = current.media\n else if (patch.media && current?.media) next.media = { ...current.media, ...patch.media }\n if (!Object.hasOwn(patch, 'modelPresets') && current?.modelPresets !== undefined) next.modelPresets = current.modelPresets\n if (!Object.hasOwn(patch, 'autoPool') && current?.autoPool !== undefined) next.autoPool = current.autoPool\n return next\n}\n\nexport interface ResolvedBotModelSettings {\n provider: string\n model: string\n reasoningEffort: string\n fastMode: BotFastMode\n}\n\nexport interface BotModelOption {\n provider: string\n providerName?: string\n model: string\n name: string\n reasoningEfforts: string[]\n reasoningKnown: boolean\n fastModes: BotFastMode[]\n defaultReasoningEffort?: string\n contextWindow?: number\n contextBudget?: number\n /** Kept visible because this Bot already uses a model outside the curated list. */\n retained?: boolean\n}\n\nexport interface BotModelVisibilityView {\n revision: number\n /** null shows the full catalog; an array is the system's curated manual picker. */\n models: Array<{ provider: string; model: string }> | null\n}\n\nexport interface BotModelOptions {\n version: 1\n defaults: ResolvedBotModelSettings\n models: BotModelOption[]\n settings: BotModelSettings | null\n revision: number\n /** System-layer Hermes auxiliary slots for the Bot settings UI. */\n auxiliaryDefaults?: HermesAuxiliaryOverrides\n auto?: { available: boolean; enabled: boolean; candidateCount: number; unavailableReason?: string; backend?: 'jev' | 'jeff' }\n}\n\nexport const inheritedBotModelSettings = (): BotModelSettings => ({\n provider: null,\n model: null,\n reasoningEffort: null,\n fastMode: null,\n auxiliary: null,\n fallback: null,\n autoPool: null,\n})\n\nexport const botReasoningLabels: Record<string, string> = { none: '关闭', minimal: '最小', low: '低', medium: '中', high: '高', xhigh: '极高', max: '最大', ultra: 'Ultra' }\nexport const botFastLabels: Record<BotFastMode, string> = { normal: '普通', fast: '快速', auto: '每轮开始加速', cold: '首次回复加速' }\n\nexport function botModelChoices(options?: BotModelOptions) {\n if (!options) return [];\n const automaticDefault = !!options.auto?.enabled;\n const providerName = (row: { provider: string; providerName?: string; name: string }) =>\n row.providerName?.trim() || (row.name.includes(\" · \") ? row.name.split(\" · \")[0]!.trim() :\n ({ \"openai-codex\": \"OpenAI Codex\", openai: \"OpenAI\", anthropic: \"Anthropic\" } as Record<string, string>)[row.provider] || row.provider);\n const rows = options.models.filter(row => row.provider !== \"auto\").map(row => ({\n provider: row.provider, id: row.model, name: row.model, providerName: providerName(row),\n isDefault: !automaticDefault && row.provider === options.defaults.provider && row.model === options.defaults.model,\n disabled: false, hint: row.retained ? \"此 Bot 已选模型,系统可选清单外\" : \"\",\n }));\n if (!automaticDefault && !rows.some(row => row.isDefault)) rows.unshift({\n provider: \"inherit\", id: \"default\", name: options.defaults.model || \"默认模型\",\n providerName: options.defaults.provider || \"系统\", isDefault: true, disabled: false, hint: \"跟随系统默认\",\n });\n const decision = options.auto?.backend === 'jeff' ? 'Jeff' : 'Jev';\n const ordered = [...rows.filter(row => row.isDefault), {\n provider: \"auto\", id: \"auto\", name: \"Auto\", providerName: decision, isDefault: automaticDefault,\n disabled: !options.auto?.available, hint: options.auto?.unavailableReason || `使用系统 ${decision} 候选池`,\n }, ...rows.filter(row => !row.isDefault)];\n const explicit = !!options.settings?.provider && !!options.settings?.model;\n const current = explicit ? `${options.settings!.provider}:${options.settings!.model}` :\n automaticDefault ? \"auto:auto\" : `${options.defaults.provider}:${options.defaults.model}`;\n return ordered.map(row => ({ ...row, isCurrent: `${row.provider}:${row.id}` === current || (!explicit && row.provider === \"inherit\") }));\n}\n\n/** Decision backends for Auto routing: cloud TypeSafe Jev or local Jeff. */\nexport const DECISION_BACKENDS = ['jev', 'jeff'] as const\nexport type DecisionBackend = (typeof DECISION_BACKENDS)[number]\nexport const DECISION_BACKEND_LABELS: Record<DecisionBackend, string> = {\n jev: 'Jev(云端 TypeSafe)',\n jeff: 'Jeff(本机)',\n}\n/** Short name for Auto picker / chat controls. */\nexport function autoDecisionShortLabel(backend?: DecisionBackend | null): 'Jev' | 'Jeff' {\n return backend === 'jeff' ? 'Jeff' : 'Jev'\n}\nexport const TYPESAFE_SYSTEMONE_URL = 'https://api.typesafe.ai/v1/systemone'\nexport const JEV_DECISION_MODEL = 'jev-latest'\nexport const JEFF_DEFAULT_BASE_URL = 'http://127.0.0.1:8765'\nexport const JEFF_DEFAULT_MODEL = 'jeff-latest'\n","<script setup lang=\"ts\">\nimport { autoContinuityLabels, autoTierLabels, type AutoRouteDecision } from '@shared/autoRouting'\nimport { botReasoningLabels } from '@shared/botModelSettings'\ndefineProps<{ route: AutoRouteDecision }>()\nconst effortLabel = (value: string) => value === 'default' ? '提供方默认' : botReasoningLabels[value] ?? value\nconst sourceLabels = { jev: 'Jev 自动判断', jeff: 'Jeff 自动判断', fallback: '回退组合', single: '仅剩一个候选' }\n</script>\n<template>\n <details class=\"auto-route\" aria-label=\"Auto 选模依据\">\n <summary>Auto · {{ route.model }} · {{ effortLabel(route.reasoningEffort) }}{{ !['none','default'].includes(route.reasoningEffort) ? '思考' : '' }}<span v-if=\"route.reason !== 'jev' && route.reason !== 'jeff'\"> · 回退</span></summary>\n <div class=\"auto-route__detail\">\n <p>{{ route.explanation }}</p>\n <dl>\n <div><dt>决策来源</dt><dd>{{ sourceLabels[route.reason] }}</dd></div>\n <div v-if=\"route.taskTier\"><dt>任务能力</dt><dd>{{ autoTierLabels[route.taskTier] }}{{ route.requestedTier && route.requestedTier !== route.taskTier ? `(本轮判断 ${autoTierLabels[route.requestedTier]},保留任务下限)` : '' }}</dd></div>\n <div v-if=\"route.continuity\"><dt>任务关系</dt><dd>{{ autoContinuityLabels[route.continuity] }}</dd></div>\n <div><dt>判断置信度</dt><dd>{{ Math.round(route.confidence * 100) }}%</dd></div>\n <div v-if=\"route.requestedEffort && route.requestedEffort !== route.reasoningEffort\"><dt>思考适配</dt><dd>{{ effortLabel(route.requestedEffort) }} → {{ effortLabel(route.reasoningEffort) }}</dd></div>\n <div><dt>模型服务</dt><dd>{{ route.provider }}</dd></div>\n </dl>\n </div>\n </details>\n</template>\n<style scoped>\n.auto-route{max-width:100%;margin-top:8px;color:var(--text-secondary);font-size:12px;line-height:1.6;overflow-wrap:anywhere}.auto-route summary{cursor:pointer;min-height:28px;padding:4px 0}.auto-route summary:focus-visible{outline:2px solid var(--accent);outline-offset:2px}.auto-route__detail{padding:10px 12px;background:var(--surface-soft);border-radius:8px;margin-top:4px}.auto-route p{margin:0 0 8px}.auto-route dl{margin:0;display:grid;gap:5px}.auto-route dl>div{display:grid;grid-template-columns:88px minmax(0,1fr);gap:10px}.auto-route dt{color:var(--text-secondary)}.auto-route dd{margin:0;color:var(--text-primary)}@media(pointer:coarse){.auto-route summary{min-height:44px;display:list-item;align-content:center}}\n</style>\n","<script setup lang=\"ts\">\nimport { autoContinuityLabels, autoTierLabels, type AutoRouteDecision } from '@shared/autoRouting'\nimport { botReasoningLabels } from '@shared/botModelSettings'\ndefineProps<{ route: AutoRouteDecision }>()\nconst effortLabel = (value: string) => value === 'default' ? '提供方默认' : botReasoningLabels[value] ?? value\nconst sourceLabels = { jev: 'Jev 自动判断', jeff: 'Jeff 自动判断', fallback: '回退组合', single: '仅剩一个候选' }\n</script>\n<template>\n <details class=\"auto-route\" aria-label=\"Auto 选模依据\">\n <summary>Auto · {{ route.model }} · {{ effortLabel(route.reasoningEffort) }}{{ !['none','default'].includes(route.reasoningEffort) ? '思考' : '' }}<span v-if=\"route.reason !== 'jev' && route.reason !== 'jeff'\"> · 回退</span></summary>\n <div class=\"auto-route__detail\">\n <p>{{ route.explanation }}</p>\n <dl>\n <div><dt>决策来源</dt><dd>{{ sourceLabels[route.reason] }}</dd></div>\n <div v-if=\"route.taskTier\"><dt>任务能力</dt><dd>{{ autoTierLabels[route.taskTier] }}{{ route.requestedTier && route.requestedTier !== route.taskTier ? `(本轮判断 ${autoTierLabels[route.requestedTier]},保留任务下限)` : '' }}</dd></div>\n <div v-if=\"route.continuity\"><dt>任务关系</dt><dd>{{ autoContinuityLabels[route.continuity] }}</dd></div>\n <div><dt>判断置信度</dt><dd>{{ Math.round(route.confidence * 100) }}%</dd></div>\n <div v-if=\"route.requestedEffort && route.requestedEffort !== route.reasoningEffort\"><dt>思考适配</dt><dd>{{ effortLabel(route.requestedEffort) }} → {{ effortLabel(route.reasoningEffort) }}</dd></div>\n <div><dt>模型服务</dt><dd>{{ route.provider }}</dd></div>\n </dl>\n </div>\n </details>\n</template>\n<style scoped>\n.auto-route{max-width:100%;margin-top:8px;color:var(--text-secondary);font-size:12px;line-height:1.6;overflow-wrap:anywhere}.auto-route summary{cursor:pointer;min-height:28px;padding:4px 0}.auto-route summary:focus-visible{outline:2px solid var(--accent);outline-offset:2px}.auto-route__detail{padding:10px 12px;background:var(--surface-soft);border-radius:8px;margin-top:4px}.auto-route p{margin:0 0 8px}.auto-route dl{margin:0;display:grid;gap:5px}.auto-route dl>div{display:grid;grid-template-columns:88px minmax(0,1fr);gap:10px}.auto-route dt{color:var(--text-secondary)}.auto-route dd{margin:0;color:var(--text-primary)}@media(pointer:coarse){.auto-route summary{min-height:44px;display:list-item;align-content:center}}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, onMounted, ref, watch } from 'vue'\nimport { hermesApi, type HermesModelOptions, type JevAutoView } from '@/api/hermes'\nimport { autoEfforts, autoPolicy, autoTiers, autoTierLabels, autoTierDescriptions, candidateTier, compatibleAutoEffort, effortRank, suggestedAutoTier, type AutoEffort, type AutoRouteDecision, type AutoTier } from '@shared/autoRouting'\nimport { BOT_AUTO_DEFAULT_MIN_CONFIDENCE, DECISION_BACKEND_LABELS, DECISION_BACKENDS, JEFF_DEFAULT_BASE_URL, JEFF_DEFAULT_MODEL, botReasoningLabels, type BotAutoPool, type BotModelOption, type DecisionBackend } from '@shared/botModelSettings'\nimport AutoRouteNotice from '../messages/AutoRouteNotice.vue'\n\nconst props = defineProps<{ models?: HermesModelOptions; disabled?: boolean }>()\nconst emit = defineEmits<{ 'dirty-change': [value: boolean]; 'busy-change': [value: boolean] }>()\nconst view = ref<JevAutoView>(), modelOptions = ref<BotModelOption[]>([])\nconst enabled = ref(false), selected = ref<string[]>([]), fallback = ref(''), apiKey = ref('')\nconst backend = ref<DecisionBackend>('jev'), jeffBaseUrl = ref(JEFF_DEFAULT_BASE_URL), jeffModel = ref(JEFF_DEFAULT_MODEL)\nconst drafts = ref<Record<string, {tier: AutoTier; blurb: string}>>({})\nconst preserveTaskAbility = ref(true), maxReasoningEffort = ref<AutoEffort>('high'), fallbackReasoningEffort = ref('medium'), minConfidence = ref(BOT_AUTO_DEFAULT_MIN_CONFIDENCE)\nconst busy = ref(false), error = ref(''), notice = ref(''), baseline = ref(''), search = ref('')\nconst previewText = ref('你好'), preview = ref<AutoRouteDecision>(), previewBusy = ref(false), previewError = ref('')\nconst blocked = computed(() => props.disabled || busy.value || previewBusy.value || !view.value)\nconst keyOf = (provider: string, model: string) => JSON.stringify([provider, model])\nconst pairOf = (key: string) => { const [provider, model] = JSON.parse(key) as [string, string]; return { provider, model } }\nconst nameOf = (key: string) => pairOf(key).model\nconst optionOf = (key: string) => { const pair = pairOf(key); return modelOptions.value.find(m => m.provider === pair.provider && m.model === pair.model) }\nconst candidates = computed(() => selected.value.map(id => ({ ...pairOf(id), tier: drafts.value[id]?.tier ?? suggestedAutoTier(nameOf(id)), ...(drafts.value[id]?.blurb.trim() ? { blurb: drafts.value[id]!.blurb.trim() } : {}) })))\nconst pool = (): BotAutoPool => ({ candidates: candidates.value, ...(fallback.value ? { fallback: pairOf(fallback.value) } : {}), minConfidence: minConfidence.value, preserveTaskAbility: preserveTaskAbility.value, maxReasoningEffort: maxReasoningEffort.value, fallbackReasoningEffort: fallbackReasoningEffort.value })\nconst snapshot = () => JSON.stringify([enabled.value, backend.value, jeffBaseUrl.value.trim(), jeffModel.value.trim(), pool()])\nconst dirty = computed(() => !!view.value && (snapshot() !== baseline.value || !!apiKey.value.trim()))\nconst valid = computed(() => Number.isFinite(minConfidence.value) && minConfidence.value >= 0 && minConfidence.value <= 1 && (!enabled.value || selected.value.length >= 2))\nconst decisionReady = computed(() => backend.value === 'jeff' || !!apiKey.value.trim() || !!view.value?.hasApiKey)\nconst previewBlocked = computed(() => blocked.value || !enabled.value || !valid.value || !previewText.value.trim() || !decisionReady.value)\nwatch(dirty, value => emit('dirty-change', value))\nwatch(() => busy.value || previewBusy.value, value => emit('busy-change', value))\nwatch([snapshot, previewText, apiKey], () => { preview.value = undefined; previewError.value = '' })\nconst groups = computed(() => (props.models?.providers ?? []).filter(p => p.authenticated !== false && p.models.length))\nconst shownGroups = computed(() => groups.value.map(p => ({ ...p, models: p.models.filter(m => `${p.name} ${m}`.toLowerCase().includes(search.value.trim().toLowerCase())) })).filter(p => p.models.length))\nconst fallbackEfforts = computed(() => {\n const option = fallback.value ? optionOf(fallback.value) : undefined\n return option?.reasoningKnown ? autoEfforts.filter(e => option.reasoningEfforts.includes(e) && effortRank(e) <= effortRank(maxReasoningEffort.value)) : []\n})\nconst fallbackActual = computed(() => {\n const option = fallback.value ? optionOf(fallback.value) : undefined\n const value = option ? compatibleAutoEffort(option, fallbackReasoningEffort.value, maxReasoningEffort.value) : 'default'\n return value === null ? '当前模型无符合思考上限的档位' : value === 'default' ? '提供方默认' : botReasoningLabels[value] ?? value\n})\nconst thinkingLabel = computed(() => backend.value === 'jeff' ? '自动(Jeff)' : '自动(Jev)')\nfunction load(data: JevAutoView) {\n view.value = data\n if (data.modelOptions) modelOptions.value = data.modelOptions\n enabled.value = data.enabled\n backend.value = data.backend ?? 'jev'\n jeffBaseUrl.value = data.jeffBaseUrl || JEFF_DEFAULT_BASE_URL\n jeffModel.value = data.jeffModel || JEFF_DEFAULT_MODEL\n selected.value = data.candidates.map(c => keyOf(c.provider, c.model))\n drafts.value = Object.fromEntries(data.candidates.map(c => [keyOf(c.provider, c.model), {tier: candidateTier(c), blurb: c.blurb ?? ''}]))\n fallback.value = data.fallback ? keyOf(data.fallback.provider, data.fallback.model) : selected.value[0] ?? ''\n const policy = autoPolicy(data)\n preserveTaskAbility.value = policy.preserveTaskAbility; maxReasoningEffort.value = policy.maxReasoningEffort; fallbackReasoningEffort.value = policy.fallbackReasoningEffort\n minConfidence.value = data.minConfidence ?? BOT_AUTO_DEFAULT_MIN_CONFIDENCE\n apiKey.value = ''; baseline.value = snapshot()\n}\nfunction toggle(id: string) {\n if (!drafts.value[id]) drafts.value[id] = { tier: suggestedAutoTier(nameOf(id)), blurb: '' }\n selected.value = selected.value.includes(id) ? selected.value.filter(item => item !== id) : [...selected.value, id]\n if (!selected.value.includes(fallback.value)) fallback.value = selected.value[0] ?? ''\n}\nasync function save() {\n // The parent disables all panels while invoking their exposed save methods.\n if (!view.value || busy.value || previewBusy.value) return false\n if (!valid.value) { error.value = '请选择至少两个候选模型,并将置信度设为 0 到 1。'; return false }\n busy.value = true; error.value = ''; notice.value = ''\n try {\n load(await hermesApi.saveJev({\n revision: view.value.revision,\n enabled: enabled.value,\n backend: backend.value,\n jeffBaseUrl: jeffBaseUrl.value.trim() || JEFF_DEFAULT_BASE_URL,\n jeffModel: jeffModel.value.trim() || JEFF_DEFAULT_MODEL,\n ...pool(),\n ...(apiKey.value.trim() ? { apiKey: apiKey.value.trim() } : {}),\n }))\n notice.value = '自动选模已保存,新的 Bot 回合使用此配置。'\n return true\n } catch (cause) { error.value = cause instanceof Error ? cause.message : '保存失败'; return false }\n finally { busy.value = false }\n}\nasync function reset() {\n if (busy.value || previewBusy.value) return\n busy.value = true; error.value = ''; notice.value = ''\n try { load(await hermesApi.jev()) } catch (cause) { error.value = cause instanceof Error ? cause.message : '无法读取自动选模设置' }\n finally { busy.value = false }\n}\nasync function runPreview() {\n if (previewBlocked.value) return\n previewBusy.value = true; previewError.value = ''; preview.value = undefined\n try {\n preview.value = await hermesApi.previewJev({\n pool: pool(),\n enabled: enabled.value,\n userText: previewText.value.trim(),\n backend: backend.value,\n jeffBaseUrl: jeffBaseUrl.value.trim() || JEFF_DEFAULT_BASE_URL,\n jeffModel: jeffModel.value.trim() || JEFF_DEFAULT_MODEL,\n ...(apiKey.value.trim() ? { apiKey: apiKey.value.trim() } : {}),\n })\n }\n catch (cause) { previewError.value = cause instanceof Error ? cause.message : '预览失败' }\n finally { previewBusy.value = false }\n}\nonMounted(reset)\ndefineExpose({ reset, save })\n</script>\n<template>\n <section class=\"jev-auto\" aria-label=\"自动选模\" :aria-busy=\"busy || previewBusy\">\n <div class=\"jev-title\"><h4>自动选模</h4><label class=\"jev-toggle\"><input v-model=\"enabled\" type=\"checkbox\" :disabled=\"blocked\"> 启用自动选模</label></div>\n <p>由决策模型结合任务和上下文,选择能胜任的最轻模型与思考强度。关闭后 Bot 不可选择 Auto。</p>\n <p v-if=\"error\" class=\"error\" role=\"alert\">{{ error }}</p>\n <p v-if=\"notice\" role=\"status\">{{ notice }}</p>\n <label>决策服务<select v-model=\"backend\" aria-label=\"决策服务\" :disabled=\"blocked\"><option v-for=\"id in DECISION_BACKENDS\" :key=\"id\" :value=\"id\">{{ DECISION_BACKEND_LABELS[id] }}</option></select></label>\n <template v-if=\"backend === 'jeff'\">\n <div class=\"jev-fields\">\n <label>Jeff 地址<input v-model=\"jeffBaseUrl\" type=\"url\" placeholder=\"http://127.0.0.1:8765\" :disabled=\"blocked\"></label>\n <label>Jeff 模型<input v-model=\"jeffModel\" type=\"text\" placeholder=\"jeff-latest\" :disabled=\"blocked\"></label>\n </div>\n <p>本机 Jeff 默认无密钥。地址仅允许 127.0.0.1 / localhost。可用环境变量 <code>YAOVI_DECISION_BACKEND=jeff</code>、<code>JEFF_BASE_URL</code> 覆盖。</p>\n </template>\n <label v-else>TypeSafe API 密钥<input v-model=\"apiKey\" type=\"password\" autocomplete=\"new-password\" :placeholder=\"view?.hasApiKey ? '已保存,留空则不修改' : 'sk-…'\" :disabled=\"blocked\"></label>\n <div class=\"jev-section-title\"><h5>模型分工</h5><small>建议分工,可按实际表现调整</small></div>\n <div class=\"jev-roles\">\n <div v-for=\"id in selected\" :key=\"id\" class=\"jev-role\">\n <div class=\"jev-model-name\"><strong>{{ nameOf(id) }}</strong><small>{{ autoTierDescriptions[drafts[id]!.tier] }}</small><small v-if=\"modelOptions.length && !optionOf(id)\" class=\"error\">当前不可用</small></div>\n <label><span class=\"sr-only\">{{ nameOf(id) }} 的任务分工</span><select v-model=\"drafts[id]!.tier\" :aria-label=\"`${nameOf(id)} 的任务分工`\" :disabled=\"blocked\"><option v-for=\"tier in autoTiers\" :key=\"tier\" :value=\"tier\">{{ autoTierLabels[tier] }}任务</option></select></label>\n </div>\n <p v-if=\"!selected.length\">选择至少两个候选模型后配置分工。</p>\n </div>\n <details class=\"jev-picker\" :open=\"!selected.length\">\n <summary>选择候选模型 · 已选 {{ selected.length }} 个</summary>\n <label>筛选候选模型<input v-model=\"search\" type=\"search\" placeholder=\"搜索模型或供应商\" :disabled=\"blocked\"></label>\n <div class=\"jev-model-list\"><div v-for=\"group in shownGroups\" :key=\"group.slug\" class=\"jev-group\"><strong>{{ group.name }}</strong><label v-for=\"model in group.models\" :key=\"group.slug + model\"><input type=\"checkbox\" :checked=\"selected.includes(keyOf(group.slug, model))\" :disabled=\"blocked || selected.length >= 32 && !selected.includes(keyOf(group.slug, model))\" @change=\"toggle(keyOf(group.slug, model))\">{{ model }}</label></div><p v-if=\"!shownGroups.length\">没有匹配的已连接模型。</p><label v-for=\"id in selected.filter(key => !groups.some(g => g.slug === pairOf(key).provider && g.models.includes(nameOf(key))))\" :key=\"id\" class=\"jev-toggle\"><input type=\"checkbox\" checked :disabled=\"blocked\" @change=\"toggle(id)\">{{ nameOf(id) }}(目录外,可移除)</label></div>\n </details>\n <label class=\"jev-continuity\"><input v-model=\"preserveTaskAbility\" type=\"checkbox\" :disabled=\"blocked\"><span>保留未完成任务所需能力<small>继续复杂任务时保留能力与思考下限;新的简单任务允许降级。</small></span></label>\n <label>思考强度<input :value=\"thinkingLabel\" readonly aria-label=\"Auto 思考强度\"></label>\n <details class=\"jev-advanced\"><summary>高级设置与回退</summary>\n <div class=\"jev-fields\">\n <label>最高允许思考等级<select v-model=\"maxReasoningEffort\" :disabled=\"blocked\"><option v-for=\"effort in autoEfforts\" :key=\"effort\" :value=\"effort\">{{ botReasoningLabels[effort] }}</option></select></label>\n <label>最低置信度<input v-model.number=\"minConfidence\" type=\"number\" min=\"0\" max=\"1\" step=\"0.05\" :disabled=\"blocked\"></label>\n <label v-if=\"selected.length\">回退模型<select v-model=\"fallback\" :disabled=\"blocked\"><option v-for=\"id in selected\" :key=\"id\" :value=\"id\">{{ nameOf(id) }}</option></select></label>\n <label>回退思考强度<select v-model=\"fallbackReasoningEffort\" :disabled=\"blocked\"><option value=\"default\">模型默认</option><option v-if=\"fallbackReasoningEffort !== 'default' && !fallbackEfforts.includes(fallbackReasoningEffort as AutoEffort)\" :value=\"fallbackReasoningEffort\">{{ botReasoningLabels[fallbackReasoningEffort] }}(自动适配)</option><option v-for=\"effort in fallbackEfforts\" :key=\"effort\" :value=\"effort\">{{ botReasoningLabels[effort] }}</option></select><small>实际档位:{{ fallbackActual }}</small></label>\n </div>\n <p>回退不影响下一轮偏好。继续原任务时仍保留必要能力;思考档位未知时使用提供方默认。</p>\n <label v-for=\"id in selected\" :key=\"id\" class=\"jev-hint\">{{ nameOf(id) }} · 补充能力说明<input v-model=\"drafts[id]!.blurb\" maxlength=\"280\" placeholder=\"可选,例如擅长代码排查或长文分析\" :disabled=\"blocked\"></label>\n </details>\n <details class=\"jev-preview\"><summary>选模预览</summary>\n <p>使用当前草稿调用 {{ backend === 'jeff' ? 'Jeff' : 'Jev' }},仅判断这个新任务,不执行任务,也不保存设置。</p>\n <label>任务内容<textarea v-model=\"previewText\" maxlength=\"2000\" rows=\"2\" :disabled=\"blocked\" /></label>\n <button type=\"button\" :disabled=\"previewBlocked\" @click=\"runPreview\">{{ previewBusy ? (backend === 'jeff' ? 'Jeff 正在判断…' : 'Jev 正在判断…') : '预览模型与思考强度' }}</button>\n <p v-if=\"previewError\" class=\"error\" role=\"alert\">{{ previewError }}</p>\n <div aria-live=\"polite\"><AutoRouteNotice v-if=\"preview\" :route=\"preview\"/></div>\n </details>\n <button type=\"button\" :disabled=\"blocked || !dirty || !valid\" @click=\"save\">{{ busy ? '正在处理…' : '保存自动选模' }}</button>\n <button v-if=\"error\" type=\"button\" :disabled=\"busy || previewBusy\" @click=\"reset\">重新读取设置</button>\n </section>\n</template>\n<style scoped>\n.jev-auto{display:grid;gap:14px;margin-top:16px;padding-top:16px;border-top:1px solid var(--line);min-width:0}h4,h5,p{margin:0}h5{font-size:13px;font-weight:550}p,small{color:var(--text-secondary);font-size:12px;line-height:1.6}.jev-title,.jev-section-title{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap}.jev-model-list{display:grid;gap:16px;max-height:280px;overflow:auto;padding:4px}.jev-group{display:grid;gap:6px}.jev-group strong{font-size:12px;color:var(--text-secondary)}label{display:grid;gap:6px;font-size:13px;min-width:0}.jev-toggle,.jev-group label{display:flex;align-items:center;gap:8px;min-height:44px;overflow-wrap:anywhere}.jev-role{display:grid;grid-template-columns:minmax(0,1fr) 132px;gap:12px;align-items:center;padding:12px 0;border-bottom:1px solid var(--line)}.jev-role:last-child{border:0}.jev-model-name{display:grid;gap:4px;min-width:0;overflow-wrap:anywhere}.jev-model-name strong{font-size:13px;font-weight:550}.jev-continuity{display:flex;align-items:flex-start;gap:8px;min-height:44px}.jev-continuity input{margin-top:4px}.jev-continuity small{display:block;margin-top:3px}.jev-fields{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px}.jev-auto input:not([type=checkbox]),select,textarea{box-sizing:border-box;width:100%;min-width:0;min-height:44px;padding:8px 10px;border:1px solid var(--line);border-radius:8px;background:var(--surface);color:var(--text-primary);font:13px var(--font-ui)}textarea{resize:vertical}input[readonly]{color:var(--text-secondary)!important;background:var(--surface-soft)!important}.jev-auto details>label,.jev-auto details>p,.jev-auto details>.jev-fields,.jev-preview>button{margin-top:10px}.jev-auto summary{min-height:32px;cursor:pointer;color:var(--text-secondary);font-size:13px}.jev-picker>label{margin-bottom:10px}.jev-auto button{justify-self:start;min-height:44px;padding:8px 12px;border:1px solid var(--line);border-radius:8px;background:var(--surface);color:var(--text-primary);cursor:pointer;font:13px var(--font-ui)}.error{color:var(--danger)}.jev-auto :focus-visible{outline:2px solid var(--accent);outline-offset:2px}.jev-auto :disabled{opacity:.55;cursor:default}.sr-only{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}code{font-size:11px}@media(max-width:420px){.jev-fields{grid-template-columns:1fr}.jev-role{grid-template-columns:minmax(0,1fr) 108px;gap:8px}}@media(pointer:coarse){.jev-auto summary{min-height:44px;align-content:center}.jev-auto input:not([type=checkbox]),select,textarea{font-size:16px}}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, onMounted, ref, watch } from 'vue'\nimport { hermesApi, type HermesModelOptions, type JevAutoView } from '@/api/hermes'\nimport { autoEfforts, autoPolicy, autoTiers, autoTierLabels, autoTierDescriptions, candidateTier, compatibleAutoEffort, effortRank, suggestedAutoTier, type AutoEffort, type AutoRouteDecision, type AutoTier } from '@shared/autoRouting'\nimport { BOT_AUTO_DEFAULT_MIN_CONFIDENCE, DECISION_BACKEND_LABELS, DECISION_BACKENDS, JEFF_DEFAULT_BASE_URL, JEFF_DEFAULT_MODEL, botReasoningLabels, type BotAutoPool, type BotModelOption, type DecisionBackend } from '@shared/botModelSettings'\nimport AutoRouteNotice from '../messages/AutoRouteNotice.vue'\n\nconst props = defineProps<{ models?: HermesModelOptions; disabled?: boolean }>()\nconst emit = defineEmits<{ 'dirty-change': [value: boolean]; 'busy-change': [value: boolean] }>()\nconst view = ref<JevAutoView>(), modelOptions = ref<BotModelOption[]>([])\nconst enabled = ref(false), selected = ref<string[]>([]), fallback = ref(''), apiKey = ref('')\nconst backend = ref<DecisionBackend>('jev'), jeffBaseUrl = ref(JEFF_DEFAULT_BASE_URL), jeffModel = ref(JEFF_DEFAULT_MODEL)\nconst drafts = ref<Record<string, {tier: AutoTier; blurb: string}>>({})\nconst preserveTaskAbility = ref(true), maxReasoningEffort = ref<AutoEffort>('high'), fallbackReasoningEffort = ref('medium'), minConfidence = ref(BOT_AUTO_DEFAULT_MIN_CONFIDENCE)\nconst busy = ref(false), error = ref(''), notice = ref(''), baseline = ref(''), search = ref('')\nconst previewText = ref('你好'), preview = ref<AutoRouteDecision>(), previewBusy = ref(false), previewError = ref('')\nconst blocked = computed(() => props.disabled || busy.value || previewBusy.value || !view.value)\nconst keyOf = (provider: string, model: string) => JSON.stringify([provider, model])\nconst pairOf = (key: string) => { const [provider, model] = JSON.parse(key) as [string, string]; return { provider, model } }\nconst nameOf = (key: string) => pairOf(key).model\nconst optionOf = (key: string) => { const pair = pairOf(key); return modelOptions.value.find(m => m.provider === pair.provider && m.model === pair.model) }\nconst candidates = computed(() => selected.value.map(id => ({ ...pairOf(id), tier: drafts.value[id]?.tier ?? suggestedAutoTier(nameOf(id)), ...(drafts.value[id]?.blurb.trim() ? { blurb: drafts.value[id]!.blurb.trim() } : {}) })))\nconst pool = (): BotAutoPool => ({ candidates: candidates.value, ...(fallback.value ? { fallback: pairOf(fallback.value) } : {}), minConfidence: minConfidence.value, preserveTaskAbility: preserveTaskAbility.value, maxReasoningEffort: maxReasoningEffort.value, fallbackReasoningEffort: fallbackReasoningEffort.value })\nconst snapshot = () => JSON.stringify([enabled.value, backend.value, jeffBaseUrl.value.trim(), jeffModel.value.trim(), pool()])\nconst dirty = computed(() => !!view.value && (snapshot() !== baseline.value || !!apiKey.value.trim()))\nconst valid = computed(() => Number.isFinite(minConfidence.value) && minConfidence.value >= 0 && minConfidence.value <= 1 && (!enabled.value || selected.value.length >= 2))\nconst decisionReady = computed(() => backend.value === 'jeff' || !!apiKey.value.trim() || !!view.value?.hasApiKey)\nconst previewBlocked = computed(() => blocked.value || !enabled.value || !valid.value || !previewText.value.trim() || !decisionReady.value)\nwatch(dirty, value => emit('dirty-change', value))\nwatch(() => busy.value || previewBusy.value, value => emit('busy-change', value))\nwatch([snapshot, previewText, apiKey], () => { preview.value = undefined; previewError.value = '' })\nconst groups = computed(() => (props.models?.providers ?? []).filter(p => p.authenticated !== false && p.models.length))\nconst shownGroups = computed(() => groups.value.map(p => ({ ...p, models: p.models.filter(m => `${p.name} ${m}`.toLowerCase().includes(search.value.trim().toLowerCase())) })).filter(p => p.models.length))\nconst fallbackEfforts = computed(() => {\n const option = fallback.value ? optionOf(fallback.value) : undefined\n return option?.reasoningKnown ? autoEfforts.filter(e => option.reasoningEfforts.includes(e) && effortRank(e) <= effortRank(maxReasoningEffort.value)) : []\n})\nconst fallbackActual = computed(() => {\n const option = fallback.value ? optionOf(fallback.value) : undefined\n const value = option ? compatibleAutoEffort(option, fallbackReasoningEffort.value, maxReasoningEffort.value) : 'default'\n return value === null ? '当前模型无符合思考上限的档位' : value === 'default' ? '提供方默认' : botReasoningLabels[value] ?? value\n})\nconst thinkingLabel = computed(() => backend.value === 'jeff' ? '自动(Jeff)' : '自动(Jev)')\nfunction load(data: JevAutoView) {\n view.value = data\n if (data.modelOptions) modelOptions.value = data.modelOptions\n enabled.value = data.enabled\n backend.value = data.backend ?? 'jev'\n jeffBaseUrl.value = data.jeffBaseUrl || JEFF_DEFAULT_BASE_URL\n jeffModel.value = data.jeffModel || JEFF_DEFAULT_MODEL\n selected.value = data.candidates.map(c => keyOf(c.provider, c.model))\n drafts.value = Object.fromEntries(data.candidates.map(c => [keyOf(c.provider, c.model), {tier: candidateTier(c), blurb: c.blurb ?? ''}]))\n fallback.value = data.fallback ? keyOf(data.fallback.provider, data.fallback.model) : selected.value[0] ?? ''\n const policy = autoPolicy(data)\n preserveTaskAbility.value = policy.preserveTaskAbility; maxReasoningEffort.value = policy.maxReasoningEffort; fallbackReasoningEffort.value = policy.fallbackReasoningEffort\n minConfidence.value = data.minConfidence ?? BOT_AUTO_DEFAULT_MIN_CONFIDENCE\n apiKey.value = ''; baseline.value = snapshot()\n}\nfunction toggle(id: string) {\n if (!drafts.value[id]) drafts.value[id] = { tier: suggestedAutoTier(nameOf(id)), blurb: '' }\n selected.value = selected.value.includes(id) ? selected.value.filter(item => item !== id) : [...selected.value, id]\n if (!selected.value.includes(fallback.value)) fallback.value = selected.value[0] ?? ''\n}\nasync function save() {\n // The parent disables all panels while invoking their exposed save methods.\n if (!view.value || busy.value || previewBusy.value) return false\n if (!valid.value) { error.value = '请选择至少两个候选模型,并将置信度设为 0 到 1。'; return false }\n busy.value = true; error.value = ''; notice.value = ''\n try {\n load(await hermesApi.saveJev({\n revision: view.value.revision,\n enabled: enabled.value,\n backend: backend.value,\n jeffBaseUrl: jeffBaseUrl.value.trim() || JEFF_DEFAULT_BASE_URL,\n jeffModel: jeffModel.value.trim() || JEFF_DEFAULT_MODEL,\n ...pool(),\n ...(apiKey.value.trim() ? { apiKey: apiKey.value.trim() } : {}),\n }))\n notice.value = '自动选模已保存,新的 Bot 回合使用此配置。'\n return true\n } catch (cause) { error.value = cause instanceof Error ? cause.message : '保存失败'; return false }\n finally { busy.value = false }\n}\nasync function reset() {\n if (busy.value || previewBusy.value) return\n busy.value = true; error.value = ''; notice.value = ''\n try { load(await hermesApi.jev()) } catch (cause) { error.value = cause instanceof Error ? cause.message : '无法读取自动选模设置' }\n finally { busy.value = false }\n}\nasync function runPreview() {\n if (previewBlocked.value) return\n previewBusy.value = true; previewError.value = ''; preview.value = undefined\n try {\n preview.value = await hermesApi.previewJev({\n pool: pool(),\n enabled: enabled.value,\n userText: previewText.value.trim(),\n backend: backend.value,\n jeffBaseUrl: jeffBaseUrl.value.trim() || JEFF_DEFAULT_BASE_URL,\n jeffModel: jeffModel.value.trim() || JEFF_DEFAULT_MODEL,\n ...(apiKey.value.trim() ? { apiKey: apiKey.value.trim() } : {}),\n })\n }\n catch (cause) { previewError.value = cause instanceof Error ? cause.message : '预览失败' }\n finally { previewBusy.value = false }\n}\nonMounted(reset)\ndefineExpose({ reset, save })\n</script>\n<template>\n <section class=\"jev-auto\" aria-label=\"自动选模\" :aria-busy=\"busy || previewBusy\">\n <div class=\"jev-title\"><h4>自动选模</h4><label class=\"jev-toggle\"><input v-model=\"enabled\" type=\"checkbox\" :disabled=\"blocked\"> 启用自动选模</label></div>\n <p>由决策模型结合任务和上下文,选择能胜任的最轻模型与思考强度。关闭后 Bot 不可选择 Auto。</p>\n <p v-if=\"error\" class=\"error\" role=\"alert\">{{ error }}</p>\n <p v-if=\"notice\" role=\"status\">{{ notice }}</p>\n <label>决策服务<select v-model=\"backend\" aria-label=\"决策服务\" :disabled=\"blocked\"><option v-for=\"id in DECISION_BACKENDS\" :key=\"id\" :value=\"id\">{{ DECISION_BACKEND_LABELS[id] }}</option></select></label>\n <template v-if=\"backend === 'jeff'\">\n <div class=\"jev-fields\">\n <label>Jeff 地址<input v-model=\"jeffBaseUrl\" type=\"url\" placeholder=\"http://127.0.0.1:8765\" :disabled=\"blocked\"></label>\n <label>Jeff 模型<input v-model=\"jeffModel\" type=\"text\" placeholder=\"jeff-latest\" :disabled=\"blocked\"></label>\n </div>\n <p>本机 Jeff 默认无密钥。地址仅允许 127.0.0.1 / localhost。可用环境变量 <code>YAOVI_DECISION_BACKEND=jeff</code>、<code>JEFF_BASE_URL</code> 覆盖。</p>\n </template>\n <label v-else>TypeSafe API 密钥<input v-model=\"apiKey\" type=\"password\" autocomplete=\"new-password\" :placeholder=\"view?.hasApiKey ? '已保存,留空则不修改' : 'sk-…'\" :disabled=\"blocked\"></label>\n <div class=\"jev-section-title\"><h5>模型分工</h5><small>建议分工,可按实际表现调整</small></div>\n <div class=\"jev-roles\">\n <div v-for=\"id in selected\" :key=\"id\" class=\"jev-role\">\n <div class=\"jev-model-name\"><strong>{{ nameOf(id) }}</strong><small>{{ autoTierDescriptions[drafts[id]!.tier] }}</small><small v-if=\"modelOptions.length && !optionOf(id)\" class=\"error\">当前不可用</small></div>\n <label><span class=\"sr-only\">{{ nameOf(id) }} 的任务分工</span><select v-model=\"drafts[id]!.tier\" :aria-label=\"`${nameOf(id)} 的任务分工`\" :disabled=\"blocked\"><option v-for=\"tier in autoTiers\" :key=\"tier\" :value=\"tier\">{{ autoTierLabels[tier] }}任务</option></select></label>\n </div>\n <p v-if=\"!selected.length\">选择至少两个候选模型后配置分工。</p>\n </div>\n <details class=\"jev-picker\" :open=\"!selected.length\">\n <summary>选择候选模型 · 已选 {{ selected.length }} 个</summary>\n <label>筛选候选模型<input v-model=\"search\" type=\"search\" placeholder=\"搜索模型或供应商\" :disabled=\"blocked\"></label>\n <div class=\"jev-model-list\"><div v-for=\"group in shownGroups\" :key=\"group.slug\" class=\"jev-group\"><strong>{{ group.name }}</strong><label v-for=\"model in group.models\" :key=\"group.slug + model\"><input type=\"checkbox\" :checked=\"selected.includes(keyOf(group.slug, model))\" :disabled=\"blocked || selected.length >= 32 && !selected.includes(keyOf(group.slug, model))\" @change=\"toggle(keyOf(group.slug, model))\">{{ model }}</label></div><p v-if=\"!shownGroups.length\">没有匹配的已连接模型。</p><label v-for=\"id in selected.filter(key => !groups.some(g => g.slug === pairOf(key).provider && g.models.includes(nameOf(key))))\" :key=\"id\" class=\"jev-toggle\"><input type=\"checkbox\" checked :disabled=\"blocked\" @change=\"toggle(id)\">{{ nameOf(id) }}(目录外,可移除)</label></div>\n </details>\n <label class=\"jev-continuity\"><input v-model=\"preserveTaskAbility\" type=\"checkbox\" :disabled=\"blocked\"><span>保留未完成任务所需能力<small>继续复杂任务时保留能力与思考下限;新的简单任务允许降级。</small></span></label>\n <label>思考强度<input :value=\"thinkingLabel\" readonly aria-label=\"Auto 思考强度\"></label>\n <details class=\"jev-advanced\"><summary>高级设置与回退</summary>\n <div class=\"jev-fields\">\n <label>最高允许思考等级<select v-model=\"maxReasoningEffort\" :disabled=\"blocked\"><option v-for=\"effort in autoEfforts\" :key=\"effort\" :value=\"effort\">{{ botReasoningLabels[effort] }}</option></select></label>\n <label>最低置信度<input v-model.number=\"minConfidence\" type=\"number\" min=\"0\" max=\"1\" step=\"0.05\" :disabled=\"blocked\"></label>\n <label v-if=\"selected.length\">回退模型<select v-model=\"fallback\" :disabled=\"blocked\"><option v-for=\"id in selected\" :key=\"id\" :value=\"id\">{{ nameOf(id) }}</option></select></label>\n <label>回退思考强度<select v-model=\"fallbackReasoningEffort\" :disabled=\"blocked\"><option value=\"default\">模型默认</option><option v-if=\"fallbackReasoningEffort !== 'default' && !fallbackEfforts.includes(fallbackReasoningEffort as AutoEffort)\" :value=\"fallbackReasoningEffort\">{{ botReasoningLabels[fallbackReasoningEffort] }}(自动适配)</option><option v-for=\"effort in fallbackEfforts\" :key=\"effort\" :value=\"effort\">{{ botReasoningLabels[effort] }}</option></select><small>实际档位:{{ fallbackActual }}</small></label>\n </div>\n <p>回退不影响下一轮偏好。继续原任务时仍保留必要能力;思考档位未知时使用提供方默认。</p>\n <label v-for=\"id in selected\" :key=\"id\" class=\"jev-hint\">{{ nameOf(id) }} · 补充能力说明<input v-model=\"drafts[id]!.blurb\" maxlength=\"280\" placeholder=\"可选,例如擅长代码排查或长文分析\" :disabled=\"blocked\"></label>\n </details>\n <details class=\"jev-preview\"><summary>选模预览</summary>\n <p>使用当前草稿调用 {{ backend === 'jeff' ? 'Jeff' : 'Jev' }},仅判断这个新任务,不执行任务,也不保存设置。</p>\n <label>任务内容<textarea v-model=\"previewText\" maxlength=\"2000\" rows=\"2\" :disabled=\"blocked\" /></label>\n <button type=\"button\" :disabled=\"previewBlocked\" @click=\"runPreview\">{{ previewBusy ? (backend === 'jeff' ? 'Jeff 正在判断…' : 'Jev 正在判断…') : '预览模型与思考强度' }}</button>\n <p v-if=\"previewError\" class=\"error\" role=\"alert\">{{ previewError }}</p>\n <div aria-live=\"polite\"><AutoRouteNotice v-if=\"preview\" :route=\"preview\"/></div>\n </details>\n <button type=\"button\" :disabled=\"blocked || !dirty || !valid\" @click=\"save\">{{ busy ? '正在处理…' : '保存自动选模' }}</button>\n <button v-if=\"error\" type=\"button\" :disabled=\"busy || previewBusy\" @click=\"reset\">重新读取设置</button>\n </section>\n</template>\n<style scoped>\n.jev-auto{display:grid;gap:14px;margin-top:16px;padding-top:16px;border-top:1px solid var(--line);min-width:0}h4,h5,p{margin:0}h5{font-size:13px;font-weight:550}p,small{color:var(--text-secondary);font-size:12px;line-height:1.6}.jev-title,.jev-section-title{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap}.jev-model-list{display:grid;gap:16px;max-height:280px;overflow:auto;padding:4px}.jev-group{display:grid;gap:6px}.jev-group strong{font-size:12px;color:var(--text-secondary)}label{display:grid;gap:6px;font-size:13px;min-width:0}.jev-toggle,.jev-group label{display:flex;align-items:center;gap:8px;min-height:44px;overflow-wrap:anywhere}.jev-role{display:grid;grid-template-columns:minmax(0,1fr) 132px;gap:12px;align-items:center;padding:12px 0;border-bottom:1px solid var(--line)}.jev-role:last-child{border:0}.jev-model-name{display:grid;gap:4px;min-width:0;overflow-wrap:anywhere}.jev-model-name strong{font-size:13px;font-weight:550}.jev-continuity{display:flex;align-items:flex-start;gap:8px;min-height:44px}.jev-continuity input{margin-top:4px}.jev-continuity small{display:block;margin-top:3px}.jev-fields{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px}.jev-auto input:not([type=checkbox]),select,textarea{box-sizing:border-box;width:100%;min-width:0;min-height:44px;padding:8px 10px;border:1px solid var(--line);border-radius:8px;background:var(--surface);color:var(--text-primary);font:13px var(--font-ui)}textarea{resize:vertical}input[readonly]{color:var(--text-secondary)!important;background:var(--surface-soft)!important}.jev-auto details>label,.jev-auto details>p,.jev-auto details>.jev-fields,.jev-preview>button{margin-top:10px}.jev-auto summary{min-height:32px;cursor:pointer;color:var(--text-secondary);font-size:13px}.jev-picker>label{margin-bottom:10px}.jev-auto button{justify-self:start;min-height:44px;padding:8px 12px;border:1px solid var(--line);border-radius:8px;background:var(--surface);color:var(--text-primary);cursor:pointer;font:13px var(--font-ui)}.error{color:var(--danger)}.jev-auto :focus-visible{outline:2px solid var(--accent);outline-offset:2px}.jev-auto :disabled{opacity:.55;cursor:default}.sr-only{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}code{font-size:11px}@media(max-width:420px){.jev-fields{grid-template-columns:1fr}.jev-role{grid-template-columns:minmax(0,1fr) 108px;gap:8px}}@media(pointer:coarse){.jev-auto summary{min-height:44px;align-content:center}.jev-auto input:not([type=checkbox]),select,textarea{font-size:16px}}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, onMounted, ref, watch } from 'vue'\nimport { modelNetworkApi } from '@/api/modelNetwork'\nimport { JEV_NETWORK_PROVIDER } from '@shared/botModelSettings'\nimport type { ModelNetworkView, NetworkPolicy } from '@shared/modelNetwork'\nimport ModelNetworkChoice from './ModelNetworkChoice.vue'\ndefineProps<{ disabled?: boolean }>()\nconst emit = defineEmits<{ 'dirty-change': [value: boolean]; 'busy-change': [value: boolean]; 'manage-network': [] }>()\nconst view = ref<ModelNetworkView>(), policy = ref<NetworkPolicy>({ mode: 'inherit' })\nconst busy = ref(false), testing = ref(false), error = ref(''), notice = ref('')\nconst dirty = computed(() => !!view.value && JSON.stringify(policy.value) !== JSON.stringify(view.value.connections[JEV_NETWORK_PROVIDER] ?? { mode: 'inherit' }))\nwatch(dirty, value => emit('dirty-change', value)); watch(() => busy.value || testing.value, value => emit('busy-change', value))\nasync function reset() {\n error.value = ''; notice.value = ''\n try { view.value = await modelNetworkApi.get(); policy.value = { ...view.value.connections[JEV_NETWORK_PROVIDER] ?? { mode: 'inherit' } } }\n catch (cause) { error.value = cause instanceof Error ? cause.message : '无法读取 Jev 网络设置' }\n}\nasync function save() {\n if (!view.value || busy.value || testing.value) return false\n busy.value = true; error.value = ''; notice.value = ''\n try { view.value = await modelNetworkApi.save(view.value.revision, policy.value, JEV_NETWORK_PROVIDER); notice.value = 'Jev 独立网络已保存,从下一次选模请求生效。'; return true }\n catch (cause) { error.value = cause instanceof Error ? cause.message : '保存失败,草稿已保留。'; return false }\n finally { busy.value = false }\n}\nonMounted(reset); defineExpose({ reset, save })\n</script>\n<template>\n <section class=\"jev-network\" aria-label=\"Jev 独立网络\">\n <h4>Jev 独立网络</h4><p>仅用于云端 TypeSafe Jev 选模请求。选择本机 Jeff 时走回环,不经此代理。各模型供应商使用各自的连接网络。</p>\n <p v-if=\"error\" class=\"error\" role=\"alert\">{{ error }}</p><p v-if=\"notice\" role=\"status\">{{ notice }}</p>\n <ModelNetworkChoice v-if=\"view\" v-model=\"policy\" :view=\"view\" :provider=\"JEV_NETWORK_PROVIDER\" :disabled=\"disabled || busy\" compact @busy=\"testing = $event\" />\n <div class=\"actions\"><button type=\"button\" :disabled=\"disabled || busy || testing || !dirty || policy.mode === 'proxy' && !policy.proxyId\" @click=\"save\">{{ busy ? '正在保存…' : '保存 Jev 网络' }}</button><button type=\"button\" :disabled=\"disabled || busy || testing\" @click=\"emit('manage-network')\">管理代理</button><button v-if=\"error\" type=\"button\" :disabled=\"disabled || busy || testing\" @click=\"reset\">重新读取</button></div>\n </section>\n</template>\n<style scoped>\n.jev-network{display:grid;gap:12px;min-width:0;margin-top:20px;padding-top:20px;border-top:1px solid var(--line)}h4,p{margin:0}p{color:var(--text-secondary);font-size:13px;line-height:1.6}.actions{display:flex;flex-wrap:wrap;gap:12px}button{min-height:44px;padding:8px 12px;border:1px solid var(--line);border-radius:8px;background:var(--surface);color:var(--text-primary);font:13px var(--font-ui);cursor:pointer}.error{color:var(--danger)}:disabled{opacity:.55;cursor:default}:focus-visible{outline:2px solid var(--accent);outline-offset:2px}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, onMounted, ref, watch } from 'vue'\nimport { modelNetworkApi } from '@/api/modelNetwork'\nimport { JEV_NETWORK_PROVIDER } from '@shared/botModelSettings'\nimport type { ModelNetworkView, NetworkPolicy } from '@shared/modelNetwork'\nimport ModelNetworkChoice from './ModelNetworkChoice.vue'\ndefineProps<{ disabled?: boolean }>()\nconst emit = defineEmits<{ 'dirty-change': [value: boolean]; 'busy-change': [value: boolean]; 'manage-network': [] }>()\nconst view = ref<ModelNetworkView>(), policy = ref<NetworkPolicy>({ mode: 'inherit' })\nconst busy = ref(false), testing = ref(false), error = ref(''), notice = ref('')\nconst dirty = computed(() => !!view.value && JSON.stringify(policy.value) !== JSON.stringify(view.value.connections[JEV_NETWORK_PROVIDER] ?? { mode: 'inherit' }))\nwatch(dirty, value => emit('dirty-change', value)); watch(() => busy.value || testing.value, value => emit('busy-change', value))\nasync function reset() {\n error.value = ''; notice.value = ''\n try { view.value = await modelNetworkApi.get(); policy.value = { ...view.value.connections[JEV_NETWORK_PROVIDER] ?? { mode: 'inherit' } } }\n catch (cause) { error.value = cause instanceof Error ? cause.message : '无法读取 Jev 网络设置' }\n}\nasync function save() {\n if (!view.value || busy.value || testing.value) return false\n busy.value = true; error.value = ''; notice.value = ''\n try { view.value = await modelNetworkApi.save(view.value.revision, policy.value, JEV_NETWORK_PROVIDER); notice.value = 'Jev 独立网络已保存,从下一次选模请求生效。'; return true }\n catch (cause) { error.value = cause instanceof Error ? cause.message : '保存失败,草稿已保留。'; return false }\n finally { busy.value = false }\n}\nonMounted(reset); defineExpose({ reset, save })\n</script>\n<template>\n <section class=\"jev-network\" aria-label=\"Jev 独立网络\">\n <h4>Jev 独立网络</h4><p>仅用于云端 TypeSafe Jev 选模请求。选择本机 Jeff 时走回环,不经此代理。各模型供应商使用各自的连接网络。</p>\n <p v-if=\"error\" class=\"error\" role=\"alert\">{{ error }}</p><p v-if=\"notice\" role=\"status\">{{ notice }}</p>\n <ModelNetworkChoice v-if=\"view\" v-model=\"policy\" :view=\"view\" :provider=\"JEV_NETWORK_PROVIDER\" :disabled=\"disabled || busy\" compact @busy=\"testing = $event\" />\n <div class=\"actions\"><button type=\"button\" :disabled=\"disabled || busy || testing || !dirty || policy.mode === 'proxy' && !policy.proxyId\" @click=\"save\">{{ busy ? '正在保存…' : '保存 Jev 网络' }}</button><button type=\"button\" :disabled=\"disabled || busy || testing\" @click=\"emit('manage-network')\">管理代理</button><button v-if=\"error\" type=\"button\" :disabled=\"disabled || busy || testing\" @click=\"reset\">重新读取</button></div>\n </section>\n</template>\n<style scoped>\n.jev-network{display:grid;gap:12px;min-width:0;margin-top:20px;padding-top:20px;border-top:1px solid var(--line)}h4,p{margin:0}p{color:var(--text-secondary);font-size:13px;line-height:1.6}.actions{display:flex;flex-wrap:wrap;gap:12px}button{min-height:44px;padding:8px 12px;border:1px solid var(--line);border-radius:8px;background:var(--surface);color:var(--text-primary);font:13px var(--font-ui);cursor:pointer}.error{color:var(--danger)}:disabled{opacity:.55;cursor:default}:focus-visible{outline:2px solid var(--accent);outline-offset:2px}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, onMounted, ref, watch } from 'vue'\nimport { hermesApi, type HermesModelOptions } from '@/api/hermes'\nimport type { BotModelVisibilityView } from '@shared/botModelSettings'\nconst props = defineProps<{ models?: HermesModelOptions; disabled?: boolean }>()\nconst emit = defineEmits<{ 'dirty-change': [value: boolean]; 'busy-change': [value: boolean] }>()\nconst view = ref<BotModelVisibilityView>(), curated = ref(false), selected = ref<string[]>([]), search = ref(''), provider = ref('')\nconst busy = ref(false), error = ref(''), notice = ref(''), baseline = ref('')\nconst key = (provider: string, model: string) => JSON.stringify([provider, model])\nconst groups = computed(() => (props.models?.providers ?? []).filter(p => p.authenticated !== false && p.models.length))\nconst filtered = computed(() => groups.value.filter(p => !provider.value || p.slug === provider.value).map(p => ({ ...p, models: p.models.filter(m => `${p.name} ${m}`.toLowerCase().includes(search.value.trim().toLowerCase())) })).filter(p => p.models.length))\nconst draft = () => JSON.stringify(curated.value ? [...selected.value].sort() : null)\nconst dirty = computed(() => !!view.value && draft() !== baseline.value)\nwatch(dirty, v => emit('dirty-change', v)); watch(busy, v => emit('busy-change', v))\nfunction load(data: BotModelVisibilityView) { view.value = data; curated.value = data.models !== null; selected.value = data.models?.map(m => key(m.provider, m.model)) ?? []; baseline.value = draft() }\nfunction toggle(id: string) { selected.value = selected.value.includes(id) ? selected.value.filter(item => item !== id) : [...selected.value, id] }\nfunction selectResults(add: boolean) { const keys = filtered.value.flatMap(p => p.models.map(m => key(p.slug, m))); selected.value = add ? [...new Set([...selected.value, ...keys])] : selected.value.filter(id => !keys.includes(id)) }\nasync function reset() { error.value = ''; notice.value = ''; try { load(await hermesApi.botModels()) } catch (cause) { error.value = cause instanceof Error ? cause.message : '无法读取 Bot 可选模型' } }\nasync function save() {\n if (!view.value || busy.value) return false\n busy.value = true; error.value = ''; notice.value = ''\n try { load(await hermesApi.saveBotModels({ revision: view.value.revision, models: curated.value ? selected.value.map(id => { const [provider, model] = JSON.parse(id) as [string, string]; return { provider, model } }) : null })); notice.value = 'Bot 可选模型已保存,重新打开模型选择即可读取。'; return true }\n catch (cause) { error.value = cause instanceof Error ? cause.message : '保存失败,草稿已保留。'; return false } finally { busy.value = false }\n}\nonMounted(reset); defineExpose({ reset, save })\n</script>\n<template>\n <section class=\"bot-model-visibility\" aria-label=\"Bot 可选模型\">\n <h4>Bot 可选模型</h4><p>统一精简 Bot 的手动对话模型列表。已有选择会保留;Auto 使用上方自动选模的候选池。</p>\n <p v-if=\"error\" class=\"error\" role=\"alert\">{{ error }}</p><p v-if=\"notice\" role=\"status\">{{ notice }}</p>\n <label class=\"toggle\"><input v-model=\"curated\" type=\"checkbox\" :disabled=\"disabled || busy || !view\"> 只显示勾选的模型</label>\n <template v-if=\"curated\">\n <div class=\"filters\"><label>搜索模型<input v-model=\"search\" type=\"search\" placeholder=\"搜索模型或供应商\" :disabled=\"disabled || busy\"></label><label>供应商<select v-model=\"provider\" :disabled=\"disabled || busy\"><option value=\"\">全部已连接供应商</option><option v-for=\"group in groups\" :key=\"group.slug\" :value=\"group.slug\">{{ group.name }}</option></select></label></div>\n <div class=\"actions\"><button type=\"button\" :disabled=\"disabled || busy\" @click=\"selectResults(true)\">全选搜索结果</button><button type=\"button\" :disabled=\"disabled || busy\" @click=\"selectResults(false)\">取消搜索结果</button><small role=\"status\">已勾选 {{ selected.length }} 个模型</small></div>\n <div class=\"model-list\"><div v-for=\"group in filtered\" :key=\"group.slug\" class=\"model-group\"><strong>{{ group.name }}</strong><label v-for=\"model in group.models\" :key=\"model\" class=\"toggle\"><input type=\"checkbox\" :checked=\"selected.includes(key(group.slug, model))\" :disabled=\"disabled || busy\" @change=\"toggle(key(group.slug, model))\">{{ model }}</label></div><p v-if=\"!filtered.length\">没有匹配的模型,请调整搜索或供应商筛选。</p></div>\n <small v-if=\"!selected.length\">未勾选时只显示跟随系统默认、Auto 和此 Bot 已有选择。</small>\n </template>\n <p v-else>当前显示所有已连接模型。</p>\n <div class=\"actions\"><button type=\"button\" :disabled=\"disabled || busy || !dirty || !models\" @click=\"save\">{{ busy ? '正在保存…' : '保存 Bot 可选模型' }}</button><button v-if=\"error\" type=\"button\" :disabled=\"disabled || busy\" @click=\"reset\">重新读取</button></div>\n </section>\n</template>\n<style scoped>\n.bot-model-visibility{display:grid;gap:12px;min-width:0;border-top:1px solid var(--line);margin-top:20px;padding-top:20px}h4,p{margin:0}p,small{font-size:13px;line-height:1.6;color:var(--text-secondary)}label{display:grid;gap:6px;min-width:0;font-size:13px}.toggle{display:flex;align-items:center;gap:8px;min-height:44px;overflow-wrap:anywhere}.filters{display:grid;grid-template-columns:1fr 1fr;gap:12px}input[type=search],select{box-sizing:border-box;width:100%;min-width:0;min-height:44px;padding:8px 10px;border:1px solid var(--line);border-radius:8px;background:var(--surface);color:var(--text-primary);font:13px var(--font-ui)}.actions{display:flex;flex-wrap:wrap;align-items:center;gap:12px}button{min-height:44px;padding:8px 12px;border:1px solid var(--line);border-radius:8px;background:var(--surface);color:var(--text-primary);cursor:pointer;font:13px var(--font-ui)}.model-list{display:grid;gap:16px;max-height:280px;overflow:auto;padding:4px}.model-group{display:grid;gap:4px}.model-group strong{color:var(--text-secondary);font-size:12px}.error{color:var(--danger)}:disabled{opacity:.55;cursor:default}:focus-visible{outline:2px solid var(--accent);outline-offset:2px}@media(max-width:600px){.filters{grid-template-columns:1fr}}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, onMounted, ref, watch } from 'vue'\nimport { hermesApi, type HermesModelOptions } from '@/api/hermes'\nimport type { BotModelVisibilityView } from '@shared/botModelSettings'\nconst props = defineProps<{ models?: HermesModelOptions; disabled?: boolean }>()\nconst emit = defineEmits<{ 'dirty-change': [value: boolean]; 'busy-change': [value: boolean] }>()\nconst view = ref<BotModelVisibilityView>(), curated = ref(false), selected = ref<string[]>([]), search = ref(''), provider = ref('')\nconst busy = ref(false), error = ref(''), notice = ref(''), baseline = ref('')\nconst key = (provider: string, model: string) => JSON.stringify([provider, model])\nconst groups = computed(() => (props.models?.providers ?? []).filter(p => p.authenticated !== false && p.models.length))\nconst filtered = computed(() => groups.value.filter(p => !provider.value || p.slug === provider.value).map(p => ({ ...p, models: p.models.filter(m => `${p.name} ${m}`.toLowerCase().includes(search.value.trim().toLowerCase())) })).filter(p => p.models.length))\nconst draft = () => JSON.stringify(curated.value ? [...selected.value].sort() : null)\nconst dirty = computed(() => !!view.value && draft() !== baseline.value)\nwatch(dirty, v => emit('dirty-change', v)); watch(busy, v => emit('busy-change', v))\nfunction load(data: BotModelVisibilityView) { view.value = data; curated.value = data.models !== null; selected.value = data.models?.map(m => key(m.provider, m.model)) ?? []; baseline.value = draft() }\nfunction toggle(id: string) { selected.value = selected.value.includes(id) ? selected.value.filter(item => item !== id) : [...selected.value, id] }\nfunction selectResults(add: boolean) { const keys = filtered.value.flatMap(p => p.models.map(m => key(p.slug, m))); selected.value = add ? [...new Set([...selected.value, ...keys])] : selected.value.filter(id => !keys.includes(id)) }\nasync function reset() { error.value = ''; notice.value = ''; try { load(await hermesApi.botModels()) } catch (cause) { error.value = cause instanceof Error ? cause.message : '无法读取 Bot 可选模型' } }\nasync function save() {\n if (!view.value || busy.value) return false\n busy.value = true; error.value = ''; notice.value = ''\n try { load(await hermesApi.saveBotModels({ revision: view.value.revision, models: curated.value ? selected.value.map(id => { const [provider, model] = JSON.parse(id) as [string, string]; return { provider, model } }) : null })); notice.value = 'Bot 可选模型已保存,重新打开模型选择即可读取。'; return true }\n catch (cause) { error.value = cause instanceof Error ? cause.message : '保存失败,草稿已保留。'; return false } finally { busy.value = false }\n}\nonMounted(reset); defineExpose({ reset, save })\n</script>\n<template>\n <section class=\"bot-model-visibility\" aria-label=\"Bot 可选模型\">\n <h4>Bot 可选模型</h4><p>统一精简 Bot 的手动对话模型列表。已有选择会保留;Auto 使用上方自动选模的候选池。</p>\n <p v-if=\"error\" class=\"error\" role=\"alert\">{{ error }}</p><p v-if=\"notice\" role=\"status\">{{ notice }}</p>\n <label class=\"toggle\"><input v-model=\"curated\" type=\"checkbox\" :disabled=\"disabled || busy || !view\"> 只显示勾选的模型</label>\n <template v-if=\"curated\">\n <div class=\"filters\"><label>搜索模型<input v-model=\"search\" type=\"search\" placeholder=\"搜索模型或供应商\" :disabled=\"disabled || busy\"></label><label>供应商<select v-model=\"provider\" :disabled=\"disabled || busy\"><option value=\"\">全部已连接供应商</option><option v-for=\"group in groups\" :key=\"group.slug\" :value=\"group.slug\">{{ group.name }}</option></select></label></div>\n <div class=\"actions\"><button type=\"button\" :disabled=\"disabled || busy\" @click=\"selectResults(true)\">全选搜索结果</button><button type=\"button\" :disabled=\"disabled || busy\" @click=\"selectResults(false)\">取消搜索结果</button><small role=\"status\">已勾选 {{ selected.length }} 个模型</small></div>\n <div class=\"model-list\"><div v-for=\"group in filtered\" :key=\"group.slug\" class=\"model-group\"><strong>{{ group.name }}</strong><label v-for=\"model in group.models\" :key=\"model\" class=\"toggle\"><input type=\"checkbox\" :checked=\"selected.includes(key(group.slug, model))\" :disabled=\"disabled || busy\" @change=\"toggle(key(group.slug, model))\">{{ model }}</label></div><p v-if=\"!filtered.length\">没有匹配的模型,请调整搜索或供应商筛选。</p></div>\n <small v-if=\"!selected.length\">未勾选时只显示跟随系统默认、Auto 和此 Bot 已有选择。</small>\n </template>\n <p v-else>当前显示所有已连接模型。</p>\n <div class=\"actions\"><button type=\"button\" :disabled=\"disabled || busy || !dirty || !models\" @click=\"save\">{{ busy ? '正在保存…' : '保存 Bot 可选模型' }}</button><button v-if=\"error\" type=\"button\" :disabled=\"disabled || busy\" @click=\"reset\">重新读取</button></div>\n </section>\n</template>\n<style scoped>\n.bot-model-visibility{display:grid;gap:12px;min-width:0;border-top:1px solid var(--line);margin-top:20px;padding-top:20px}h4,p{margin:0}p,small{font-size:13px;line-height:1.6;color:var(--text-secondary)}label{display:grid;gap:6px;min-width:0;font-size:13px}.toggle{display:flex;align-items:center;gap:8px;min-height:44px;overflow-wrap:anywhere}.filters{display:grid;grid-template-columns:1fr 1fr;gap:12px}input[type=search],select{box-sizing:border-box;width:100%;min-width:0;min-height:44px;padding:8px 10px;border:1px solid var(--line);border-radius:8px;background:var(--surface);color:var(--text-primary);font:13px var(--font-ui)}.actions{display:flex;flex-wrap:wrap;align-items:center;gap:12px}button{min-height:44px;padding:8px 12px;border:1px solid var(--line);border-radius:8px;background:var(--surface);color:var(--text-primary);cursor:pointer;font:13px var(--font-ui)}.model-list{display:grid;gap:16px;max-height:280px;overflow:auto;padding:4px}.model-group{display:grid;gap:4px}.model-group strong{color:var(--text-secondary);font-size:12px}.error{color:var(--danger)}:disabled{opacity:.55;cursor:default}:focus-visible{outline:2px solid var(--accent);outline-offset:2px}@media(max-width:600px){.filters{grid-template-columns:1fr}}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, nextTick, onMounted, ref, watch } from 'vue'\nimport AppIcon from '@/components/common/AppIcon.vue'\nimport ConnectionNetworkPanel from './ConnectionNetworkPanel.vue'\nimport { modelNetworkApi, networkLabel } from '@/api/modelNetwork'\nimport type { ModelNetworkView } from '@shared/modelNetwork'\nimport ProviderLoginDialog from './ProviderLoginDialog.vue'\nimport JevAutoPanel from './JevAutoPanel.vue'\nimport JevNetworkPanel from './JevNetworkPanel.vue'\nimport BotModelVisibilityPanel from './BotModelVisibilityPanel.vue'\nimport { hermesApi, hermesMediaApi, type HermesEnvVar, type HermesModelOptions, type HermesOAuthProvider, type HermesPoolEntry, type HermesProvider } from '@/api/hermes'\n\n/**\n * Hermes provider management (same operations as the Hermes dashboard).\n * Without `bot` it edits the system layer; with `bot` it edits that Bot's own Hermes home,\n * whose logins and keys override the system layer.\n */\nconst networkView=ref<ModelNetworkView>(), networkConnection=ref<{id:string;name:string}>(), networkDirty=ref(false)\nconst networkEditor=ref<InstanceType<typeof ConnectionNetworkPanel>>()\nasync function refreshNetwork(){try{networkView.value=await modelNetworkApi.get(props.bot)}catch{networkView.value=undefined}}\nfunction networkText(id:string){return networkView.value?(props.bot?'独立凭据网络:':'网络:')+networkLabel(networkView.value,networkView.value.connections[id]??{mode:'inherit'}):'设置连接网络'}\nfunction openNetwork(id:string,name:string){networkConnection.value={id,name}}\nfunction closeNetwork(){networkDirty.value=false;networkConnection.value=undefined;void refreshNetwork()}\nonMounted(refreshNetwork)\nconst props = withDefaults(defineProps<{ bot?: string; section?: 'all' | 'connections' | 'defaults' | 'auto' | 'visibility'; embedded?: boolean; formId?: string }>(), { section: 'all', embedded: false })\nconst emit = defineEmits<{ changed: []; 'dirty-change': [value: boolean]; 'can-save-change': [value: boolean]; 'busy-change': [value: boolean]; 'manage-network': [] }>()\nconst jevEditor = ref<InstanceType<typeof JevAutoPanel>>(), jevNetworkEditor = ref<InstanceType<typeof JevNetworkPanel>>(), botModelsEditor = ref<InstanceType<typeof BotModelVisibilityPanel>>()\nconst jevDirty = ref(false), jevNetworkDirty = ref(false), botModelsDirty = ref(false)\nconst jevBusy = ref(false), jevNetworkBusy = ref(false), botModelsBusy = ref(false)\nconst panelsDirty = computed(() => jevDirty.value || jevNetworkDirty.value || botModelsDirty.value)\nconst panelsBusy = computed(() => jevBusy.value || jevNetworkBusy.value || botModelsBusy.value)\nconst providers = ref<HermesProvider[]>([]), oauth = ref<HermesOAuthProvider[]>([]), env = ref<Record<string, HermesEnvVar>>({})\nconst models = ref<HermesModelOptions>(), mainProvider = ref(''), mainModel = ref('')\nconst fallbackText = ref(''), filter = ref(''), busy = ref(false), error = ref(''), notice = ref('')\nconst loginProvider = ref<HermesOAuthProvider>()\nlet loginTrigger: HTMLElement | undefined\nconst keyDraft = ref<Record<string, string>>({}), poolOpen = ref(''), pool = ref<HermesPoolEntry[]>([]), poolKey = ref(''), poolLabel = ref(''), strategy = ref('fill_first')\nconst endpoint = ref({ name: '', base_url: '', model: '', api_key: '', api_mode: '' })\nconst mediaKeys = ref<Array<{ key: string; prompt: string; isSet: boolean; uses: string[] }>>([])\nconst mediaDraft = ref<Record<string, string>>({})\nconst mutating = ref(false)\nconst loaded = ref(false), showAll = ref(props.section === 'all'), catalogError = ref('')\nconst savedMain = ref({ provider: '', model: '' }), savedFallback = ref('')\nconst defaultsForm = ref<HTMLFormElement>()\n\nconst shown = computed(() => {\n const f = filter.value.trim().toLowerCase()\n return providers.value.filter(p => (showAll.value || !!f || configured(p)) && (!f || p.id.includes(f) || p.label.toLowerCase().includes(f) || p.aliases.some(a => a.includes(f))))\n})\nconst oauthFor = (id: string) => oauth.value.find(p => p.id === id)\n// Sign-ins that have no provider row of their own (e.g. claude-code, copilot-acp).\nconst loneOauth = computed(() => oauth.value.filter(o => !providers.value.some(p => p.id === o.id)))\nconst keyVar = (p: HermesProvider) => p.envVars[0]\nconst configured = (p: HermesProvider) => !!oauthFor(p.id)?.status.logged_in || p.envVars.some(v => env.value[v]?.is_set)\nconst providerModels = computed(() => models.value?.providers.find(p => p.slug === mainProvider.value)?.models ?? [])\nconst authorizedProviders = computed(() => models.value?.providers.filter(p => p.authenticated === true) ?? [])\nconst mainAuthorized = computed(() => authorizedProviders.value.some(p => p.slug === mainProvider.value))\nconst customConnections = computed(() => models.value?.providers.filter(p => (p.authenticated === true || p.is_current) && !providers.value.some(provider => provider.id === p.slug)) ?? [])\nconst mainDirty = computed(() => loaded.value && (mainProvider.value !== savedMain.value.provider || mainModel.value !== savedMain.value.model))\nconst fallbackDirty = computed(() => loaded.value && fallbackText.value !== savedFallback.value)\nconst connectionDirty = computed(() => Object.values(keyDraft.value).some(Boolean) || Object.values(endpoint.value).some(Boolean) || !!poolKey.value || !!poolLabel.value || Object.values(mediaDraft.value).some(value => value.trim()))\nconst dirty = computed(() => networkDirty.value || panelsDirty.value || (props.section === 'defaults' ? mainDirty.value || fallbackDirty.value : props.section === 'connections' ? connectionDirty.value : mainDirty.value || fallbackDirty.value || connectionDirty.value))\nwatch(dirty, value => { if (value) notice.value = ''; emit('dirty-change', value) })\nwatch(() => loaded.value && !busy.value && !panelsBusy.value && (!mainDirty.value || (mainAuthorized.value && !!mainModel.value.trim())) && (mainDirty.value || fallbackDirty.value || panelsDirty.value), value => emit('can-save-change', value), { immediate: true })\nwatch(() => mutating.value || panelsBusy.value, value => emit('busy-change', value), { immediate: true })\nasync function refreshModels() {\n await guard(async () => { models.value = await hermesApi.models(true); catalogError.value = '' }, '模型列表已刷新', false)\n}\n\n\nasync function guard(fn: () => Promise<unknown>, ok?: string, blocksNavigation = true) {\n if (busy.value || panelsBusy.value) return\n busy.value = true; mutating.value = blocksNavigation; error.value = ''; notice.value = ''\n try { const result = await fn(); if (ok && result !== false) notice.value = ok } catch (e) { error.value = e instanceof Error ? e.message : '操作失败' } finally { busy.value = false; mutating.value = false }\n}\nasync function load() {\n await guard(async () => {\n const [p, o, e, c] = await Promise.all([props.section === 'defaults' ? Promise.resolve({ providers: [] as HermesProvider[] }) : hermesApi.providers(props.bot), props.section === 'defaults' ? Promise.resolve({ providers: [] as HermesOAuthProvider[] }) : hermesApi.oauth(props.bot), props.section === 'defaults' ? Promise.resolve({} as Record<string, HermesEnvVar>) : hermesApi.env(props.bot), hermesApi.config(props.bot)])\n providers.value = p.providers; oauth.value = o.providers; env.value = e\n mainProvider.value = c.config.model?.provider ?? ''; mainModel.value = c.config.model?.default ?? ''\n const fb = c.config.fallback_model\n fallbackText.value = (Array.isArray(fb) ? fb : fb ? [fb] : []).map(f => `${f.provider} ${f.model}`).join('\\n')\n savedMain.value = { provider: mainProvider.value, model: mainModel.value }; savedFallback.value = fallbackText.value; loaded.value = true\n if (!props.bot) models.value = await hermesApi.models(false).catch(() => { catalogError.value = '暂时无法读取模型列表,可重试刷新。'; return undefined })\n await loadMediaKeys()\n }, undefined, false)\n}\nasync function loadMediaKeys() {\n if (props.bot || (props.section !== 'all' && props.section !== 'connections')) { mediaKeys.value = []; return }\n try {\n const [image, video] = await Promise.all([hermesMediaApi.config('image_gen'), hermesMediaApi.config('video_gen')])\n const known = new Set(providers.value.flatMap(p => p.envVars))\n const rows = new Map<string, { key: string; prompt: string; isSet: boolean; uses: string[] }>()\n for (const [label, value] of [['图片', image], ['视频', video]] as const) {\n for (const provider of value?.providers ?? []) for (const field of provider.env_vars ?? []) {\n if (!field.key || known.has(field.key)) continue\n const row = rows.get(field.key) ?? { key: field.key, prompt: field.prompt || field.key, isSet: false, uses: [] }\n row.isSet = row.isSet || !!field.is_set || !!env.value[field.key]?.is_set\n const use = `${label} · ${provider.name}`\n if (!row.uses.includes(use)) row.uses.push(use)\n rows.set(field.key, row)\n }\n }\n mediaKeys.value = [...rows.values()]\n } catch { mediaKeys.value = [] }\n}\ndefineExpose({ reset: () => networkConnection.value ? networkEditor.value?.reset() : Promise.all([load(), jevEditor.value?.reset(), jevNetworkEditor.value?.reset(), botModelsEditor.value?.reset()]) })\nonMounted(load)\n\nasync function saveMediaKey(key: string) {\n const value = mediaDraft.value[key]?.trim()\n if (!value) return\n await guard(async () => {\n await hermesApi.setEnv(key, value, props.bot)\n mediaDraft.value[key] = ''\n env.value = await hermesApi.env(props.bot)\n await loadMediaKeys()\n emit('changed')\n }, '媒体密钥已保存')\n}\nasync function saveKey(p: HermesProvider) {\n const key = keyVar(p), value = keyDraft.value[p.id]?.trim()\n if (!key || !value) return\n await guard(async () => { await hermesApi.setEnv(key, value, props.bot); keyDraft.value[p.id] = ''; env.value = await hermesApi.env(props.bot); emit('changed') }, `${p.label} 密钥已保存`)\n}\nasync function removeKey(key: string) {\n await guard(async () => { await hermesApi.deleteEnv(key, props.bot); env.value = await hermesApi.env(props.bot); await loadMediaKeys(); emit('changed') }, '密钥已移除')\n}\nfunction login(id: string) {\n if (busy.value || loginProvider.value) return\n loginTrigger = document.activeElement instanceof HTMLElement ? document.activeElement : undefined\n loginProvider.value = oauthFor(id)\n}\nfunction closeLogin() {\n loginProvider.value = undefined\n void nextTick(() => { if (loginTrigger?.isConnected) loginTrigger.focus({ preventScroll: true }) })\n}\nasync function loginSucceeded() {\n notice.value = '登录成功'\n emit('changed')\n try {\n const [o, e] = await Promise.all([hermesApi.oauth(props.bot), hermesApi.env(props.bot)])\n oauth.value = o.providers; env.value = e\n } catch { error.value = '登录已完成,连接状态刷新失败,请刷新页面。' }\n}\nasync function logout(id: string) {\n await guard(async () => { await hermesApi.oauthDisconnect(id, props.bot); oauth.value = (await hermesApi.oauth(props.bot)).providers; emit('changed') }, '已退出登录')\n}\nasync function openPool(id: string) {\n if (poolOpen.value === id) { poolOpen.value = ''; return }\n await guard(async () => { const r = await hermesApi.pool(id, props.bot); pool.value = r.entries; strategy.value = r.strategy; poolOpen.value = id }, undefined, false)\n}\nasync function addPool() {\n const id = poolOpen.value\n if (!id || !poolKey.value.trim()) return\n await guard(async () => { await hermesApi.addPool(id, poolKey.value.trim(), poolLabel.value.trim(), props.bot); poolKey.value = ''; poolLabel.value = ''; pool.value = (await hermesApi.pool(id, props.bot)).entries; emit('changed') }, '已加入凭据池')\n}\nasync function removePool(index: number) {\n const id = poolOpen.value\n await guard(async () => { await hermesApi.removePool(id, index, props.bot); pool.value = (await hermesApi.pool(id, props.bot)).entries; emit('changed') }, '已移除')\n}\nasync function saveStrategy() {\n const id = poolOpen.value\n await guard(async () => {\n const current = (await hermesApi.config(props.bot)).config.credential_pool_strategies ?? {}\n await hermesApi.patchConfig({ credential_pool_strategies: { ...current, [id]: strategy.value } }, props.bot)\n }, '轮换策略已保存')\n}\nasync function writeMain(confirm = false): Promise<boolean> {\n const result = await hermesApi.setModel({ scope: 'main', provider: mainProvider.value, model: mainModel.value.trim(), ...(confirm ? { confirm_expensive_model: true } : {}) })\n if (result.confirm_required) {\n if (!confirm && window.confirm(result.confirm_message || '该模型费用较高,确认使用?')) return writeMain(true)\n return false\n }\n savedMain.value = { provider: mainProvider.value, model: mainModel.value }\n emit('changed')\n return true\n}\nfunction fallbackRows() {\n return fallbackText.value.split('\\n').map(line => line.trim()).filter(Boolean).map((line, index) => {\n const parts = line.split(/\\s+/)\n if (parts.length !== 2) throw new Error('回退模型第 ' + (index + 1) + ' 行需要填写供应商和模型,以空格分隔。')\n return { provider: parts[0]!, model: parts[1]! }\n })\n}\nasync function writeFallback(rows = fallbackRows()) {\n await hermesApi.patchConfig({ fallback_model: rows.length ? rows : null }, props.bot)\n savedFallback.value = fallbackText.value\n emit('changed')\n}\nasync function saveMain() {\n if (!mainAuthorized.value || !mainModel.value.trim()) return\n await guard(() => writeMain(), '默认模型已保存,新一轮对话生效')\n}\nasync function saveFallback() { await guard(() => writeFallback(), '故障回退已保存') }\nasync function saveDefaults() {\n if (!defaultsForm.value?.reportValidity() || !loaded.value || (mainDirty.value && !mainAuthorized.value)) return\n await guard(async () => {\n // Validate both sections before changing either. Successful sections retain their own baseline after a partial failure.\n const rows = fallbackRows()\n let mainSaved = false\n if (mainDirty.value) { if (!await writeMain()) return false; mainSaved = true }\n try { if (fallbackDirty.value) await writeFallback(rows) }\n catch (cause) { if (mainSaved) throw new Error('默认模型已保存,故障回退尚未保存。' + (cause instanceof Error ? cause.message : '请重试。')); throw cause }\n if (jevDirty.value && await jevEditor.value?.save() === false) return false\n if (jevNetworkDirty.value && await jevNetworkEditor.value?.save() === false) return false\n if (botModelsDirty.value && await botModelsEditor.value?.save() === false) return false\n return true\n }, '设置已保存,新一轮对话生效')\n}\nasync function saveEndpoint() {\n const e = endpoint.value\n if (!e.name.trim() || !e.base_url.trim()) return\n await guard(async () => {\n await hermesApi.saveEndpoint({ name: e.name.trim(), base_url: e.base_url.trim(), model: e.model.trim(), ...(e.api_key.trim() ? { api_key: e.api_key.trim() } : {}), api_mode: e.api_mode }, props.bot)\n endpoint.value = { name: '', base_url: '', model: '', api_key: '', api_mode: '' }\n const refreshed = await Promise.all([hermesApi.providers(props.bot), hermesApi.oauth(props.bot), hermesApi.env(props.bot)])\n providers.value = refreshed[0].providers; oauth.value = refreshed[1].providers; env.value = refreshed[2]\n if (!props.bot) models.value = await hermesApi.models()\n emit('changed')\n }, '自定义端点已保存')\n}\n</script>\n<template>\n <section class=\"hermes-providers\" :aria-busy=\"busy\" aria-label=\"Hermes 供应商\">\n<p v-if=\"section !== 'defaults' && !networkConnection\" class=\"note\">{{ bot ? '这里的登录和密钥只对此 Bot 生效,并覆盖系统默认连接。' : '连接供服务器中的 Bot 使用;登录与密钥安全保存,凭据不会完整回显。' }}</p>\n <p v-if=\"error\" class=\"error\" role=\"alert\">{{ error }}</p>\n <p v-if=\"notice\" role=\"status\">{{ notice }}</p>\n <ProviderLoginDialog v-if=\"loginProvider\" :key=\"loginProvider.id\" :provider=\"loginProvider\" :bot=\"bot\" @close=\"closeLogin();refreshNetwork()\" @success=\"loginSucceeded\" />\n\n <ConnectionNetworkPanel v-if=\"networkConnection\" ref=\"networkEditor\" :provider=\"networkConnection.id\" :name=\"networkConnection.name\" :bot=\"bot\" :can-login=\"!!oauthFor(networkConnection.id) && !oauthFor(networkConnection.id)!.status.logged_in\" @back=\"closeNetwork\" @login=\"login(networkConnection!.id)\" @changed=\"refreshNetwork\" @dirty-change=\"networkDirty=$event\" @busy-change=\"mutating=$event\" />\n <template v-if=\"!networkConnection\">\n <form v-if=\"!bot && section !== 'connections'\" :id=\"formId\" ref=\"defaultsForm\" class=\"defaults-form\" @submit.prevent=\"saveDefaults\">\n <template v-if=\"section === 'all' || section === 'defaults'\">\n <div class=\"defaults-heading\"><h4>默认对话模型</h4><p>Bot 未单独指定模型时使用此配置。</p></div>\n <label class=\"setting-row\"><span><strong>供应商</strong><small>只列出模型连接中已授权的供应商。</small></span><select v-model=\"mainProvider\" :required=\"mainDirty\" aria-label=\"默认模型供应商\" :disabled=\"busy || !loaded\"><option value=\"\">请选择</option><option v-for=\"p in authorizedProviders\" :key=\"p.slug\" :value=\"p.slug\">{{ p.name }}</option><option v-if=\"mainProvider && !mainAuthorized\" :value=\"mainProvider\">{{ models?.providers.find(p => p.slug === mainProvider)?.name || mainProvider }}(未授权)</option></select></label>\n <label class=\"setting-row\"><span><strong>模型</strong><small>选择默认的对话模型。</small></span><input v-model=\"mainModel\" :required=\"mainDirty\" aria-label=\"默认对话模型\" list=\"hermes-main-models\" :disabled=\"busy || !loaded\" placeholder=\"选择或输入模型 ID\" /></label>\n <datalist id=\"hermes-main-models\"><option v-for=\"m in providerModels\" :key=\"m\" :value=\"m\" /></datalist>\n <div class=\"defaults-status\"><span :class=\"{ configured: mainAuthorized }\">{{ !loaded ? '正在读取配置…' : catalogError || (mainAuthorized ? '服务已授权' : mainProvider ? '该供应商尚未授权,请先到模型连接完成授权。' : '请选择已授权的模型服务') }}</span><button type=\"button\" class=\"refresh-models\" :disabled=\"busy\" @click=\"refreshModels\"><AppIcon name=\"refresh\" :size=\"16\" />刷新模型列表</button></div>\n <button v-if=\"!embedded\" type=\"button\" :disabled=\"busy || !mainAuthorized || !mainModel.trim()\" @click=\"saveMain\">保存默认模型</button>\n <div class=\"fallback-section\"><h4>故障回退</h4><p>默认模型不可用时,按顺序尝试备用模型。</p><details><summary><span>回退模型</span><span>{{ fallbackText.trim() ? fallbackText.trim().split('\\n').length + ' 个备用模型' : '尚未设置' }}</span><AppIcon name=\"chevron-left\" :size=\"18\" /></summary><label>备用模型顺序<textarea v-model=\"fallbackText\" rows=\"4\" placeholder=\"每行:供应商 模型,以空格分隔\" :disabled=\"busy\" /></label><small>按从上到下的顺序尝试;留空可关闭回退。</small><button v-if=\"!embedded\" type=\"button\" :disabled=\"busy\" @click=\"saveFallback\">保存回退链</button></details></div>\n </template>\n <JevAutoPanel v-if=\"section === 'all' || section === 'auto'\" ref=\"jevEditor\" :models=\"models\" :disabled=\"busy || panelsBusy\" @dirty-change=\"jevDirty=$event\" @busy-change=\"jevBusy=$event\" />\n <JevNetworkPanel v-if=\"section === 'all' || section === 'auto'\" ref=\"jevNetworkEditor\" :disabled=\"busy || panelsBusy\" @dirty-change=\"jevNetworkDirty=$event\" @busy-change=\"jevNetworkBusy=$event\" @manage-network=\"emit('manage-network')\" />\n <BotModelVisibilityPanel v-if=\"section === 'all' || section === 'visibility'\" ref=\"botModelsEditor\" :models=\"models\" :disabled=\"busy || panelsBusy\" @dirty-change=\"botModelsDirty=$event\" @busy-change=\"botModelsBusy=$event\" />\n </form>\n\n <template v-if=\"section === 'all' || section === 'connections'\">\n <div v-if=\"customConnections.length\" class=\"block\"><h4>已连接服务</h4><ul class=\"providers\"><li v-for=\"p in customConnections\" :key=\"p.slug\"><div class=\"head\"><strong>{{ p.name }}</strong><span class=\"badge ok\">{{ p.authenticated === true ? '已授权' : '当前服务' }}</span></div><p class=\"hint\">{{ p.models.length }} 个可选模型</p><button type=\"button\" class=\"link\" @click=\"openNetwork(p.slug,p.name)\">{{ networkText(p.slug) }}</button></li></ul></div>\n <div v-if=\"loneOauth.length && (showAll || loneOauth.some(o => o.status.logged_in))\" class=\"block\">\n <h4>其他登录方式</h4>\n <ul class=\"providers\">\n <li v-for=\"o in loneOauth.filter(o => showAll || o.status.logged_in)\" :key=\"o.id\">\n <div class=\"head\"><strong>{{ o.name }}</strong> <code>{{ o.id }}</code>\n <span :class=\"['badge', o.status.logged_in ? 'ok' : '']\">{{ o.status.logged_in ? '已登录' : '未登录' }}</span></div>\n <button type=\"button\" class=\"link\" @click=\"openNetwork(o.id,o.name)\">{{ networkText(o.id) }}</button><p v-if=\"o.status.logged_in && o.disconnectable\"><button type=\"button\" :disabled=\"busy\" @click=\"logout(o.id)\">退出登录</button></p>\n <p v-else-if=\"!o.status.logged_in\"><button type=\"button\" :disabled=\"busy\" aria-haspopup=\"dialog\" @click=\"login(o.id)\">登录 {{ o.name }}</button></p>\n </li>\n </ul>\n </div>\n <div class=\"block\">\n <div class=\"connection-heading\"><h4>{{ showAll ? '添加模型连接' : '已配置供应商' }}</h4><button v-if=\"section === 'connections'\" type=\"button\" :disabled=\"busy\" @click=\"showAll = !showAll\">{{ showAll ? '查看已配置' : '添加连接' }}</button></div>\n <input v-model=\"filter\" type=\"search\" placeholder=\"搜索供应商或别名\" aria-label=\"搜索供应商\" />\n <ul class=\"providers\">\n <li v-for=\"p in shown\" :key=\"p.id\">\n <div class=\"head\"><strong>{{ p.label }}</strong> <code>{{ p.id }}</code>\n <span :class=\"['badge', configured(p) ? 'ok' : '']\">{{ configured(p) ? '已配置' : '未配置' }}</span>\n </div>\n <button type=\"button\" class=\"link\" @click=\"openNetwork(p.id,p.label)\">{{ networkText(p.id) }}</button><template v-if=\"oauthFor(p.id)\">\n <p v-if=\"oauthFor(p.id)!.status.logged_in\">已登录 {{ oauthFor(p.id)!.status.token_preview ? '· …' + oauthFor(p.id)!.status.token_preview : '' }}\n <button v-if=\"oauthFor(p.id)!.disconnectable\" type=\"button\" :disabled=\"busy\" @click=\"logout(p.id)\">退出登录</button></p>\n <p v-else><button type=\"button\" :disabled=\"busy\" aria-haspopup=\"dialog\" @click=\"login(p.id)\">登录 {{ oauthFor(p.id)!.name }}</button></p>\n </template>\n <form v-if=\"keyVar(p)\" class=\"row\" @submit.prevent=\"saveKey(p)\">\n <input v-model=\"keyDraft[p.id]\" type=\"password\" autocomplete=\"new-password\" :placeholder=\"env[keyVar(p)!]?.is_set ? `${keyVar(p)} 已设置(${env[keyVar(p)!]?.redacted_value ?? '***'})` : keyVar(p)\" :aria-label=\"`${p.label} API Key`\" />\n <button type=\"submit\" :disabled=\"busy || !keyDraft[p.id]?.trim()\">保存</button>\n <button v-if=\"env[keyVar(p)!]?.is_set\" type=\"button\" :disabled=\"busy\" @click=\"removeKey(keyVar(p)!)\">移除</button>\n </form>\n <button type=\"button\" class=\"link\" @click=\"openPool(p.id)\">{{ poolOpen === p.id ? '收起凭据池' : '凭据池' }}</button>\n <div v-if=\"poolOpen === p.id\" class=\"pool\">\n <ol><li v-for=\"e in pool\" :key=\"e.id\">{{ e.label }} · {{ e.authType }} · {{ e.source }} {{ e.tokenPreview }} <em v-if=\"e.lastStatus\">{{ e.lastStatus }}</em>\n <button type=\"button\" :disabled=\"busy\" @click=\"removePool(e.index)\">删除</button></li></ol>\n <form class=\"row\" @submit.prevent=\"addPool\"><input v-model=\"poolKey\" type=\"password\" autocomplete=\"new-password\" placeholder=\"追加 API Key\" /><input v-model=\"poolLabel\" placeholder=\"标签(可选)\" /><button type=\"submit\" :disabled=\"busy || !poolKey.trim()\">加入</button></form>\n <label class=\"row\">轮换策略<select v-model=\"strategy\"><option value=\"fill_first\">fill_first</option><option value=\"round_robin\">round_robin</option><option value=\"least_used\">least_used</option><option value=\"random\">random</option></select>\n <button type=\"button\" :disabled=\"busy\" @click=\"saveStrategy\">保存</button></label>\n </div>\n </li>\n </ul>\n </div>\n\n <div v-if=\"mediaKeys.length\" class=\"block\"><h4>媒体专用凭据</h4><p class=\"hint\">这些密钥只供图片或视频使用。保存后,对应页面可以直接选用已授权的供应商。</p><ul class=\"providers\"><li v-for=\"field in mediaKeys\" :key=\"field.key\"><div class=\"head\"><strong>{{ field.prompt }}</strong> <code>{{ field.key }}</code><span :class=\"['badge', field.isSet ? 'ok' : '']\">{{ field.isSet ? '已配置' : '未配置' }}</span></div><p class=\"hint\">{{ field.uses.join('、') }}</p><form class=\"row\" @submit.prevent=\"saveMediaKey(field.key)\"><input v-model=\"mediaDraft[field.key]\" type=\"password\" autocomplete=\"new-password\" :placeholder=\"field.isSet ? `${field.key} 已设置,留空则不修改` : field.key\" :aria-label=\"field.prompt\" /><button type=\"submit\" :disabled=\"busy || !mediaDraft[field.key]?.trim()\">保存</button><button v-if=\"field.isSet\" type=\"button\" :disabled=\"busy\" @click=\"removeKey(field.key)\">移除</button></form></li></ul></div>\n <p v-if=\"!shown.length && !customConnections.length && !mediaKeys.length\" class=\"hint\">暂无匹配的连接。可添加供应商或自定义服务。</p>\n <details class=\"endpoint-section\"><summary>添加自定义模型服务</summary><form class=\"block\" @submit.prevent=\"saveEndpoint\">\n <h4>自定义 OpenAI 兼容服务</h4>\n <label>服务名称<input v-model=\"endpoint.name\" placeholder=\"名称\" /></label>\n <label>服务地址<input v-model=\"endpoint.base_url\" type=\"url\" placeholder=\"https://host/v1\" /></label>\n <label>默认模型<input v-model=\"endpoint.model\" placeholder=\"默认模型\" /></label>\n <label>API Key(可选)<input v-model=\"endpoint.api_key\" type=\"password\" autocomplete=\"new-password\" placeholder=\"API Key\" /></label>\n <label>接口协议<select v-model=\"endpoint.api_mode\"><option value=\"\">自动识别</option><option value=\"chat_completions\">chat_completions</option><option value=\"codex_responses\">codex_responses</option><option value=\"anthropic_messages\">anthropic_messages</option></select></label>\n <button type=\"submit\" :disabled=\"busy || !endpoint.name.trim() || !endpoint.base_url.trim()\">保存端点</button>\n </form></details>\n </template>\n </template>\n </section>\n</template>\n<style scoped>\n.hermes-providers{display:grid;gap:16px;max-width:760px}.note,.hint{color:var(--text-secondary);margin:0;line-height:1.6}.error{color:var(--danger,#c33)}\n.block{display:grid;gap:16px;border:0;border-top:1px solid var(--line);padding:20px 0}.block h4{margin:0}\n.row{display:flex;gap:8px;flex-wrap:wrap;align-items:center}.providers{list-style:none;margin:0;padding:0;display:grid;gap:16px}\n.providers>li{border-top:1px solid var(--line);padding-top:8px;display:grid;gap:6px}.head{display:flex;gap:8px;align-items:baseline;flex-wrap:wrap}.badge{font-size:12px;padding:1px 6px;border-radius:6px;border:1px solid var(--line)}.badge.ok{border-color:var(--accent)}\ninput,select,textarea,button{min-height:44px;padding:6px 10px;border:1px solid var(--line);border-radius:8px;background:var(--surface);color:var(--text-primary);font:inherit}button{cursor:pointer}button:disabled{opacity:.5;cursor:default}.link{border:0;background:none;padding:0;min-height:0;color:var(--accent);justify-self:start}\n.hermes-providers{max-width:none;font-size:14px}.defaults-form{display:grid;gap:0;min-width:0}.defaults-heading{margin-bottom:16px}.defaults-form h4{margin:0;font-size:18px;font-weight:650}.defaults-form p{margin:12px 0 0;font-size:14px;line-height:1.6;color:var(--text-secondary)}.setting-row{display:grid;grid-template-columns:minmax(0,1fr) minmax(200px,56%);align-items:center;gap:24px;padding:16px 0;border-bottom:1px solid var(--line)}.setting-row>span{display:grid;gap:7px}.setting-row strong{font-size:15px;font-weight:600}.setting-row small{font-size:13px;line-height:1.5;color:var(--text-secondary)}.setting-row input,.setting-row select{width:100%;box-sizing:border-box;padding:10px 12px}.defaults-status{display:flex;align-items:center;justify-content:space-between;gap:12px;margin:8px 0 8px 44%;font-size:13px;line-height:1.5;color:var(--text-secondary)}.defaults-status .configured{color:var(--success)}.defaults-status .configured:before{content:'';display:inline-block;width:9px;height:9px;border-radius:50%;background:currentColor;margin-right:8px}.defaults-status .refresh-models{min-height:44px;flex-shrink:0;padding:6px 8px;border:0;background:transparent;font-size:13px;display:inline-flex;align-items:center;gap:8px}.fallback-section{border-top:1px solid var(--line);padding-top:28px}.fallback-section details{margin-top:16px}.fallback-section summary{display:grid;grid-template-columns:minmax(0,1fr) minmax(200px,56%);align-items:center;gap:24px;min-height:48px;cursor:pointer;list-style:none}.fallback-section summary>.app-icon{position:absolute;right:14px;transform:rotate(180deg);color:var(--text-secondary)}.fallback-section summary{position:relative}.fallback-section summary>span:nth-child(2){display:block;border:1px solid var(--line);border-radius:8px;padding:12px 34px 12px 12px;color:var(--text-secondary)}.fallback-section label{display:grid;gap:10px;margin-top:18px}.fallback-section textarea{box-sizing:border-box;width:100%;resize:vertical}.fallback-section small{display:block;margin-top:10px;color:var(--text-secondary);line-height:1.6}.fallback-section details[open] summary>.app-icon{transform:rotate(-90deg)}.connection-heading{display:flex;align-items:center;justify-content:space-between;gap:16px}.endpoint-section summary{min-height:44px;line-height:44px;cursor:pointer}.endpoint-section label{display:grid;gap:8px}.hermes-providers :focus-visible{outline:2px solid var(--accent);outline-offset:2px}.hermes-providers input,.hermes-providers select,.hermes-providers textarea{min-width:0;max-width:100%;box-sizing:border-box}@media(max-width:600px){.setting-row,.fallback-section summary{grid-template-columns:1fr;gap:10px}.defaults-status{margin-left:0;flex-wrap:wrap}.fallback-section summary>.app-icon{bottom:14px}.head{align-items:center}.row input{flex:1;min-width:140px}.defaults-form h4{font-size:17px}}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, nextTick, onMounted, ref, watch } from 'vue'\nimport AppIcon from '@/components/common/AppIcon.vue'\nimport ConnectionNetworkPanel from './ConnectionNetworkPanel.vue'\nimport { modelNetworkApi, networkLabel } from '@/api/modelNetwork'\nimport type { ModelNetworkView } from '@shared/modelNetwork'\nimport ProviderLoginDialog from './ProviderLoginDialog.vue'\nimport JevAutoPanel from './JevAutoPanel.vue'\nimport JevNetworkPanel from './JevNetworkPanel.vue'\nimport BotModelVisibilityPanel from './BotModelVisibilityPanel.vue'\nimport { hermesApi, hermesMediaApi, type HermesEnvVar, type HermesModelOptions, type HermesOAuthProvider, type HermesPoolEntry, type HermesProvider } from '@/api/hermes'\n\n/**\n * Hermes provider management (same operations as the Hermes dashboard).\n * Without `bot` it edits the system layer; with `bot` it edits that Bot's own Hermes home,\n * whose logins and keys override the system layer.\n */\nconst networkView=ref<ModelNetworkView>(), networkConnection=ref<{id:string;name:string}>(), networkDirty=ref(false)\nconst networkEditor=ref<InstanceType<typeof ConnectionNetworkPanel>>()\nasync function refreshNetwork(){try{networkView.value=await modelNetworkApi.get(props.bot)}catch{networkView.value=undefined}}\nfunction networkText(id:string){return networkView.value?(props.bot?'独立凭据网络:':'网络:')+networkLabel(networkView.value,networkView.value.connections[id]??{mode:'inherit'}):'设置连接网络'}\nfunction openNetwork(id:string,name:string){networkConnection.value={id,name}}\nfunction closeNetwork(){networkDirty.value=false;networkConnection.value=undefined;void refreshNetwork()}\nonMounted(refreshNetwork)\nconst props = withDefaults(defineProps<{ bot?: string; section?: 'all' | 'connections' | 'defaults' | 'auto' | 'visibility'; embedded?: boolean; formId?: string }>(), { section: 'all', embedded: false })\nconst emit = defineEmits<{ changed: []; 'dirty-change': [value: boolean]; 'can-save-change': [value: boolean]; 'busy-change': [value: boolean]; 'manage-network': [] }>()\nconst jevEditor = ref<InstanceType<typeof JevAutoPanel>>(), jevNetworkEditor = ref<InstanceType<typeof JevNetworkPanel>>(), botModelsEditor = ref<InstanceType<typeof BotModelVisibilityPanel>>()\nconst jevDirty = ref(false), jevNetworkDirty = ref(false), botModelsDirty = ref(false)\nconst jevBusy = ref(false), jevNetworkBusy = ref(false), botModelsBusy = ref(false)\nconst panelsDirty = computed(() => jevDirty.value || jevNetworkDirty.value || botModelsDirty.value)\nconst panelsBusy = computed(() => jevBusy.value || jevNetworkBusy.value || botModelsBusy.value)\nconst providers = ref<HermesProvider[]>([]), oauth = ref<HermesOAuthProvider[]>([]), env = ref<Record<string, HermesEnvVar>>({})\nconst models = ref<HermesModelOptions>(), mainProvider = ref(''), mainModel = ref('')\nconst fallbackText = ref(''), filter = ref(''), busy = ref(false), error = ref(''), notice = ref('')\nconst loginProvider = ref<HermesOAuthProvider>()\nlet loginTrigger: HTMLElement | undefined\nconst keyDraft = ref<Record<string, string>>({}), poolOpen = ref(''), pool = ref<HermesPoolEntry[]>([]), poolKey = ref(''), poolLabel = ref(''), strategy = ref('fill_first')\nconst endpoint = ref({ name: '', base_url: '', model: '', api_key: '', api_mode: '' })\nconst mediaKeys = ref<Array<{ key: string; prompt: string; isSet: boolean; uses: string[] }>>([])\nconst mediaDraft = ref<Record<string, string>>({})\nconst mutating = ref(false)\nconst loaded = ref(false), showAll = ref(props.section === 'all'), catalogError = ref('')\nconst savedMain = ref({ provider: '', model: '' }), savedFallback = ref('')\nconst defaultsForm = ref<HTMLFormElement>()\n\nconst shown = computed(() => {\n const f = filter.value.trim().toLowerCase()\n return providers.value.filter(p => (showAll.value || !!f || configured(p)) && (!f || p.id.includes(f) || p.label.toLowerCase().includes(f) || p.aliases.some(a => a.includes(f))))\n})\nconst oauthFor = (id: string) => oauth.value.find(p => p.id === id)\n// Sign-ins that have no provider row of their own (e.g. claude-code, copilot-acp).\nconst loneOauth = computed(() => oauth.value.filter(o => !providers.value.some(p => p.id === o.id)))\nconst keyVar = (p: HermesProvider) => p.envVars[0]\nconst configured = (p: HermesProvider) => !!oauthFor(p.id)?.status.logged_in || p.envVars.some(v => env.value[v]?.is_set)\nconst providerModels = computed(() => models.value?.providers.find(p => p.slug === mainProvider.value)?.models ?? [])\nconst authorizedProviders = computed(() => models.value?.providers.filter(p => p.authenticated === true) ?? [])\nconst mainAuthorized = computed(() => authorizedProviders.value.some(p => p.slug === mainProvider.value))\nconst customConnections = computed(() => models.value?.providers.filter(p => (p.authenticated === true || p.is_current) && !providers.value.some(provider => provider.id === p.slug)) ?? [])\nconst mainDirty = computed(() => loaded.value && (mainProvider.value !== savedMain.value.provider || mainModel.value !== savedMain.value.model))\nconst fallbackDirty = computed(() => loaded.value && fallbackText.value !== savedFallback.value)\nconst connectionDirty = computed(() => Object.values(keyDraft.value).some(Boolean) || Object.values(endpoint.value).some(Boolean) || !!poolKey.value || !!poolLabel.value || Object.values(mediaDraft.value).some(value => value.trim()))\nconst dirty = computed(() => networkDirty.value || panelsDirty.value || (props.section === 'defaults' ? mainDirty.value || fallbackDirty.value : props.section === 'connections' ? connectionDirty.value : mainDirty.value || fallbackDirty.value || connectionDirty.value))\nwatch(dirty, value => { if (value) notice.value = ''; emit('dirty-change', value) })\nwatch(() => loaded.value && !busy.value && !panelsBusy.value && (!mainDirty.value || (mainAuthorized.value && !!mainModel.value.trim())) && (mainDirty.value || fallbackDirty.value || panelsDirty.value), value => emit('can-save-change', value), { immediate: true })\nwatch(() => mutating.value || panelsBusy.value, value => emit('busy-change', value), { immediate: true })\nasync function refreshModels() {\n await guard(async () => { models.value = await hermesApi.models(true); catalogError.value = '' }, '模型列表已刷新', false)\n}\n\n\nasync function guard(fn: () => Promise<unknown>, ok?: string, blocksNavigation = true) {\n if (busy.value || panelsBusy.value) return\n busy.value = true; mutating.value = blocksNavigation; error.value = ''; notice.value = ''\n try { const result = await fn(); if (ok && result !== false) notice.value = ok } catch (e) { error.value = e instanceof Error ? e.message : '操作失败' } finally { busy.value = false; mutating.value = false }\n}\nasync function load() {\n await guard(async () => {\n const [p, o, e, c] = await Promise.all([props.section === 'defaults' ? Promise.resolve({ providers: [] as HermesProvider[] }) : hermesApi.providers(props.bot), props.section === 'defaults' ? Promise.resolve({ providers: [] as HermesOAuthProvider[] }) : hermesApi.oauth(props.bot), props.section === 'defaults' ? Promise.resolve({} as Record<string, HermesEnvVar>) : hermesApi.env(props.bot), hermesApi.config(props.bot)])\n providers.value = p.providers; oauth.value = o.providers; env.value = e\n mainProvider.value = c.config.model?.provider ?? ''; mainModel.value = c.config.model?.default ?? ''\n const fb = c.config.fallback_model\n fallbackText.value = (Array.isArray(fb) ? fb : fb ? [fb] : []).map(f => `${f.provider} ${f.model}`).join('\\n')\n savedMain.value = { provider: mainProvider.value, model: mainModel.value }; savedFallback.value = fallbackText.value; loaded.value = true\n if (!props.bot) models.value = await hermesApi.models(false).catch(() => { catalogError.value = '暂时无法读取模型列表,可重试刷新。'; return undefined })\n await loadMediaKeys()\n }, undefined, false)\n}\nasync function loadMediaKeys() {\n if (props.bot || (props.section !== 'all' && props.section !== 'connections')) { mediaKeys.value = []; return }\n try {\n const [image, video] = await Promise.all([hermesMediaApi.config('image_gen'), hermesMediaApi.config('video_gen')])\n const known = new Set(providers.value.flatMap(p => p.envVars))\n const rows = new Map<string, { key: string; prompt: string; isSet: boolean; uses: string[] }>()\n for (const [label, value] of [['图片', image], ['视频', video]] as const) {\n for (const provider of value?.providers ?? []) for (const field of provider.env_vars ?? []) {\n if (!field.key || known.has(field.key)) continue\n const row = rows.get(field.key) ?? { key: field.key, prompt: field.prompt || field.key, isSet: false, uses: [] }\n row.isSet = row.isSet || !!field.is_set || !!env.value[field.key]?.is_set\n const use = `${label} · ${provider.name}`\n if (!row.uses.includes(use)) row.uses.push(use)\n rows.set(field.key, row)\n }\n }\n mediaKeys.value = [...rows.values()]\n } catch { mediaKeys.value = [] }\n}\ndefineExpose({ reset: () => networkConnection.value ? networkEditor.value?.reset() : Promise.all([load(), jevEditor.value?.reset(), jevNetworkEditor.value?.reset(), botModelsEditor.value?.reset()]) })\nonMounted(load)\n\nasync function saveMediaKey(key: string) {\n const value = mediaDraft.value[key]?.trim()\n if (!value) return\n await guard(async () => {\n await hermesApi.setEnv(key, value, props.bot)\n mediaDraft.value[key] = ''\n env.value = await hermesApi.env(props.bot)\n await loadMediaKeys()\n emit('changed')\n }, '媒体密钥已保存')\n}\nasync function saveKey(p: HermesProvider) {\n const key = keyVar(p), value = keyDraft.value[p.id]?.trim()\n if (!key || !value) return\n await guard(async () => { await hermesApi.setEnv(key, value, props.bot); keyDraft.value[p.id] = ''; env.value = await hermesApi.env(props.bot); emit('changed') }, `${p.label} 密钥已保存`)\n}\nasync function removeKey(key: string) {\n await guard(async () => { await hermesApi.deleteEnv(key, props.bot); env.value = await hermesApi.env(props.bot); await loadMediaKeys(); emit('changed') }, '密钥已移除')\n}\nfunction login(id: string) {\n if (busy.value || loginProvider.value) return\n loginTrigger = document.activeElement instanceof HTMLElement ? document.activeElement : undefined\n loginProvider.value = oauthFor(id)\n}\nfunction closeLogin() {\n loginProvider.value = undefined\n void nextTick(() => { if (loginTrigger?.isConnected) loginTrigger.focus({ preventScroll: true }) })\n}\nasync function loginSucceeded() {\n notice.value = '登录成功'\n emit('changed')\n try {\n const [o, e] = await Promise.all([hermesApi.oauth(props.bot), hermesApi.env(props.bot)])\n oauth.value = o.providers; env.value = e\n } catch { error.value = '登录已完成,连接状态刷新失败,请刷新页面。' }\n}\nasync function logout(id: string) {\n await guard(async () => { await hermesApi.oauthDisconnect(id, props.bot); oauth.value = (await hermesApi.oauth(props.bot)).providers; emit('changed') }, '已退出登录')\n}\nasync function openPool(id: string) {\n if (poolOpen.value === id) { poolOpen.value = ''; return }\n await guard(async () => { const r = await hermesApi.pool(id, props.bot); pool.value = r.entries; strategy.value = r.strategy; poolOpen.value = id }, undefined, false)\n}\nasync function addPool() {\n const id = poolOpen.value\n if (!id || !poolKey.value.trim()) return\n await guard(async () => { await hermesApi.addPool(id, poolKey.value.trim(), poolLabel.value.trim(), props.bot); poolKey.value = ''; poolLabel.value = ''; pool.value = (await hermesApi.pool(id, props.bot)).entries; emit('changed') }, '已加入凭据池')\n}\nasync function removePool(index: number) {\n const id = poolOpen.value\n await guard(async () => { await hermesApi.removePool(id, index, props.bot); pool.value = (await hermesApi.pool(id, props.bot)).entries; emit('changed') }, '已移除')\n}\nasync function saveStrategy() {\n const id = poolOpen.value\n await guard(async () => {\n const current = (await hermesApi.config(props.bot)).config.credential_pool_strategies ?? {}\n await hermesApi.patchConfig({ credential_pool_strategies: { ...current, [id]: strategy.value } }, props.bot)\n }, '轮换策略已保存')\n}\nasync function writeMain(confirm = false): Promise<boolean> {\n const result = await hermesApi.setModel({ scope: 'main', provider: mainProvider.value, model: mainModel.value.trim(), ...(confirm ? { confirm_expensive_model: true } : {}) })\n if (result.confirm_required) {\n if (!confirm && window.confirm(result.confirm_message || '该模型费用较高,确认使用?')) return writeMain(true)\n return false\n }\n savedMain.value = { provider: mainProvider.value, model: mainModel.value }\n emit('changed')\n return true\n}\nfunction fallbackRows() {\n return fallbackText.value.split('\\n').map(line => line.trim()).filter(Boolean).map((line, index) => {\n const parts = line.split(/\\s+/)\n if (parts.length !== 2) throw new Error('回退模型第 ' + (index + 1) + ' 行需要填写供应商和模型,以空格分隔。')\n return { provider: parts[0]!, model: parts[1]! }\n })\n}\nasync function writeFallback(rows = fallbackRows()) {\n await hermesApi.patchConfig({ fallback_model: rows.length ? rows : null }, props.bot)\n savedFallback.value = fallbackText.value\n emit('changed')\n}\nasync function saveMain() {\n if (!mainAuthorized.value || !mainModel.value.trim()) return\n await guard(() => writeMain(), '默认模型已保存,新一轮对话生效')\n}\nasync function saveFallback() { await guard(() => writeFallback(), '故障回退已保存') }\nasync function saveDefaults() {\n if (!defaultsForm.value?.reportValidity() || !loaded.value || (mainDirty.value && !mainAuthorized.value)) return\n await guard(async () => {\n // Validate both sections before changing either. Successful sections retain their own baseline after a partial failure.\n const rows = fallbackRows()\n let mainSaved = false\n if (mainDirty.value) { if (!await writeMain()) return false; mainSaved = true }\n try { if (fallbackDirty.value) await writeFallback(rows) }\n catch (cause) { if (mainSaved) throw new Error('默认模型已保存,故障回退尚未保存。' + (cause instanceof Error ? cause.message : '请重试。')); throw cause }\n if (jevDirty.value && await jevEditor.value?.save() === false) return false\n if (jevNetworkDirty.value && await jevNetworkEditor.value?.save() === false) return false\n if (botModelsDirty.value && await botModelsEditor.value?.save() === false) return false\n return true\n }, '设置已保存,新一轮对话生效')\n}\nasync function saveEndpoint() {\n const e = endpoint.value\n if (!e.name.trim() || !e.base_url.trim()) return\n await guard(async () => {\n await hermesApi.saveEndpoint({ name: e.name.trim(), base_url: e.base_url.trim(), model: e.model.trim(), ...(e.api_key.trim() ? { api_key: e.api_key.trim() } : {}), api_mode: e.api_mode }, props.bot)\n endpoint.value = { name: '', base_url: '', model: '', api_key: '', api_mode: '' }\n const refreshed = await Promise.all([hermesApi.providers(props.bot), hermesApi.oauth(props.bot), hermesApi.env(props.bot)])\n providers.value = refreshed[0].providers; oauth.value = refreshed[1].providers; env.value = refreshed[2]\n if (!props.bot) models.value = await hermesApi.models()\n emit('changed')\n }, '自定义端点已保存')\n}\n</script>\n<template>\n <section class=\"hermes-providers\" :aria-busy=\"busy\" aria-label=\"Hermes 供应商\">\n<p v-if=\"section !== 'defaults' && !networkConnection\" class=\"note\">{{ bot ? '这里的登录和密钥只对此 Bot 生效,并覆盖系统默认连接。' : '连接供服务器中的 Bot 使用;登录与密钥安全保存,凭据不会完整回显。' }}</p>\n <p v-if=\"error\" class=\"error\" role=\"alert\">{{ error }}</p>\n <p v-if=\"notice\" role=\"status\">{{ notice }}</p>\n <ProviderLoginDialog v-if=\"loginProvider\" :key=\"loginProvider.id\" :provider=\"loginProvider\" :bot=\"bot\" @close=\"closeLogin();refreshNetwork()\" @success=\"loginSucceeded\" />\n\n <ConnectionNetworkPanel v-if=\"networkConnection\" ref=\"networkEditor\" :provider=\"networkConnection.id\" :name=\"networkConnection.name\" :bot=\"bot\" :can-login=\"!!oauthFor(networkConnection.id) && !oauthFor(networkConnection.id)!.status.logged_in\" @back=\"closeNetwork\" @login=\"login(networkConnection!.id)\" @changed=\"refreshNetwork\" @dirty-change=\"networkDirty=$event\" @busy-change=\"mutating=$event\" />\n <template v-if=\"!networkConnection\">\n <form v-if=\"!bot && section !== 'connections'\" :id=\"formId\" ref=\"defaultsForm\" class=\"defaults-form\" @submit.prevent=\"saveDefaults\">\n <template v-if=\"section === 'all' || section === 'defaults'\">\n <div class=\"defaults-heading\"><h4>默认对话模型</h4><p>Bot 未单独指定模型时使用此配置。</p></div>\n <label class=\"setting-row\"><span><strong>供应商</strong><small>只列出模型连接中已授权的供应商。</small></span><select v-model=\"mainProvider\" :required=\"mainDirty\" aria-label=\"默认模型供应商\" :disabled=\"busy || !loaded\"><option value=\"\">请选择</option><option v-for=\"p in authorizedProviders\" :key=\"p.slug\" :value=\"p.slug\">{{ p.name }}</option><option v-if=\"mainProvider && !mainAuthorized\" :value=\"mainProvider\">{{ models?.providers.find(p => p.slug === mainProvider)?.name || mainProvider }}(未授权)</option></select></label>\n <label class=\"setting-row\"><span><strong>模型</strong><small>选择默认的对话模型。</small></span><input v-model=\"mainModel\" :required=\"mainDirty\" aria-label=\"默认对话模型\" list=\"hermes-main-models\" :disabled=\"busy || !loaded\" placeholder=\"选择或输入模型 ID\" /></label>\n <datalist id=\"hermes-main-models\"><option v-for=\"m in providerModels\" :key=\"m\" :value=\"m\" /></datalist>\n <div class=\"defaults-status\"><span :class=\"{ configured: mainAuthorized }\">{{ !loaded ? '正在读取配置…' : catalogError || (mainAuthorized ? '服务已授权' : mainProvider ? '该供应商尚未授权,请先到模型连接完成授权。' : '请选择已授权的模型服务') }}</span><button type=\"button\" class=\"refresh-models\" :disabled=\"busy\" @click=\"refreshModels\"><AppIcon name=\"refresh\" :size=\"16\" />刷新模型列表</button></div>\n <button v-if=\"!embedded\" type=\"button\" :disabled=\"busy || !mainAuthorized || !mainModel.trim()\" @click=\"saveMain\">保存默认模型</button>\n <div class=\"fallback-section\"><h4>故障回退</h4><p>默认模型不可用时,按顺序尝试备用模型。</p><details><summary><span>回退模型</span><span>{{ fallbackText.trim() ? fallbackText.trim().split('\\n').length + ' 个备用模型' : '尚未设置' }}</span><AppIcon name=\"chevron-left\" :size=\"18\" /></summary><label>备用模型顺序<textarea v-model=\"fallbackText\" rows=\"4\" placeholder=\"每行:供应商 模型,以空格分隔\" :disabled=\"busy\" /></label><small>按从上到下的顺序尝试;留空可关闭回退。</small><button v-if=\"!embedded\" type=\"button\" :disabled=\"busy\" @click=\"saveFallback\">保存回退链</button></details></div>\n </template>\n <JevAutoPanel v-if=\"section === 'all' || section === 'auto'\" ref=\"jevEditor\" :models=\"models\" :disabled=\"busy || panelsBusy\" @dirty-change=\"jevDirty=$event\" @busy-change=\"jevBusy=$event\" />\n <JevNetworkPanel v-if=\"section === 'all' || section === 'auto'\" ref=\"jevNetworkEditor\" :disabled=\"busy || panelsBusy\" @dirty-change=\"jevNetworkDirty=$event\" @busy-change=\"jevNetworkBusy=$event\" @manage-network=\"emit('manage-network')\" />\n <BotModelVisibilityPanel v-if=\"section === 'all' || section === 'visibility'\" ref=\"botModelsEditor\" :models=\"models\" :disabled=\"busy || panelsBusy\" @dirty-change=\"botModelsDirty=$event\" @busy-change=\"botModelsBusy=$event\" />\n </form>\n\n <template v-if=\"section === 'all' || section === 'connections'\">\n <div v-if=\"customConnections.length\" class=\"block\"><h4>已连接服务</h4><ul class=\"providers\"><li v-for=\"p in customConnections\" :key=\"p.slug\"><div class=\"head\"><strong>{{ p.name }}</strong><span class=\"badge ok\">{{ p.authenticated === true ? '已授权' : '当前服务' }}</span></div><p class=\"hint\">{{ p.models.length }} 个可选模型</p><button type=\"button\" class=\"link\" @click=\"openNetwork(p.slug,p.name)\">{{ networkText(p.slug) }}</button></li></ul></div>\n <div v-if=\"loneOauth.length && (showAll || loneOauth.some(o => o.status.logged_in))\" class=\"block\">\n <h4>其他登录方式</h4>\n <ul class=\"providers\">\n <li v-for=\"o in loneOauth.filter(o => showAll || o.status.logged_in)\" :key=\"o.id\">\n <div class=\"head\"><strong>{{ o.name }}</strong> <code>{{ o.id }}</code>\n <span :class=\"['badge', o.status.logged_in ? 'ok' : '']\">{{ o.status.logged_in ? '已登录' : '未登录' }}</span></div>\n <button type=\"button\" class=\"link\" @click=\"openNetwork(o.id,o.name)\">{{ networkText(o.id) }}</button><p v-if=\"o.status.logged_in && o.disconnectable\"><button type=\"button\" :disabled=\"busy\" @click=\"logout(o.id)\">退出登录</button></p>\n <p v-else-if=\"!o.status.logged_in\"><button type=\"button\" :disabled=\"busy\" aria-haspopup=\"dialog\" @click=\"login(o.id)\">登录 {{ o.name }}</button></p>\n </li>\n </ul>\n </div>\n <div class=\"block\">\n <div class=\"connection-heading\"><h4>{{ showAll ? '添加模型连接' : '已配置供应商' }}</h4><button v-if=\"section === 'connections'\" type=\"button\" :disabled=\"busy\" @click=\"showAll = !showAll\">{{ showAll ? '查看已配置' : '添加连接' }}</button></div>\n <input v-model=\"filter\" type=\"search\" placeholder=\"搜索供应商或别名\" aria-label=\"搜索供应商\" />\n <ul class=\"providers\">\n <li v-for=\"p in shown\" :key=\"p.id\">\n <div class=\"head\"><strong>{{ p.label }}</strong> <code>{{ p.id }}</code>\n <span :class=\"['badge', configured(p) ? 'ok' : '']\">{{ configured(p) ? '已配置' : '未配置' }}</span>\n </div>\n <button type=\"button\" class=\"link\" @click=\"openNetwork(p.id,p.label)\">{{ networkText(p.id) }}</button><template v-if=\"oauthFor(p.id)\">\n <p v-if=\"oauthFor(p.id)!.status.logged_in\">已登录 {{ oauthFor(p.id)!.status.token_preview ? '· …' + oauthFor(p.id)!.status.token_preview : '' }}\n <button v-if=\"oauthFor(p.id)!.disconnectable\" type=\"button\" :disabled=\"busy\" @click=\"logout(p.id)\">退出登录</button></p>\n <p v-else><button type=\"button\" :disabled=\"busy\" aria-haspopup=\"dialog\" @click=\"login(p.id)\">登录 {{ oauthFor(p.id)!.name }}</button></p>\n </template>\n <form v-if=\"keyVar(p)\" class=\"row\" @submit.prevent=\"saveKey(p)\">\n <input v-model=\"keyDraft[p.id]\" type=\"password\" autocomplete=\"new-password\" :placeholder=\"env[keyVar(p)!]?.is_set ? `${keyVar(p)} 已设置(${env[keyVar(p)!]?.redacted_value ?? '***'})` : keyVar(p)\" :aria-label=\"`${p.label} API Key`\" />\n <button type=\"submit\" :disabled=\"busy || !keyDraft[p.id]?.trim()\">保存</button>\n <button v-if=\"env[keyVar(p)!]?.is_set\" type=\"button\" :disabled=\"busy\" @click=\"removeKey(keyVar(p)!)\">移除</button>\n </form>\n <button type=\"button\" class=\"link\" @click=\"openPool(p.id)\">{{ poolOpen === p.id ? '收起凭据池' : '凭据池' }}</button>\n <div v-if=\"poolOpen === p.id\" class=\"pool\">\n <ol><li v-for=\"e in pool\" :key=\"e.id\">{{ e.label }} · {{ e.authType }} · {{ e.source }} {{ e.tokenPreview }} <em v-if=\"e.lastStatus\">{{ e.lastStatus }}</em>\n <button type=\"button\" :disabled=\"busy\" @click=\"removePool(e.index)\">删除</button></li></ol>\n <form class=\"row\" @submit.prevent=\"addPool\"><input v-model=\"poolKey\" type=\"password\" autocomplete=\"new-password\" placeholder=\"追加 API Key\" /><input v-model=\"poolLabel\" placeholder=\"标签(可选)\" /><button type=\"submit\" :disabled=\"busy || !poolKey.trim()\">加入</button></form>\n <label class=\"row\">轮换策略<select v-model=\"strategy\"><option value=\"fill_first\">fill_first</option><option value=\"round_robin\">round_robin</option><option value=\"least_used\">least_used</option><option value=\"random\">random</option></select>\n <button type=\"button\" :disabled=\"busy\" @click=\"saveStrategy\">保存</button></label>\n </div>\n </li>\n </ul>\n </div>\n\n <div v-if=\"mediaKeys.length\" class=\"block\"><h4>媒体专用凭据</h4><p class=\"hint\">这些密钥只供图片或视频使用。保存后,对应页面可以直接选用已授权的供应商。</p><ul class=\"providers\"><li v-for=\"field in mediaKeys\" :key=\"field.key\"><div class=\"head\"><strong>{{ field.prompt }}</strong> <code>{{ field.key }}</code><span :class=\"['badge', field.isSet ? 'ok' : '']\">{{ field.isSet ? '已配置' : '未配置' }}</span></div><p class=\"hint\">{{ field.uses.join('、') }}</p><form class=\"row\" @submit.prevent=\"saveMediaKey(field.key)\"><input v-model=\"mediaDraft[field.key]\" type=\"password\" autocomplete=\"new-password\" :placeholder=\"field.isSet ? `${field.key} 已设置,留空则不修改` : field.key\" :aria-label=\"field.prompt\" /><button type=\"submit\" :disabled=\"busy || !mediaDraft[field.key]?.trim()\">保存</button><button v-if=\"field.isSet\" type=\"button\" :disabled=\"busy\" @click=\"removeKey(field.key)\">移除</button></form></li></ul></div>\n <p v-if=\"!shown.length && !customConnections.length && !mediaKeys.length\" class=\"hint\">暂无匹配的连接。可添加供应商或自定义服务。</p>\n <details class=\"endpoint-section\"><summary>添加自定义模型服务</summary><form class=\"block\" @submit.prevent=\"saveEndpoint\">\n <h4>自定义 OpenAI 兼容服务</h4>\n <label>服务名称<input v-model=\"endpoint.name\" placeholder=\"名称\" /></label>\n <label>服务地址<input v-model=\"endpoint.base_url\" type=\"url\" placeholder=\"https://host/v1\" /></label>\n <label>默认模型<input v-model=\"endpoint.model\" placeholder=\"默认模型\" /></label>\n <label>API Key(可选)<input v-model=\"endpoint.api_key\" type=\"password\" autocomplete=\"new-password\" placeholder=\"API Key\" /></label>\n <label>接口协议<select v-model=\"endpoint.api_mode\"><option value=\"\">自动识别</option><option value=\"chat_completions\">chat_completions</option><option value=\"codex_responses\">codex_responses</option><option value=\"anthropic_messages\">anthropic_messages</option></select></label>\n <button type=\"submit\" :disabled=\"busy || !endpoint.name.trim() || !endpoint.base_url.trim()\">保存端点</button>\n </form></details>\n </template>\n </template>\n </section>\n</template>\n<style scoped>\n.hermes-providers{display:grid;gap:16px;max-width:760px}.note,.hint{color:var(--text-secondary);margin:0;line-height:1.6}.error{color:var(--danger,#c33)}\n.block{display:grid;gap:16px;border:0;border-top:1px solid var(--line);padding:20px 0}.block h4{margin:0}\n.row{display:flex;gap:8px;flex-wrap:wrap;align-items:center}.providers{list-style:none;margin:0;padding:0;display:grid;gap:16px}\n.providers>li{border-top:1px solid var(--line);padding-top:8px;display:grid;gap:6px}.head{display:flex;gap:8px;align-items:baseline;flex-wrap:wrap}.badge{font-size:12px;padding:1px 6px;border-radius:6px;border:1px solid var(--line)}.badge.ok{border-color:var(--accent)}\ninput,select,textarea,button{min-height:44px;padding:6px 10px;border:1px solid var(--line);border-radius:8px;background:var(--surface);color:var(--text-primary);font:inherit}button{cursor:pointer}button:disabled{opacity:.5;cursor:default}.link{border:0;background:none;padding:0;min-height:0;color:var(--accent);justify-self:start}\n.hermes-providers{max-width:none;font-size:14px}.defaults-form{display:grid;gap:0;min-width:0}.defaults-heading{margin-bottom:16px}.defaults-form h4{margin:0;font-size:18px;font-weight:650}.defaults-form p{margin:12px 0 0;font-size:14px;line-height:1.6;color:var(--text-secondary)}.setting-row{display:grid;grid-template-columns:minmax(0,1fr) minmax(200px,56%);align-items:center;gap:24px;padding:16px 0;border-bottom:1px solid var(--line)}.setting-row>span{display:grid;gap:7px}.setting-row strong{font-size:15px;font-weight:600}.setting-row small{font-size:13px;line-height:1.5;color:var(--text-secondary)}.setting-row input,.setting-row select{width:100%;box-sizing:border-box;padding:10px 12px}.defaults-status{display:flex;align-items:center;justify-content:space-between;gap:12px;margin:8px 0 8px 44%;font-size:13px;line-height:1.5;color:var(--text-secondary)}.defaults-status .configured{color:var(--success)}.defaults-status .configured:before{content:'';display:inline-block;width:9px;height:9px;border-radius:50%;background:currentColor;margin-right:8px}.defaults-status .refresh-models{min-height:44px;flex-shrink:0;padding:6px 8px;border:0;background:transparent;font-size:13px;display:inline-flex;align-items:center;gap:8px}.fallback-section{border-top:1px solid var(--line);padding-top:28px}.fallback-section details{margin-top:16px}.fallback-section summary{display:grid;grid-template-columns:minmax(0,1fr) minmax(200px,56%);align-items:center;gap:24px;min-height:48px;cursor:pointer;list-style:none}.fallback-section summary>.app-icon{position:absolute;right:14px;transform:rotate(180deg);color:var(--text-secondary)}.fallback-section summary{position:relative}.fallback-section summary>span:nth-child(2){display:block;border:1px solid var(--line);border-radius:8px;padding:12px 34px 12px 12px;color:var(--text-secondary)}.fallback-section label{display:grid;gap:10px;margin-top:18px}.fallback-section textarea{box-sizing:border-box;width:100%;resize:vertical}.fallback-section small{display:block;margin-top:10px;color:var(--text-secondary);line-height:1.6}.fallback-section details[open] summary>.app-icon{transform:rotate(-90deg)}.connection-heading{display:flex;align-items:center;justify-content:space-between;gap:16px}.endpoint-section summary{min-height:44px;line-height:44px;cursor:pointer}.endpoint-section label{display:grid;gap:8px}.hermes-providers :focus-visible{outline:2px solid var(--accent);outline-offset:2px}.hermes-providers input,.hermes-providers select,.hermes-providers textarea{min-width:0;max-width:100%;box-sizing:border-box}@media(max-width:600px){.setting-row,.fallback-section summary{grid-template-columns:1fr;gap:10px}.defaults-status{margin-left:0;flex-wrap:wrap}.fallback-section summary>.app-icon{bottom:14px}.head{align-items:center}.row input{flex:1;min-width:140px}.defaults-form h4{font-size:17px}}\n</style>\n","/** Hermes auxiliary model slots (config.yaml `auxiliary.<task>`), same set as the Hermes dashboard. */\nexport const HERMES_AUXILIARY_TASKS = [\n 'vision', 'compression', 'skills_hub', 'approval', 'mcp', 'title_generation', 'review', 'voice_chat',\n 'triage_specifier', 'kanban_decomposer', 'profile_describer', 'curator', 'memory_query_rewrite',\n] as const\nexport type HermesAuxiliaryTask = (typeof HERMES_AUXILIARY_TASKS)[number]\n\nexport const HERMES_AUXILIARY_LABELS: Record<HermesAuxiliaryTask, string> = {\n vision: '看图', compression: '上下文压缩', skills_hub: '技能中心', approval: '智能审批', mcp: 'MCP',\n title_generation: '会话标题', review: '后台复盘', voice_chat: '语音对话', triage_specifier: '任务分诊',\n kanban_decomposer: '看板拆解', profile_describer: '简介生成', curator: '技能整理', memory_query_rewrite: '记忆检索改写',\n}\n\n/** One slot override. `provider: \"auto\"` (or omitted) follows the main model, as in Hermes. */\nexport interface HermesAuxiliaryRoute {\n provider?: string\n model?: string\n base_url?: string\n reasoning_effort?: string | null\n}\nexport type HermesAuxiliaryOverrides = Partial<Record<HermesAuxiliaryTask, HermesAuxiliaryRoute | null>>\n/** Hermes `fallback_model` chain: tried in order when the main provider fails. */\nexport type HermesFallbackChain = Array<{ provider: string; model: string; base_url?: string }>\n","<script setup lang=\"ts\">\nimport { ref, watch, onBeforeUnmount } from \"vue\";\nimport { apiRequest } from \"@/api/client\";\nimport { createUuid } from \"@/utils/id\";\nconst props = defineProps<{\n agentId: string;\n scope: string;\n projectId?: string;\n}>();\nconst emit = defineEmits<{ \"dirty-change\": [dirty: boolean]; changed: [] }>();\nconst base = \"/api/app/workspace\";\ntype Doc = { path: string; content: string; hash: string };\ntype Revision = {\n id: string;\n path: string;\n before: string;\n after: string;\n afterHash: string;\n at: number;\n};\nconst files = ref<{ path: string; bytes: number }[]>([]),\n doc = ref<Doc>(),\n draft = ref(\"\"),\n newPath = ref(\"memory/notes.md\"),\n error = ref(\"\"),\n notice = ref(\"\"),\n busy = ref(false),\n history = ref<Revision[]>([]);\nlet generation = 0;\nconst scope = () => ({\n scope: props.scope,\n agentId: props.agentId,\n ...(props.scope === \"project\" ? { projectId: props.projectId } : {}),\n});\nconst query = (extra: Record<string, string> = {}) =>\n new URLSearchParams({ ...scope(), ...extra } as Record<string, string>);\nasync function action(fn: () => Promise<void>) {\n if (busy.value) return;\n busy.value = true;\n error.value = \"\";\n notice.value = \"\";\n try {\n await fn();\n } catch (e) {\n error.value = e instanceof Error ? e.message : \"操作失败\";\n } finally {\n busy.value = false;\n }\n}\nasync function load() {\n const epoch = ++generation;\n if (!props.agentId || (props.scope === \"project\" && !props.projectId)) {\n files.value = [];\n return;\n }\n try {\n const result = await apiRequest<{\n files: { path: string; bytes: number }[];\n }>(`${base}/memory-files?${query()}`);\n if (epoch === generation) files.value = result.files;\n } catch (e) {\n if (epoch === generation) error.value = String(e);\n }\n}\nasync function open(path: string) {\n await action(async () => {\n const epoch = generation;\n const result = await apiRequest<Doc>(\n `${base}/memory-file?${query({ path })}`,\n );\n if (epoch !== generation) return;\n doc.value = result;\n draft.value = result.content;\n history.value = [];\n });\n}\nasync function save() {\n if (!doc.value) return;\n await action(async () => {\n doc.value = await apiRequest<Doc>(base + \"/memory-file\", {\n method: \"PUT\",\n body: {\n ...scope(),\n requestId: createUuid(),\n path: doc.value!.path,\n content: draft.value,\n expectedHash: doc.value!.hash,\n },\n });\n draft.value = doc.value.content;\n notice.value = \"文件已保存,下一轮对话生效。\";\n emit(\"changed\");\n await load();\n });\n}\nasync function revisions() {\n await action(async () => {\n history.value = (\n await apiRequest<{ revisions: Revision[] }>(\n `${base}/memory-file-history?${query()}`,\n )\n ).revisions.filter((r) => r.path === doc.value?.path);\n });\n}\nasync function revert(r: Revision) {\n await action(async () => {\n doc.value = await apiRequest<Doc>(base + \"/memory-file-revert\", {\n method: \"POST\",\n body: {\n ...scope(),\n requestId: createUuid(),\n id: r.id,\n expectedHash: doc.value!.hash,\n },\n });\n draft.value = doc.value.content;\n notice.value = \"已撤销该次修改。\";\n await load();\n emit(\"changed\");\n });\n}\nwatch(\n () => [props.scope, props.agentId, props.projectId],\n () => {\n doc.value = undefined;\n draft.value = \"\";\n history.value = [];\n void load();\n },\n { immediate: true },\n);\nwatch(\n () => !!doc.value && draft.value !== doc.value.content,\n (v) => emit(\"dirty-change\", v),\n);\nonBeforeUnmount(() => {\n generation++;\n});\n</script>\n<template>\n <section class=\"memory-files\" aria-label=\"Markdown 记忆文件\">\n <h3>记忆文件</h3>\n <p>MEMORY.md 自动加载;主题和日记按需读取。可以直接编辑 Markdown。</p>\n <p v-if=\"error\" role=\"alert\">{{ error }}</p>\n <p v-if=\"notice\" role=\"status\">{{ notice }}</p>\n <template v-if=\"!doc\"\n ><div class=\"file-list\">\n <button\n v-for=\"file in files\"\n :key=\"file.path\"\n :disabled=\"busy\"\n @click=\"open(file.path)\"\n >\n {{ file.path }} · {{ file.bytes }} B\n </button>\n </div>\n <form @submit.prevent=\"open(newPath)\">\n <label\n >新文件路径<input\n v-model=\"newPath\"\n placeholder=\"memory/主题.md\"\n :disabled=\"busy\" /></label\n ><button :disabled=\"busy || !agentId\">创建或打开</button>\n </form></template\n >\n <template v-else\n ><label\n >{{ doc.path\n }}<textarea\n v-model=\"draft\"\n :disabled=\"busy\"\n rows=\"16\"\n spellcheck=\"false\"\n aria-label=\"记忆 Markdown 内容\"\n />\n </label>\n <div class=\"actions\">\n <button :disabled=\"busy || draft === doc.content\" @click=\"save\">\n 保存</button\n ><button\n :disabled=\"busy\"\n @click=\"\n doc = undefined;\n history = [];\n \"\n >\n 取消编辑</button\n ><button :disabled=\"busy\" @click=\"revisions\">修改历史</button>\n </div>\n <details v-for=\"revision in history\" :key=\"revision.id\">\n <summary>{{ new Date(revision.at).toLocaleString() }}</summary>\n <p>修改前</p>\n <pre>{{ revision.before }}</pre>\n <p>修改后</p>\n <pre>{{ revision.after }}</pre>\n <button\n :disabled=\"\n busy || revision.afterHash !== doc.hash || draft !== doc.content\n \"\n @click=\"revert(revision)\"\n >\n 撤销此修改\n </button>\n </details></template\n >\n </section>\n</template>\n<style scoped>\n.memory-files {\n display: grid;\n gap: 12px;\n margin-block: 20px;\n}\n.memory-files h3,\n.memory-files p {\n margin: 0;\n line-height: 1.6;\n}\n.memory-files p {\n color: var(--text-secondary);\n}\n.memory-files label {\n display: grid;\n gap: 8px;\n}\n.memory-files input,\n.memory-files textarea,\n.memory-files button {\n font: inherit;\n padding: 10px;\n border: 1px solid var(--line);\n border-radius: 8px;\n color: var(--text-primary);\n background: var(--surface);\n min-height: 44px;\n box-sizing: border-box;\n max-width: 100%;\n}\n.memory-files textarea {\n width: 100%;\n resize: vertical;\n font-family: monospace;\n}\n.file-list,\n.actions,\n.memory-files form {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n}\n.memory-files pre {\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n}\n.memory-files [role=\"alert\"] {\n color: var(--color-error, #d44);\n}\n</style>\n","<script setup lang=\"ts\">\nimport { ref, watch, onBeforeUnmount } from \"vue\";\nimport { apiRequest } from \"@/api/client\";\nimport { createUuid } from \"@/utils/id\";\nconst props = defineProps<{\n agentId: string;\n scope: string;\n projectId?: string;\n}>();\nconst emit = defineEmits<{ \"dirty-change\": [dirty: boolean]; changed: [] }>();\nconst base = \"/api/app/workspace\";\ntype Doc = { path: string; content: string; hash: string };\ntype Revision = {\n id: string;\n path: string;\n before: string;\n after: string;\n afterHash: string;\n at: number;\n};\nconst files = ref<{ path: string; bytes: number }[]>([]),\n doc = ref<Doc>(),\n draft = ref(\"\"),\n newPath = ref(\"memory/notes.md\"),\n error = ref(\"\"),\n notice = ref(\"\"),\n busy = ref(false),\n history = ref<Revision[]>([]);\nlet generation = 0;\nconst scope = () => ({\n scope: props.scope,\n agentId: props.agentId,\n ...(props.scope === \"project\" ? { projectId: props.projectId } : {}),\n});\nconst query = (extra: Record<string, string> = {}) =>\n new URLSearchParams({ ...scope(), ...extra } as Record<string, string>);\nasync function action(fn: () => Promise<void>) {\n if (busy.value) return;\n busy.value = true;\n error.value = \"\";\n notice.value = \"\";\n try {\n await fn();\n } catch (e) {\n error.value = e instanceof Error ? e.message : \"操作失败\";\n } finally {\n busy.value = false;\n }\n}\nasync function load() {\n const epoch = ++generation;\n if (!props.agentId || (props.scope === \"project\" && !props.projectId)) {\n files.value = [];\n return;\n }\n try {\n const result = await apiRequest<{\n files: { path: string; bytes: number }[];\n }>(`${base}/memory-files?${query()}`);\n if (epoch === generation) files.value = result.files;\n } catch (e) {\n if (epoch === generation) error.value = String(e);\n }\n}\nasync function open(path: string) {\n await action(async () => {\n const epoch = generation;\n const result = await apiRequest<Doc>(\n `${base}/memory-file?${query({ path })}`,\n );\n if (epoch !== generation) return;\n doc.value = result;\n draft.value = result.content;\n history.value = [];\n });\n}\nasync function save() {\n if (!doc.value) return;\n await action(async () => {\n doc.value = await apiRequest<Doc>(base + \"/memory-file\", {\n method: \"PUT\",\n body: {\n ...scope(),\n requestId: createUuid(),\n path: doc.value!.path,\n content: draft.value,\n expectedHash: doc.value!.hash,\n },\n });\n draft.value = doc.value.content;\n notice.value = \"文件已保存,下一轮对话生效。\";\n emit(\"changed\");\n await load();\n });\n}\nasync function revisions() {\n await action(async () => {\n history.value = (\n await apiRequest<{ revisions: Revision[] }>(\n `${base}/memory-file-history?${query()}`,\n )\n ).revisions.filter((r) => r.path === doc.value?.path);\n });\n}\nasync function revert(r: Revision) {\n await action(async () => {\n doc.value = await apiRequest<Doc>(base + \"/memory-file-revert\", {\n method: \"POST\",\n body: {\n ...scope(),\n requestId: createUuid(),\n id: r.id,\n expectedHash: doc.value!.hash,\n },\n });\n draft.value = doc.value.content;\n notice.value = \"已撤销该次修改。\";\n await load();\n emit(\"changed\");\n });\n}\nwatch(\n () => [props.scope, props.agentId, props.projectId],\n () => {\n doc.value = undefined;\n draft.value = \"\";\n history.value = [];\n void load();\n },\n { immediate: true },\n);\nwatch(\n () => !!doc.value && draft.value !== doc.value.content,\n (v) => emit(\"dirty-change\", v),\n);\nonBeforeUnmount(() => {\n generation++;\n});\n</script>\n<template>\n <section class=\"memory-files\" aria-label=\"Markdown 记忆文件\">\n <h3>记忆文件</h3>\n <p>MEMORY.md 自动加载;主题和日记按需读取。可以直接编辑 Markdown。</p>\n <p v-if=\"error\" role=\"alert\">{{ error }}</p>\n <p v-if=\"notice\" role=\"status\">{{ notice }}</p>\n <template v-if=\"!doc\"\n ><div class=\"file-list\">\n <button\n v-for=\"file in files\"\n :key=\"file.path\"\n :disabled=\"busy\"\n @click=\"open(file.path)\"\n >\n {{ file.path }} · {{ file.bytes }} B\n </button>\n </div>\n <form @submit.prevent=\"open(newPath)\">\n <label\n >新文件路径<input\n v-model=\"newPath\"\n placeholder=\"memory/主题.md\"\n :disabled=\"busy\" /></label\n ><button :disabled=\"busy || !agentId\">创建或打开</button>\n </form></template\n >\n <template v-else\n ><label\n >{{ doc.path\n }}<textarea\n v-model=\"draft\"\n :disabled=\"busy\"\n rows=\"16\"\n spellcheck=\"false\"\n aria-label=\"记忆 Markdown 内容\"\n />\n </label>\n <div class=\"actions\">\n <button :disabled=\"busy || draft === doc.content\" @click=\"save\">\n 保存</button\n ><button\n :disabled=\"busy\"\n @click=\"\n doc = undefined;\n history = [];\n \"\n >\n 取消编辑</button\n ><button :disabled=\"busy\" @click=\"revisions\">修改历史</button>\n </div>\n <details v-for=\"revision in history\" :key=\"revision.id\">\n <summary>{{ new Date(revision.at).toLocaleString() }}</summary>\n <p>修改前</p>\n <pre>{{ revision.before }}</pre>\n <p>修改后</p>\n <pre>{{ revision.after }}</pre>\n <button\n :disabled=\"\n busy || revision.afterHash !== doc.hash || draft !== doc.content\n \"\n @click=\"revert(revision)\"\n >\n 撤销此修改\n </button>\n </details></template\n >\n </section>\n</template>\n<style scoped>\n.memory-files {\n display: grid;\n gap: 12px;\n margin-block: 20px;\n}\n.memory-files h3,\n.memory-files p {\n margin: 0;\n line-height: 1.6;\n}\n.memory-files p {\n color: var(--text-secondary);\n}\n.memory-files label {\n display: grid;\n gap: 8px;\n}\n.memory-files input,\n.memory-files textarea,\n.memory-files button {\n font: inherit;\n padding: 10px;\n border: 1px solid var(--line);\n border-radius: 8px;\n color: var(--text-primary);\n background: var(--surface);\n min-height: 44px;\n box-sizing: border-box;\n max-width: 100%;\n}\n.memory-files textarea {\n width: 100%;\n resize: vertical;\n font-family: monospace;\n}\n.file-list,\n.actions,\n.memory-files form {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n}\n.memory-files pre {\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n}\n.memory-files [role=\"alert\"] {\n color: var(--color-error, #d44);\n}\n</style>\n","/** Execution acknowledgement and a real return delivery are distinct facts. */\nexport function communicationStatus(value: { status?: string; hasReply?: boolean; replyTo?: string }): string {\n if (value.status === 'failed') return '投递或执行失败'\n if (value.status === 'stopped') return '协作已停止'\n if (value.hasReply) return '已收到回复'\n if (value.replyTo) return '回复已投递'\n return ({ queued: '已投递 · 排队中', running: '正在处理', waiting: '等待补充信息', complete: '执行已结束 · 暂无回复' } as Record<string, string>)[value.status ?? ''] ?? '协作消息'\n}\nexport function goalStatus(status: string): string {\n return ({ queued: '排队中', pending: '待执行', failed: '执行失败', interrupted: '已中断', running: '进行中', review: '待复核', waiting: '需要补充信息', blocked: '遇到阻碍', complete: '已完成', cancelling: '正在停止', cancelled: '已停止' } as Record<string, string>)[status] ?? '状态待确认'\n}\nexport const activityLabels = { bot_created: '创建了 Bot', helper_created: '创建了临时助手', team_created: '组建了团队', assignment_created: '派发了任务' } as const\n/** Host-authored caption for a real Bot-to-Bot delivery. Outgoing rows are a\n * caption only (plus attachments); incoming rows keep the delivered body. */\nexport function communicationCaption(direction: 'outgoing' | 'incoming'): string {\n return direction === 'outgoing' ? '已发消息给' : '消息来自'\n}\nexport function communicationShowsBody(direction: 'outgoing' | 'incoming'): boolean {\n return direction === 'incoming'\n}\n","import { activityLabels, communicationStatus, goalStatus } from './collaborationPresentation.js'\n\nexport interface CollaborationPeer {\n id: string; fromAgentId: string; toAgentId?: string; targetGroupId?: string;\n fromName?: string; targetName?: string; content: string; status: string;\n hasReply?: boolean; replyTo?: string; error?: string; createdAt?: number;\n}\ninterface Assignment {\n id: string; agentId: string; title: string; brief?: string; status: string;\n result?: string | null; review?: string | null; createdAt?: number; updatedAt?: number;\n}\ninterface ActivityMessage {\n id: string; createdAt: number;\n activity?: { kind: keyof typeof activityLabels; actorName: string; targetName: string; description: string } | null;\n}\nexport interface CollaborationEvent {\n id: string; title: string; status: string; content: string; at: number;\n error?: string; peer?: CollaborationPeer;\n}\n/** Read projection only: assignment IDs own their events; retries never execute work. */\nexport function collaborationTimeline(input: {\n peers: CollaborationPeer[]; assignments: Assignment[]; activities?: ActivityMessage[];\n coordinatorId?: string; name: (id?: string) => string;\n}): CollaborationEvent[] {\n const events: CollaborationEvent[] = [];\n const leader = input.coordinatorId ? input.name(input.coordinatorId) : '负责人';\n for (const message of input.activities ?? []) {\n const a = message.activity;\n // Canonical assignments below cover dispatch, result and review without text matching.\n if (!a || (a.kind === 'assignment_created' && input.assignments.length)) continue;\n events.push({ id: `activity:${message.id}`, title: `${a.actorName} ${activityLabels[a.kind]} ${a.targetName}`, status: '已记录', content: a.description, at: message.createdAt });\n }\n for (const a of input.assignments) {\n const member = input.name(a.agentId);\n events.push({ id: `assignment:${a.id}:created`, title: `${leader} → ${member} · 派发任务`, status: goalStatus(a.status), content: [a.title, a.brief].filter(Boolean).join('\\n'), at: a.createdAt ?? 0 });\n if (a.result) events.push({ id: `assignment:${a.id}:result`, title: `${member} → ${leader} · 回传结果`, status: '已回传', content: `${a.title}\\n${a.result}`, at: a.updatedAt ?? a.createdAt ?? 0 });\n if (a.review) events.push({ id: `assignment:${a.id}:review`, title: `${leader} → ${member} · 复核意见`, status: goalStatus(a.status), content: a.review, at: a.updatedAt ?? a.createdAt ?? 0 });\n }\n for (const p of input.peers) events.push({\n id: `peer:${p.id}`, title: `${p.fromName || input.name(p.fromAgentId)} → ${p.targetName || (p.toAgentId ? input.name(p.toAgentId) : '群聊')}`,\n status: communicationStatus(p), content: p.content, at: p.createdAt ?? 0, error: p.error, peer: p,\n });\n return [...new Map(events.map(event => [event.id, event])).values()].sort((a, b) => a.at - b.at);\n}\n","<script setup lang=\"ts\">\nimport { computed, nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue'\nimport MemoryFilesPanel from './MemoryFilesPanel.vue'\nimport type { AgentAssignment, AgentGoal } from '@shared/agentTasks'\nimport { collaborationTimeline } from '@shared/collaborationTimeline'\nimport { apiRequest } from '@/api/client'\nimport { createUuid } from '@/utils/id'\nimport AppIcon from '@/components/common/AppIcon.vue'\nimport AgentAvatar from '@/components/common/AgentAvatar.vue'\nimport { ChevronForwardOutline } from '@vicons/ionicons5'\nimport type { WorkspaceAgent, WorkspaceConversation, WorkspaceMessage } from '@shared/workspace'\nimport type { MemoryScope, MemorySkipReason, WorkspaceMemory, WorkspaceMemoryJob, WorkspaceMemoryRevision, WorkspacePeerMessage, WorkspaceProject } from '@shared/workspaceKnowledge'\n\nconst props = defineProps<{ agents: WorkspaceAgent[]; conversations: WorkspaceConversation[]; conversationId?: string; taskId?: string; assignments?: AgentAssignment[]; goal?: AgentGoal; revision?: number; embedded?: boolean; initialTab?: 'projects' | 'user' | 'agent'; selectedAgentId?: string; hideAgentControls?: boolean }>()\nconst emit = defineEmits<{ changed: []; 'dirty-change': [dirty: boolean] }>()\nconst dialog = ref<HTMLDialogElement>(), opened = ref(false), busy = ref(false), error = ref(''), tab = ref('agent'), agentId = ref(''), projectId = ref(''), search = ref('')\nconst projects = ref<WorkspaceProject[]>([]), memories = ref<WorkspaceMemory[]>([]), peers = ref<WorkspacePeerMessage[]>([]), jobs = ref<WorkspaceMemoryJob[]>([]), revisions = ref<WorkspaceMemoryRevision[]>([])\nconst draft = ref<{ id?: string; expectedRevision?: number; agentId: string; content: string; tier: WorkspaceMemory['tier'] }>()\nconst projectDraft = ref<WorkspaceProject>()\nconst memoryTotal=ref(0), nextMemoryOffset=ref<number>(), loadedMore=ref(false)\nconst fileDirty=ref(false)\nconst activities = ref<WorkspaceMessage[]>([])\nlet generation = 0, timer: ReturnType<typeof setInterval> | undefined\nconst available = computed(() => props.agents.filter(a => !a.archived && !a.temporaryGoalId))\nconst currentAgent = computed(() => props.agents.find(a => a.id === agentId.value))\nconst currentProject = computed(() => projects.value.find(p => p.id === projectId.value))\nconst scope = computed(() => (['agent', 'user', 'project'].includes(tab.value) ? tab.value : 'agent') as MemoryScope)\nconst name = (id?: string) => props.agents.find(a => a.id === id)?.name ?? '原贡献者'\nconst collaboration = computed(() => collaborationTimeline({ peers: peers.value, activities: activities.value, assignments: props.assignments ?? [], coordinatorId: props.goal?.coordinatorId, name }))\nconst query = () => new URLSearchParams({ scope: scope.value, ...(tab.value === 'agent' && agentId.value ? { agentId: agentId.value } : {}), ...(tab.value === 'project' && projectId.value ? { projectId: projectId.value } : {}), ...(search.value ? { search: search.value } : {}) }).toString()\nconst stateNames: Record<string, string> = { queued: '已排队', pending: '待提炼', running: '处理中', waiting: '等待同伴', complete: '已完成', failed: '失败', stopped: '已停止', skipped: '已跳过' }\nconst skipReasonNames: Record<MemorySkipReason, string> = {\n source_missing: '找不到对应的来源消息', quote_mismatch: '引用与原文不一致', sensitive_content: '包含凭据等敏感内容',\n project_unbound: '项目记忆缺少关联项目', user_not_explicit: '缺少用户明确表达的长期信息', forgotten: '已遗忘的内容或来源不再保存', stale: '推理期间记忆已更新,本次旧提炼结果未应用',\n}\nfunction jobSummary(job: WorkspaceMemoryJob): string {\n if (job.status !== 'complete') return stateNames[job.status] ?? job.status\n const result = job.result\n if (!result) return '已结束(旧记录未统计保存结果)'\n if (!result.extractedCount) return '本轮没有可记录内容'\n if (result.writtenCount) return `已保存 ${result.writtenCount} 条记忆`\n if (result.replayedCount) return `重试已确认 ${result.replayedCount} 条记录`\n if (result.duplicateCount) return '未新增记忆,已有相同内容'\n return '候选记忆均未保存'\n}\nfunction skippedReasons(job: WorkspaceMemoryJob): string[] {\n return Object.entries(job.result?.skippedReasons ?? {}).filter(([, count]) => count > 0)\n .map(([reason, count]) => `${skipReasonNames[reason as MemorySkipReason] ?? '其他原因'}:${count} 条`)\n}\nasync function load(silent = false) {\n if (silent && loadedMore.value && tab.value !== 'collaboration') return\n const epoch = ++generation\n if (!silent) error.value = ''\n try {\n const projectResult = await apiRequest<{ projects: WorkspaceProject[] }>('/api/app/workspace/projects')\n if (epoch !== generation || !opened.value) return\n projects.value = projectResult.projects\n if (!projectId.value) projectId.value = projects.value.find(p => !p.archived)?.id ?? ''\n if (tab.value === 'collaboration') {\n const [result, milestones] = await Promise.all([\n apiRequest<{ messages: WorkspacePeerMessage[] }>(`/api/app/workspace/collaboration?${new URLSearchParams({ ...(props.conversationId ? { conversationId: props.conversationId } : {}), ...(props.taskId ? { taskId: props.taskId } : {}) })}`),\n props.conversationId ? apiRequest<{ messages: WorkspaceMessage[] }>(`/api/app/conversations/${encodeURIComponent(props.conversationId)}/activities${props.taskId ? `?taskId=${encodeURIComponent(props.taskId)}` : ''}`) : Promise.resolve({ messages: [] }),\n ])\n if (epoch === generation) { peers.value = result.messages; activities.value = milestones.messages }\n } else if (tab.value !== 'projects' && (tab.value !== 'project' || projectId.value)) {\n const result = await apiRequest<{ memories: WorkspaceMemory[]; total?: number; nextOffset?: number }>(`/api/app/workspace/memories?${query()}`)\n if (epoch === generation) { memories.value = result.memories; memoryTotal.value = result.total ?? result.memories.length; nextMemoryOffset.value = result.nextOffset; loadedMore.value = false }\n } else { memories.value = []; memoryTotal.value = 0; nextMemoryOffset.value = undefined; loadedMore.value = false }\n if (agentId.value) {\n const result = await apiRequest<{ jobs: WorkspaceMemoryJob[] }>(`/api/app/workspace/memory-jobs?agentId=${agentId.value}`)\n if (epoch === generation) jobs.value = result.jobs\n }\n } catch (cause) { if (epoch === generation) error.value = String(cause) }\n}\nasync function loadMoreMemories() {\n if (busy.value || nextMemoryOffset.value === undefined) return\n const epoch = generation, filter = query(), offset = nextMemoryOffset.value\n busy.value = true; error.value = ''\n try {\n const result = await apiRequest<{ memories: WorkspaceMemory[]; total: number; nextOffset?: number }>(`/api/app/workspace/memories?${filter}&offset=${offset}&limit=100`)\n if (epoch !== generation || !opened.value || filter !== query()) return\n const existing = new Set(memories.value.map(m => `${m.scope}:${m.agentId}:${m.id}`))\n memories.value.push(...result.memories.filter(m => !existing.has(`${m.scope}:${m.agentId}:${m.id}`)))\n memoryTotal.value = result.total; nextMemoryOffset.value = result.nextOffset; loadedMore.value = true\n } catch (cause) { if (epoch === generation) error.value = String(cause) } finally { busy.value = false }\n}\nasync function open(initial = 'agent', selectedAgent?: string, selectedProject?: string) {\n tab.value = initial; agentId.value = selectedAgent ?? available.value[0]?.id ?? ''; projectId.value = selectedProject ?? ''\n opened.value = true; draft.value = undefined; projectDraft.value = undefined; revisions.value = []; search.value = ''\n await nextTick(); if (!props.embedded) dialog.value?.showModal(); await load()\n clearInterval(timer); timer = setInterval(() => { if (!busy.value && !draft.value && !projectDraft.value) void load(true) }, 5000)\n}\nfunction close() { if(fileDirty.value){error.value='请先保存文件或取消编辑。';return} opened.value = false; generation++; clearInterval(timer); if (!props.embedded) dialog.value?.close() }\nfunction switchTab(value: string) { if(fileDirty.value)return; tab.value = value; draft.value = undefined; projectDraft.value = undefined; revisions.value = []; void load() }\nasync function perform(action: () => Promise<void>) {\n if (busy.value) return\n busy.value = true; error.value = ''\n try { await action(); emit('changed'); await load() } catch (cause) { error.value = String(cause) } finally { busy.value = false }\n}\nfunction newMemory(memory?: WorkspaceMemory) {\n revisions.value = []\n draft.value = memory ? { id: memory.id, expectedRevision: memory.revision, agentId: memory.agentId, content: memory.content, tier: memory.tier } : { agentId: agentId.value || available.value[0]?.id || '', content: '', tier: 'log' }\n}\nasync function saveMemory() {\n const value = draft.value\n if (!value?.content.trim()) { error.value = '请输入需要记住的事实'; return }\n await perform(async () => {\n await apiRequest('/api/app/workspace/memories', { method: 'POST', body: { requestId: createUuid(), scope: scope.value, ...(scope.value === 'project' ? { projectId: projectId.value } : {}), ...value } })\n draft.value = undefined\n })\n}\nasync function forget(memory: WorkspaceMemory) {\n await perform(async () => { await apiRequest('/api/app/workspace/memories/forget', { method: 'POST', body: { requestId: createUuid(), scope: memory.scope, agentId: memory.agentId, ...(memory.projectId ? { projectId: memory.projectId } : {}), id: memory.id, expectedRevision: memory.revision } }) })\n}\nasync function history(memory: WorkspaceMemory) {\n const query = new URLSearchParams({ scope: memory.scope, agentId: memory.agentId, ...(memory.projectId ? { projectId: memory.projectId } : {}) })\n await perform(async () => { revisions.value = (await apiRequest<{ revisions: WorkspaceMemoryRevision[] }>(`/api/app/workspace/memories/${memory.id}/revisions?${query}`)).revisions })\n}\nfunction editProject(project?: WorkspaceProject) {\n projectDraft.value = project ? { ...project, memberIds: [...project.memberIds], groupIds: [...project.groupIds] } : { id: '', name: '', description: '', memberIds: [], groupIds: [], revision: 0, archived: false, createdAt: 0, updatedAt: 0 }\n}\nasync function saveProject() {\n const value = projectDraft.value\n if (!value?.name.trim()) { error.value = '请输入项目名称'; return }\n await perform(async () => {\n const result = await apiRequest<{ project: WorkspaceProject }>('/api/app/workspace/projects', { method: 'POST', body: { requestId: createUuid(), ...(value.id ? { id: value.id, expectedRevision: value.revision } : {}), name: value.name, description: value.description, memberIds: value.memberIds, groupIds: value.groupIds, archived: value.archived } })\n projectId.value = result.project.id; projectDraft.value = undefined\n })\n}\nasync function setAgent(field: 'canCollaborate' | 'memoryEnabled', enabled: boolean) {\n await perform(async () => { await apiRequest(`/api/app/agents/${agentId.value}`, { method: 'PATCH', body: { [field]: enabled } }) })\n}\nonBeforeUnmount(() => { generation++; clearInterval(timer) })\nonMounted(() => { if (props.embedded) void open(props.initialTab ?? 'projects', props.selectedAgentId) })\nwatch(() => props.initialTab, value => { if (props.embedded && value) switchTab(value) })\nwatch(() => props.revision, () => { if (opened.value && !busy.value && !draft.value && !projectDraft.value) void load(true) })\nwatch(() => [props.conversationId, props.taskId], () => { generation++; peers.value = []; activities.value = []; if (opened.value && tab.value === 'collaboration') void load() })\nwatch(() => fileDirty.value || !!draft.value || !!projectDraft.value, value => emit('dirty-change', value))\ndefineExpose({ open, close })\n</script>\n\n<template>\n <component :is=\"embedded ? 'section' : 'dialog'\" ref=\"dialog\" class=\"knowledge-dialog\" :class=\"{ 'knowledge-dialog--embedded': embedded }\" :aria-labelledby=\"embedded ? undefined : 'knowledge-title'\" @cancel.prevent=\"close\" @close=\"opened = false\">\n <header v-if=\"!embedded\"><div><h2 id=\"knowledge-title\">Bot 记忆与协作</h2><p>管理长期事实、项目和同伴请求</p></div><button type=\"button\" @click=\"close\" aria-label=\"关闭记忆与协作\">关闭</button></header>\n <nav v-if=\"!embedded\" aria-label=\"记忆与项目分类\"><button v-for=\"item in [['agent','Bot 记忆'],['user','用户记忆'],['projects','项目'],['project','项目记忆'],['collaboration','协作']]\" :key=\"item[0]\" :aria-pressed=\"tab === item[0]\" @click=\"switchTab(item[0]!)\">{{ item[1] }}</button></nav>\n <div class=\"knowledge-body\" :aria-busy=\"busy\">\n <div v-if=\"embedded && tab === 'project'\" class=\"actions\"><button type=\"button\" @click=\"switchTab('projects')\">返回项目</button><h3>项目记忆</h3></div>\n <p v-if=\"error\" role=\"alert\" class=\"knowledge-error\">{{ error }}</p>\n <template v-if=\"tab === 'projects'\">\n <div v-if=\"embedded\" class=\"project-heading\"><div><h3>项目</h3><p>让同一项目的 Bot 共享决策与约定。</p></div><button v-if=\"!projectDraft\" type=\"button\" class=\"project-primary\" @click=\"editProject()\">新建项目</button></div>\n <button v-else-if=\"!projectDraft\" @click=\"editProject()\">新建项目</button>\n <form v-if=\"projectDraft\" class=\"knowledge-editor\" @submit.prevent=\"saveProject\">\n <h3>{{ projectDraft.id ? '编辑项目' : '新建项目' }}</h3>\n <label>名称<input v-model=\"projectDraft.name\" required maxlength=\"100\" /></label>\n <label>说明<textarea v-model=\"projectDraft.description\" rows=\"3\" maxlength=\"16000\" /></label>\n <fieldset><legend>项目成员</legend><label v-for=\"agent in available\" :key=\"agent.id\" class=\"check\"><input v-model=\"projectDraft.memberIds\" type=\"checkbox\" :value=\"agent.id\" />{{ agent.name }}</label></fieldset>\n <fieldset><legend>关联群聊</legend><p>群内所有 Bot 需要先加入此项目。</p><label v-for=\"group in conversations.filter(c => c.kind === 'group' && !c.archived)\" :key=\"group.id\" class=\"check\"><input v-model=\"projectDraft.groupIds\" type=\"checkbox\" :value=\"group.id\" :disabled=\"group.memberIds.some(id => !projectDraft!.memberIds.includes(id)) || !!group.projectId && group.projectId !== projectDraft.id\" />{{ group.name }}</label></fieldset>\n <label v-if=\"projectDraft.id\" class=\"check\"><input v-model=\"projectDraft.archived\" type=\"checkbox\" />归档项目</label>\n <div class=\"actions\"><button type=\"submit\" :disabled=\"busy\">保存项目</button><button type=\"button\" @click=\"projectDraft = undefined\">取消</button></div>\n </form>\n <template v-if=\"embedded && !projectDraft\">\n <div v-if=\"projects.length\" class=\"project-list\" aria-label=\"项目列表\"><button v-for=\"project in projects\" :key=\"project.id\" type=\"button\" :aria-pressed=\"projectId === project.id\" @click=\"projectId = project.id\"><AppIcon name=\"files\" :size=\"21\"/><span><strong>{{project.name}}{{project.archived ? ' · 已归档' : ''}}</strong><small>{{project.memberIds.length}} 位 Bot · {{project.groupIds.length}} 个群聊</small></span><ChevronForwardOutline class=\"project-chevron\" aria-hidden=\"true\"/></button></div>\n <section v-if=\"currentProject\" class=\"project-details\" aria-label=\"当前项目详情\">\n <h3>{{currentProject.name}}</h3><p v-if=\"currentProject.description\" class=\"project-description\">{{currentProject.description}}</p>\n <div class=\"project-detail-row\"><span>项目成员</span><div class=\"project-members\"><span v-for=\"id in currentProject.memberIds\" :key=\"id\"><AgentAvatar :name=\"name(id)\" :avatar=\"agents.find(a => a.id === id)?.avatar || ''\" :size=\"24\"/>{{name(id)}}</span><small v-if=\"!currentProject.memberIds.length\">尚无成员</small></div></div>\n <div class=\"project-detail-row\"><span>关联群聊</span><div>{{currentProject.groupIds.map(id => conversations.find(c => c.id === id)?.name ?? '原群聊').join('、') || '尚未关联群聊'}}</div></div>\n <div class=\"project-detail-row\"><span>项目记忆</span><div><button type=\"button\" @click=\"switchTab('project')\">查看记忆</button></div></div>\n <div class=\"project-detail-actions\"><button type=\"button\" class=\"project-primary\" @click=\"editProject(currentProject)\">编辑项目</button></div>\n </section>\n </template>\n <template v-else-if=\"!embedded\"><article v-for=\"project in projects\" :key=\"project.id\"><h3>{{ project.name }}{{ project.archived ? ' · 已归档' : '' }}</h3><p>{{ project.description || '暂无说明' }}</p><small>{{ project.memberIds.map(id => name(id)).join('、') || '尚无成员' }} · {{ project.groupIds.length }} 个群</small><div class=\"actions\"><button @click=\"editProject(project)\">编辑</button><button @click=\"projectId = project.id; switchTab('project')\">查看记忆</button></div></article></template>\n <p v-if=\"!projects.length && !projectDraft\" class=\"empty\">创建项目后,多个群可以共享该项目的决策和约定。</p>\n </template>\n <template v-else-if=\"tab === 'collaboration'\">\n <p class=\"scope-note\">{{ taskId ? '当前话题' : '当前聊天' }} · {{ collaboration.length }} 条协作记录</p>\n <article v-for=\"event in collaboration\" :key=\"event.id\"><details><summary>{{ event.title }} · {{ event.status }}</summary><p class=\"pre-wrap\">{{ event.content }}</p><small v-if=\"event.at\">{{ new Date(event.at).toLocaleString() }}</small><p v-if=\"event.error\" class=\"knowledge-error\">{{ event.error }}</p></details><button v-if=\"event.peer && ['queued','running','waiting'].includes(event.peer.status)\" :disabled=\"busy\" @click=\"perform(async () => { await apiRequest(`/api/app/workspace/collaboration/${encodeURIComponent(event.peer!.id)}/stop`, { method: 'POST' }) })\">停止此次协作</button></article>\n <p v-if=\"!collaboration.length\" class=\"empty\">暂无协作记录。你可以在聊天中让 Bot 联系同伴,或派发任务。</p>\n </template>\n <template v-else>\n <MemoryFilesPanel v-if=\"agentId && (scope !== 'project' || projectId)\" :agent-id=\"agentId\" :scope=\"scope\" :project-id=\"projectId\" @dirty-change=\"fileDirty=$event\" @changed=\"emit('changed');load()\" />\n <div class=\"filters\">\n <label v-if=\"['agent','user','project'].includes(tab) && !selectedAgentId\">记忆贡献 Bot<select :disabled=\"fileDirty\" v-model=\"agentId\" @change=\"draft = undefined; load()\"><option v-for=\"agent in available\" :key=\"agent.id\" :value=\"agent.id\">{{ agent.name }}</option></select></label>\n <label v-if=\"tab === 'project'\">项目<select :disabled=\"fileDirty\" v-model=\"projectId\" @change=\"draft = undefined; load()\"><option v-for=\"project in projects\" :key=\"project.id\" :value=\"project.id\">{{ project.name }}</option></select></label>\n <form @submit.prevent=\"load()\"><label>搜索记忆<input v-model=\"search\" type=\"search\" placeholder=\"搜索事实、偏好或决策\" /></label><button type=\"submit\">搜索</button></form>\n </div>\n <p class=\"scope-note\">{{ tab === 'agent' ? '仅此 Bot 使用,可跨单聊和群聊延续。' : tab === 'user' ? '同一账号的 Bot 共享,按贡献者保存。' : `仅「${currentProject?.name ?? '当前项目'}」成员读取。` }}</p>\n <template v-if=\"tab === 'agent' && currentAgent\"><label v-if=\"!hideAgentControls\" class=\"check\"><input type=\"checkbox\" :checked=\"currentAgent.memoryEnabled !== false\" :disabled=\"busy\" @change=\"setAgent('memoryEnabled', ($event.target as HTMLInputElement).checked)\" />自动记录长期事实</label><p v-if=\"currentAgent.memoryStatus === 'upgrade_required'\" role=\"status\">执行节点需要升级后才能启用隔离记忆;已保存的文件仍可管理。</p></template>\n <div v-if=\"tab !== 'project' || projectId\" class=\"actions\"><button @click=\"newMemory()\" :disabled=\"!available.length\">添加记忆</button><a :href=\"`/api/app/workspace/memory-export?${query()}`\" download=\"bot-memory.md\">导出 Markdown</a></div>\n <form v-if=\"draft\" class=\"knowledge-editor\" @submit.prevent=\"saveMemory\"><h3>{{ draft.id ? '编辑记忆' : '添加记忆' }}</h3><label v-if=\"!draft.id && tab !== 'agent'\">贡献 Bot<select v-model=\"draft.agentId\"><option v-for=\"agent in available.filter(a => tab !== 'project' || currentProject?.memberIds.includes(a.id))\" :key=\"agent.id\" :value=\"agent.id\">{{ agent.name }}</option></select></label><label>事实<textarea v-model=\"draft.content\" required rows=\"4\" maxlength=\"2000\" /></label><label>类别<select v-model=\"draft.tier\"><option value=\"profile\">长期事实</option><option value=\"log\">历史记录</option><option value=\"note\">补充笔记</option></select></label><div class=\"actions\"><button type=\"submit\" :disabled=\"busy\">保存</button><button type=\"button\" @click=\"draft = undefined\">取消</button></div></form>\n <article v-for=\"memory in memories\" :key=\"`${memory.scope}:${memory.agentId}:${memory.id}`\"><p class=\"pre-wrap\">{{ memory.content }}</p><p v-if=\"memory.conflict\" role=\"status\">同主题有不同贡献,请核对来源。</p><small>{{ name(memory.agentId) }} · {{ memory.origin === 'manual' ? '用户维护' : memory.origin === 'explicit' ? '明确保存' : '自动提炼' }} · {{ new Date(memory.updatedAt).toLocaleString() }} · 版本 {{ memory.revision }}</small><details v-if=\"memory.sources.length\"><summary>查看来源</summary><p v-for=\"source in memory.sources\" :key=\"source.messageId\"><a :href=\"`/conversations/${source.conversationId}${source.taskId ? `?taskId=${source.taskId}` : ''}`\">{{ source.quote || '查看原话题' }}</a><small v-if=\"source.at\"> · 来源 {{ new Date(source.at).toLocaleString() }}</small></p></details><div class=\"actions\"><button @click=\"newMemory(memory)\">编辑</button><button @click=\"history(memory)\" :disabled=\"busy\">修订记录</button><button @click=\"forget(memory)\" :disabled=\"busy\">遗忘</button></div></article>\n <div v-if=\"memories.length\" class=\"actions\"><small role=\"status\">已显示 {{ memories.length }} / {{ memoryTotal }} 条</small><button v-if=\"nextMemoryOffset !== undefined\" :disabled=\"busy\" @click=\"loadMoreMemories\">加载更多记忆</button><button v-if=\"loadedMore\" :disabled=\"busy\" @click=\"load()\">刷新结果</button></div>\n <p v-if=\"!memories.length && !draft\" class=\"empty\">暂无记忆。可手动添加,也可在对话中说明需要长期记住的事实。</p>\n <section v-if=\"revisions.length\" class=\"knowledge-editor\"><h3>修订记录</h3><article v-for=\"revision in revisions\" :key=\"revision.id\"><small>版本 {{ revision.revision }} · {{ revision.operation === 'forget' ? '遗忘' : '保存' }} · {{ new Date(revision.at).toLocaleString() }}</small><p>{{ revision.after?.content ?? revision.before?.content }}</p></article><button @click=\"revisions = []\">收起</button></section>\n <details v-if=\"tab === 'agent' && jobs.length\">\n <summary>后台提炼记录</summary>\n <article v-for=\"job in jobs\" :key=\"job.id\">\n <small>{{ new Date(job.createdAt).toLocaleString() }} · {{ jobSummary(job) }}</small>\n <p v-if=\"job.result\">本次提炼 {{ job.result.extractedCount }} 条 · 新增保存 {{ job.result.writtenCount }} 条 · 重复 {{ job.result.duplicateCount }} 条 · 重试确认 {{ job.result.replayedCount }} 条</p>\n <p v-for=\"reason in skippedReasons(job)\" :key=\"reason\">{{ reason }}</p>\n <p v-if=\"job.error\">{{ job.error }}</p>\n <button v-if=\"job.status === 'failed'\" :disabled=\"busy\" @click=\"perform(async () => { await apiRequest(`/api/app/workspace/memory-jobs/${job.id}/retry`, { method: 'POST' }) })\">重试</button>\n </article>\n </details>\n </template>\n </div>\n </component>\n</template>\n\n<style scoped>\n.knowledge-dialog{width:min(820px,calc(100vw - 24px));max-height:calc(100dvh - 32px);padding:0;border:1px solid var(--line);border-radius:18px;background:var(--surface);color:var(--text-primary)}\n.knowledge-dialog::backdrop{background:rgb(0 0 0 / .5)}header{display:flex;justify-content:space-between;align-items:center;gap:16px;padding:20px 24px;border-bottom:1px solid var(--line)}h2,h3,p{margin:0}header p,.scope-note,.empty,small{color:var(--text-secondary)}header p{margin-top:5px;font-size:13px}nav{display:flex;flex-wrap:wrap;gap:4px;padding:10px 20px;border-bottom:1px solid var(--line)}button,a{min-height:44px;display:inline-flex;align-items:center;justify-content:center;border:1px solid var(--line);border-radius:9px;padding:8px 12px;background:var(--surface);color:var(--text-primary);font:inherit;font-size:14px;cursor:pointer;text-decoration:none}button:hover,a:hover{background:var(--surface-hover)}button[aria-pressed=true]{background:var(--surface-hover);border-color:var(--accent);color:var(--accent)}button:disabled{opacity:.5;cursor:default}button:focus-visible,a:focus-visible,input:focus-visible,textarea:focus-visible,select:focus-visible,summary:focus-visible{outline:2px solid var(--accent);outline-offset:2px}.knowledge-body{display:grid;gap:16px;padding:20px 24px;max-height:calc(100dvh - 210px);overflow:auto;overscroll-behavior:contain}label{display:grid;gap:6px;font-size:14px}input:not([type=checkbox]),textarea,select{min-height:44px;padding:9px 10px;border:1px solid var(--line);border-radius:8px;background:var(--surface);color:var(--text-primary);font:inherit;box-sizing:border-box;width:100%}textarea{resize:vertical}.filters{display:flex;flex-wrap:wrap;align-items:end;gap:12px}.filters>label{min-width:160px}.filters form{display:flex;align-items:end;gap:8px;flex:1}.filters form label{flex:1}.actions{display:flex;flex-wrap:wrap;gap:8px;margin-top:10px}article{padding:16px;border:1px solid var(--line);border-radius:12px;display:grid;gap:9px}.knowledge-editor{display:grid;gap:12px;padding:16px;border:1px solid var(--accent);border-radius:12px}fieldset{border:1px solid var(--line);border-radius:10px;padding:12px;display:grid;gap:8px;max-height:240px;overflow:auto}.check{display:flex;align-items:center;min-height:44px;gap:9px}.check input{width:18px;height:18px;accent-color:var(--accent)}small,.scope-note{font-size:13px;line-height:1.5}.pre-wrap{white-space:pre-wrap;overflow-wrap:anywhere;line-height:1.6}.knowledge-error{color:var(--danger,#c0392b);white-space:pre-wrap}.empty{padding:24px 8px;text-align:center;line-height:1.6}summary{cursor:pointer;min-height:36px;line-height:1.6}details p{margin-top:8px}\n@media(max-width:520px){header{padding:16px}h2{font-size:19px}nav{padding:8px}nav button{flex:1;white-space:nowrap}.knowledge-body{padding:16px;max-height:calc(100dvh - 250px)}.filters{display:grid}.filters form{min-width:0}}\n.knowledge-dialog--embedded{width:100%;max-height:none;border:0;border-radius:0;background:transparent;min-width:0}.knowledge-dialog--embedded .knowledge-body{padding:0;max-height:none;overflow:visible}.knowledge-dialog--embedded .actions{align-items:center}\n.project-heading{display:flex;align-items:flex-start;justify-content:space-between;gap:20px;margin-bottom:8px}.project-heading h3{font-size:18px;font-weight:650}.project-heading p{font-size:13px;color:var(--text-secondary);margin-top:6px;line-height:1.6}.knowledge-dialog--embedded .project-primary{flex-shrink:0;padding:8px 16px;background:var(--accent);color:var(--text-on-solid);border-color:var(--accent);font-size:13px}.project-list{border:1px solid var(--line);border-radius:11px;overflow:hidden}.project-list button{display:flex;gap:20px;width:100%;padding:18px 22px;border:0;border-radius:0;text-align:left;justify-content:flex-start;min-height:76px}.project-list button+button{border-top:1px solid var(--line)}.project-list button[aria-pressed=true]{background:var(--settings-selected);color:var(--text-primary)}.project-list button>span{flex:1;min-width:0;display:grid;gap:4px}.project-list strong{font-size:15px;font-weight:600;overflow-wrap:anywhere}.project-list small{font-size:12px}.project-list .app-icon{color:var(--text-muted)}.project-details{background:var(--settings-panel);padding:20px;border-radius:12px}.project-details h3{font-size:17px;font-weight:650;margin-bottom:12px}.project-description{font-size:13px;color:var(--text-secondary);line-height:1.6;padding-bottom:12px;white-space:pre-wrap;overflow-wrap:anywhere}.project-detail-row{display:grid;grid-template-columns:104px minmax(0,1fr);align-items:center;gap:16px;min-height:48px;border-top:1px solid var(--line);font-size:14px}.project-detail-row>span{color:var(--text-secondary)}.project-detail-row>div{overflow-wrap:anywhere}.project-detail-row button{min-height:36px;background:var(--settings-selected);border:0;font-size:12px}.project-members{display:flex;gap:10px;flex-wrap:wrap;padding-block:10px}.project-members>span{display:inline-flex;align-items:center;gap:7px}.project-detail-actions{display:flex;justify-content:flex-end;margin-top:8px}.project-detail-actions .project-primary{min-height:36px}.knowledge-dialog--embedded article{border:0;background:var(--settings-panel)}@media(max-width:520px){.project-heading{gap:10px}.project-heading p{max-width:210px}.project-list button{padding:16px;gap:12px}.project-details{padding:16px}.project-detail-row{grid-template-columns:76px minmax(0,1fr);gap:10px}}\n</style>\n<style scoped>.project-chevron{width:17px;height:17px;flex-shrink:0;color:var(--text-muted)}</style>\n","<script setup lang=\"ts\">\nimport { computed, nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue'\nimport MemoryFilesPanel from './MemoryFilesPanel.vue'\nimport type { AgentAssignment, AgentGoal } from '@shared/agentTasks'\nimport { collaborationTimeline } from '@shared/collaborationTimeline'\nimport { apiRequest } from '@/api/client'\nimport { createUuid } from '@/utils/id'\nimport AppIcon from '@/components/common/AppIcon.vue'\nimport AgentAvatar from '@/components/common/AgentAvatar.vue'\nimport { ChevronForwardOutline } from '@vicons/ionicons5'\nimport type { WorkspaceAgent, WorkspaceConversation, WorkspaceMessage } from '@shared/workspace'\nimport type { MemoryScope, MemorySkipReason, WorkspaceMemory, WorkspaceMemoryJob, WorkspaceMemoryRevision, WorkspacePeerMessage, WorkspaceProject } from '@shared/workspaceKnowledge'\n\nconst props = defineProps<{ agents: WorkspaceAgent[]; conversations: WorkspaceConversation[]; conversationId?: string; taskId?: string; assignments?: AgentAssignment[]; goal?: AgentGoal; revision?: number; embedded?: boolean; initialTab?: 'projects' | 'user' | 'agent'; selectedAgentId?: string; hideAgentControls?: boolean }>()\nconst emit = defineEmits<{ changed: []; 'dirty-change': [dirty: boolean] }>()\nconst dialog = ref<HTMLDialogElement>(), opened = ref(false), busy = ref(false), error = ref(''), tab = ref('agent'), agentId = ref(''), projectId = ref(''), search = ref('')\nconst projects = ref<WorkspaceProject[]>([]), memories = ref<WorkspaceMemory[]>([]), peers = ref<WorkspacePeerMessage[]>([]), jobs = ref<WorkspaceMemoryJob[]>([]), revisions = ref<WorkspaceMemoryRevision[]>([])\nconst draft = ref<{ id?: string; expectedRevision?: number; agentId: string; content: string; tier: WorkspaceMemory['tier'] }>()\nconst projectDraft = ref<WorkspaceProject>()\nconst memoryTotal=ref(0), nextMemoryOffset=ref<number>(), loadedMore=ref(false)\nconst fileDirty=ref(false)\nconst activities = ref<WorkspaceMessage[]>([])\nlet generation = 0, timer: ReturnType<typeof setInterval> | undefined\nconst available = computed(() => props.agents.filter(a => !a.archived && !a.temporaryGoalId))\nconst currentAgent = computed(() => props.agents.find(a => a.id === agentId.value))\nconst currentProject = computed(() => projects.value.find(p => p.id === projectId.value))\nconst scope = computed(() => (['agent', 'user', 'project'].includes(tab.value) ? tab.value : 'agent') as MemoryScope)\nconst name = (id?: string) => props.agents.find(a => a.id === id)?.name ?? '原贡献者'\nconst collaboration = computed(() => collaborationTimeline({ peers: peers.value, activities: activities.value, assignments: props.assignments ?? [], coordinatorId: props.goal?.coordinatorId, name }))\nconst query = () => new URLSearchParams({ scope: scope.value, ...(tab.value === 'agent' && agentId.value ? { agentId: agentId.value } : {}), ...(tab.value === 'project' && projectId.value ? { projectId: projectId.value } : {}), ...(search.value ? { search: search.value } : {}) }).toString()\nconst stateNames: Record<string, string> = { queued: '已排队', pending: '待提炼', running: '处理中', waiting: '等待同伴', complete: '已完成', failed: '失败', stopped: '已停止', skipped: '已跳过' }\nconst skipReasonNames: Record<MemorySkipReason, string> = {\n source_missing: '找不到对应的来源消息', quote_mismatch: '引用与原文不一致', sensitive_content: '包含凭据等敏感内容',\n project_unbound: '项目记忆缺少关联项目', user_not_explicit: '缺少用户明确表达的长期信息', forgotten: '已遗忘的内容或来源不再保存', stale: '推理期间记忆已更新,本次旧提炼结果未应用',\n}\nfunction jobSummary(job: WorkspaceMemoryJob): string {\n if (job.status !== 'complete') return stateNames[job.status] ?? job.status\n const result = job.result\n if (!result) return '已结束(旧记录未统计保存结果)'\n if (!result.extractedCount) return '本轮没有可记录内容'\n if (result.writtenCount) return `已保存 ${result.writtenCount} 条记忆`\n if (result.replayedCount) return `重试已确认 ${result.replayedCount} 条记录`\n if (result.duplicateCount) return '未新增记忆,已有相同内容'\n return '候选记忆均未保存'\n}\nfunction skippedReasons(job: WorkspaceMemoryJob): string[] {\n return Object.entries(job.result?.skippedReasons ?? {}).filter(([, count]) => count > 0)\n .map(([reason, count]) => `${skipReasonNames[reason as MemorySkipReason] ?? '其他原因'}:${count} 条`)\n}\nasync function load(silent = false) {\n if (silent && loadedMore.value && tab.value !== 'collaboration') return\n const epoch = ++generation\n if (!silent) error.value = ''\n try {\n const projectResult = await apiRequest<{ projects: WorkspaceProject[] }>('/api/app/workspace/projects')\n if (epoch !== generation || !opened.value) return\n projects.value = projectResult.projects\n if (!projectId.value) projectId.value = projects.value.find(p => !p.archived)?.id ?? ''\n if (tab.value === 'collaboration') {\n const [result, milestones] = await Promise.all([\n apiRequest<{ messages: WorkspacePeerMessage[] }>(`/api/app/workspace/collaboration?${new URLSearchParams({ ...(props.conversationId ? { conversationId: props.conversationId } : {}), ...(props.taskId ? { taskId: props.taskId } : {}) })}`),\n props.conversationId ? apiRequest<{ messages: WorkspaceMessage[] }>(`/api/app/conversations/${encodeURIComponent(props.conversationId)}/activities${props.taskId ? `?taskId=${encodeURIComponent(props.taskId)}` : ''}`) : Promise.resolve({ messages: [] }),\n ])\n if (epoch === generation) { peers.value = result.messages; activities.value = milestones.messages }\n } else if (tab.value !== 'projects' && (tab.value !== 'project' || projectId.value)) {\n const result = await apiRequest<{ memories: WorkspaceMemory[]; total?: number; nextOffset?: number }>(`/api/app/workspace/memories?${query()}`)\n if (epoch === generation) { memories.value = result.memories; memoryTotal.value = result.total ?? result.memories.length; nextMemoryOffset.value = result.nextOffset; loadedMore.value = false }\n } else { memories.value = []; memoryTotal.value = 0; nextMemoryOffset.value = undefined; loadedMore.value = false }\n if (agentId.value) {\n const result = await apiRequest<{ jobs: WorkspaceMemoryJob[] }>(`/api/app/workspace/memory-jobs?agentId=${agentId.value}`)\n if (epoch === generation) jobs.value = result.jobs\n }\n } catch (cause) { if (epoch === generation) error.value = String(cause) }\n}\nasync function loadMoreMemories() {\n if (busy.value || nextMemoryOffset.value === undefined) return\n const epoch = generation, filter = query(), offset = nextMemoryOffset.value\n busy.value = true; error.value = ''\n try {\n const result = await apiRequest<{ memories: WorkspaceMemory[]; total: number; nextOffset?: number }>(`/api/app/workspace/memories?${filter}&offset=${offset}&limit=100`)\n if (epoch !== generation || !opened.value || filter !== query()) return\n const existing = new Set(memories.value.map(m => `${m.scope}:${m.agentId}:${m.id}`))\n memories.value.push(...result.memories.filter(m => !existing.has(`${m.scope}:${m.agentId}:${m.id}`)))\n memoryTotal.value = result.total; nextMemoryOffset.value = result.nextOffset; loadedMore.value = true\n } catch (cause) { if (epoch === generation) error.value = String(cause) } finally { busy.value = false }\n}\nasync function open(initial = 'agent', selectedAgent?: string, selectedProject?: string) {\n tab.value = initial; agentId.value = selectedAgent ?? available.value[0]?.id ?? ''; projectId.value = selectedProject ?? ''\n opened.value = true; draft.value = undefined; projectDraft.value = undefined; revisions.value = []; search.value = ''\n await nextTick(); if (!props.embedded) dialog.value?.showModal(); await load()\n clearInterval(timer); timer = setInterval(() => { if (!busy.value && !draft.value && !projectDraft.value) void load(true) }, 5000)\n}\nfunction close() { if(fileDirty.value){error.value='请先保存文件或取消编辑。';return} opened.value = false; generation++; clearInterval(timer); if (!props.embedded) dialog.value?.close() }\nfunction switchTab(value: string) { if(fileDirty.value)return; tab.value = value; draft.value = undefined; projectDraft.value = undefined; revisions.value = []; void load() }\nasync function perform(action: () => Promise<void>) {\n if (busy.value) return\n busy.value = true; error.value = ''\n try { await action(); emit('changed'); await load() } catch (cause) { error.value = String(cause) } finally { busy.value = false }\n}\nfunction newMemory(memory?: WorkspaceMemory) {\n revisions.value = []\n draft.value = memory ? { id: memory.id, expectedRevision: memory.revision, agentId: memory.agentId, content: memory.content, tier: memory.tier } : { agentId: agentId.value || available.value[0]?.id || '', content: '', tier: 'log' }\n}\nasync function saveMemory() {\n const value = draft.value\n if (!value?.content.trim()) { error.value = '请输入需要记住的事实'; return }\n await perform(async () => {\n await apiRequest('/api/app/workspace/memories', { method: 'POST', body: { requestId: createUuid(), scope: scope.value, ...(scope.value === 'project' ? { projectId: projectId.value } : {}), ...value } })\n draft.value = undefined\n })\n}\nasync function forget(memory: WorkspaceMemory) {\n await perform(async () => { await apiRequest('/api/app/workspace/memories/forget', { method: 'POST', body: { requestId: createUuid(), scope: memory.scope, agentId: memory.agentId, ...(memory.projectId ? { projectId: memory.projectId } : {}), id: memory.id, expectedRevision: memory.revision } }) })\n}\nasync function history(memory: WorkspaceMemory) {\n const query = new URLSearchParams({ scope: memory.scope, agentId: memory.agentId, ...(memory.projectId ? { projectId: memory.projectId } : {}) })\n await perform(async () => { revisions.value = (await apiRequest<{ revisions: WorkspaceMemoryRevision[] }>(`/api/app/workspace/memories/${memory.id}/revisions?${query}`)).revisions })\n}\nfunction editProject(project?: WorkspaceProject) {\n projectDraft.value = project ? { ...project, memberIds: [...project.memberIds], groupIds: [...project.groupIds] } : { id: '', name: '', description: '', memberIds: [], groupIds: [], revision: 0, archived: false, createdAt: 0, updatedAt: 0 }\n}\nasync function saveProject() {\n const value = projectDraft.value\n if (!value?.name.trim()) { error.value = '请输入项目名称'; return }\n await perform(async () => {\n const result = await apiRequest<{ project: WorkspaceProject }>('/api/app/workspace/projects', { method: 'POST', body: { requestId: createUuid(), ...(value.id ? { id: value.id, expectedRevision: value.revision } : {}), name: value.name, description: value.description, memberIds: value.memberIds, groupIds: value.groupIds, archived: value.archived } })\n projectId.value = result.project.id; projectDraft.value = undefined\n })\n}\nasync function setAgent(field: 'canCollaborate' | 'memoryEnabled', enabled: boolean) {\n await perform(async () => { await apiRequest(`/api/app/agents/${agentId.value}`, { method: 'PATCH', body: { [field]: enabled } }) })\n}\nonBeforeUnmount(() => { generation++; clearInterval(timer) })\nonMounted(() => { if (props.embedded) void open(props.initialTab ?? 'projects', props.selectedAgentId) })\nwatch(() => props.initialTab, value => { if (props.embedded && value) switchTab(value) })\nwatch(() => props.revision, () => { if (opened.value && !busy.value && !draft.value && !projectDraft.value) void load(true) })\nwatch(() => [props.conversationId, props.taskId], () => { generation++; peers.value = []; activities.value = []; if (opened.value && tab.value === 'collaboration') void load() })\nwatch(() => fileDirty.value || !!draft.value || !!projectDraft.value, value => emit('dirty-change', value))\ndefineExpose({ open, close })\n</script>\n\n<template>\n <component :is=\"embedded ? 'section' : 'dialog'\" ref=\"dialog\" class=\"knowledge-dialog\" :class=\"{ 'knowledge-dialog--embedded': embedded }\" :aria-labelledby=\"embedded ? undefined : 'knowledge-title'\" @cancel.prevent=\"close\" @close=\"opened = false\">\n <header v-if=\"!embedded\"><div><h2 id=\"knowledge-title\">Bot 记忆与协作</h2><p>管理长期事实、项目和同伴请求</p></div><button type=\"button\" @click=\"close\" aria-label=\"关闭记忆与协作\">关闭</button></header>\n <nav v-if=\"!embedded\" aria-label=\"记忆与项目分类\"><button v-for=\"item in [['agent','Bot 记忆'],['user','用户记忆'],['projects','项目'],['project','项目记忆'],['collaboration','协作']]\" :key=\"item[0]\" :aria-pressed=\"tab === item[0]\" @click=\"switchTab(item[0]!)\">{{ item[1] }}</button></nav>\n <div class=\"knowledge-body\" :aria-busy=\"busy\">\n <div v-if=\"embedded && tab === 'project'\" class=\"actions\"><button type=\"button\" @click=\"switchTab('projects')\">返回项目</button><h3>项目记忆</h3></div>\n <p v-if=\"error\" role=\"alert\" class=\"knowledge-error\">{{ error }}</p>\n <template v-if=\"tab === 'projects'\">\n <div v-if=\"embedded\" class=\"project-heading\"><div><h3>项目</h3><p>让同一项目的 Bot 共享决策与约定。</p></div><button v-if=\"!projectDraft\" type=\"button\" class=\"project-primary\" @click=\"editProject()\">新建项目</button></div>\n <button v-else-if=\"!projectDraft\" @click=\"editProject()\">新建项目</button>\n <form v-if=\"projectDraft\" class=\"knowledge-editor\" @submit.prevent=\"saveProject\">\n <h3>{{ projectDraft.id ? '编辑项目' : '新建项目' }}</h3>\n <label>名称<input v-model=\"projectDraft.name\" required maxlength=\"100\" /></label>\n <label>说明<textarea v-model=\"projectDraft.description\" rows=\"3\" maxlength=\"16000\" /></label>\n <fieldset><legend>项目成员</legend><label v-for=\"agent in available\" :key=\"agent.id\" class=\"check\"><input v-model=\"projectDraft.memberIds\" type=\"checkbox\" :value=\"agent.id\" />{{ agent.name }}</label></fieldset>\n <fieldset><legend>关联群聊</legend><p>群内所有 Bot 需要先加入此项目。</p><label v-for=\"group in conversations.filter(c => c.kind === 'group' && !c.archived)\" :key=\"group.id\" class=\"check\"><input v-model=\"projectDraft.groupIds\" type=\"checkbox\" :value=\"group.id\" :disabled=\"group.memberIds.some(id => !projectDraft!.memberIds.includes(id)) || !!group.projectId && group.projectId !== projectDraft.id\" />{{ group.name }}</label></fieldset>\n <label v-if=\"projectDraft.id\" class=\"check\"><input v-model=\"projectDraft.archived\" type=\"checkbox\" />归档项目</label>\n <div class=\"actions\"><button type=\"submit\" :disabled=\"busy\">保存项目</button><button type=\"button\" @click=\"projectDraft = undefined\">取消</button></div>\n </form>\n <template v-if=\"embedded && !projectDraft\">\n <div v-if=\"projects.length\" class=\"project-list\" aria-label=\"项目列表\"><button v-for=\"project in projects\" :key=\"project.id\" type=\"button\" :aria-pressed=\"projectId === project.id\" @click=\"projectId = project.id\"><AppIcon name=\"files\" :size=\"21\"/><span><strong>{{project.name}}{{project.archived ? ' · 已归档' : ''}}</strong><small>{{project.memberIds.length}} 位 Bot · {{project.groupIds.length}} 个群聊</small></span><ChevronForwardOutline class=\"project-chevron\" aria-hidden=\"true\"/></button></div>\n <section v-if=\"currentProject\" class=\"project-details\" aria-label=\"当前项目详情\">\n <h3>{{currentProject.name}}</h3><p v-if=\"currentProject.description\" class=\"project-description\">{{currentProject.description}}</p>\n <div class=\"project-detail-row\"><span>项目成员</span><div class=\"project-members\"><span v-for=\"id in currentProject.memberIds\" :key=\"id\"><AgentAvatar :name=\"name(id)\" :avatar=\"agents.find(a => a.id === id)?.avatar || ''\" :size=\"24\"/>{{name(id)}}</span><small v-if=\"!currentProject.memberIds.length\">尚无成员</small></div></div>\n <div class=\"project-detail-row\"><span>关联群聊</span><div>{{currentProject.groupIds.map(id => conversations.find(c => c.id === id)?.name ?? '原群聊').join('、') || '尚未关联群聊'}}</div></div>\n <div class=\"project-detail-row\"><span>项目记忆</span><div><button type=\"button\" @click=\"switchTab('project')\">查看记忆</button></div></div>\n <div class=\"project-detail-actions\"><button type=\"button\" class=\"project-primary\" @click=\"editProject(currentProject)\">编辑项目</button></div>\n </section>\n </template>\n <template v-else-if=\"!embedded\"><article v-for=\"project in projects\" :key=\"project.id\"><h3>{{ project.name }}{{ project.archived ? ' · 已归档' : '' }}</h3><p>{{ project.description || '暂无说明' }}</p><small>{{ project.memberIds.map(id => name(id)).join('、') || '尚无成员' }} · {{ project.groupIds.length }} 个群</small><div class=\"actions\"><button @click=\"editProject(project)\">编辑</button><button @click=\"projectId = project.id; switchTab('project')\">查看记忆</button></div></article></template>\n <p v-if=\"!projects.length && !projectDraft\" class=\"empty\">创建项目后,多个群可以共享该项目的决策和约定。</p>\n </template>\n <template v-else-if=\"tab === 'collaboration'\">\n <p class=\"scope-note\">{{ taskId ? '当前话题' : '当前聊天' }} · {{ collaboration.length }} 条协作记录</p>\n <article v-for=\"event in collaboration\" :key=\"event.id\"><details><summary>{{ event.title }} · {{ event.status }}</summary><p class=\"pre-wrap\">{{ event.content }}</p><small v-if=\"event.at\">{{ new Date(event.at).toLocaleString() }}</small><p v-if=\"event.error\" class=\"knowledge-error\">{{ event.error }}</p></details><button v-if=\"event.peer && ['queued','running','waiting'].includes(event.peer.status)\" :disabled=\"busy\" @click=\"perform(async () => { await apiRequest(`/api/app/workspace/collaboration/${encodeURIComponent(event.peer!.id)}/stop`, { method: 'POST' }) })\">停止此次协作</button></article>\n <p v-if=\"!collaboration.length\" class=\"empty\">暂无协作记录。你可以在聊天中让 Bot 联系同伴,或派发任务。</p>\n </template>\n <template v-else>\n <MemoryFilesPanel v-if=\"agentId && (scope !== 'project' || projectId)\" :agent-id=\"agentId\" :scope=\"scope\" :project-id=\"projectId\" @dirty-change=\"fileDirty=$event\" @changed=\"emit('changed');load()\" />\n <div class=\"filters\">\n <label v-if=\"['agent','user','project'].includes(tab) && !selectedAgentId\">记忆贡献 Bot<select :disabled=\"fileDirty\" v-model=\"agentId\" @change=\"draft = undefined; load()\"><option v-for=\"agent in available\" :key=\"agent.id\" :value=\"agent.id\">{{ agent.name }}</option></select></label>\n <label v-if=\"tab === 'project'\">项目<select :disabled=\"fileDirty\" v-model=\"projectId\" @change=\"draft = undefined; load()\"><option v-for=\"project in projects\" :key=\"project.id\" :value=\"project.id\">{{ project.name }}</option></select></label>\n <form @submit.prevent=\"load()\"><label>搜索记忆<input v-model=\"search\" type=\"search\" placeholder=\"搜索事实、偏好或决策\" /></label><button type=\"submit\">搜索</button></form>\n </div>\n <p class=\"scope-note\">{{ tab === 'agent' ? '仅此 Bot 使用,可跨单聊和群聊延续。' : tab === 'user' ? '同一账号的 Bot 共享,按贡献者保存。' : `仅「${currentProject?.name ?? '当前项目'}」成员读取。` }}</p>\n <template v-if=\"tab === 'agent' && currentAgent\"><label v-if=\"!hideAgentControls\" class=\"check\"><input type=\"checkbox\" :checked=\"currentAgent.memoryEnabled !== false\" :disabled=\"busy\" @change=\"setAgent('memoryEnabled', ($event.target as HTMLInputElement).checked)\" />自动记录长期事实</label><p v-if=\"currentAgent.memoryStatus === 'upgrade_required'\" role=\"status\">执行节点需要升级后才能启用隔离记忆;已保存的文件仍可管理。</p></template>\n <div v-if=\"tab !== 'project' || projectId\" class=\"actions\"><button @click=\"newMemory()\" :disabled=\"!available.length\">添加记忆</button><a :href=\"`/api/app/workspace/memory-export?${query()}`\" download=\"bot-memory.md\">导出 Markdown</a></div>\n <form v-if=\"draft\" class=\"knowledge-editor\" @submit.prevent=\"saveMemory\"><h3>{{ draft.id ? '编辑记忆' : '添加记忆' }}</h3><label v-if=\"!draft.id && tab !== 'agent'\">贡献 Bot<select v-model=\"draft.agentId\"><option v-for=\"agent in available.filter(a => tab !== 'project' || currentProject?.memberIds.includes(a.id))\" :key=\"agent.id\" :value=\"agent.id\">{{ agent.name }}</option></select></label><label>事实<textarea v-model=\"draft.content\" required rows=\"4\" maxlength=\"2000\" /></label><label>类别<select v-model=\"draft.tier\"><option value=\"profile\">长期事实</option><option value=\"log\">历史记录</option><option value=\"note\">补充笔记</option></select></label><div class=\"actions\"><button type=\"submit\" :disabled=\"busy\">保存</button><button type=\"button\" @click=\"draft = undefined\">取消</button></div></form>\n <article v-for=\"memory in memories\" :key=\"`${memory.scope}:${memory.agentId}:${memory.id}`\"><p class=\"pre-wrap\">{{ memory.content }}</p><p v-if=\"memory.conflict\" role=\"status\">同主题有不同贡献,请核对来源。</p><small>{{ name(memory.agentId) }} · {{ memory.origin === 'manual' ? '用户维护' : memory.origin === 'explicit' ? '明确保存' : '自动提炼' }} · {{ new Date(memory.updatedAt).toLocaleString() }} · 版本 {{ memory.revision }}</small><details v-if=\"memory.sources.length\"><summary>查看来源</summary><p v-for=\"source in memory.sources\" :key=\"source.messageId\"><a :href=\"`/conversations/${source.conversationId}${source.taskId ? `?taskId=${source.taskId}` : ''}`\">{{ source.quote || '查看原话题' }}</a><small v-if=\"source.at\"> · 来源 {{ new Date(source.at).toLocaleString() }}</small></p></details><div class=\"actions\"><button @click=\"newMemory(memory)\">编辑</button><button @click=\"history(memory)\" :disabled=\"busy\">修订记录</button><button @click=\"forget(memory)\" :disabled=\"busy\">遗忘</button></div></article>\n <div v-if=\"memories.length\" class=\"actions\"><small role=\"status\">已显示 {{ memories.length }} / {{ memoryTotal }} 条</small><button v-if=\"nextMemoryOffset !== undefined\" :disabled=\"busy\" @click=\"loadMoreMemories\">加载更多记忆</button><button v-if=\"loadedMore\" :disabled=\"busy\" @click=\"load()\">刷新结果</button></div>\n <p v-if=\"!memories.length && !draft\" class=\"empty\">暂无记忆。可手动添加,也可在对话中说明需要长期记住的事实。</p>\n <section v-if=\"revisions.length\" class=\"knowledge-editor\"><h3>修订记录</h3><article v-for=\"revision in revisions\" :key=\"revision.id\"><small>版本 {{ revision.revision }} · {{ revision.operation === 'forget' ? '遗忘' : '保存' }} · {{ new Date(revision.at).toLocaleString() }}</small><p>{{ revision.after?.content ?? revision.before?.content }}</p></article><button @click=\"revisions = []\">收起</button></section>\n <details v-if=\"tab === 'agent' && jobs.length\">\n <summary>后台提炼记录</summary>\n <article v-for=\"job in jobs\" :key=\"job.id\">\n <small>{{ new Date(job.createdAt).toLocaleString() }} · {{ jobSummary(job) }}</small>\n <p v-if=\"job.result\">本次提炼 {{ job.result.extractedCount }} 条 · 新增保存 {{ job.result.writtenCount }} 条 · 重复 {{ job.result.duplicateCount }} 条 · 重试确认 {{ job.result.replayedCount }} 条</p>\n <p v-for=\"reason in skippedReasons(job)\" :key=\"reason\">{{ reason }}</p>\n <p v-if=\"job.error\">{{ job.error }}</p>\n <button v-if=\"job.status === 'failed'\" :disabled=\"busy\" @click=\"perform(async () => { await apiRequest(`/api/app/workspace/memory-jobs/${job.id}/retry`, { method: 'POST' }) })\">重试</button>\n </article>\n </details>\n </template>\n </div>\n </component>\n</template>\n\n<style scoped>\n.knowledge-dialog{width:min(820px,calc(100vw - 24px));max-height:calc(100dvh - 32px);padding:0;border:1px solid var(--line);border-radius:18px;background:var(--surface);color:var(--text-primary)}\n.knowledge-dialog::backdrop{background:rgb(0 0 0 / .5)}header{display:flex;justify-content:space-between;align-items:center;gap:16px;padding:20px 24px;border-bottom:1px solid var(--line)}h2,h3,p{margin:0}header p,.scope-note,.empty,small{color:var(--text-secondary)}header p{margin-top:5px;font-size:13px}nav{display:flex;flex-wrap:wrap;gap:4px;padding:10px 20px;border-bottom:1px solid var(--line)}button,a{min-height:44px;display:inline-flex;align-items:center;justify-content:center;border:1px solid var(--line);border-radius:9px;padding:8px 12px;background:var(--surface);color:var(--text-primary);font:inherit;font-size:14px;cursor:pointer;text-decoration:none}button:hover,a:hover{background:var(--surface-hover)}button[aria-pressed=true]{background:var(--surface-hover);border-color:var(--accent);color:var(--accent)}button:disabled{opacity:.5;cursor:default}button:focus-visible,a:focus-visible,input:focus-visible,textarea:focus-visible,select:focus-visible,summary:focus-visible{outline:2px solid var(--accent);outline-offset:2px}.knowledge-body{display:grid;gap:16px;padding:20px 24px;max-height:calc(100dvh - 210px);overflow:auto;overscroll-behavior:contain}label{display:grid;gap:6px;font-size:14px}input:not([type=checkbox]),textarea,select{min-height:44px;padding:9px 10px;border:1px solid var(--line);border-radius:8px;background:var(--surface);color:var(--text-primary);font:inherit;box-sizing:border-box;width:100%}textarea{resize:vertical}.filters{display:flex;flex-wrap:wrap;align-items:end;gap:12px}.filters>label{min-width:160px}.filters form{display:flex;align-items:end;gap:8px;flex:1}.filters form label{flex:1}.actions{display:flex;flex-wrap:wrap;gap:8px;margin-top:10px}article{padding:16px;border:1px solid var(--line);border-radius:12px;display:grid;gap:9px}.knowledge-editor{display:grid;gap:12px;padding:16px;border:1px solid var(--accent);border-radius:12px}fieldset{border:1px solid var(--line);border-radius:10px;padding:12px;display:grid;gap:8px;max-height:240px;overflow:auto}.check{display:flex;align-items:center;min-height:44px;gap:9px}.check input{width:18px;height:18px;accent-color:var(--accent)}small,.scope-note{font-size:13px;line-height:1.5}.pre-wrap{white-space:pre-wrap;overflow-wrap:anywhere;line-height:1.6}.knowledge-error{color:var(--danger,#c0392b);white-space:pre-wrap}.empty{padding:24px 8px;text-align:center;line-height:1.6}summary{cursor:pointer;min-height:36px;line-height:1.6}details p{margin-top:8px}\n@media(max-width:520px){header{padding:16px}h2{font-size:19px}nav{padding:8px}nav button{flex:1;white-space:nowrap}.knowledge-body{padding:16px;max-height:calc(100dvh - 250px)}.filters{display:grid}.filters form{min-width:0}}\n.knowledge-dialog--embedded{width:100%;max-height:none;border:0;border-radius:0;background:transparent;min-width:0}.knowledge-dialog--embedded .knowledge-body{padding:0;max-height:none;overflow:visible}.knowledge-dialog--embedded .actions{align-items:center}\n.project-heading{display:flex;align-items:flex-start;justify-content:space-between;gap:20px;margin-bottom:8px}.project-heading h3{font-size:18px;font-weight:650}.project-heading p{font-size:13px;color:var(--text-secondary);margin-top:6px;line-height:1.6}.knowledge-dialog--embedded .project-primary{flex-shrink:0;padding:8px 16px;background:var(--accent);color:var(--text-on-solid);border-color:var(--accent);font-size:13px}.project-list{border:1px solid var(--line);border-radius:11px;overflow:hidden}.project-list button{display:flex;gap:20px;width:100%;padding:18px 22px;border:0;border-radius:0;text-align:left;justify-content:flex-start;min-height:76px}.project-list button+button{border-top:1px solid var(--line)}.project-list button[aria-pressed=true]{background:var(--settings-selected);color:var(--text-primary)}.project-list button>span{flex:1;min-width:0;display:grid;gap:4px}.project-list strong{font-size:15px;font-weight:600;overflow-wrap:anywhere}.project-list small{font-size:12px}.project-list .app-icon{color:var(--text-muted)}.project-details{background:var(--settings-panel);padding:20px;border-radius:12px}.project-details h3{font-size:17px;font-weight:650;margin-bottom:12px}.project-description{font-size:13px;color:var(--text-secondary);line-height:1.6;padding-bottom:12px;white-space:pre-wrap;overflow-wrap:anywhere}.project-detail-row{display:grid;grid-template-columns:104px minmax(0,1fr);align-items:center;gap:16px;min-height:48px;border-top:1px solid var(--line);font-size:14px}.project-detail-row>span{color:var(--text-secondary)}.project-detail-row>div{overflow-wrap:anywhere}.project-detail-row button{min-height:36px;background:var(--settings-selected);border:0;font-size:12px}.project-members{display:flex;gap:10px;flex-wrap:wrap;padding-block:10px}.project-members>span{display:inline-flex;align-items:center;gap:7px}.project-detail-actions{display:flex;justify-content:flex-end;margin-top:8px}.project-detail-actions .project-primary{min-height:36px}.knowledge-dialog--embedded article{border:0;background:var(--settings-panel)}@media(max-width:520px){.project-heading{gap:10px}.project-heading p{max-width:210px}.project-list button{padding:16px;gap:12px}.project-details{padding:16px}.project-detail-row{grid-template-columns:76px minmax(0,1fr);gap:10px}}\n</style>\n<style scoped>.project-chevron{width:17px;height:17px;flex-shrink:0;color:var(--text-muted)}</style>\n"],"x_google_ignoreList":[0],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"WorkspaceKnowledgePanel-hy_IkIJI.js","names":["_hoisted_1","_openBlock","_createElementBlock","_createElementVNode"],"sources":["../../node_modules/@vicons/ionicons5/es/ChevronForwardOutline.js","../../src/client/components/app/ConnectionNetworkPanel.vue","../../src/client/components/app/ConnectionNetworkPanel.vue","../../src/shared/autoRouting.ts","../../src/shared/botModelSettings.ts","../../src/client/components/messages/AutoRouteNotice.vue","../../src/client/components/messages/AutoRouteNotice.vue","../../src/client/components/app/JevAutoPanel.vue","../../src/client/components/app/JevAutoPanel.vue","../../src/client/components/app/JevNetworkPanel.vue","../../src/client/components/app/JevNetworkPanel.vue","../../src/client/components/app/BotModelVisibilityPanel.vue","../../src/client/components/app/BotModelVisibilityPanel.vue","../../src/client/components/app/HermesProvidersPanel.vue","../../src/client/components/app/HermesProvidersPanel.vue","../../src/shared/hermesAuxiliary.ts","../../src/client/components/workspace/MemoryFilesPanel.vue","../../src/client/components/workspace/MemoryFilesPanel.vue","../../src/shared/collaborationPresentation.ts","../../src/shared/collaborationTimeline.ts","../../src/client/components/workspace/WorkspaceKnowledgePanel.vue","../../src/client/components/workspace/WorkspaceKnowledgePanel.vue"],"sourcesContent":["import { createElementVNode as _createElementVNode, openBlock as _openBlock, createElementBlock as _createElementBlock, defineComponent } from 'vue'\nconst _hoisted_1 = {\n xmlns: 'http://www.w3.org/2000/svg',\n 'xmlns:xlink': 'http://www.w3.org/1999/xlink',\n viewBox: '0 0 512 512'\n}\nexport default defineComponent({\n name: 'ChevronForwardOutline',\n render: function render(_ctx, _cache) {\n return (\n _openBlock(),\n _createElementBlock(\n 'svg',\n _hoisted_1,\n _cache[0] ||\n (_cache[0] = [\n _createElementVNode(\n 'path',\n {\n fill: 'none',\n stroke: 'currentColor',\n 'stroke-linecap': 'round',\n 'stroke-linejoin': 'round',\n 'stroke-width': '48',\n d: 'M184 112l144 144l-144 144'\n },\n null,\n -1 /* HOISTED */\n )\n ])\n )\n )\n }\n})\n","<script setup lang=\"ts\">\nimport { computed, onMounted, ref, watch } from 'vue'\nimport AppIcon from '@/components/common/AppIcon.vue'\nimport ModelNetworkChoice from './ModelNetworkChoice.vue'\nimport { modelNetworkApi } from '@/api/modelNetwork'\nimport type { ModelNetworkView, NetworkPolicy } from '@shared/modelNetwork'\nconst props=defineProps<{provider:string;name:string;bot?:string;canLogin?:boolean}>()\nconst emit=defineEmits<{back:[];login:[];changed:[];'dirty-change':[value:boolean];'busy-change':[value:boolean]}>()\nconst view=ref<ModelNetworkView>(),policy=ref<NetworkPolicy>({mode:'inherit'}),busy=ref(false),testing=ref(false),error=ref(''),notice=ref('')\nconst dirty=computed(()=>!!view.value&&JSON.stringify(policy.value)!==JSON.stringify(view.value.connections[props.provider]??{mode:'inherit'}))\nwatch(dirty,v=>emit('dirty-change',v));watch(busy,v=>emit('busy-change',v))\nasync function load(){try{view.value=await modelNetworkApi.get(props.bot);policy.value={...view.value.connections[props.provider]??{mode:'inherit'}}}catch(cause){error.value=cause instanceof Error?cause.message:'读取失败'}}\nfunction back(){if(!busy.value&&(!dirty.value||window.confirm('放弃尚未保存的网络更改?')))emit('back')}\nasync function save(login=false){busy.value=true;error.value='';try{view.value=await modelNetworkApi.save(view.value!.revision,policy.value,props.provider,props.bot);notice.value='网络设置已保存,从下一轮任务或新登录生效。';emit('changed');if(login)emit('login')}catch(cause){error.value=cause instanceof Error?cause.message:'保存失败'}finally{busy.value=false}}\nonMounted(load)\ndefineExpose({reset:()=>{if(view.value)policy.value={...view.value.connections[props.provider]??{mode:'inherit'}};notice.value=''}})\n</script>\n<template>\n <section class=\"connection-network\">\n <button class=\"back\" type=\"button\" :disabled=\"busy\" @click=\"back\"><AppIcon name=\"chevron-left\" :size=\"16\" />返回模型连接</button>\n <div class=\"connection-heading\"><h3>{{ name }}</h3><span>{{ canLogin?'尚未登录':'模型连接' }}</span></div>\n <p class=\"hint\">用于登录、自动续期、模型列表与模型请求。{{ bot?'继承服务器凭据时沿用服务器连接的网络;此处配置用于本 Bot 独立保存的凭据。':'' }}</p>\n <p v-if=\"error\" role=\"alert\">{{ error }}</p><p v-if=\"notice\" role=\"status\">{{ notice }}</p>\n <ModelNetworkChoice v-if=\"view\" v-model=\"policy\" :view=\"view\" :provider=\"provider\" :bot=\"bot\" :disabled=\"busy\" @busy=\"testing=$event\" />\n <footer v-if=\"view\"><button type=\"button\" :disabled=\"busy || !dirty\" @click=\"policy={...view.connections[provider]??{mode:'inherit'}}\">取消更改</button><button class=\"primary\" type=\"button\" :disabled=\"busy || testing || (!dirty && !canLogin) || (policy.mode==='proxy'&&!policy.proxyId)\" @click=\"save(!!canLogin)\">{{ busy?'正在保存…':canLogin?'保存并登录':'保存更改' }}</button></footer>\n </section>\n</template>\n<style scoped>\n.connection-heading{display:flex;align-items:center;gap:16px}.connection-heading span{font-size:12px;background:var(--surface-soft);color:var(--text-secondary);border-radius:20px;padding:4px 12px}.connection-heading h3{margin:0!important}\n.connection-network{display:grid;gap:8px;margin-top:-12px;max-width:100%;font-size:14px;line-height:1.6}.connection-network h3{margin:0 0 6px;font-size:24px;font-weight:600}.connection-network p{margin:0;color:var(--text-secondary)}.connection-network .hint{font-size:13px}.connection-network footer{display:flex;justify-content:space-between;gap:16px;border-top:1px solid var(--line);padding-top:16px}.connection-network button{min-height:44px;border:1px solid var(--line);border-radius:8px;padding:10px 16px;background:var(--surface);color:var(--text-primary);font:inherit;cursor:pointer}.connection-network .back{display:flex;align-items:center;gap:8px;justify-self:start;border:0;padding-left:0;color:var(--text-secondary)}.connection-network .primary{background:var(--accent);color:var(--text-on-solid);border-color:var(--accent)}.connection-network :disabled{opacity:.5}.connection-network [role=alert]{color:var(--danger)}.connection-network :focus-visible{outline:2px solid var(--accent);outline-offset:3px}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, onMounted, ref, watch } from 'vue'\nimport AppIcon from '@/components/common/AppIcon.vue'\nimport ModelNetworkChoice from './ModelNetworkChoice.vue'\nimport { modelNetworkApi } from '@/api/modelNetwork'\nimport type { ModelNetworkView, NetworkPolicy } from '@shared/modelNetwork'\nconst props=defineProps<{provider:string;name:string;bot?:string;canLogin?:boolean}>()\nconst emit=defineEmits<{back:[];login:[];changed:[];'dirty-change':[value:boolean];'busy-change':[value:boolean]}>()\nconst view=ref<ModelNetworkView>(),policy=ref<NetworkPolicy>({mode:'inherit'}),busy=ref(false),testing=ref(false),error=ref(''),notice=ref('')\nconst dirty=computed(()=>!!view.value&&JSON.stringify(policy.value)!==JSON.stringify(view.value.connections[props.provider]??{mode:'inherit'}))\nwatch(dirty,v=>emit('dirty-change',v));watch(busy,v=>emit('busy-change',v))\nasync function load(){try{view.value=await modelNetworkApi.get(props.bot);policy.value={...view.value.connections[props.provider]??{mode:'inherit'}}}catch(cause){error.value=cause instanceof Error?cause.message:'读取失败'}}\nfunction back(){if(!busy.value&&(!dirty.value||window.confirm('放弃尚未保存的网络更改?')))emit('back')}\nasync function save(login=false){busy.value=true;error.value='';try{view.value=await modelNetworkApi.save(view.value!.revision,policy.value,props.provider,props.bot);notice.value='网络设置已保存,从下一轮任务或新登录生效。';emit('changed');if(login)emit('login')}catch(cause){error.value=cause instanceof Error?cause.message:'保存失败'}finally{busy.value=false}}\nonMounted(load)\ndefineExpose({reset:()=>{if(view.value)policy.value={...view.value.connections[props.provider]??{mode:'inherit'}};notice.value=''}})\n</script>\n<template>\n <section class=\"connection-network\">\n <button class=\"back\" type=\"button\" :disabled=\"busy\" @click=\"back\"><AppIcon name=\"chevron-left\" :size=\"16\" />返回模型连接</button>\n <div class=\"connection-heading\"><h3>{{ name }}</h3><span>{{ canLogin?'尚未登录':'模型连接' }}</span></div>\n <p class=\"hint\">用于登录、自动续期、模型列表与模型请求。{{ bot?'继承服务器凭据时沿用服务器连接的网络;此处配置用于本 Bot 独立保存的凭据。':'' }}</p>\n <p v-if=\"error\" role=\"alert\">{{ error }}</p><p v-if=\"notice\" role=\"status\">{{ notice }}</p>\n <ModelNetworkChoice v-if=\"view\" v-model=\"policy\" :view=\"view\" :provider=\"provider\" :bot=\"bot\" :disabled=\"busy\" @busy=\"testing=$event\" />\n <footer v-if=\"view\"><button type=\"button\" :disabled=\"busy || !dirty\" @click=\"policy={...view.connections[provider]??{mode:'inherit'}}\">取消更改</button><button class=\"primary\" type=\"button\" :disabled=\"busy || testing || (!dirty && !canLogin) || (policy.mode==='proxy'&&!policy.proxyId)\" @click=\"save(!!canLogin)\">{{ busy?'正在保存…':canLogin?'保存并登录':'保存更改' }}</button></footer>\n </section>\n</template>\n<style scoped>\n.connection-heading{display:flex;align-items:center;gap:16px}.connection-heading span{font-size:12px;background:var(--surface-soft);color:var(--text-secondary);border-radius:20px;padding:4px 12px}.connection-heading h3{margin:0!important}\n.connection-network{display:grid;gap:8px;margin-top:-12px;max-width:100%;font-size:14px;line-height:1.6}.connection-network h3{margin:0 0 6px;font-size:24px;font-weight:600}.connection-network p{margin:0;color:var(--text-secondary)}.connection-network .hint{font-size:13px}.connection-network footer{display:flex;justify-content:space-between;gap:16px;border-top:1px solid var(--line);padding-top:16px}.connection-network button{min-height:44px;border:1px solid var(--line);border-radius:8px;padding:10px 16px;background:var(--surface);color:var(--text-primary);font:inherit;cursor:pointer}.connection-network .back{display:flex;align-items:center;gap:8px;justify-self:start;border:0;padding-left:0;color:var(--text-secondary)}.connection-network .primary{background:var(--accent);color:var(--text-on-solid);border-color:var(--accent)}.connection-network :disabled{opacity:.5}.connection-network [role=alert]{color:var(--danger)}.connection-network :focus-visible{outline:2px solid var(--accent);outline-offset:3px}\n</style>\n","import type { BotAutoCandidate, BotAutoPool, BotModelOption } from './botModelSettings.js'\n\nexport const autoTiers = ['light', 'standard', 'complex', 'deep'] as const\nexport type AutoTier = typeof autoTiers[number]\nexport const autoTierLabels: Record<AutoTier, string> = { light: '轻量', standard: '常规', complex: '复杂', deep: '深度' }\nexport const autoTierDescriptions: Record<AutoTier, string> = {\n light: '问候、短答、单步查询,以及目标清晰、范围有限的操作。',\n standard: '常规多步任务、一般分析与内容整理。',\n complex: '跨模块修改、复杂排查和有多项约束的工作。',\n deep: '高难推理、系统性研究与架构设计。',\n}\nexport const autoEfforts = ['low', 'medium', 'high', 'xhigh', 'max'] as const\nexport type AutoEffort = typeof autoEfforts[number]\nexport const effortOrder = ['none', 'minimal', ...autoEfforts, 'ultra'] as const\nexport const effortRank = (value: string) => (effortOrder as readonly string[]).indexOf(value)\nexport type AutoContinuity = 'new' | 'continue' | 'correction' | 'unclear'\nexport const autoContinuityLabels: Record<AutoContinuity, string> = { new: '新任务', continue: '继续未完成任务', correction: '纠正原任务', unclear: '上下文不足' }\nexport type AutoTaskRequirement = { tier: AutoTier; reasoningEffort: AutoEffort }\nexport type AutoRouteDecision = {\n provider: string\n model: string\n reasoningEffort: string\n confidence: number\n reason: 'jev' | 'jeff' | 'fallback' | 'single'\n taskTier?: AutoTier\n requestedTier?: AutoTier\n requestedEffort?: string\n continuity?: AutoContinuity\n taskRequirement?: AutoTaskRequirement\n explanation: string\n fallbackReason?: 'low_confidence' | 'invalid_response' | 'request_failed' | 'not_configured'\n probabilities?: Record<string, Record<string, number>>\n previous?: { provider: string; model: string }\n}\n\n/** Editable starting recommendations for existing pools; unknown models remain standard. */\nexport function suggestedAutoTier(model: string): AutoTier {\n if (model === 'gpt-6-luna') return 'light'\n if (model === 'gpt-6.1-sol') return 'complex'\n if (model === 'gpt-6-astra') return 'deep'\n return 'standard'\n}\nexport function candidateTier(candidate: BotAutoCandidate): AutoTier { return candidate.tier ?? suggestedAutoTier(candidate.model) }\nexport function autoPolicy(pool: BotAutoPool) {\n return { preserveTaskAbility: pool.preserveTaskAbility !== false, maxReasoningEffort: pool.maxReasoningEffort ?? 'high' as AutoEffort, fallbackReasoningEffort: pool.fallbackReasoningEffort ?? 'medium' }\n}\n\n/** No inferred effort ladder. Unknown capabilities use the provider default. */\nexport function compatibleAutoEffort(model: Pick<BotModelOption, 'reasoningKnown' | 'reasoningEfforts' | 'defaultReasoningEffort'>, requested: string, maximum: AutoEffort): string | null {\n if (!model.reasoningKnown) return 'default'\n if (!model.reasoningEfforts.length) return 'none'\n const supported = model.reasoningEfforts.filter(e => effortRank(e) >= 0 && effortRank(e) <= effortRank(maximum)).sort((a, b) => effortRank(a) - effortRank(b))\n if (!supported.length) return null\n if (requested === 'default') requested = model.defaultReasoningEffort ?? 'medium'\n if (requested === 'none' && supported.includes('none')) return 'none'\n if (supported.every(e => e === 'none')) return 'none'\n const target = Math.min(Math.max(effortRank(requested), effortRank('low')), effortRank(maximum))\n // Do not disable thinking just because a requested nonzero level is absent.\n const enabled = requested === 'none' ? supported : supported.filter(e => e !== 'none')\n if (!enabled.length) return null\n // A lower supported level cannot satisfy an established task's effort floor.\n return enabled.find(e => effortRank(e) >= target) ?? null\n}\n\nexport function selectAutoCombination(candidates: BotAutoCandidate[], options: BotModelOption[], requirement: AutoTaskRequirement, pool: BotAutoPool, preferred?: {provider: string; model: string}) {\n const policy = autoPolicy(pool)\n const eligible = candidates.flatMap((candidate, index) => {\n const option = options.find(o => o.provider === candidate.provider && o.model === candidate.model)\n if (!option || autoTiers.indexOf(candidateTier(candidate)) < autoTiers.indexOf(requirement.tier)) return []\n const reasoningEffort = compatibleAutoEffort(option, requirement.reasoningEffort, policy.maxReasoningEffort)\n return reasoningEffort === null ? [] : [{ ...candidate, reasoningEffort, index }]\n }).sort((a,b) => autoTiers.indexOf(candidateTier(a)) - autoTiers.indexOf(candidateTier(b)) || a.index - b.index)\n return (preferred && eligible.find(c => c.provider === preferred.provider && c.model === preferred.model)) || eligible[0]\n}\n","import type { HermesAuxiliaryOverrides, HermesFallbackChain } from './hermesAuxiliary.js'\nimport type { BotMediaSettings } from './botMediaSettings.js'\n\nexport type BotFastMode = 'normal' | 'fast' | 'auto' | 'cold'\n\n/** Virtual provider/model pair for TypeSafe Jev Auto routing. */\nexport const BOT_MODEL_AUTO_PROVIDER = 'auto'\nexport const BOT_MODEL_AUTO_MODEL = 'auto'\nexport const JEV_NETWORK_PROVIDER = 'typesafe'\nexport const BOT_AUTO_MIN_CANDIDATES = 2\nexport const BOT_AUTO_DEFAULT_MIN_CONFIDENCE = 0.55\n\nexport interface BotAutoCandidate {\n provider: string\n model: string\n /** Short capability hint for Jev Choice criteria. */\n blurb?: string\n /** User-configurable capability/cost tier; not a provider capability claim. */\n tier?: 'light' | 'standard' | 'complex' | 'deep'\n}\n\nexport interface BotAutoPool {\n candidates: BotAutoCandidate[]\n /** Used when Jev fails or confidence is low. Defaults to candidates[0]. */\n fallback?: { provider: string; model: string }\n minConfidence?: number\n preserveTaskAbility?: boolean\n maxReasoningEffort?: 'low' | 'medium' | 'high' | 'xhigh' | 'max'\n fallbackReasoningEffort?: string\n}\n\nexport interface BotModelPreset {\n provider: string\n model: string\n reasoningEffort: string | null\n fastMode: BotFastMode | null\n}\n\nexport interface BotModelSettings {\n /** Per-model tuning; editing an inactive model never selects it. Omitted PATCH preserves these. */\n modelPresets?: BotModelPreset[] | null\n provider: string | null\n model: string | null\n reasoningEffort: string | null\n fastMode: BotFastMode | null\n /** Hermes `auxiliary.<task>` overlay. Null inherits the system layer; omission in a PATCH preserves it. */\n auxiliary?: HermesAuxiliaryOverrides | null\n /** Hermes `fallback_model` overlay. Null inherits the system layer. */\n fallback?: HermesFallbackChain | null\n /** Null follows system defaults; omitted PATCH fields preserve Bot choices. */\n media?: BotMediaSettings | null\n /** Candidate pool for Auto (`provider`/`model` === `auto`). Omitted PATCH preserves it. */\n autoPool?: BotAutoPool | null\n}\n\nexport function isBotModelAuto(settings: Pick<BotModelSettings, 'provider' | 'model'> | null | undefined): boolean {\n return settings?.provider === BOT_MODEL_AUTO_PROVIDER && settings?.model === BOT_MODEL_AUTO_MODEL\n}\n\nexport function autoCandidateKey(candidate: Pick<BotAutoCandidate, 'provider' | 'model'>): string {\n return `${candidate.provider}::${candidate.model}`\n}\n\nexport function parseAutoCandidateKey(key: string): { provider: string; model: string } | null {\n const sep = key.indexOf('::')\n if (sep <= 0 || sep === key.length - 2) return null\n const provider = key.slice(0, sep), model = key.slice(sep + 2)\n return provider && model ? { provider, model } : null\n}\n\nexport function mergeBotModelSettings<T extends BotModelSettings>(current: BotModelSettings | null | undefined, patch: T | null | undefined) {\n if (!patch) return patch\n const next = { ...patch }\n if (!Object.hasOwn(patch, 'auxiliary') && current?.auxiliary !== undefined) next.auxiliary = current.auxiliary\n if (!Object.hasOwn(patch, 'fallback') && current?.fallback !== undefined) next.fallback = current.fallback\n if (!Object.hasOwn(patch, 'media') && current?.media !== undefined) next.media = current.media\n else if (patch.media && current?.media) next.media = { ...current.media, ...patch.media }\n if (!Object.hasOwn(patch, 'modelPresets') && current?.modelPresets !== undefined) next.modelPresets = current.modelPresets\n if (!Object.hasOwn(patch, 'autoPool') && current?.autoPool !== undefined) next.autoPool = current.autoPool\n return next\n}\n\nexport interface ResolvedBotModelSettings {\n provider: string\n model: string\n reasoningEffort: string\n fastMode: BotFastMode\n}\n\nexport interface BotModelOption {\n provider: string\n providerName?: string\n model: string\n name: string\n reasoningEfforts: string[]\n reasoningKnown: boolean\n fastModes: BotFastMode[]\n defaultReasoningEffort?: string\n contextWindow?: number\n contextBudget?: number\n /** Kept visible because this Bot already uses a model outside the curated list. */\n retained?: boolean\n}\n\nexport interface BotModelVisibilityView {\n revision: number\n /** null shows the full catalog; an array is the system's curated manual picker. */\n models: Array<{ provider: string; model: string }> | null\n}\n\nexport interface BotModelOptions {\n version: 1\n defaults: ResolvedBotModelSettings\n models: BotModelOption[]\n settings: BotModelSettings | null\n revision: number\n /** System-layer Hermes auxiliary slots for the Bot settings UI. */\n auxiliaryDefaults?: HermesAuxiliaryOverrides\n auto?: { available: boolean; enabled: boolean; candidateCount: number; unavailableReason?: string; backend?: 'jev' | 'jeff' }\n}\n\nexport const inheritedBotModelSettings = (): BotModelSettings => ({\n provider: null,\n model: null,\n reasoningEffort: null,\n fastMode: null,\n auxiliary: null,\n fallback: null,\n autoPool: null,\n})\n\nexport const botReasoningLabels: Record<string, string> = { none: '关闭', minimal: '最小', low: '低', medium: '中', high: '高', xhigh: '极高', max: '最大', ultra: 'Ultra' }\nexport const botFastLabels: Record<BotFastMode, string> = { normal: '普通', fast: '快速', auto: '每轮开始加速', cold: '首次回复加速' }\n\nexport function botModelChoices(options?: BotModelOptions) {\n if (!options) return [];\n const automaticDefault = !!options.auto?.enabled;\n const providerName = (row: { provider: string; providerName?: string; name: string }) =>\n row.providerName?.trim() || (row.name.includes(\" · \") ? row.name.split(\" · \")[0]!.trim() :\n ({ \"openai-codex\": \"OpenAI Codex\", openai: \"OpenAI\", anthropic: \"Anthropic\" } as Record<string, string>)[row.provider] || row.provider);\n const rows = options.models.filter(row => row.provider !== \"auto\").map(row => ({\n provider: row.provider, id: row.model, name: row.model, providerName: providerName(row),\n isDefault: !automaticDefault && row.provider === options.defaults.provider && row.model === options.defaults.model,\n disabled: false, hint: row.retained ? \"此 Bot 已选模型,系统可选清单外\" : \"\",\n }));\n if (!automaticDefault && !rows.some(row => row.isDefault)) rows.unshift({\n provider: \"inherit\", id: \"default\", name: options.defaults.model || \"默认模型\",\n providerName: options.defaults.provider || \"系统\", isDefault: true, disabled: false, hint: \"跟随系统默认\",\n });\n const decision = options.auto?.backend === 'jeff' ? 'Jeff' : 'Jev';\n const ordered = [...rows.filter(row => row.isDefault), {\n provider: \"auto\", id: \"auto\", name: \"Auto\", providerName: decision, isDefault: automaticDefault,\n disabled: !options.auto?.available, hint: options.auto?.unavailableReason || `使用系统 ${decision} 候选池`,\n }, ...rows.filter(row => !row.isDefault)];\n const explicit = !!options.settings?.provider && !!options.settings?.model;\n const current = explicit ? `${options.settings!.provider}:${options.settings!.model}` :\n automaticDefault ? \"auto:auto\" : `${options.defaults.provider}:${options.defaults.model}`;\n return ordered.map(row => ({ ...row, isCurrent: `${row.provider}:${row.id}` === current || (!explicit && row.provider === \"inherit\") }));\n}\n\n/** Decision backends for Auto routing: cloud TypeSafe Jev or local Jeff. */\nexport const DECISION_BACKENDS = ['jev', 'jeff'] as const\nexport type DecisionBackend = (typeof DECISION_BACKENDS)[number]\nexport const DECISION_BACKEND_LABELS: Record<DecisionBackend, string> = {\n jev: 'Jev(云端 TypeSafe)',\n jeff: 'Jeff(本机)',\n}\n/** Short name for Auto picker / chat controls. */\nexport function autoDecisionShortLabel(backend?: DecisionBackend | null): 'Jev' | 'Jeff' {\n return backend === 'jeff' ? 'Jeff' : 'Jev'\n}\nexport const TYPESAFE_SYSTEMONE_URL = 'https://api.typesafe.ai/v1/systemone'\nexport const JEV_DECISION_MODEL = 'jev-latest'\nexport const JEFF_DEFAULT_BASE_URL = 'http://127.0.0.1:8765'\nexport const JEFF_DEFAULT_MODEL = 'jeff-latest'\n","<script setup lang=\"ts\">\nimport { autoContinuityLabels, autoTierLabels, type AutoRouteDecision } from '@shared/autoRouting'\nimport { botReasoningLabels } from '@shared/botModelSettings'\ndefineProps<{ route: AutoRouteDecision }>()\nconst effortLabel = (value: string) => value === 'default' ? '提供方默认' : botReasoningLabels[value] ?? value\nconst sourceLabels = { jev: 'Jev 自动判断', jeff: 'Jeff 自动判断', fallback: '回退组合', single: '仅剩一个候选' }\n</script>\n<template>\n <details class=\"auto-route\" aria-label=\"Auto 选模依据\">\n <summary>Auto · {{ route.model }} · {{ effortLabel(route.reasoningEffort) }}{{ !['none','default'].includes(route.reasoningEffort) ? '思考' : '' }}<span v-if=\"route.reason !== 'jev' && route.reason !== 'jeff'\"> · 回退</span></summary>\n <div class=\"auto-route__detail\">\n <p>{{ route.explanation }}</p>\n <dl>\n <div><dt>决策来源</dt><dd>{{ sourceLabels[route.reason] }}</dd></div>\n <div v-if=\"route.taskTier\"><dt>任务能力</dt><dd>{{ autoTierLabels[route.taskTier] }}{{ route.requestedTier && route.requestedTier !== route.taskTier ? `(本轮判断 ${autoTierLabels[route.requestedTier]},保留任务下限)` : '' }}</dd></div>\n <div v-if=\"route.continuity\"><dt>任务关系</dt><dd>{{ autoContinuityLabels[route.continuity] }}</dd></div>\n <div><dt>判断置信度</dt><dd>{{ Math.round(route.confidence * 100) }}%</dd></div>\n <div v-if=\"route.requestedEffort && route.requestedEffort !== route.reasoningEffort\"><dt>思考适配</dt><dd>{{ effortLabel(route.requestedEffort) }} → {{ effortLabel(route.reasoningEffort) }}</dd></div>\n <div><dt>模型服务</dt><dd>{{ route.provider }}</dd></div>\n </dl>\n </div>\n </details>\n</template>\n<style scoped>\n.auto-route{max-width:100%;margin-top:8px;color:var(--text-secondary);font-size:12px;line-height:1.6;overflow-wrap:anywhere}.auto-route summary{cursor:pointer;min-height:28px;padding:4px 0}.auto-route summary:focus-visible{outline:2px solid var(--accent);outline-offset:2px}.auto-route__detail{padding:10px 12px;background:var(--surface-soft);border-radius:8px;margin-top:4px}.auto-route p{margin:0 0 8px}.auto-route dl{margin:0;display:grid;gap:5px}.auto-route dl>div{display:grid;grid-template-columns:88px minmax(0,1fr);gap:10px}.auto-route dt{color:var(--text-secondary)}.auto-route dd{margin:0;color:var(--text-primary)}@media(pointer:coarse){.auto-route summary{min-height:44px;display:list-item;align-content:center}}\n</style>\n","<script setup lang=\"ts\">\nimport { autoContinuityLabels, autoTierLabels, type AutoRouteDecision } from '@shared/autoRouting'\nimport { botReasoningLabels } from '@shared/botModelSettings'\ndefineProps<{ route: AutoRouteDecision }>()\nconst effortLabel = (value: string) => value === 'default' ? '提供方默认' : botReasoningLabels[value] ?? value\nconst sourceLabels = { jev: 'Jev 自动判断', jeff: 'Jeff 自动判断', fallback: '回退组合', single: '仅剩一个候选' }\n</script>\n<template>\n <details class=\"auto-route\" aria-label=\"Auto 选模依据\">\n <summary>Auto · {{ route.model }} · {{ effortLabel(route.reasoningEffort) }}{{ !['none','default'].includes(route.reasoningEffort) ? '思考' : '' }}<span v-if=\"route.reason !== 'jev' && route.reason !== 'jeff'\"> · 回退</span></summary>\n <div class=\"auto-route__detail\">\n <p>{{ route.explanation }}</p>\n <dl>\n <div><dt>决策来源</dt><dd>{{ sourceLabels[route.reason] }}</dd></div>\n <div v-if=\"route.taskTier\"><dt>任务能力</dt><dd>{{ autoTierLabels[route.taskTier] }}{{ route.requestedTier && route.requestedTier !== route.taskTier ? `(本轮判断 ${autoTierLabels[route.requestedTier]},保留任务下限)` : '' }}</dd></div>\n <div v-if=\"route.continuity\"><dt>任务关系</dt><dd>{{ autoContinuityLabels[route.continuity] }}</dd></div>\n <div><dt>判断置信度</dt><dd>{{ Math.round(route.confidence * 100) }}%</dd></div>\n <div v-if=\"route.requestedEffort && route.requestedEffort !== route.reasoningEffort\"><dt>思考适配</dt><dd>{{ effortLabel(route.requestedEffort) }} → {{ effortLabel(route.reasoningEffort) }}</dd></div>\n <div><dt>模型服务</dt><dd>{{ route.provider }}</dd></div>\n </dl>\n </div>\n </details>\n</template>\n<style scoped>\n.auto-route{max-width:100%;margin-top:8px;color:var(--text-secondary);font-size:12px;line-height:1.6;overflow-wrap:anywhere}.auto-route summary{cursor:pointer;min-height:28px;padding:4px 0}.auto-route summary:focus-visible{outline:2px solid var(--accent);outline-offset:2px}.auto-route__detail{padding:10px 12px;background:var(--surface-soft);border-radius:8px;margin-top:4px}.auto-route p{margin:0 0 8px}.auto-route dl{margin:0;display:grid;gap:5px}.auto-route dl>div{display:grid;grid-template-columns:88px minmax(0,1fr);gap:10px}.auto-route dt{color:var(--text-secondary)}.auto-route dd{margin:0;color:var(--text-primary)}@media(pointer:coarse){.auto-route summary{min-height:44px;display:list-item;align-content:center}}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, onMounted, ref, watch } from 'vue'\nimport { hermesApi, type HermesModelOptions, type JevAutoView } from '@/api/hermes'\nimport { autoEfforts, autoPolicy, autoTiers, autoTierLabels, autoTierDescriptions, candidateTier, compatibleAutoEffort, effortRank, suggestedAutoTier, type AutoEffort, type AutoRouteDecision, type AutoTier } from '@shared/autoRouting'\nimport { BOT_AUTO_DEFAULT_MIN_CONFIDENCE, DECISION_BACKEND_LABELS, DECISION_BACKENDS, JEFF_DEFAULT_BASE_URL, JEFF_DEFAULT_MODEL, botReasoningLabels, type BotAutoPool, type BotModelOption, type DecisionBackend } from '@shared/botModelSettings'\nimport AutoRouteNotice from '../messages/AutoRouteNotice.vue'\n\nconst props = defineProps<{ models?: HermesModelOptions; disabled?: boolean }>()\nconst emit = defineEmits<{ 'dirty-change': [value: boolean]; 'busy-change': [value: boolean] }>()\nconst view = ref<JevAutoView>(), modelOptions = ref<BotModelOption[]>([])\nconst enabled = ref(false), selected = ref<string[]>([]), fallback = ref(''), apiKey = ref('')\nconst backend = ref<DecisionBackend>('jev'), jeffBaseUrl = ref(JEFF_DEFAULT_BASE_URL), jeffModel = ref(JEFF_DEFAULT_MODEL)\nconst drafts = ref<Record<string, {tier: AutoTier; blurb: string}>>({})\nconst preserveTaskAbility = ref(true), maxReasoningEffort = ref<AutoEffort>('high'), fallbackReasoningEffort = ref('medium'), minConfidence = ref(BOT_AUTO_DEFAULT_MIN_CONFIDENCE)\nconst busy = ref(false), error = ref(''), notice = ref(''), baseline = ref(''), search = ref('')\nconst previewText = ref('你好'), preview = ref<AutoRouteDecision>(), previewBusy = ref(false), previewError = ref('')\nconst blocked = computed(() => props.disabled || busy.value || previewBusy.value || !view.value)\nconst keyOf = (provider: string, model: string) => JSON.stringify([provider, model])\nconst pairOf = (key: string) => { const [provider, model] = JSON.parse(key) as [string, string]; return { provider, model } }\nconst nameOf = (key: string) => pairOf(key).model\nconst optionOf = (key: string) => { const pair = pairOf(key); return modelOptions.value.find(m => m.provider === pair.provider && m.model === pair.model) }\nconst candidates = computed(() => selected.value.map(id => ({ ...pairOf(id), tier: drafts.value[id]?.tier ?? suggestedAutoTier(nameOf(id)), ...(drafts.value[id]?.blurb.trim() ? { blurb: drafts.value[id]!.blurb.trim() } : {}) })))\nconst pool = (): BotAutoPool => ({ candidates: candidates.value, ...(fallback.value ? { fallback: pairOf(fallback.value) } : {}), minConfidence: minConfidence.value, preserveTaskAbility: preserveTaskAbility.value, maxReasoningEffort: maxReasoningEffort.value, fallbackReasoningEffort: fallbackReasoningEffort.value })\nconst snapshot = () => JSON.stringify([enabled.value, backend.value, jeffBaseUrl.value.trim(), jeffModel.value.trim(), pool()])\nconst dirty = computed(() => !!view.value && (snapshot() !== baseline.value || !!apiKey.value.trim()))\nconst valid = computed(() => Number.isFinite(minConfidence.value) && minConfidence.value >= 0 && minConfidence.value <= 1 && (!enabled.value || selected.value.length >= 2))\nconst decisionReady = computed(() => backend.value === 'jeff' || !!apiKey.value.trim() || !!view.value?.hasApiKey)\nconst previewBlocked = computed(() => blocked.value || !enabled.value || !valid.value || !previewText.value.trim() || !decisionReady.value)\nwatch(dirty, value => emit('dirty-change', value))\nwatch(() => busy.value || previewBusy.value, value => emit('busy-change', value))\nwatch([snapshot, previewText, apiKey], () => { preview.value = undefined; previewError.value = '' })\nconst groups = computed(() => (props.models?.providers ?? []).filter(p => p.authenticated !== false && p.models.length))\nconst shownGroups = computed(() => groups.value.map(p => ({ ...p, models: p.models.filter(m => `${p.name} ${m}`.toLowerCase().includes(search.value.trim().toLowerCase())) })).filter(p => p.models.length))\nconst fallbackEfforts = computed(() => {\n const option = fallback.value ? optionOf(fallback.value) : undefined\n return option?.reasoningKnown ? autoEfforts.filter(e => option.reasoningEfforts.includes(e) && effortRank(e) <= effortRank(maxReasoningEffort.value)) : []\n})\nconst fallbackActual = computed(() => {\n const option = fallback.value ? optionOf(fallback.value) : undefined\n const value = option ? compatibleAutoEffort(option, fallbackReasoningEffort.value, maxReasoningEffort.value) : 'default'\n return value === null ? '当前模型无符合思考上限的档位' : value === 'default' ? '提供方默认' : botReasoningLabels[value] ?? value\n})\nconst thinkingLabel = computed(() => backend.value === 'jeff' ? '自动(Jeff)' : '自动(Jev)')\nfunction load(data: JevAutoView) {\n view.value = data\n if (data.modelOptions) modelOptions.value = data.modelOptions\n enabled.value = data.enabled\n backend.value = data.backend ?? 'jev'\n jeffBaseUrl.value = data.jeffBaseUrl || JEFF_DEFAULT_BASE_URL\n jeffModel.value = data.jeffModel || JEFF_DEFAULT_MODEL\n selected.value = data.candidates.map(c => keyOf(c.provider, c.model))\n drafts.value = Object.fromEntries(data.candidates.map(c => [keyOf(c.provider, c.model), {tier: candidateTier(c), blurb: c.blurb ?? ''}]))\n fallback.value = data.fallback ? keyOf(data.fallback.provider, data.fallback.model) : selected.value[0] ?? ''\n const policy = autoPolicy(data)\n preserveTaskAbility.value = policy.preserveTaskAbility; maxReasoningEffort.value = policy.maxReasoningEffort; fallbackReasoningEffort.value = policy.fallbackReasoningEffort\n minConfidence.value = data.minConfidence ?? BOT_AUTO_DEFAULT_MIN_CONFIDENCE\n apiKey.value = ''; baseline.value = snapshot()\n}\nfunction toggle(id: string) {\n if (!drafts.value[id]) drafts.value[id] = { tier: suggestedAutoTier(nameOf(id)), blurb: '' }\n selected.value = selected.value.includes(id) ? selected.value.filter(item => item !== id) : [...selected.value, id]\n if (!selected.value.includes(fallback.value)) fallback.value = selected.value[0] ?? ''\n}\nasync function save() {\n // The parent disables all panels while invoking their exposed save methods.\n if (!view.value || busy.value || previewBusy.value) return false\n if (!valid.value) { error.value = '请选择至少两个候选模型,并将置信度设为 0 到 1。'; return false }\n busy.value = true; error.value = ''; notice.value = ''\n try {\n load(await hermesApi.saveJev({\n revision: view.value.revision,\n enabled: enabled.value,\n backend: backend.value,\n jeffBaseUrl: jeffBaseUrl.value.trim() || JEFF_DEFAULT_BASE_URL,\n jeffModel: jeffModel.value.trim() || JEFF_DEFAULT_MODEL,\n ...pool(),\n ...(apiKey.value.trim() ? { apiKey: apiKey.value.trim() } : {}),\n }))\n notice.value = '自动选模已保存,新的 Bot 回合使用此配置。'\n return true\n } catch (cause) { error.value = cause instanceof Error ? cause.message : '保存失败'; return false }\n finally { busy.value = false }\n}\nasync function reset() {\n if (busy.value || previewBusy.value) return\n busy.value = true; error.value = ''; notice.value = ''\n try { load(await hermesApi.jev()) } catch (cause) { error.value = cause instanceof Error ? cause.message : '无法读取自动选模设置' }\n finally { busy.value = false }\n}\nasync function runPreview() {\n if (previewBlocked.value) return\n previewBusy.value = true; previewError.value = ''; preview.value = undefined\n try {\n preview.value = await hermesApi.previewJev({\n pool: pool(),\n enabled: enabled.value,\n userText: previewText.value.trim(),\n backend: backend.value,\n jeffBaseUrl: jeffBaseUrl.value.trim() || JEFF_DEFAULT_BASE_URL,\n jeffModel: jeffModel.value.trim() || JEFF_DEFAULT_MODEL,\n ...(apiKey.value.trim() ? { apiKey: apiKey.value.trim() } : {}),\n })\n }\n catch (cause) { previewError.value = cause instanceof Error ? cause.message : '预览失败' }\n finally { previewBusy.value = false }\n}\nonMounted(reset)\ndefineExpose({ reset, save })\n</script>\n<template>\n <section class=\"jev-auto\" aria-label=\"自动选模\" :aria-busy=\"busy || previewBusy\">\n <div class=\"jev-title\"><h4>自动选模</h4><label class=\"jev-toggle\"><input v-model=\"enabled\" type=\"checkbox\" :disabled=\"blocked\"> 启用自动选模</label></div>\n <p>由决策模型结合任务和上下文,选择能胜任的最轻模型与思考强度。关闭后 Bot 不可选择 Auto。</p>\n <p v-if=\"error\" class=\"error\" role=\"alert\">{{ error }}</p>\n <p v-if=\"notice\" role=\"status\">{{ notice }}</p>\n <label>决策服务<select v-model=\"backend\" aria-label=\"决策服务\" :disabled=\"blocked\"><option v-for=\"id in DECISION_BACKENDS\" :key=\"id\" :value=\"id\">{{ DECISION_BACKEND_LABELS[id] }}</option></select></label>\n <template v-if=\"backend === 'jeff'\">\n <div class=\"jev-fields\">\n <label>Jeff 地址<input v-model=\"jeffBaseUrl\" type=\"url\" placeholder=\"http://127.0.0.1:8765\" :disabled=\"blocked\"></label>\n <label>Jeff 模型<input v-model=\"jeffModel\" type=\"text\" placeholder=\"jeff-latest\" :disabled=\"blocked\"></label>\n </div>\n <p>本机 Jeff 默认无密钥。地址仅允许 127.0.0.1 / localhost。可用环境变量 <code>YAOVI_DECISION_BACKEND=jeff</code>、<code>JEFF_BASE_URL</code> 覆盖。</p>\n </template>\n <label v-else>TypeSafe API 密钥<input v-model=\"apiKey\" type=\"password\" autocomplete=\"new-password\" :placeholder=\"view?.hasApiKey ? '已保存,留空则不修改' : 'sk-…'\" :disabled=\"blocked\"></label>\n <div class=\"jev-section-title\"><h5>模型分工</h5><small>建议分工,可按实际表现调整</small></div>\n <div class=\"jev-roles\">\n <div v-for=\"id in selected\" :key=\"id\" class=\"jev-role\">\n <div class=\"jev-model-name\"><strong>{{ nameOf(id) }}</strong><small>{{ autoTierDescriptions[drafts[id]!.tier] }}</small><small v-if=\"modelOptions.length && !optionOf(id)\" class=\"error\">当前不可用</small></div>\n <label><span class=\"sr-only\">{{ nameOf(id) }} 的任务分工</span><select v-model=\"drafts[id]!.tier\" :aria-label=\"`${nameOf(id)} 的任务分工`\" :disabled=\"blocked\"><option v-for=\"tier in autoTiers\" :key=\"tier\" :value=\"tier\">{{ autoTierLabels[tier] }}任务</option></select></label>\n </div>\n <p v-if=\"!selected.length\">选择至少两个候选模型后配置分工。</p>\n </div>\n <details class=\"jev-picker\" :open=\"!selected.length\">\n <summary>选择候选模型 · 已选 {{ selected.length }} 个</summary>\n <label>筛选候选模型<input v-model=\"search\" type=\"search\" placeholder=\"搜索模型或供应商\" :disabled=\"blocked\"></label>\n <div class=\"jev-model-list\"><div v-for=\"group in shownGroups\" :key=\"group.slug\" class=\"jev-group\"><strong>{{ group.name }}</strong><label v-for=\"model in group.models\" :key=\"group.slug + model\"><input type=\"checkbox\" :checked=\"selected.includes(keyOf(group.slug, model))\" :disabled=\"blocked || selected.length >= 32 && !selected.includes(keyOf(group.slug, model))\" @change=\"toggle(keyOf(group.slug, model))\">{{ model }}</label></div><p v-if=\"!shownGroups.length\">没有匹配的已连接模型。</p><label v-for=\"id in selected.filter(key => !groups.some(g => g.slug === pairOf(key).provider && g.models.includes(nameOf(key))))\" :key=\"id\" class=\"jev-toggle\"><input type=\"checkbox\" checked :disabled=\"blocked\" @change=\"toggle(id)\">{{ nameOf(id) }}(目录外,可移除)</label></div>\n </details>\n <label class=\"jev-continuity\"><input v-model=\"preserveTaskAbility\" type=\"checkbox\" :disabled=\"blocked\"><span>保留未完成任务所需能力<small>继续复杂任务时保留能力与思考下限;新的简单任务允许降级。</small></span></label>\n <label>思考强度<input :value=\"thinkingLabel\" readonly aria-label=\"Auto 思考强度\"></label>\n <details class=\"jev-advanced\"><summary>高级设置与回退</summary>\n <div class=\"jev-fields\">\n <label>最高允许思考等级<select v-model=\"maxReasoningEffort\" :disabled=\"blocked\"><option v-for=\"effort in autoEfforts\" :key=\"effort\" :value=\"effort\">{{ botReasoningLabels[effort] }}</option></select></label>\n <label>最低置信度<input v-model.number=\"minConfidence\" type=\"number\" min=\"0\" max=\"1\" step=\"0.05\" :disabled=\"blocked\"></label>\n <label v-if=\"selected.length\">回退模型<select v-model=\"fallback\" :disabled=\"blocked\"><option v-for=\"id in selected\" :key=\"id\" :value=\"id\">{{ nameOf(id) }}</option></select></label>\n <label>回退思考强度<select v-model=\"fallbackReasoningEffort\" :disabled=\"blocked\"><option value=\"default\">模型默认</option><option v-if=\"fallbackReasoningEffort !== 'default' && !fallbackEfforts.includes(fallbackReasoningEffort as AutoEffort)\" :value=\"fallbackReasoningEffort\">{{ botReasoningLabels[fallbackReasoningEffort] }}(自动适配)</option><option v-for=\"effort in fallbackEfforts\" :key=\"effort\" :value=\"effort\">{{ botReasoningLabels[effort] }}</option></select><small>实际档位:{{ fallbackActual }}</small></label>\n </div>\n <p>回退不影响下一轮偏好。继续原任务时仍保留必要能力;思考档位未知时使用提供方默认。</p>\n <label v-for=\"id in selected\" :key=\"id\" class=\"jev-hint\">{{ nameOf(id) }} · 补充能力说明<input v-model=\"drafts[id]!.blurb\" maxlength=\"280\" placeholder=\"可选,例如擅长代码排查或长文分析\" :disabled=\"blocked\"></label>\n </details>\n <details class=\"jev-preview\"><summary>选模预览</summary>\n <p>使用当前草稿调用 {{ backend === 'jeff' ? 'Jeff' : 'Jev' }},仅判断这个新任务,不执行任务,也不保存设置。</p>\n <label>任务内容<textarea v-model=\"previewText\" maxlength=\"2000\" rows=\"2\" :disabled=\"blocked\" /></label>\n <button type=\"button\" :disabled=\"previewBlocked\" @click=\"runPreview\">{{ previewBusy ? (backend === 'jeff' ? 'Jeff 正在判断…' : 'Jev 正在判断…') : '预览模型与思考强度' }}</button>\n <p v-if=\"previewError\" class=\"error\" role=\"alert\">{{ previewError }}</p>\n <div aria-live=\"polite\"><AutoRouteNotice v-if=\"preview\" :route=\"preview\"/></div>\n </details>\n <button type=\"button\" :disabled=\"blocked || !dirty || !valid\" @click=\"save\">{{ busy ? '正在处理…' : '保存自动选模' }}</button>\n <button v-if=\"error\" type=\"button\" :disabled=\"busy || previewBusy\" @click=\"reset\">重新读取设置</button>\n </section>\n</template>\n<style scoped>\n.jev-auto{display:grid;gap:14px;margin-top:16px;padding-top:16px;border-top:1px solid var(--line);min-width:0}h4,h5,p{margin:0}h5{font-size:13px;font-weight:550}p,small{color:var(--text-secondary);font-size:12px;line-height:1.6}.jev-title,.jev-section-title{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap}.jev-model-list{display:grid;gap:16px;max-height:280px;overflow:auto;padding:4px}.jev-group{display:grid;gap:6px}.jev-group strong{font-size:12px;color:var(--text-secondary)}label{display:grid;gap:6px;font-size:13px;min-width:0}.jev-toggle,.jev-group label{display:flex;align-items:center;gap:8px;min-height:44px;overflow-wrap:anywhere}.jev-role{display:grid;grid-template-columns:minmax(0,1fr) 132px;gap:12px;align-items:center;padding:12px 0;border-bottom:1px solid var(--line)}.jev-role:last-child{border:0}.jev-model-name{display:grid;gap:4px;min-width:0;overflow-wrap:anywhere}.jev-model-name strong{font-size:13px;font-weight:550}.jev-continuity{display:flex;align-items:flex-start;gap:8px;min-height:44px}.jev-continuity input{margin-top:4px}.jev-continuity small{display:block;margin-top:3px}.jev-fields{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px}.jev-auto input:not([type=checkbox]),select,textarea{box-sizing:border-box;width:100%;min-width:0;min-height:44px;padding:8px 10px;border:1px solid var(--line);border-radius:8px;background:var(--surface);color:var(--text-primary);font:13px var(--font-ui)}textarea{resize:vertical}input[readonly]{color:var(--text-secondary)!important;background:var(--surface-soft)!important}.jev-auto details>label,.jev-auto details>p,.jev-auto details>.jev-fields,.jev-preview>button{margin-top:10px}.jev-auto summary{min-height:32px;cursor:pointer;color:var(--text-secondary);font-size:13px}.jev-picker>label{margin-bottom:10px}.jev-auto button{justify-self:start;min-height:44px;padding:8px 12px;border:1px solid var(--line);border-radius:8px;background:var(--surface);color:var(--text-primary);cursor:pointer;font:13px var(--font-ui)}.error{color:var(--danger)}.jev-auto :focus-visible{outline:2px solid var(--accent);outline-offset:2px}.jev-auto :disabled{opacity:.55;cursor:default}.sr-only{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}code{font-size:11px}@media(max-width:420px){.jev-fields{grid-template-columns:1fr}.jev-role{grid-template-columns:minmax(0,1fr) 108px;gap:8px}}@media(pointer:coarse){.jev-auto summary{min-height:44px;align-content:center}.jev-auto input:not([type=checkbox]),select,textarea{font-size:16px}}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, onMounted, ref, watch } from 'vue'\nimport { hermesApi, type HermesModelOptions, type JevAutoView } from '@/api/hermes'\nimport { autoEfforts, autoPolicy, autoTiers, autoTierLabels, autoTierDescriptions, candidateTier, compatibleAutoEffort, effortRank, suggestedAutoTier, type AutoEffort, type AutoRouteDecision, type AutoTier } from '@shared/autoRouting'\nimport { BOT_AUTO_DEFAULT_MIN_CONFIDENCE, DECISION_BACKEND_LABELS, DECISION_BACKENDS, JEFF_DEFAULT_BASE_URL, JEFF_DEFAULT_MODEL, botReasoningLabels, type BotAutoPool, type BotModelOption, type DecisionBackend } from '@shared/botModelSettings'\nimport AutoRouteNotice from '../messages/AutoRouteNotice.vue'\n\nconst props = defineProps<{ models?: HermesModelOptions; disabled?: boolean }>()\nconst emit = defineEmits<{ 'dirty-change': [value: boolean]; 'busy-change': [value: boolean] }>()\nconst view = ref<JevAutoView>(), modelOptions = ref<BotModelOption[]>([])\nconst enabled = ref(false), selected = ref<string[]>([]), fallback = ref(''), apiKey = ref('')\nconst backend = ref<DecisionBackend>('jev'), jeffBaseUrl = ref(JEFF_DEFAULT_BASE_URL), jeffModel = ref(JEFF_DEFAULT_MODEL)\nconst drafts = ref<Record<string, {tier: AutoTier; blurb: string}>>({})\nconst preserveTaskAbility = ref(true), maxReasoningEffort = ref<AutoEffort>('high'), fallbackReasoningEffort = ref('medium'), minConfidence = ref(BOT_AUTO_DEFAULT_MIN_CONFIDENCE)\nconst busy = ref(false), error = ref(''), notice = ref(''), baseline = ref(''), search = ref('')\nconst previewText = ref('你好'), preview = ref<AutoRouteDecision>(), previewBusy = ref(false), previewError = ref('')\nconst blocked = computed(() => props.disabled || busy.value || previewBusy.value || !view.value)\nconst keyOf = (provider: string, model: string) => JSON.stringify([provider, model])\nconst pairOf = (key: string) => { const [provider, model] = JSON.parse(key) as [string, string]; return { provider, model } }\nconst nameOf = (key: string) => pairOf(key).model\nconst optionOf = (key: string) => { const pair = pairOf(key); return modelOptions.value.find(m => m.provider === pair.provider && m.model === pair.model) }\nconst candidates = computed(() => selected.value.map(id => ({ ...pairOf(id), tier: drafts.value[id]?.tier ?? suggestedAutoTier(nameOf(id)), ...(drafts.value[id]?.blurb.trim() ? { blurb: drafts.value[id]!.blurb.trim() } : {}) })))\nconst pool = (): BotAutoPool => ({ candidates: candidates.value, ...(fallback.value ? { fallback: pairOf(fallback.value) } : {}), minConfidence: minConfidence.value, preserveTaskAbility: preserveTaskAbility.value, maxReasoningEffort: maxReasoningEffort.value, fallbackReasoningEffort: fallbackReasoningEffort.value })\nconst snapshot = () => JSON.stringify([enabled.value, backend.value, jeffBaseUrl.value.trim(), jeffModel.value.trim(), pool()])\nconst dirty = computed(() => !!view.value && (snapshot() !== baseline.value || !!apiKey.value.trim()))\nconst valid = computed(() => Number.isFinite(minConfidence.value) && minConfidence.value >= 0 && minConfidence.value <= 1 && (!enabled.value || selected.value.length >= 2))\nconst decisionReady = computed(() => backend.value === 'jeff' || !!apiKey.value.trim() || !!view.value?.hasApiKey)\nconst previewBlocked = computed(() => blocked.value || !enabled.value || !valid.value || !previewText.value.trim() || !decisionReady.value)\nwatch(dirty, value => emit('dirty-change', value))\nwatch(() => busy.value || previewBusy.value, value => emit('busy-change', value))\nwatch([snapshot, previewText, apiKey], () => { preview.value = undefined; previewError.value = '' })\nconst groups = computed(() => (props.models?.providers ?? []).filter(p => p.authenticated !== false && p.models.length))\nconst shownGroups = computed(() => groups.value.map(p => ({ ...p, models: p.models.filter(m => `${p.name} ${m}`.toLowerCase().includes(search.value.trim().toLowerCase())) })).filter(p => p.models.length))\nconst fallbackEfforts = computed(() => {\n const option = fallback.value ? optionOf(fallback.value) : undefined\n return option?.reasoningKnown ? autoEfforts.filter(e => option.reasoningEfforts.includes(e) && effortRank(e) <= effortRank(maxReasoningEffort.value)) : []\n})\nconst fallbackActual = computed(() => {\n const option = fallback.value ? optionOf(fallback.value) : undefined\n const value = option ? compatibleAutoEffort(option, fallbackReasoningEffort.value, maxReasoningEffort.value) : 'default'\n return value === null ? '当前模型无符合思考上限的档位' : value === 'default' ? '提供方默认' : botReasoningLabels[value] ?? value\n})\nconst thinkingLabel = computed(() => backend.value === 'jeff' ? '自动(Jeff)' : '自动(Jev)')\nfunction load(data: JevAutoView) {\n view.value = data\n if (data.modelOptions) modelOptions.value = data.modelOptions\n enabled.value = data.enabled\n backend.value = data.backend ?? 'jev'\n jeffBaseUrl.value = data.jeffBaseUrl || JEFF_DEFAULT_BASE_URL\n jeffModel.value = data.jeffModel || JEFF_DEFAULT_MODEL\n selected.value = data.candidates.map(c => keyOf(c.provider, c.model))\n drafts.value = Object.fromEntries(data.candidates.map(c => [keyOf(c.provider, c.model), {tier: candidateTier(c), blurb: c.blurb ?? ''}]))\n fallback.value = data.fallback ? keyOf(data.fallback.provider, data.fallback.model) : selected.value[0] ?? ''\n const policy = autoPolicy(data)\n preserveTaskAbility.value = policy.preserveTaskAbility; maxReasoningEffort.value = policy.maxReasoningEffort; fallbackReasoningEffort.value = policy.fallbackReasoningEffort\n minConfidence.value = data.minConfidence ?? BOT_AUTO_DEFAULT_MIN_CONFIDENCE\n apiKey.value = ''; baseline.value = snapshot()\n}\nfunction toggle(id: string) {\n if (!drafts.value[id]) drafts.value[id] = { tier: suggestedAutoTier(nameOf(id)), blurb: '' }\n selected.value = selected.value.includes(id) ? selected.value.filter(item => item !== id) : [...selected.value, id]\n if (!selected.value.includes(fallback.value)) fallback.value = selected.value[0] ?? ''\n}\nasync function save() {\n // The parent disables all panels while invoking their exposed save methods.\n if (!view.value || busy.value || previewBusy.value) return false\n if (!valid.value) { error.value = '请选择至少两个候选模型,并将置信度设为 0 到 1。'; return false }\n busy.value = true; error.value = ''; notice.value = ''\n try {\n load(await hermesApi.saveJev({\n revision: view.value.revision,\n enabled: enabled.value,\n backend: backend.value,\n jeffBaseUrl: jeffBaseUrl.value.trim() || JEFF_DEFAULT_BASE_URL,\n jeffModel: jeffModel.value.trim() || JEFF_DEFAULT_MODEL,\n ...pool(),\n ...(apiKey.value.trim() ? { apiKey: apiKey.value.trim() } : {}),\n }))\n notice.value = '自动选模已保存,新的 Bot 回合使用此配置。'\n return true\n } catch (cause) { error.value = cause instanceof Error ? cause.message : '保存失败'; return false }\n finally { busy.value = false }\n}\nasync function reset() {\n if (busy.value || previewBusy.value) return\n busy.value = true; error.value = ''; notice.value = ''\n try { load(await hermesApi.jev()) } catch (cause) { error.value = cause instanceof Error ? cause.message : '无法读取自动选模设置' }\n finally { busy.value = false }\n}\nasync function runPreview() {\n if (previewBlocked.value) return\n previewBusy.value = true; previewError.value = ''; preview.value = undefined\n try {\n preview.value = await hermesApi.previewJev({\n pool: pool(),\n enabled: enabled.value,\n userText: previewText.value.trim(),\n backend: backend.value,\n jeffBaseUrl: jeffBaseUrl.value.trim() || JEFF_DEFAULT_BASE_URL,\n jeffModel: jeffModel.value.trim() || JEFF_DEFAULT_MODEL,\n ...(apiKey.value.trim() ? { apiKey: apiKey.value.trim() } : {}),\n })\n }\n catch (cause) { previewError.value = cause instanceof Error ? cause.message : '预览失败' }\n finally { previewBusy.value = false }\n}\nonMounted(reset)\ndefineExpose({ reset, save })\n</script>\n<template>\n <section class=\"jev-auto\" aria-label=\"自动选模\" :aria-busy=\"busy || previewBusy\">\n <div class=\"jev-title\"><h4>自动选模</h4><label class=\"jev-toggle\"><input v-model=\"enabled\" type=\"checkbox\" :disabled=\"blocked\"> 启用自动选模</label></div>\n <p>由决策模型结合任务和上下文,选择能胜任的最轻模型与思考强度。关闭后 Bot 不可选择 Auto。</p>\n <p v-if=\"error\" class=\"error\" role=\"alert\">{{ error }}</p>\n <p v-if=\"notice\" role=\"status\">{{ notice }}</p>\n <label>决策服务<select v-model=\"backend\" aria-label=\"决策服务\" :disabled=\"blocked\"><option v-for=\"id in DECISION_BACKENDS\" :key=\"id\" :value=\"id\">{{ DECISION_BACKEND_LABELS[id] }}</option></select></label>\n <template v-if=\"backend === 'jeff'\">\n <div class=\"jev-fields\">\n <label>Jeff 地址<input v-model=\"jeffBaseUrl\" type=\"url\" placeholder=\"http://127.0.0.1:8765\" :disabled=\"blocked\"></label>\n <label>Jeff 模型<input v-model=\"jeffModel\" type=\"text\" placeholder=\"jeff-latest\" :disabled=\"blocked\"></label>\n </div>\n <p>本机 Jeff 默认无密钥。地址仅允许 127.0.0.1 / localhost。可用环境变量 <code>YAOVI_DECISION_BACKEND=jeff</code>、<code>JEFF_BASE_URL</code> 覆盖。</p>\n </template>\n <label v-else>TypeSafe API 密钥<input v-model=\"apiKey\" type=\"password\" autocomplete=\"new-password\" :placeholder=\"view?.hasApiKey ? '已保存,留空则不修改' : 'sk-…'\" :disabled=\"blocked\"></label>\n <div class=\"jev-section-title\"><h5>模型分工</h5><small>建议分工,可按实际表现调整</small></div>\n <div class=\"jev-roles\">\n <div v-for=\"id in selected\" :key=\"id\" class=\"jev-role\">\n <div class=\"jev-model-name\"><strong>{{ nameOf(id) }}</strong><small>{{ autoTierDescriptions[drafts[id]!.tier] }}</small><small v-if=\"modelOptions.length && !optionOf(id)\" class=\"error\">当前不可用</small></div>\n <label><span class=\"sr-only\">{{ nameOf(id) }} 的任务分工</span><select v-model=\"drafts[id]!.tier\" :aria-label=\"`${nameOf(id)} 的任务分工`\" :disabled=\"blocked\"><option v-for=\"tier in autoTiers\" :key=\"tier\" :value=\"tier\">{{ autoTierLabels[tier] }}任务</option></select></label>\n </div>\n <p v-if=\"!selected.length\">选择至少两个候选模型后配置分工。</p>\n </div>\n <details class=\"jev-picker\" :open=\"!selected.length\">\n <summary>选择候选模型 · 已选 {{ selected.length }} 个</summary>\n <label>筛选候选模型<input v-model=\"search\" type=\"search\" placeholder=\"搜索模型或供应商\" :disabled=\"blocked\"></label>\n <div class=\"jev-model-list\"><div v-for=\"group in shownGroups\" :key=\"group.slug\" class=\"jev-group\"><strong>{{ group.name }}</strong><label v-for=\"model in group.models\" :key=\"group.slug + model\"><input type=\"checkbox\" :checked=\"selected.includes(keyOf(group.slug, model))\" :disabled=\"blocked || selected.length >= 32 && !selected.includes(keyOf(group.slug, model))\" @change=\"toggle(keyOf(group.slug, model))\">{{ model }}</label></div><p v-if=\"!shownGroups.length\">没有匹配的已连接模型。</p><label v-for=\"id in selected.filter(key => !groups.some(g => g.slug === pairOf(key).provider && g.models.includes(nameOf(key))))\" :key=\"id\" class=\"jev-toggle\"><input type=\"checkbox\" checked :disabled=\"blocked\" @change=\"toggle(id)\">{{ nameOf(id) }}(目录外,可移除)</label></div>\n </details>\n <label class=\"jev-continuity\"><input v-model=\"preserveTaskAbility\" type=\"checkbox\" :disabled=\"blocked\"><span>保留未完成任务所需能力<small>继续复杂任务时保留能力与思考下限;新的简单任务允许降级。</small></span></label>\n <label>思考强度<input :value=\"thinkingLabel\" readonly aria-label=\"Auto 思考强度\"></label>\n <details class=\"jev-advanced\"><summary>高级设置与回退</summary>\n <div class=\"jev-fields\">\n <label>最高允许思考等级<select v-model=\"maxReasoningEffort\" :disabled=\"blocked\"><option v-for=\"effort in autoEfforts\" :key=\"effort\" :value=\"effort\">{{ botReasoningLabels[effort] }}</option></select></label>\n <label>最低置信度<input v-model.number=\"minConfidence\" type=\"number\" min=\"0\" max=\"1\" step=\"0.05\" :disabled=\"blocked\"></label>\n <label v-if=\"selected.length\">回退模型<select v-model=\"fallback\" :disabled=\"blocked\"><option v-for=\"id in selected\" :key=\"id\" :value=\"id\">{{ nameOf(id) }}</option></select></label>\n <label>回退思考强度<select v-model=\"fallbackReasoningEffort\" :disabled=\"blocked\"><option value=\"default\">模型默认</option><option v-if=\"fallbackReasoningEffort !== 'default' && !fallbackEfforts.includes(fallbackReasoningEffort as AutoEffort)\" :value=\"fallbackReasoningEffort\">{{ botReasoningLabels[fallbackReasoningEffort] }}(自动适配)</option><option v-for=\"effort in fallbackEfforts\" :key=\"effort\" :value=\"effort\">{{ botReasoningLabels[effort] }}</option></select><small>实际档位:{{ fallbackActual }}</small></label>\n </div>\n <p>回退不影响下一轮偏好。继续原任务时仍保留必要能力;思考档位未知时使用提供方默认。</p>\n <label v-for=\"id in selected\" :key=\"id\" class=\"jev-hint\">{{ nameOf(id) }} · 补充能力说明<input v-model=\"drafts[id]!.blurb\" maxlength=\"280\" placeholder=\"可选,例如擅长代码排查或长文分析\" :disabled=\"blocked\"></label>\n </details>\n <details class=\"jev-preview\"><summary>选模预览</summary>\n <p>使用当前草稿调用 {{ backend === 'jeff' ? 'Jeff' : 'Jev' }},仅判断这个新任务,不执行任务,也不保存设置。</p>\n <label>任务内容<textarea v-model=\"previewText\" maxlength=\"2000\" rows=\"2\" :disabled=\"blocked\" /></label>\n <button type=\"button\" :disabled=\"previewBlocked\" @click=\"runPreview\">{{ previewBusy ? (backend === 'jeff' ? 'Jeff 正在判断…' : 'Jev 正在判断…') : '预览模型与思考强度' }}</button>\n <p v-if=\"previewError\" class=\"error\" role=\"alert\">{{ previewError }}</p>\n <div aria-live=\"polite\"><AutoRouteNotice v-if=\"preview\" :route=\"preview\"/></div>\n </details>\n <button type=\"button\" :disabled=\"blocked || !dirty || !valid\" @click=\"save\">{{ busy ? '正在处理…' : '保存自动选模' }}</button>\n <button v-if=\"error\" type=\"button\" :disabled=\"busy || previewBusy\" @click=\"reset\">重新读取设置</button>\n </section>\n</template>\n<style scoped>\n.jev-auto{display:grid;gap:14px;margin-top:16px;padding-top:16px;border-top:1px solid var(--line);min-width:0}h4,h5,p{margin:0}h5{font-size:13px;font-weight:550}p,small{color:var(--text-secondary);font-size:12px;line-height:1.6}.jev-title,.jev-section-title{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap}.jev-model-list{display:grid;gap:16px;max-height:280px;overflow:auto;padding:4px}.jev-group{display:grid;gap:6px}.jev-group strong{font-size:12px;color:var(--text-secondary)}label{display:grid;gap:6px;font-size:13px;min-width:0}.jev-toggle,.jev-group label{display:flex;align-items:center;gap:8px;min-height:44px;overflow-wrap:anywhere}.jev-role{display:grid;grid-template-columns:minmax(0,1fr) 132px;gap:12px;align-items:center;padding:12px 0;border-bottom:1px solid var(--line)}.jev-role:last-child{border:0}.jev-model-name{display:grid;gap:4px;min-width:0;overflow-wrap:anywhere}.jev-model-name strong{font-size:13px;font-weight:550}.jev-continuity{display:flex;align-items:flex-start;gap:8px;min-height:44px}.jev-continuity input{margin-top:4px}.jev-continuity small{display:block;margin-top:3px}.jev-fields{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px}.jev-auto input:not([type=checkbox]),select,textarea{box-sizing:border-box;width:100%;min-width:0;min-height:44px;padding:8px 10px;border:1px solid var(--line);border-radius:8px;background:var(--surface);color:var(--text-primary);font:13px var(--font-ui)}textarea{resize:vertical}input[readonly]{color:var(--text-secondary)!important;background:var(--surface-soft)!important}.jev-auto details>label,.jev-auto details>p,.jev-auto details>.jev-fields,.jev-preview>button{margin-top:10px}.jev-auto summary{min-height:32px;cursor:pointer;color:var(--text-secondary);font-size:13px}.jev-picker>label{margin-bottom:10px}.jev-auto button{justify-self:start;min-height:44px;padding:8px 12px;border:1px solid var(--line);border-radius:8px;background:var(--surface);color:var(--text-primary);cursor:pointer;font:13px var(--font-ui)}.error{color:var(--danger)}.jev-auto :focus-visible{outline:2px solid var(--accent);outline-offset:2px}.jev-auto :disabled{opacity:.55;cursor:default}.sr-only{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}code{font-size:11px}@media(max-width:420px){.jev-fields{grid-template-columns:1fr}.jev-role{grid-template-columns:minmax(0,1fr) 108px;gap:8px}}@media(pointer:coarse){.jev-auto summary{min-height:44px;align-content:center}.jev-auto input:not([type=checkbox]),select,textarea{font-size:16px}}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, onMounted, ref, watch } from 'vue'\nimport { modelNetworkApi } from '@/api/modelNetwork'\nimport { JEV_NETWORK_PROVIDER } from '@shared/botModelSettings'\nimport type { ModelNetworkView, NetworkPolicy } from '@shared/modelNetwork'\nimport ModelNetworkChoice from './ModelNetworkChoice.vue'\ndefineProps<{ disabled?: boolean }>()\nconst emit = defineEmits<{ 'dirty-change': [value: boolean]; 'busy-change': [value: boolean]; 'manage-network': [] }>()\nconst view = ref<ModelNetworkView>(), policy = ref<NetworkPolicy>({ mode: 'inherit' })\nconst busy = ref(false), testing = ref(false), error = ref(''), notice = ref('')\nconst dirty = computed(() => !!view.value && JSON.stringify(policy.value) !== JSON.stringify(view.value.connections[JEV_NETWORK_PROVIDER] ?? { mode: 'inherit' }))\nwatch(dirty, value => emit('dirty-change', value)); watch(() => busy.value || testing.value, value => emit('busy-change', value))\nasync function reset() {\n error.value = ''; notice.value = ''\n try { view.value = await modelNetworkApi.get(); policy.value = { ...view.value.connections[JEV_NETWORK_PROVIDER] ?? { mode: 'inherit' } } }\n catch (cause) { error.value = cause instanceof Error ? cause.message : '无法读取 Jev 网络设置' }\n}\nasync function save() {\n if (!view.value || busy.value || testing.value) return false\n busy.value = true; error.value = ''; notice.value = ''\n try { view.value = await modelNetworkApi.save(view.value.revision, policy.value, JEV_NETWORK_PROVIDER); notice.value = 'Jev 独立网络已保存,从下一次选模请求生效。'; return true }\n catch (cause) { error.value = cause instanceof Error ? cause.message : '保存失败,草稿已保留。'; return false }\n finally { busy.value = false }\n}\nonMounted(reset); defineExpose({ reset, save })\n</script>\n<template>\n <section class=\"jev-network\" aria-label=\"Jev 独立网络\">\n <h4>Jev 独立网络</h4><p>仅用于云端 TypeSafe Jev 选模请求。选择本机 Jeff 时走回环,不经此代理。各模型供应商使用各自的连接网络。</p>\n <p v-if=\"error\" class=\"error\" role=\"alert\">{{ error }}</p><p v-if=\"notice\" role=\"status\">{{ notice }}</p>\n <ModelNetworkChoice v-if=\"view\" v-model=\"policy\" :view=\"view\" :provider=\"JEV_NETWORK_PROVIDER\" :disabled=\"disabled || busy\" compact @busy=\"testing = $event\" />\n <div class=\"actions\"><button type=\"button\" :disabled=\"disabled || busy || testing || !dirty || policy.mode === 'proxy' && !policy.proxyId\" @click=\"save\">{{ busy ? '正在保存…' : '保存 Jev 网络' }}</button><button type=\"button\" :disabled=\"disabled || busy || testing\" @click=\"emit('manage-network')\">管理代理</button><button v-if=\"error\" type=\"button\" :disabled=\"disabled || busy || testing\" @click=\"reset\">重新读取</button></div>\n </section>\n</template>\n<style scoped>\n.jev-network{display:grid;gap:12px;min-width:0;margin-top:20px;padding-top:20px;border-top:1px solid var(--line)}h4,p{margin:0}p{color:var(--text-secondary);font-size:13px;line-height:1.6}.actions{display:flex;flex-wrap:wrap;gap:12px}button{min-height:44px;padding:8px 12px;border:1px solid var(--line);border-radius:8px;background:var(--surface);color:var(--text-primary);font:13px var(--font-ui);cursor:pointer}.error{color:var(--danger)}:disabled{opacity:.55;cursor:default}:focus-visible{outline:2px solid var(--accent);outline-offset:2px}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, onMounted, ref, watch } from 'vue'\nimport { modelNetworkApi } from '@/api/modelNetwork'\nimport { JEV_NETWORK_PROVIDER } from '@shared/botModelSettings'\nimport type { ModelNetworkView, NetworkPolicy } from '@shared/modelNetwork'\nimport ModelNetworkChoice from './ModelNetworkChoice.vue'\ndefineProps<{ disabled?: boolean }>()\nconst emit = defineEmits<{ 'dirty-change': [value: boolean]; 'busy-change': [value: boolean]; 'manage-network': [] }>()\nconst view = ref<ModelNetworkView>(), policy = ref<NetworkPolicy>({ mode: 'inherit' })\nconst busy = ref(false), testing = ref(false), error = ref(''), notice = ref('')\nconst dirty = computed(() => !!view.value && JSON.stringify(policy.value) !== JSON.stringify(view.value.connections[JEV_NETWORK_PROVIDER] ?? { mode: 'inherit' }))\nwatch(dirty, value => emit('dirty-change', value)); watch(() => busy.value || testing.value, value => emit('busy-change', value))\nasync function reset() {\n error.value = ''; notice.value = ''\n try { view.value = await modelNetworkApi.get(); policy.value = { ...view.value.connections[JEV_NETWORK_PROVIDER] ?? { mode: 'inherit' } } }\n catch (cause) { error.value = cause instanceof Error ? cause.message : '无法读取 Jev 网络设置' }\n}\nasync function save() {\n if (!view.value || busy.value || testing.value) return false\n busy.value = true; error.value = ''; notice.value = ''\n try { view.value = await modelNetworkApi.save(view.value.revision, policy.value, JEV_NETWORK_PROVIDER); notice.value = 'Jev 独立网络已保存,从下一次选模请求生效。'; return true }\n catch (cause) { error.value = cause instanceof Error ? cause.message : '保存失败,草稿已保留。'; return false }\n finally { busy.value = false }\n}\nonMounted(reset); defineExpose({ reset, save })\n</script>\n<template>\n <section class=\"jev-network\" aria-label=\"Jev 独立网络\">\n <h4>Jev 独立网络</h4><p>仅用于云端 TypeSafe Jev 选模请求。选择本机 Jeff 时走回环,不经此代理。各模型供应商使用各自的连接网络。</p>\n <p v-if=\"error\" class=\"error\" role=\"alert\">{{ error }}</p><p v-if=\"notice\" role=\"status\">{{ notice }}</p>\n <ModelNetworkChoice v-if=\"view\" v-model=\"policy\" :view=\"view\" :provider=\"JEV_NETWORK_PROVIDER\" :disabled=\"disabled || busy\" compact @busy=\"testing = $event\" />\n <div class=\"actions\"><button type=\"button\" :disabled=\"disabled || busy || testing || !dirty || policy.mode === 'proxy' && !policy.proxyId\" @click=\"save\">{{ busy ? '正在保存…' : '保存 Jev 网络' }}</button><button type=\"button\" :disabled=\"disabled || busy || testing\" @click=\"emit('manage-network')\">管理代理</button><button v-if=\"error\" type=\"button\" :disabled=\"disabled || busy || testing\" @click=\"reset\">重新读取</button></div>\n </section>\n</template>\n<style scoped>\n.jev-network{display:grid;gap:12px;min-width:0;margin-top:20px;padding-top:20px;border-top:1px solid var(--line)}h4,p{margin:0}p{color:var(--text-secondary);font-size:13px;line-height:1.6}.actions{display:flex;flex-wrap:wrap;gap:12px}button{min-height:44px;padding:8px 12px;border:1px solid var(--line);border-radius:8px;background:var(--surface);color:var(--text-primary);font:13px var(--font-ui);cursor:pointer}.error{color:var(--danger)}:disabled{opacity:.55;cursor:default}:focus-visible{outline:2px solid var(--accent);outline-offset:2px}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, onMounted, ref, watch } from 'vue'\nimport { hermesApi, type HermesModelOptions } from '@/api/hermes'\nimport type { BotModelVisibilityView } from '@shared/botModelSettings'\nconst props = defineProps<{ models?: HermesModelOptions; disabled?: boolean }>()\nconst emit = defineEmits<{ 'dirty-change': [value: boolean]; 'busy-change': [value: boolean] }>()\nconst view = ref<BotModelVisibilityView>(), curated = ref(false), selected = ref<string[]>([]), search = ref(''), provider = ref('')\nconst busy = ref(false), error = ref(''), notice = ref(''), baseline = ref('')\nconst key = (provider: string, model: string) => JSON.stringify([provider, model])\nconst groups = computed(() => (props.models?.providers ?? []).filter(p => p.authenticated !== false && p.models.length))\nconst filtered = computed(() => groups.value.filter(p => !provider.value || p.slug === provider.value).map(p => ({ ...p, models: p.models.filter(m => `${p.name} ${m}`.toLowerCase().includes(search.value.trim().toLowerCase())) })).filter(p => p.models.length))\nconst draft = () => JSON.stringify(curated.value ? [...selected.value].sort() : null)\nconst dirty = computed(() => !!view.value && draft() !== baseline.value)\nwatch(dirty, v => emit('dirty-change', v)); watch(busy, v => emit('busy-change', v))\nfunction load(data: BotModelVisibilityView) { view.value = data; curated.value = data.models !== null; selected.value = data.models?.map(m => key(m.provider, m.model)) ?? []; baseline.value = draft() }\nfunction toggle(id: string) { selected.value = selected.value.includes(id) ? selected.value.filter(item => item !== id) : [...selected.value, id] }\nfunction selectResults(add: boolean) { const keys = filtered.value.flatMap(p => p.models.map(m => key(p.slug, m))); selected.value = add ? [...new Set([...selected.value, ...keys])] : selected.value.filter(id => !keys.includes(id)) }\nasync function reset() { error.value = ''; notice.value = ''; try { load(await hermesApi.botModels()) } catch (cause) { error.value = cause instanceof Error ? cause.message : '无法读取 Bot 可选模型' } }\nasync function save() {\n if (!view.value || busy.value) return false\n busy.value = true; error.value = ''; notice.value = ''\n try { load(await hermesApi.saveBotModels({ revision: view.value.revision, models: curated.value ? selected.value.map(id => { const [provider, model] = JSON.parse(id) as [string, string]; return { provider, model } }) : null })); notice.value = 'Bot 可选模型已保存,重新打开模型选择即可读取。'; return true }\n catch (cause) { error.value = cause instanceof Error ? cause.message : '保存失败,草稿已保留。'; return false } finally { busy.value = false }\n}\nonMounted(reset); defineExpose({ reset, save })\n</script>\n<template>\n <section class=\"bot-model-visibility\" aria-label=\"Bot 可选模型\">\n <h4>Bot 可选模型</h4><p>统一精简 Bot 的手动对话模型列表。已有选择会保留;Auto 使用上方自动选模的候选池。</p>\n <p v-if=\"error\" class=\"error\" role=\"alert\">{{ error }}</p><p v-if=\"notice\" role=\"status\">{{ notice }}</p>\n <label class=\"toggle\"><input v-model=\"curated\" type=\"checkbox\" :disabled=\"disabled || busy || !view\"> 只显示勾选的模型</label>\n <template v-if=\"curated\">\n <div class=\"filters\"><label>搜索模型<input v-model=\"search\" type=\"search\" placeholder=\"搜索模型或供应商\" :disabled=\"disabled || busy\"></label><label>供应商<select v-model=\"provider\" :disabled=\"disabled || busy\"><option value=\"\">全部已连接供应商</option><option v-for=\"group in groups\" :key=\"group.slug\" :value=\"group.slug\">{{ group.name }}</option></select></label></div>\n <div class=\"actions\"><button type=\"button\" :disabled=\"disabled || busy\" @click=\"selectResults(true)\">全选搜索结果</button><button type=\"button\" :disabled=\"disabled || busy\" @click=\"selectResults(false)\">取消搜索结果</button><small role=\"status\">已勾选 {{ selected.length }} 个模型</small></div>\n <div class=\"model-list\"><div v-for=\"group in filtered\" :key=\"group.slug\" class=\"model-group\"><strong>{{ group.name }}</strong><label v-for=\"model in group.models\" :key=\"model\" class=\"toggle\"><input type=\"checkbox\" :checked=\"selected.includes(key(group.slug, model))\" :disabled=\"disabled || busy\" @change=\"toggle(key(group.slug, model))\">{{ model }}</label></div><p v-if=\"!filtered.length\">没有匹配的模型,请调整搜索或供应商筛选。</p></div>\n <small v-if=\"!selected.length\">未勾选时只显示跟随系统默认、Auto 和此 Bot 已有选择。</small>\n </template>\n <p v-else>当前显示所有已连接模型。</p>\n <div class=\"actions\"><button type=\"button\" :disabled=\"disabled || busy || !dirty || !models\" @click=\"save\">{{ busy ? '正在保存…' : '保存 Bot 可选模型' }}</button><button v-if=\"error\" type=\"button\" :disabled=\"disabled || busy\" @click=\"reset\">重新读取</button></div>\n </section>\n</template>\n<style scoped>\n.bot-model-visibility{display:grid;gap:12px;min-width:0;border-top:1px solid var(--line);margin-top:20px;padding-top:20px}h4,p{margin:0}p,small{font-size:13px;line-height:1.6;color:var(--text-secondary)}label{display:grid;gap:6px;min-width:0;font-size:13px}.toggle{display:flex;align-items:center;gap:8px;min-height:44px;overflow-wrap:anywhere}.filters{display:grid;grid-template-columns:1fr 1fr;gap:12px}input[type=search],select{box-sizing:border-box;width:100%;min-width:0;min-height:44px;padding:8px 10px;border:1px solid var(--line);border-radius:8px;background:var(--surface);color:var(--text-primary);font:13px var(--font-ui)}.actions{display:flex;flex-wrap:wrap;align-items:center;gap:12px}button{min-height:44px;padding:8px 12px;border:1px solid var(--line);border-radius:8px;background:var(--surface);color:var(--text-primary);cursor:pointer;font:13px var(--font-ui)}.model-list{display:grid;gap:16px;max-height:280px;overflow:auto;padding:4px}.model-group{display:grid;gap:4px}.model-group strong{color:var(--text-secondary);font-size:12px}.error{color:var(--danger)}:disabled{opacity:.55;cursor:default}:focus-visible{outline:2px solid var(--accent);outline-offset:2px}@media(max-width:600px){.filters{grid-template-columns:1fr}}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, onMounted, ref, watch } from 'vue'\nimport { hermesApi, type HermesModelOptions } from '@/api/hermes'\nimport type { BotModelVisibilityView } from '@shared/botModelSettings'\nconst props = defineProps<{ models?: HermesModelOptions; disabled?: boolean }>()\nconst emit = defineEmits<{ 'dirty-change': [value: boolean]; 'busy-change': [value: boolean] }>()\nconst view = ref<BotModelVisibilityView>(), curated = ref(false), selected = ref<string[]>([]), search = ref(''), provider = ref('')\nconst busy = ref(false), error = ref(''), notice = ref(''), baseline = ref('')\nconst key = (provider: string, model: string) => JSON.stringify([provider, model])\nconst groups = computed(() => (props.models?.providers ?? []).filter(p => p.authenticated !== false && p.models.length))\nconst filtered = computed(() => groups.value.filter(p => !provider.value || p.slug === provider.value).map(p => ({ ...p, models: p.models.filter(m => `${p.name} ${m}`.toLowerCase().includes(search.value.trim().toLowerCase())) })).filter(p => p.models.length))\nconst draft = () => JSON.stringify(curated.value ? [...selected.value].sort() : null)\nconst dirty = computed(() => !!view.value && draft() !== baseline.value)\nwatch(dirty, v => emit('dirty-change', v)); watch(busy, v => emit('busy-change', v))\nfunction load(data: BotModelVisibilityView) { view.value = data; curated.value = data.models !== null; selected.value = data.models?.map(m => key(m.provider, m.model)) ?? []; baseline.value = draft() }\nfunction toggle(id: string) { selected.value = selected.value.includes(id) ? selected.value.filter(item => item !== id) : [...selected.value, id] }\nfunction selectResults(add: boolean) { const keys = filtered.value.flatMap(p => p.models.map(m => key(p.slug, m))); selected.value = add ? [...new Set([...selected.value, ...keys])] : selected.value.filter(id => !keys.includes(id)) }\nasync function reset() { error.value = ''; notice.value = ''; try { load(await hermesApi.botModels()) } catch (cause) { error.value = cause instanceof Error ? cause.message : '无法读取 Bot 可选模型' } }\nasync function save() {\n if (!view.value || busy.value) return false\n busy.value = true; error.value = ''; notice.value = ''\n try { load(await hermesApi.saveBotModels({ revision: view.value.revision, models: curated.value ? selected.value.map(id => { const [provider, model] = JSON.parse(id) as [string, string]; return { provider, model } }) : null })); notice.value = 'Bot 可选模型已保存,重新打开模型选择即可读取。'; return true }\n catch (cause) { error.value = cause instanceof Error ? cause.message : '保存失败,草稿已保留。'; return false } finally { busy.value = false }\n}\nonMounted(reset); defineExpose({ reset, save })\n</script>\n<template>\n <section class=\"bot-model-visibility\" aria-label=\"Bot 可选模型\">\n <h4>Bot 可选模型</h4><p>统一精简 Bot 的手动对话模型列表。已有选择会保留;Auto 使用上方自动选模的候选池。</p>\n <p v-if=\"error\" class=\"error\" role=\"alert\">{{ error }}</p><p v-if=\"notice\" role=\"status\">{{ notice }}</p>\n <label class=\"toggle\"><input v-model=\"curated\" type=\"checkbox\" :disabled=\"disabled || busy || !view\"> 只显示勾选的模型</label>\n <template v-if=\"curated\">\n <div class=\"filters\"><label>搜索模型<input v-model=\"search\" type=\"search\" placeholder=\"搜索模型或供应商\" :disabled=\"disabled || busy\"></label><label>供应商<select v-model=\"provider\" :disabled=\"disabled || busy\"><option value=\"\">全部已连接供应商</option><option v-for=\"group in groups\" :key=\"group.slug\" :value=\"group.slug\">{{ group.name }}</option></select></label></div>\n <div class=\"actions\"><button type=\"button\" :disabled=\"disabled || busy\" @click=\"selectResults(true)\">全选搜索结果</button><button type=\"button\" :disabled=\"disabled || busy\" @click=\"selectResults(false)\">取消搜索结果</button><small role=\"status\">已勾选 {{ selected.length }} 个模型</small></div>\n <div class=\"model-list\"><div v-for=\"group in filtered\" :key=\"group.slug\" class=\"model-group\"><strong>{{ group.name }}</strong><label v-for=\"model in group.models\" :key=\"model\" class=\"toggle\"><input type=\"checkbox\" :checked=\"selected.includes(key(group.slug, model))\" :disabled=\"disabled || busy\" @change=\"toggle(key(group.slug, model))\">{{ model }}</label></div><p v-if=\"!filtered.length\">没有匹配的模型,请调整搜索或供应商筛选。</p></div>\n <small v-if=\"!selected.length\">未勾选时只显示跟随系统默认、Auto 和此 Bot 已有选择。</small>\n </template>\n <p v-else>当前显示所有已连接模型。</p>\n <div class=\"actions\"><button type=\"button\" :disabled=\"disabled || busy || !dirty || !models\" @click=\"save\">{{ busy ? '正在保存…' : '保存 Bot 可选模型' }}</button><button v-if=\"error\" type=\"button\" :disabled=\"disabled || busy\" @click=\"reset\">重新读取</button></div>\n </section>\n</template>\n<style scoped>\n.bot-model-visibility{display:grid;gap:12px;min-width:0;border-top:1px solid var(--line);margin-top:20px;padding-top:20px}h4,p{margin:0}p,small{font-size:13px;line-height:1.6;color:var(--text-secondary)}label{display:grid;gap:6px;min-width:0;font-size:13px}.toggle{display:flex;align-items:center;gap:8px;min-height:44px;overflow-wrap:anywhere}.filters{display:grid;grid-template-columns:1fr 1fr;gap:12px}input[type=search],select{box-sizing:border-box;width:100%;min-width:0;min-height:44px;padding:8px 10px;border:1px solid var(--line);border-radius:8px;background:var(--surface);color:var(--text-primary);font:13px var(--font-ui)}.actions{display:flex;flex-wrap:wrap;align-items:center;gap:12px}button{min-height:44px;padding:8px 12px;border:1px solid var(--line);border-radius:8px;background:var(--surface);color:var(--text-primary);cursor:pointer;font:13px var(--font-ui)}.model-list{display:grid;gap:16px;max-height:280px;overflow:auto;padding:4px}.model-group{display:grid;gap:4px}.model-group strong{color:var(--text-secondary);font-size:12px}.error{color:var(--danger)}:disabled{opacity:.55;cursor:default}:focus-visible{outline:2px solid var(--accent);outline-offset:2px}@media(max-width:600px){.filters{grid-template-columns:1fr}}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, nextTick, onMounted, ref, watch } from 'vue'\nimport AppIcon from '@/components/common/AppIcon.vue'\nimport ConnectionNetworkPanel from './ConnectionNetworkPanel.vue'\nimport { modelNetworkApi, networkLabel } from '@/api/modelNetwork'\nimport type { ModelNetworkView } from '@shared/modelNetwork'\nimport ProviderLoginDialog from './ProviderLoginDialog.vue'\nimport JevAutoPanel from './JevAutoPanel.vue'\nimport JevNetworkPanel from './JevNetworkPanel.vue'\nimport BotModelVisibilityPanel from './BotModelVisibilityPanel.vue'\nimport { hermesApi, hermesMediaApi, type HermesEnvVar, type HermesModelOptions, type HermesOAuthProvider, type HermesPoolEntry, type HermesProvider } from '@/api/hermes'\n\n/**\n * Hermes provider management (same operations as the Hermes dashboard).\n * Without `bot` it edits the system layer; with `bot` it edits that Bot's own Hermes home,\n * whose logins and keys override the system layer.\n */\nconst networkView=ref<ModelNetworkView>(), networkConnection=ref<{id:string;name:string}>(), networkDirty=ref(false)\nconst networkEditor=ref<InstanceType<typeof ConnectionNetworkPanel>>()\nasync function refreshNetwork(){try{networkView.value=await modelNetworkApi.get(props.bot)}catch{networkView.value=undefined}}\nfunction networkText(id:string){return networkView.value?(props.bot?'独立凭据网络:':'网络:')+networkLabel(networkView.value,networkView.value.connections[id]??{mode:'inherit'}):'设置连接网络'}\nfunction openNetwork(id:string,name:string){networkConnection.value={id,name}}\nfunction closeNetwork(){networkDirty.value=false;networkConnection.value=undefined;void refreshNetwork()}\nonMounted(refreshNetwork)\nconst props = withDefaults(defineProps<{ bot?: string; section?: 'all' | 'connections' | 'defaults' | 'auto' | 'visibility'; embedded?: boolean; formId?: string }>(), { section: 'all', embedded: false })\nconst emit = defineEmits<{ changed: []; 'dirty-change': [value: boolean]; 'can-save-change': [value: boolean]; 'busy-change': [value: boolean]; 'manage-network': [] }>()\nconst jevEditor = ref<InstanceType<typeof JevAutoPanel>>(), jevNetworkEditor = ref<InstanceType<typeof JevNetworkPanel>>(), botModelsEditor = ref<InstanceType<typeof BotModelVisibilityPanel>>()\nconst jevDirty = ref(false), jevNetworkDirty = ref(false), botModelsDirty = ref(false)\nconst jevBusy = ref(false), jevNetworkBusy = ref(false), botModelsBusy = ref(false)\nconst panelsDirty = computed(() => jevDirty.value || jevNetworkDirty.value || botModelsDirty.value)\nconst panelsBusy = computed(() => jevBusy.value || jevNetworkBusy.value || botModelsBusy.value)\nconst providers = ref<HermesProvider[]>([]), oauth = ref<HermesOAuthProvider[]>([]), env = ref<Record<string, HermesEnvVar>>({})\nconst models = ref<HermesModelOptions>(), mainProvider = ref(''), mainModel = ref('')\nconst fallbackText = ref(''), filter = ref(''), busy = ref(false), error = ref(''), notice = ref('')\nconst loginProvider = ref<HermesOAuthProvider>()\nlet loginTrigger: HTMLElement | undefined\nconst keyDraft = ref<Record<string, string>>({}), poolOpen = ref(''), pool = ref<HermesPoolEntry[]>([]), poolKey = ref(''), poolLabel = ref(''), strategy = ref('fill_first')\nconst endpoint = ref({ name: '', base_url: '', model: '', api_key: '', api_mode: '' })\nconst mediaKeys = ref<Array<{ key: string; prompt: string; isSet: boolean; uses: string[] }>>([])\nconst mediaDraft = ref<Record<string, string>>({})\nconst mutating = ref(false)\nconst loaded = ref(false), showAll = ref(props.section === 'all'), catalogError = ref('')\nconst savedMain = ref({ provider: '', model: '' }), savedFallback = ref('')\nconst defaultsForm = ref<HTMLFormElement>()\n\nconst shown = computed(() => {\n const f = filter.value.trim().toLowerCase()\n return providers.value.filter(p => (showAll.value || !!f || configured(p)) && (!f || p.id.includes(f) || p.label.toLowerCase().includes(f) || p.aliases.some(a => a.includes(f))))\n})\nconst oauthFor = (id: string) => oauth.value.find(p => p.id === id)\n// Sign-ins that have no provider row of their own (e.g. claude-code, copilot-acp).\nconst loneOauth = computed(() => oauth.value.filter(o => !providers.value.some(p => p.id === o.id)))\nconst keyVar = (p: HermesProvider) => p.envVars[0]\nconst configured = (p: HermesProvider) => !!oauthFor(p.id)?.status.logged_in || p.envVars.some(v => env.value[v]?.is_set)\nconst providerModels = computed(() => models.value?.providers.find(p => p.slug === mainProvider.value)?.models ?? [])\nconst authorizedProviders = computed(() => models.value?.providers.filter(p => p.authenticated === true) ?? [])\nconst mainAuthorized = computed(() => authorizedProviders.value.some(p => p.slug === mainProvider.value))\nconst customConnections = computed(() => models.value?.providers.filter(p => (p.authenticated === true || p.is_current) && !providers.value.some(provider => provider.id === p.slug)) ?? [])\nconst mainDirty = computed(() => loaded.value && (mainProvider.value !== savedMain.value.provider || mainModel.value !== savedMain.value.model))\nconst fallbackDirty = computed(() => loaded.value && fallbackText.value !== savedFallback.value)\nconst connectionDirty = computed(() => Object.values(keyDraft.value).some(Boolean) || Object.values(endpoint.value).some(Boolean) || !!poolKey.value || !!poolLabel.value || Object.values(mediaDraft.value).some(value => value.trim()))\nconst dirty = computed(() => networkDirty.value || panelsDirty.value || (props.section === 'defaults' ? mainDirty.value || fallbackDirty.value : props.section === 'connections' ? connectionDirty.value : mainDirty.value || fallbackDirty.value || connectionDirty.value))\nwatch(dirty, value => { if (value) notice.value = ''; emit('dirty-change', value) })\nwatch(() => loaded.value && !busy.value && !panelsBusy.value && (!mainDirty.value || (mainAuthorized.value && !!mainModel.value.trim())) && (mainDirty.value || fallbackDirty.value || panelsDirty.value), value => emit('can-save-change', value), { immediate: true })\nwatch(() => mutating.value || panelsBusy.value, value => emit('busy-change', value), { immediate: true })\nasync function refreshModels() {\n await guard(async () => { models.value = await hermesApi.models(true); catalogError.value = '' }, '模型列表已刷新', false)\n}\n\n\nasync function guard(fn: () => Promise<unknown>, ok?: string, blocksNavigation = true) {\n if (busy.value || panelsBusy.value) return\n busy.value = true; mutating.value = blocksNavigation; error.value = ''; notice.value = ''\n try { const result = await fn(); if (ok && result !== false) notice.value = ok } catch (e) { error.value = e instanceof Error ? e.message : '操作失败' } finally { busy.value = false; mutating.value = false }\n}\nasync function load() {\n await guard(async () => {\n const [p, o, e, c] = await Promise.all([props.section === 'defaults' ? Promise.resolve({ providers: [] as HermesProvider[] }) : hermesApi.providers(props.bot), props.section === 'defaults' ? Promise.resolve({ providers: [] as HermesOAuthProvider[] }) : hermesApi.oauth(props.bot), props.section === 'defaults' ? Promise.resolve({} as Record<string, HermesEnvVar>) : hermesApi.env(props.bot), hermesApi.config(props.bot)])\n providers.value = p.providers; oauth.value = o.providers; env.value = e\n mainProvider.value = c.config.model?.provider ?? ''; mainModel.value = c.config.model?.default ?? ''\n const fb = c.config.fallback_model\n fallbackText.value = (Array.isArray(fb) ? fb : fb ? [fb] : []).map(f => `${f.provider} ${f.model}`).join('\\n')\n savedMain.value = { provider: mainProvider.value, model: mainModel.value }; savedFallback.value = fallbackText.value; loaded.value = true\n if (!props.bot) models.value = await hermesApi.models(false).catch(() => { catalogError.value = '暂时无法读取模型列表,可重试刷新。'; return undefined })\n await loadMediaKeys()\n }, undefined, false)\n}\nasync function loadMediaKeys() {\n if (props.bot || (props.section !== 'all' && props.section !== 'connections')) { mediaKeys.value = []; return }\n try {\n const [image, video] = await Promise.all([hermesMediaApi.config('image_gen'), hermesMediaApi.config('video_gen')])\n const known = new Set(providers.value.flatMap(p => p.envVars))\n const rows = new Map<string, { key: string; prompt: string; isSet: boolean; uses: string[] }>()\n for (const [label, value] of [['图片', image], ['视频', video]] as const) {\n for (const provider of value?.providers ?? []) for (const field of provider.env_vars ?? []) {\n if (!field.key || known.has(field.key)) continue\n const row = rows.get(field.key) ?? { key: field.key, prompt: field.prompt || field.key, isSet: false, uses: [] }\n row.isSet = row.isSet || !!field.is_set || !!env.value[field.key]?.is_set\n const use = `${label} · ${provider.name}`\n if (!row.uses.includes(use)) row.uses.push(use)\n rows.set(field.key, row)\n }\n }\n mediaKeys.value = [...rows.values()]\n } catch { mediaKeys.value = [] }\n}\ndefineExpose({ reset: () => networkConnection.value ? networkEditor.value?.reset() : Promise.all([load(), jevEditor.value?.reset(), jevNetworkEditor.value?.reset(), botModelsEditor.value?.reset()]) })\nonMounted(load)\n\nasync function saveMediaKey(key: string) {\n const value = mediaDraft.value[key]?.trim()\n if (!value) return\n await guard(async () => {\n await hermesApi.setEnv(key, value, props.bot)\n mediaDraft.value[key] = ''\n env.value = await hermesApi.env(props.bot)\n await loadMediaKeys()\n emit('changed')\n }, '媒体密钥已保存')\n}\nasync function saveKey(p: HermesProvider) {\n const key = keyVar(p), value = keyDraft.value[p.id]?.trim()\n if (!key || !value) return\n await guard(async () => { await hermesApi.setEnv(key, value, props.bot); keyDraft.value[p.id] = ''; env.value = await hermesApi.env(props.bot); emit('changed') }, `${p.label} 密钥已保存`)\n}\nasync function removeKey(key: string) {\n await guard(async () => { await hermesApi.deleteEnv(key, props.bot); env.value = await hermesApi.env(props.bot); await loadMediaKeys(); emit('changed') }, '密钥已移除')\n}\nfunction login(id: string) {\n if (busy.value || loginProvider.value) return\n loginTrigger = document.activeElement instanceof HTMLElement ? document.activeElement : undefined\n loginProvider.value = oauthFor(id)\n}\nfunction closeLogin() {\n loginProvider.value = undefined\n void nextTick(() => { if (loginTrigger?.isConnected) loginTrigger.focus({ preventScroll: true }) })\n}\nasync function loginSucceeded() {\n notice.value = '登录成功'\n emit('changed')\n try {\n const [o, e] = await Promise.all([hermesApi.oauth(props.bot), hermesApi.env(props.bot)])\n oauth.value = o.providers; env.value = e\n } catch { error.value = '登录已完成,连接状态刷新失败,请刷新页面。' }\n}\nasync function logout(id: string) {\n await guard(async () => { await hermesApi.oauthDisconnect(id, props.bot); oauth.value = (await hermesApi.oauth(props.bot)).providers; emit('changed') }, '已退出登录')\n}\nasync function openPool(id: string) {\n if (poolOpen.value === id) { poolOpen.value = ''; return }\n await guard(async () => { const r = await hermesApi.pool(id, props.bot); pool.value = r.entries; strategy.value = r.strategy; poolOpen.value = id }, undefined, false)\n}\nasync function addPool() {\n const id = poolOpen.value\n if (!id || !poolKey.value.trim()) return\n await guard(async () => { await hermesApi.addPool(id, poolKey.value.trim(), poolLabel.value.trim(), props.bot); poolKey.value = ''; poolLabel.value = ''; pool.value = (await hermesApi.pool(id, props.bot)).entries; emit('changed') }, '已加入凭据池')\n}\nasync function removePool(index: number) {\n const id = poolOpen.value\n await guard(async () => { await hermesApi.removePool(id, index, props.bot); pool.value = (await hermesApi.pool(id, props.bot)).entries; emit('changed') }, '已移除')\n}\nasync function saveStrategy() {\n const id = poolOpen.value\n await guard(async () => {\n const current = (await hermesApi.config(props.bot)).config.credential_pool_strategies ?? {}\n await hermesApi.patchConfig({ credential_pool_strategies: { ...current, [id]: strategy.value } }, props.bot)\n }, '轮换策略已保存')\n}\nasync function writeMain(confirm = false): Promise<boolean> {\n const result = await hermesApi.setModel({ scope: 'main', provider: mainProvider.value, model: mainModel.value.trim(), ...(confirm ? { confirm_expensive_model: true } : {}) })\n if (result.confirm_required) {\n if (!confirm && window.confirm(result.confirm_message || '该模型费用较高,确认使用?')) return writeMain(true)\n return false\n }\n savedMain.value = { provider: mainProvider.value, model: mainModel.value }\n emit('changed')\n return true\n}\nfunction fallbackRows() {\n return fallbackText.value.split('\\n').map(line => line.trim()).filter(Boolean).map((line, index) => {\n const parts = line.split(/\\s+/)\n if (parts.length !== 2) throw new Error('回退模型第 ' + (index + 1) + ' 行需要填写供应商和模型,以空格分隔。')\n return { provider: parts[0]!, model: parts[1]! }\n })\n}\nasync function writeFallback(rows = fallbackRows()) {\n await hermesApi.patchConfig({ fallback_model: rows.length ? rows : null }, props.bot)\n savedFallback.value = fallbackText.value\n emit('changed')\n}\nasync function saveMain() {\n if (!mainAuthorized.value || !mainModel.value.trim()) return\n await guard(() => writeMain(), '默认模型已保存,新一轮对话生效')\n}\nasync function saveFallback() { await guard(() => writeFallback(), '故障回退已保存') }\nasync function saveDefaults() {\n if (!defaultsForm.value?.reportValidity() || !loaded.value || (mainDirty.value && !mainAuthorized.value)) return\n await guard(async () => {\n // Validate both sections before changing either. Successful sections retain their own baseline after a partial failure.\n const rows = fallbackRows()\n let mainSaved = false\n if (mainDirty.value) { if (!await writeMain()) return false; mainSaved = true }\n try { if (fallbackDirty.value) await writeFallback(rows) }\n catch (cause) { if (mainSaved) throw new Error('默认模型已保存,故障回退尚未保存。' + (cause instanceof Error ? cause.message : '请重试。')); throw cause }\n if (jevDirty.value && await jevEditor.value?.save() === false) return false\n if (jevNetworkDirty.value && await jevNetworkEditor.value?.save() === false) return false\n if (botModelsDirty.value && await botModelsEditor.value?.save() === false) return false\n return true\n }, '设置已保存,新一轮对话生效')\n}\nasync function saveEndpoint() {\n const e = endpoint.value\n if (!e.name.trim() || !e.base_url.trim()) return\n await guard(async () => {\n await hermesApi.saveEndpoint({ name: e.name.trim(), base_url: e.base_url.trim(), model: e.model.trim(), ...(e.api_key.trim() ? { api_key: e.api_key.trim() } : {}), api_mode: e.api_mode }, props.bot)\n endpoint.value = { name: '', base_url: '', model: '', api_key: '', api_mode: '' }\n const refreshed = await Promise.all([hermesApi.providers(props.bot), hermesApi.oauth(props.bot), hermesApi.env(props.bot)])\n providers.value = refreshed[0].providers; oauth.value = refreshed[1].providers; env.value = refreshed[2]\n if (!props.bot) models.value = await hermesApi.models()\n emit('changed')\n }, '自定义端点已保存')\n}\n</script>\n<template>\n <section class=\"hermes-providers\" :aria-busy=\"busy\" aria-label=\"Hermes 供应商\">\n<p v-if=\"section !== 'defaults' && !networkConnection\" class=\"note\">{{ bot ? '这里的登录和密钥只对此 Bot 生效,并覆盖系统默认连接。' : '连接供服务器中的 Bot 使用;登录与密钥安全保存,凭据不会完整回显。' }}</p>\n <p v-if=\"error\" class=\"error\" role=\"alert\">{{ error }}</p>\n <p v-if=\"notice\" role=\"status\">{{ notice }}</p>\n <ProviderLoginDialog v-if=\"loginProvider\" :key=\"loginProvider.id\" :provider=\"loginProvider\" :bot=\"bot\" @close=\"closeLogin();refreshNetwork()\" @success=\"loginSucceeded\" />\n\n <ConnectionNetworkPanel v-if=\"networkConnection\" ref=\"networkEditor\" :provider=\"networkConnection.id\" :name=\"networkConnection.name\" :bot=\"bot\" :can-login=\"!!oauthFor(networkConnection.id) && !oauthFor(networkConnection.id)!.status.logged_in\" @back=\"closeNetwork\" @login=\"login(networkConnection!.id)\" @changed=\"refreshNetwork\" @dirty-change=\"networkDirty=$event\" @busy-change=\"mutating=$event\" />\n <template v-if=\"!networkConnection\">\n <form v-if=\"!bot && section !== 'connections'\" :id=\"formId\" ref=\"defaultsForm\" class=\"defaults-form\" @submit.prevent=\"saveDefaults\">\n <template v-if=\"section === 'all' || section === 'defaults'\">\n <div class=\"defaults-heading\"><h4>默认对话模型</h4><p>Bot 未单独指定模型时使用此配置。</p></div>\n <label class=\"setting-row\"><span><strong>供应商</strong><small>只列出模型连接中已授权的供应商。</small></span><select v-model=\"mainProvider\" :required=\"mainDirty\" aria-label=\"默认模型供应商\" :disabled=\"busy || !loaded\"><option value=\"\">请选择</option><option v-for=\"p in authorizedProviders\" :key=\"p.slug\" :value=\"p.slug\">{{ p.name }}</option><option v-if=\"mainProvider && !mainAuthorized\" :value=\"mainProvider\">{{ models?.providers.find(p => p.slug === mainProvider)?.name || mainProvider }}(未授权)</option></select></label>\n <label class=\"setting-row\"><span><strong>模型</strong><small>选择默认的对话模型。</small></span><input v-model=\"mainModel\" :required=\"mainDirty\" aria-label=\"默认对话模型\" list=\"hermes-main-models\" :disabled=\"busy || !loaded\" placeholder=\"选择或输入模型 ID\" /></label>\n <datalist id=\"hermes-main-models\"><option v-for=\"m in providerModels\" :key=\"m\" :value=\"m\" /></datalist>\n <div class=\"defaults-status\"><span :class=\"{ configured: mainAuthorized }\">{{ !loaded ? '正在读取配置…' : catalogError || (mainAuthorized ? '服务已授权' : mainProvider ? '该供应商尚未授权,请先到模型连接完成授权。' : '请选择已授权的模型服务') }}</span><button type=\"button\" class=\"refresh-models\" :disabled=\"busy\" @click=\"refreshModels\"><AppIcon name=\"refresh\" :size=\"16\" />刷新模型列表</button></div>\n <button v-if=\"!embedded\" type=\"button\" :disabled=\"busy || !mainAuthorized || !mainModel.trim()\" @click=\"saveMain\">保存默认模型</button>\n <div class=\"fallback-section\"><h4>故障回退</h4><p>默认模型不可用时,按顺序尝试备用模型。</p><details><summary><span>回退模型</span><span>{{ fallbackText.trim() ? fallbackText.trim().split('\\n').length + ' 个备用模型' : '尚未设置' }}</span><AppIcon name=\"chevron-left\" :size=\"18\" /></summary><label>备用模型顺序<textarea v-model=\"fallbackText\" rows=\"4\" placeholder=\"每行:供应商 模型,以空格分隔\" :disabled=\"busy\" /></label><small>按从上到下的顺序尝试;留空可关闭回退。</small><button v-if=\"!embedded\" type=\"button\" :disabled=\"busy\" @click=\"saveFallback\">保存回退链</button></details></div>\n </template>\n <JevAutoPanel v-if=\"section === 'all' || section === 'auto'\" ref=\"jevEditor\" :models=\"models\" :disabled=\"busy || panelsBusy\" @dirty-change=\"jevDirty=$event\" @busy-change=\"jevBusy=$event\" />\n <JevNetworkPanel v-if=\"section === 'all' || section === 'auto'\" ref=\"jevNetworkEditor\" :disabled=\"busy || panelsBusy\" @dirty-change=\"jevNetworkDirty=$event\" @busy-change=\"jevNetworkBusy=$event\" @manage-network=\"emit('manage-network')\" />\n <BotModelVisibilityPanel v-if=\"section === 'all' || section === 'visibility'\" ref=\"botModelsEditor\" :models=\"models\" :disabled=\"busy || panelsBusy\" @dirty-change=\"botModelsDirty=$event\" @busy-change=\"botModelsBusy=$event\" />\n </form>\n\n <template v-if=\"section === 'all' || section === 'connections'\">\n <div v-if=\"customConnections.length\" class=\"block\"><h4>已连接服务</h4><ul class=\"providers\"><li v-for=\"p in customConnections\" :key=\"p.slug\"><div class=\"head\"><strong>{{ p.name }}</strong><span class=\"badge ok\">{{ p.authenticated === true ? '已授权' : '当前服务' }}</span></div><p class=\"hint\">{{ p.models.length }} 个可选模型</p><button type=\"button\" class=\"link\" @click=\"openNetwork(p.slug,p.name)\">{{ networkText(p.slug) }}</button></li></ul></div>\n <div v-if=\"loneOauth.length && (showAll || loneOauth.some(o => o.status.logged_in))\" class=\"block\">\n <h4>其他登录方式</h4>\n <ul class=\"providers\">\n <li v-for=\"o in loneOauth.filter(o => showAll || o.status.logged_in)\" :key=\"o.id\">\n <div class=\"head\"><strong>{{ o.name }}</strong> <code>{{ o.id }}</code>\n <span :class=\"['badge', o.status.logged_in ? 'ok' : '']\">{{ o.status.logged_in ? '已登录' : '未登录' }}</span></div>\n <button type=\"button\" class=\"link\" @click=\"openNetwork(o.id,o.name)\">{{ networkText(o.id) }}</button><p v-if=\"o.status.logged_in && o.disconnectable\"><button type=\"button\" :disabled=\"busy\" @click=\"logout(o.id)\">退出登录</button></p>\n <p v-else-if=\"!o.status.logged_in\"><button type=\"button\" :disabled=\"busy\" aria-haspopup=\"dialog\" @click=\"login(o.id)\">登录 {{ o.name }}</button></p>\n </li>\n </ul>\n </div>\n <div class=\"block\">\n <div class=\"connection-heading\"><h4>{{ showAll ? '添加模型连接' : '已配置供应商' }}</h4><button v-if=\"section === 'connections'\" type=\"button\" :disabled=\"busy\" @click=\"showAll = !showAll\">{{ showAll ? '查看已配置' : '添加连接' }}</button></div>\n <input v-model=\"filter\" type=\"search\" placeholder=\"搜索供应商或别名\" aria-label=\"搜索供应商\" />\n <ul class=\"providers\">\n <li v-for=\"p in shown\" :key=\"p.id\">\n <div class=\"head\"><strong>{{ p.label }}</strong> <code>{{ p.id }}</code>\n <span :class=\"['badge', configured(p) ? 'ok' : '']\">{{ configured(p) ? '已配置' : '未配置' }}</span>\n </div>\n <button type=\"button\" class=\"link\" @click=\"openNetwork(p.id,p.label)\">{{ networkText(p.id) }}</button><template v-if=\"oauthFor(p.id)\">\n <p v-if=\"oauthFor(p.id)!.status.logged_in\">已登录 {{ oauthFor(p.id)!.status.token_preview ? '· …' + oauthFor(p.id)!.status.token_preview : '' }}\n <button v-if=\"oauthFor(p.id)!.disconnectable\" type=\"button\" :disabled=\"busy\" @click=\"logout(p.id)\">退出登录</button></p>\n <p v-else><button type=\"button\" :disabled=\"busy\" aria-haspopup=\"dialog\" @click=\"login(p.id)\">登录 {{ oauthFor(p.id)!.name }}</button></p>\n </template>\n <form v-if=\"keyVar(p)\" class=\"row\" @submit.prevent=\"saveKey(p)\">\n <input v-model=\"keyDraft[p.id]\" type=\"password\" autocomplete=\"new-password\" :placeholder=\"env[keyVar(p)!]?.is_set ? `${keyVar(p)} 已设置(${env[keyVar(p)!]?.redacted_value ?? '***'})` : keyVar(p)\" :aria-label=\"`${p.label} API Key`\" />\n <button type=\"submit\" :disabled=\"busy || !keyDraft[p.id]?.trim()\">保存</button>\n <button v-if=\"env[keyVar(p)!]?.is_set\" type=\"button\" :disabled=\"busy\" @click=\"removeKey(keyVar(p)!)\">移除</button>\n </form>\n <button type=\"button\" class=\"link\" @click=\"openPool(p.id)\">{{ poolOpen === p.id ? '收起凭据池' : '凭据池' }}</button>\n <div v-if=\"poolOpen === p.id\" class=\"pool\">\n <ol><li v-for=\"e in pool\" :key=\"e.id\">{{ e.label }} · {{ e.authType }} · {{ e.source }} {{ e.tokenPreview }} <em v-if=\"e.lastStatus\">{{ e.lastStatus }}</em>\n <button type=\"button\" :disabled=\"busy\" @click=\"removePool(e.index)\">删除</button></li></ol>\n <form class=\"row\" @submit.prevent=\"addPool\"><input v-model=\"poolKey\" type=\"password\" autocomplete=\"new-password\" placeholder=\"追加 API Key\" /><input v-model=\"poolLabel\" placeholder=\"标签(可选)\" /><button type=\"submit\" :disabled=\"busy || !poolKey.trim()\">加入</button></form>\n <label class=\"row\">轮换策略<select v-model=\"strategy\"><option value=\"fill_first\">fill_first</option><option value=\"round_robin\">round_robin</option><option value=\"least_used\">least_used</option><option value=\"random\">random</option></select>\n <button type=\"button\" :disabled=\"busy\" @click=\"saveStrategy\">保存</button></label>\n </div>\n </li>\n </ul>\n </div>\n\n <div v-if=\"mediaKeys.length\" class=\"block\"><h4>媒体专用凭据</h4><p class=\"hint\">这些密钥只供图片或视频使用。保存后,对应页面可以直接选用已授权的供应商。</p><ul class=\"providers\"><li v-for=\"field in mediaKeys\" :key=\"field.key\"><div class=\"head\"><strong>{{ field.prompt }}</strong> <code>{{ field.key }}</code><span :class=\"['badge', field.isSet ? 'ok' : '']\">{{ field.isSet ? '已配置' : '未配置' }}</span></div><p class=\"hint\">{{ field.uses.join('、') }}</p><form class=\"row\" @submit.prevent=\"saveMediaKey(field.key)\"><input v-model=\"mediaDraft[field.key]\" type=\"password\" autocomplete=\"new-password\" :placeholder=\"field.isSet ? `${field.key} 已设置,留空则不修改` : field.key\" :aria-label=\"field.prompt\" /><button type=\"submit\" :disabled=\"busy || !mediaDraft[field.key]?.trim()\">保存</button><button v-if=\"field.isSet\" type=\"button\" :disabled=\"busy\" @click=\"removeKey(field.key)\">移除</button></form></li></ul></div>\n <p v-if=\"!shown.length && !customConnections.length && !mediaKeys.length\" class=\"hint\">暂无匹配的连接。可添加供应商或自定义服务。</p>\n <details class=\"endpoint-section\"><summary>添加自定义模型服务</summary><form class=\"block\" @submit.prevent=\"saveEndpoint\">\n <h4>自定义 OpenAI 兼容服务</h4>\n <label>服务名称<input v-model=\"endpoint.name\" placeholder=\"名称\" /></label>\n <label>服务地址<input v-model=\"endpoint.base_url\" type=\"url\" placeholder=\"https://host/v1\" /></label>\n <label>默认模型<input v-model=\"endpoint.model\" placeholder=\"默认模型\" /></label>\n <label>API Key(可选)<input v-model=\"endpoint.api_key\" type=\"password\" autocomplete=\"new-password\" placeholder=\"API Key\" /></label>\n <label>接口协议<select v-model=\"endpoint.api_mode\"><option value=\"\">自动识别</option><option value=\"chat_completions\">chat_completions</option><option value=\"codex_responses\">codex_responses</option><option value=\"anthropic_messages\">anthropic_messages</option></select></label>\n <button type=\"submit\" :disabled=\"busy || !endpoint.name.trim() || !endpoint.base_url.trim()\">保存端点</button>\n </form></details>\n </template>\n </template>\n </section>\n</template>\n<style scoped>\n.hermes-providers{display:grid;gap:16px;max-width:760px}.note,.hint{color:var(--text-secondary);margin:0;line-height:1.6}.error{color:var(--danger,#c33)}\n.block{display:grid;gap:16px;border:0;border-top:1px solid var(--line);padding:20px 0}.block h4{margin:0}\n.row{display:flex;gap:8px;flex-wrap:wrap;align-items:center}.providers{list-style:none;margin:0;padding:0;display:grid;gap:16px}\n.providers>li{border-top:1px solid var(--line);padding-top:8px;display:grid;gap:6px}.head{display:flex;gap:8px;align-items:baseline;flex-wrap:wrap}.badge{font-size:12px;padding:1px 6px;border-radius:6px;border:1px solid var(--line)}.badge.ok{border-color:var(--accent)}\ninput,select,textarea,button{min-height:44px;padding:6px 10px;border:1px solid var(--line);border-radius:8px;background:var(--surface);color:var(--text-primary);font:inherit}button{cursor:pointer}button:disabled{opacity:.5;cursor:default}.link{border:0;background:none;padding:0;min-height:0;color:var(--accent);justify-self:start}\n.hermes-providers{max-width:none;font-size:14px}.defaults-form{display:grid;gap:0;min-width:0}.defaults-heading{margin-bottom:16px}.defaults-form h4{margin:0;font-size:18px;font-weight:650}.defaults-form p{margin:12px 0 0;font-size:14px;line-height:1.6;color:var(--text-secondary)}.setting-row{display:grid;grid-template-columns:minmax(0,1fr) minmax(200px,56%);align-items:center;gap:24px;padding:16px 0;border-bottom:1px solid var(--line)}.setting-row>span{display:grid;gap:7px}.setting-row strong{font-size:15px;font-weight:600}.setting-row small{font-size:13px;line-height:1.5;color:var(--text-secondary)}.setting-row input,.setting-row select{width:100%;box-sizing:border-box;padding:10px 12px}.defaults-status{display:flex;align-items:center;justify-content:space-between;gap:12px;margin:8px 0 8px 44%;font-size:13px;line-height:1.5;color:var(--text-secondary)}.defaults-status .configured{color:var(--success)}.defaults-status .configured:before{content:'';display:inline-block;width:9px;height:9px;border-radius:50%;background:currentColor;margin-right:8px}.defaults-status .refresh-models{min-height:44px;flex-shrink:0;padding:6px 8px;border:0;background:transparent;font-size:13px;display:inline-flex;align-items:center;gap:8px}.fallback-section{border-top:1px solid var(--line);padding-top:28px}.fallback-section details{margin-top:16px}.fallback-section summary{display:grid;grid-template-columns:minmax(0,1fr) minmax(200px,56%);align-items:center;gap:24px;min-height:48px;cursor:pointer;list-style:none}.fallback-section summary>.app-icon{position:absolute;right:14px;transform:rotate(180deg);color:var(--text-secondary)}.fallback-section summary{position:relative}.fallback-section summary>span:nth-child(2){display:block;border:1px solid var(--line);border-radius:8px;padding:12px 34px 12px 12px;color:var(--text-secondary)}.fallback-section label{display:grid;gap:10px;margin-top:18px}.fallback-section textarea{box-sizing:border-box;width:100%;resize:vertical}.fallback-section small{display:block;margin-top:10px;color:var(--text-secondary);line-height:1.6}.fallback-section details[open] summary>.app-icon{transform:rotate(-90deg)}.connection-heading{display:flex;align-items:center;justify-content:space-between;gap:16px}.endpoint-section summary{min-height:44px;line-height:44px;cursor:pointer}.endpoint-section label{display:grid;gap:8px}.hermes-providers :focus-visible{outline:2px solid var(--accent);outline-offset:2px}.hermes-providers input,.hermes-providers select,.hermes-providers textarea{min-width:0;max-width:100%;box-sizing:border-box}@media(max-width:600px){.setting-row,.fallback-section summary{grid-template-columns:1fr;gap:10px}.defaults-status{margin-left:0;flex-wrap:wrap}.fallback-section summary>.app-icon{bottom:14px}.head{align-items:center}.row input{flex:1;min-width:140px}.defaults-form h4{font-size:17px}}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, nextTick, onMounted, ref, watch } from 'vue'\nimport AppIcon from '@/components/common/AppIcon.vue'\nimport ConnectionNetworkPanel from './ConnectionNetworkPanel.vue'\nimport { modelNetworkApi, networkLabel } from '@/api/modelNetwork'\nimport type { ModelNetworkView } from '@shared/modelNetwork'\nimport ProviderLoginDialog from './ProviderLoginDialog.vue'\nimport JevAutoPanel from './JevAutoPanel.vue'\nimport JevNetworkPanel from './JevNetworkPanel.vue'\nimport BotModelVisibilityPanel from './BotModelVisibilityPanel.vue'\nimport { hermesApi, hermesMediaApi, type HermesEnvVar, type HermesModelOptions, type HermesOAuthProvider, type HermesPoolEntry, type HermesProvider } from '@/api/hermes'\n\n/**\n * Hermes provider management (same operations as the Hermes dashboard).\n * Without `bot` it edits the system layer; with `bot` it edits that Bot's own Hermes home,\n * whose logins and keys override the system layer.\n */\nconst networkView=ref<ModelNetworkView>(), networkConnection=ref<{id:string;name:string}>(), networkDirty=ref(false)\nconst networkEditor=ref<InstanceType<typeof ConnectionNetworkPanel>>()\nasync function refreshNetwork(){try{networkView.value=await modelNetworkApi.get(props.bot)}catch{networkView.value=undefined}}\nfunction networkText(id:string){return networkView.value?(props.bot?'独立凭据网络:':'网络:')+networkLabel(networkView.value,networkView.value.connections[id]??{mode:'inherit'}):'设置连接网络'}\nfunction openNetwork(id:string,name:string){networkConnection.value={id,name}}\nfunction closeNetwork(){networkDirty.value=false;networkConnection.value=undefined;void refreshNetwork()}\nonMounted(refreshNetwork)\nconst props = withDefaults(defineProps<{ bot?: string; section?: 'all' | 'connections' | 'defaults' | 'auto' | 'visibility'; embedded?: boolean; formId?: string }>(), { section: 'all', embedded: false })\nconst emit = defineEmits<{ changed: []; 'dirty-change': [value: boolean]; 'can-save-change': [value: boolean]; 'busy-change': [value: boolean]; 'manage-network': [] }>()\nconst jevEditor = ref<InstanceType<typeof JevAutoPanel>>(), jevNetworkEditor = ref<InstanceType<typeof JevNetworkPanel>>(), botModelsEditor = ref<InstanceType<typeof BotModelVisibilityPanel>>()\nconst jevDirty = ref(false), jevNetworkDirty = ref(false), botModelsDirty = ref(false)\nconst jevBusy = ref(false), jevNetworkBusy = ref(false), botModelsBusy = ref(false)\nconst panelsDirty = computed(() => jevDirty.value || jevNetworkDirty.value || botModelsDirty.value)\nconst panelsBusy = computed(() => jevBusy.value || jevNetworkBusy.value || botModelsBusy.value)\nconst providers = ref<HermesProvider[]>([]), oauth = ref<HermesOAuthProvider[]>([]), env = ref<Record<string, HermesEnvVar>>({})\nconst models = ref<HermesModelOptions>(), mainProvider = ref(''), mainModel = ref('')\nconst fallbackText = ref(''), filter = ref(''), busy = ref(false), error = ref(''), notice = ref('')\nconst loginProvider = ref<HermesOAuthProvider>()\nlet loginTrigger: HTMLElement | undefined\nconst keyDraft = ref<Record<string, string>>({}), poolOpen = ref(''), pool = ref<HermesPoolEntry[]>([]), poolKey = ref(''), poolLabel = ref(''), strategy = ref('fill_first')\nconst endpoint = ref({ name: '', base_url: '', model: '', api_key: '', api_mode: '' })\nconst mediaKeys = ref<Array<{ key: string; prompt: string; isSet: boolean; uses: string[] }>>([])\nconst mediaDraft = ref<Record<string, string>>({})\nconst mutating = ref(false)\nconst loaded = ref(false), showAll = ref(props.section === 'all'), catalogError = ref('')\nconst savedMain = ref({ provider: '', model: '' }), savedFallback = ref('')\nconst defaultsForm = ref<HTMLFormElement>()\n\nconst shown = computed(() => {\n const f = filter.value.trim().toLowerCase()\n return providers.value.filter(p => (showAll.value || !!f || configured(p)) && (!f || p.id.includes(f) || p.label.toLowerCase().includes(f) || p.aliases.some(a => a.includes(f))))\n})\nconst oauthFor = (id: string) => oauth.value.find(p => p.id === id)\n// Sign-ins that have no provider row of their own (e.g. claude-code, copilot-acp).\nconst loneOauth = computed(() => oauth.value.filter(o => !providers.value.some(p => p.id === o.id)))\nconst keyVar = (p: HermesProvider) => p.envVars[0]\nconst configured = (p: HermesProvider) => !!oauthFor(p.id)?.status.logged_in || p.envVars.some(v => env.value[v]?.is_set)\nconst providerModels = computed(() => models.value?.providers.find(p => p.slug === mainProvider.value)?.models ?? [])\nconst authorizedProviders = computed(() => models.value?.providers.filter(p => p.authenticated === true) ?? [])\nconst mainAuthorized = computed(() => authorizedProviders.value.some(p => p.slug === mainProvider.value))\nconst customConnections = computed(() => models.value?.providers.filter(p => (p.authenticated === true || p.is_current) && !providers.value.some(provider => provider.id === p.slug)) ?? [])\nconst mainDirty = computed(() => loaded.value && (mainProvider.value !== savedMain.value.provider || mainModel.value !== savedMain.value.model))\nconst fallbackDirty = computed(() => loaded.value && fallbackText.value !== savedFallback.value)\nconst connectionDirty = computed(() => Object.values(keyDraft.value).some(Boolean) || Object.values(endpoint.value).some(Boolean) || !!poolKey.value || !!poolLabel.value || Object.values(mediaDraft.value).some(value => value.trim()))\nconst dirty = computed(() => networkDirty.value || panelsDirty.value || (props.section === 'defaults' ? mainDirty.value || fallbackDirty.value : props.section === 'connections' ? connectionDirty.value : mainDirty.value || fallbackDirty.value || connectionDirty.value))\nwatch(dirty, value => { if (value) notice.value = ''; emit('dirty-change', value) })\nwatch(() => loaded.value && !busy.value && !panelsBusy.value && (!mainDirty.value || (mainAuthorized.value && !!mainModel.value.trim())) && (mainDirty.value || fallbackDirty.value || panelsDirty.value), value => emit('can-save-change', value), { immediate: true })\nwatch(() => mutating.value || panelsBusy.value, value => emit('busy-change', value), { immediate: true })\nasync function refreshModels() {\n await guard(async () => { models.value = await hermesApi.models(true); catalogError.value = '' }, '模型列表已刷新', false)\n}\n\n\nasync function guard(fn: () => Promise<unknown>, ok?: string, blocksNavigation = true) {\n if (busy.value || panelsBusy.value) return\n busy.value = true; mutating.value = blocksNavigation; error.value = ''; notice.value = ''\n try { const result = await fn(); if (ok && result !== false) notice.value = ok } catch (e) { error.value = e instanceof Error ? e.message : '操作失败' } finally { busy.value = false; mutating.value = false }\n}\nasync function load() {\n await guard(async () => {\n const [p, o, e, c] = await Promise.all([props.section === 'defaults' ? Promise.resolve({ providers: [] as HermesProvider[] }) : hermesApi.providers(props.bot), props.section === 'defaults' ? Promise.resolve({ providers: [] as HermesOAuthProvider[] }) : hermesApi.oauth(props.bot), props.section === 'defaults' ? Promise.resolve({} as Record<string, HermesEnvVar>) : hermesApi.env(props.bot), hermesApi.config(props.bot)])\n providers.value = p.providers; oauth.value = o.providers; env.value = e\n mainProvider.value = c.config.model?.provider ?? ''; mainModel.value = c.config.model?.default ?? ''\n const fb = c.config.fallback_model\n fallbackText.value = (Array.isArray(fb) ? fb : fb ? [fb] : []).map(f => `${f.provider} ${f.model}`).join('\\n')\n savedMain.value = { provider: mainProvider.value, model: mainModel.value }; savedFallback.value = fallbackText.value; loaded.value = true\n if (!props.bot) models.value = await hermesApi.models(false).catch(() => { catalogError.value = '暂时无法读取模型列表,可重试刷新。'; return undefined })\n await loadMediaKeys()\n }, undefined, false)\n}\nasync function loadMediaKeys() {\n if (props.bot || (props.section !== 'all' && props.section !== 'connections')) { mediaKeys.value = []; return }\n try {\n const [image, video] = await Promise.all([hermesMediaApi.config('image_gen'), hermesMediaApi.config('video_gen')])\n const known = new Set(providers.value.flatMap(p => p.envVars))\n const rows = new Map<string, { key: string; prompt: string; isSet: boolean; uses: string[] }>()\n for (const [label, value] of [['图片', image], ['视频', video]] as const) {\n for (const provider of value?.providers ?? []) for (const field of provider.env_vars ?? []) {\n if (!field.key || known.has(field.key)) continue\n const row = rows.get(field.key) ?? { key: field.key, prompt: field.prompt || field.key, isSet: false, uses: [] }\n row.isSet = row.isSet || !!field.is_set || !!env.value[field.key]?.is_set\n const use = `${label} · ${provider.name}`\n if (!row.uses.includes(use)) row.uses.push(use)\n rows.set(field.key, row)\n }\n }\n mediaKeys.value = [...rows.values()]\n } catch { mediaKeys.value = [] }\n}\ndefineExpose({ reset: () => networkConnection.value ? networkEditor.value?.reset() : Promise.all([load(), jevEditor.value?.reset(), jevNetworkEditor.value?.reset(), botModelsEditor.value?.reset()]) })\nonMounted(load)\n\nasync function saveMediaKey(key: string) {\n const value = mediaDraft.value[key]?.trim()\n if (!value) return\n await guard(async () => {\n await hermesApi.setEnv(key, value, props.bot)\n mediaDraft.value[key] = ''\n env.value = await hermesApi.env(props.bot)\n await loadMediaKeys()\n emit('changed')\n }, '媒体密钥已保存')\n}\nasync function saveKey(p: HermesProvider) {\n const key = keyVar(p), value = keyDraft.value[p.id]?.trim()\n if (!key || !value) return\n await guard(async () => { await hermesApi.setEnv(key, value, props.bot); keyDraft.value[p.id] = ''; env.value = await hermesApi.env(props.bot); emit('changed') }, `${p.label} 密钥已保存`)\n}\nasync function removeKey(key: string) {\n await guard(async () => { await hermesApi.deleteEnv(key, props.bot); env.value = await hermesApi.env(props.bot); await loadMediaKeys(); emit('changed') }, '密钥已移除')\n}\nfunction login(id: string) {\n if (busy.value || loginProvider.value) return\n loginTrigger = document.activeElement instanceof HTMLElement ? document.activeElement : undefined\n loginProvider.value = oauthFor(id)\n}\nfunction closeLogin() {\n loginProvider.value = undefined\n void nextTick(() => { if (loginTrigger?.isConnected) loginTrigger.focus({ preventScroll: true }) })\n}\nasync function loginSucceeded() {\n notice.value = '登录成功'\n emit('changed')\n try {\n const [o, e] = await Promise.all([hermesApi.oauth(props.bot), hermesApi.env(props.bot)])\n oauth.value = o.providers; env.value = e\n } catch { error.value = '登录已完成,连接状态刷新失败,请刷新页面。' }\n}\nasync function logout(id: string) {\n await guard(async () => { await hermesApi.oauthDisconnect(id, props.bot); oauth.value = (await hermesApi.oauth(props.bot)).providers; emit('changed') }, '已退出登录')\n}\nasync function openPool(id: string) {\n if (poolOpen.value === id) { poolOpen.value = ''; return }\n await guard(async () => { const r = await hermesApi.pool(id, props.bot); pool.value = r.entries; strategy.value = r.strategy; poolOpen.value = id }, undefined, false)\n}\nasync function addPool() {\n const id = poolOpen.value\n if (!id || !poolKey.value.trim()) return\n await guard(async () => { await hermesApi.addPool(id, poolKey.value.trim(), poolLabel.value.trim(), props.bot); poolKey.value = ''; poolLabel.value = ''; pool.value = (await hermesApi.pool(id, props.bot)).entries; emit('changed') }, '已加入凭据池')\n}\nasync function removePool(index: number) {\n const id = poolOpen.value\n await guard(async () => { await hermesApi.removePool(id, index, props.bot); pool.value = (await hermesApi.pool(id, props.bot)).entries; emit('changed') }, '已移除')\n}\nasync function saveStrategy() {\n const id = poolOpen.value\n await guard(async () => {\n const current = (await hermesApi.config(props.bot)).config.credential_pool_strategies ?? {}\n await hermesApi.patchConfig({ credential_pool_strategies: { ...current, [id]: strategy.value } }, props.bot)\n }, '轮换策略已保存')\n}\nasync function writeMain(confirm = false): Promise<boolean> {\n const result = await hermesApi.setModel({ scope: 'main', provider: mainProvider.value, model: mainModel.value.trim(), ...(confirm ? { confirm_expensive_model: true } : {}) })\n if (result.confirm_required) {\n if (!confirm && window.confirm(result.confirm_message || '该模型费用较高,确认使用?')) return writeMain(true)\n return false\n }\n savedMain.value = { provider: mainProvider.value, model: mainModel.value }\n emit('changed')\n return true\n}\nfunction fallbackRows() {\n return fallbackText.value.split('\\n').map(line => line.trim()).filter(Boolean).map((line, index) => {\n const parts = line.split(/\\s+/)\n if (parts.length !== 2) throw new Error('回退模型第 ' + (index + 1) + ' 行需要填写供应商和模型,以空格分隔。')\n return { provider: parts[0]!, model: parts[1]! }\n })\n}\nasync function writeFallback(rows = fallbackRows()) {\n await hermesApi.patchConfig({ fallback_model: rows.length ? rows : null }, props.bot)\n savedFallback.value = fallbackText.value\n emit('changed')\n}\nasync function saveMain() {\n if (!mainAuthorized.value || !mainModel.value.trim()) return\n await guard(() => writeMain(), '默认模型已保存,新一轮对话生效')\n}\nasync function saveFallback() { await guard(() => writeFallback(), '故障回退已保存') }\nasync function saveDefaults() {\n if (!defaultsForm.value?.reportValidity() || !loaded.value || (mainDirty.value && !mainAuthorized.value)) return\n await guard(async () => {\n // Validate both sections before changing either. Successful sections retain their own baseline after a partial failure.\n const rows = fallbackRows()\n let mainSaved = false\n if (mainDirty.value) { if (!await writeMain()) return false; mainSaved = true }\n try { if (fallbackDirty.value) await writeFallback(rows) }\n catch (cause) { if (mainSaved) throw new Error('默认模型已保存,故障回退尚未保存。' + (cause instanceof Error ? cause.message : '请重试。')); throw cause }\n if (jevDirty.value && await jevEditor.value?.save() === false) return false\n if (jevNetworkDirty.value && await jevNetworkEditor.value?.save() === false) return false\n if (botModelsDirty.value && await botModelsEditor.value?.save() === false) return false\n return true\n }, '设置已保存,新一轮对话生效')\n}\nasync function saveEndpoint() {\n const e = endpoint.value\n if (!e.name.trim() || !e.base_url.trim()) return\n await guard(async () => {\n await hermesApi.saveEndpoint({ name: e.name.trim(), base_url: e.base_url.trim(), model: e.model.trim(), ...(e.api_key.trim() ? { api_key: e.api_key.trim() } : {}), api_mode: e.api_mode }, props.bot)\n endpoint.value = { name: '', base_url: '', model: '', api_key: '', api_mode: '' }\n const refreshed = await Promise.all([hermesApi.providers(props.bot), hermesApi.oauth(props.bot), hermesApi.env(props.bot)])\n providers.value = refreshed[0].providers; oauth.value = refreshed[1].providers; env.value = refreshed[2]\n if (!props.bot) models.value = await hermesApi.models()\n emit('changed')\n }, '自定义端点已保存')\n}\n</script>\n<template>\n <section class=\"hermes-providers\" :aria-busy=\"busy\" aria-label=\"Hermes 供应商\">\n<p v-if=\"section !== 'defaults' && !networkConnection\" class=\"note\">{{ bot ? '这里的登录和密钥只对此 Bot 生效,并覆盖系统默认连接。' : '连接供服务器中的 Bot 使用;登录与密钥安全保存,凭据不会完整回显。' }}</p>\n <p v-if=\"error\" class=\"error\" role=\"alert\">{{ error }}</p>\n <p v-if=\"notice\" role=\"status\">{{ notice }}</p>\n <ProviderLoginDialog v-if=\"loginProvider\" :key=\"loginProvider.id\" :provider=\"loginProvider\" :bot=\"bot\" @close=\"closeLogin();refreshNetwork()\" @success=\"loginSucceeded\" />\n\n <ConnectionNetworkPanel v-if=\"networkConnection\" ref=\"networkEditor\" :provider=\"networkConnection.id\" :name=\"networkConnection.name\" :bot=\"bot\" :can-login=\"!!oauthFor(networkConnection.id) && !oauthFor(networkConnection.id)!.status.logged_in\" @back=\"closeNetwork\" @login=\"login(networkConnection!.id)\" @changed=\"refreshNetwork\" @dirty-change=\"networkDirty=$event\" @busy-change=\"mutating=$event\" />\n <template v-if=\"!networkConnection\">\n <form v-if=\"!bot && section !== 'connections'\" :id=\"formId\" ref=\"defaultsForm\" class=\"defaults-form\" @submit.prevent=\"saveDefaults\">\n <template v-if=\"section === 'all' || section === 'defaults'\">\n <div class=\"defaults-heading\"><h4>默认对话模型</h4><p>Bot 未单独指定模型时使用此配置。</p></div>\n <label class=\"setting-row\"><span><strong>供应商</strong><small>只列出模型连接中已授权的供应商。</small></span><select v-model=\"mainProvider\" :required=\"mainDirty\" aria-label=\"默认模型供应商\" :disabled=\"busy || !loaded\"><option value=\"\">请选择</option><option v-for=\"p in authorizedProviders\" :key=\"p.slug\" :value=\"p.slug\">{{ p.name }}</option><option v-if=\"mainProvider && !mainAuthorized\" :value=\"mainProvider\">{{ models?.providers.find(p => p.slug === mainProvider)?.name || mainProvider }}(未授权)</option></select></label>\n <label class=\"setting-row\"><span><strong>模型</strong><small>选择默认的对话模型。</small></span><input v-model=\"mainModel\" :required=\"mainDirty\" aria-label=\"默认对话模型\" list=\"hermes-main-models\" :disabled=\"busy || !loaded\" placeholder=\"选择或输入模型 ID\" /></label>\n <datalist id=\"hermes-main-models\"><option v-for=\"m in providerModels\" :key=\"m\" :value=\"m\" /></datalist>\n <div class=\"defaults-status\"><span :class=\"{ configured: mainAuthorized }\">{{ !loaded ? '正在读取配置…' : catalogError || (mainAuthorized ? '服务已授权' : mainProvider ? '该供应商尚未授权,请先到模型连接完成授权。' : '请选择已授权的模型服务') }}</span><button type=\"button\" class=\"refresh-models\" :disabled=\"busy\" @click=\"refreshModels\"><AppIcon name=\"refresh\" :size=\"16\" />刷新模型列表</button></div>\n <button v-if=\"!embedded\" type=\"button\" :disabled=\"busy || !mainAuthorized || !mainModel.trim()\" @click=\"saveMain\">保存默认模型</button>\n <div class=\"fallback-section\"><h4>故障回退</h4><p>默认模型不可用时,按顺序尝试备用模型。</p><details><summary><span>回退模型</span><span>{{ fallbackText.trim() ? fallbackText.trim().split('\\n').length + ' 个备用模型' : '尚未设置' }}</span><AppIcon name=\"chevron-left\" :size=\"18\" /></summary><label>备用模型顺序<textarea v-model=\"fallbackText\" rows=\"4\" placeholder=\"每行:供应商 模型,以空格分隔\" :disabled=\"busy\" /></label><small>按从上到下的顺序尝试;留空可关闭回退。</small><button v-if=\"!embedded\" type=\"button\" :disabled=\"busy\" @click=\"saveFallback\">保存回退链</button></details></div>\n </template>\n <JevAutoPanel v-if=\"section === 'all' || section === 'auto'\" ref=\"jevEditor\" :models=\"models\" :disabled=\"busy || panelsBusy\" @dirty-change=\"jevDirty=$event\" @busy-change=\"jevBusy=$event\" />\n <JevNetworkPanel v-if=\"section === 'all' || section === 'auto'\" ref=\"jevNetworkEditor\" :disabled=\"busy || panelsBusy\" @dirty-change=\"jevNetworkDirty=$event\" @busy-change=\"jevNetworkBusy=$event\" @manage-network=\"emit('manage-network')\" />\n <BotModelVisibilityPanel v-if=\"section === 'all' || section === 'visibility'\" ref=\"botModelsEditor\" :models=\"models\" :disabled=\"busy || panelsBusy\" @dirty-change=\"botModelsDirty=$event\" @busy-change=\"botModelsBusy=$event\" />\n </form>\n\n <template v-if=\"section === 'all' || section === 'connections'\">\n <div v-if=\"customConnections.length\" class=\"block\"><h4>已连接服务</h4><ul class=\"providers\"><li v-for=\"p in customConnections\" :key=\"p.slug\"><div class=\"head\"><strong>{{ p.name }}</strong><span class=\"badge ok\">{{ p.authenticated === true ? '已授权' : '当前服务' }}</span></div><p class=\"hint\">{{ p.models.length }} 个可选模型</p><button type=\"button\" class=\"link\" @click=\"openNetwork(p.slug,p.name)\">{{ networkText(p.slug) }}</button></li></ul></div>\n <div v-if=\"loneOauth.length && (showAll || loneOauth.some(o => o.status.logged_in))\" class=\"block\">\n <h4>其他登录方式</h4>\n <ul class=\"providers\">\n <li v-for=\"o in loneOauth.filter(o => showAll || o.status.logged_in)\" :key=\"o.id\">\n <div class=\"head\"><strong>{{ o.name }}</strong> <code>{{ o.id }}</code>\n <span :class=\"['badge', o.status.logged_in ? 'ok' : '']\">{{ o.status.logged_in ? '已登录' : '未登录' }}</span></div>\n <button type=\"button\" class=\"link\" @click=\"openNetwork(o.id,o.name)\">{{ networkText(o.id) }}</button><p v-if=\"o.status.logged_in && o.disconnectable\"><button type=\"button\" :disabled=\"busy\" @click=\"logout(o.id)\">退出登录</button></p>\n <p v-else-if=\"!o.status.logged_in\"><button type=\"button\" :disabled=\"busy\" aria-haspopup=\"dialog\" @click=\"login(o.id)\">登录 {{ o.name }}</button></p>\n </li>\n </ul>\n </div>\n <div class=\"block\">\n <div class=\"connection-heading\"><h4>{{ showAll ? '添加模型连接' : '已配置供应商' }}</h4><button v-if=\"section === 'connections'\" type=\"button\" :disabled=\"busy\" @click=\"showAll = !showAll\">{{ showAll ? '查看已配置' : '添加连接' }}</button></div>\n <input v-model=\"filter\" type=\"search\" placeholder=\"搜索供应商或别名\" aria-label=\"搜索供应商\" />\n <ul class=\"providers\">\n <li v-for=\"p in shown\" :key=\"p.id\">\n <div class=\"head\"><strong>{{ p.label }}</strong> <code>{{ p.id }}</code>\n <span :class=\"['badge', configured(p) ? 'ok' : '']\">{{ configured(p) ? '已配置' : '未配置' }}</span>\n </div>\n <button type=\"button\" class=\"link\" @click=\"openNetwork(p.id,p.label)\">{{ networkText(p.id) }}</button><template v-if=\"oauthFor(p.id)\">\n <p v-if=\"oauthFor(p.id)!.status.logged_in\">已登录 {{ oauthFor(p.id)!.status.token_preview ? '· …' + oauthFor(p.id)!.status.token_preview : '' }}\n <button v-if=\"oauthFor(p.id)!.disconnectable\" type=\"button\" :disabled=\"busy\" @click=\"logout(p.id)\">退出登录</button></p>\n <p v-else><button type=\"button\" :disabled=\"busy\" aria-haspopup=\"dialog\" @click=\"login(p.id)\">登录 {{ oauthFor(p.id)!.name }}</button></p>\n </template>\n <form v-if=\"keyVar(p)\" class=\"row\" @submit.prevent=\"saveKey(p)\">\n <input v-model=\"keyDraft[p.id]\" type=\"password\" autocomplete=\"new-password\" :placeholder=\"env[keyVar(p)!]?.is_set ? `${keyVar(p)} 已设置(${env[keyVar(p)!]?.redacted_value ?? '***'})` : keyVar(p)\" :aria-label=\"`${p.label} API Key`\" />\n <button type=\"submit\" :disabled=\"busy || !keyDraft[p.id]?.trim()\">保存</button>\n <button v-if=\"env[keyVar(p)!]?.is_set\" type=\"button\" :disabled=\"busy\" @click=\"removeKey(keyVar(p)!)\">移除</button>\n </form>\n <button type=\"button\" class=\"link\" @click=\"openPool(p.id)\">{{ poolOpen === p.id ? '收起凭据池' : '凭据池' }}</button>\n <div v-if=\"poolOpen === p.id\" class=\"pool\">\n <ol><li v-for=\"e in pool\" :key=\"e.id\">{{ e.label }} · {{ e.authType }} · {{ e.source }} {{ e.tokenPreview }} <em v-if=\"e.lastStatus\">{{ e.lastStatus }}</em>\n <button type=\"button\" :disabled=\"busy\" @click=\"removePool(e.index)\">删除</button></li></ol>\n <form class=\"row\" @submit.prevent=\"addPool\"><input v-model=\"poolKey\" type=\"password\" autocomplete=\"new-password\" placeholder=\"追加 API Key\" /><input v-model=\"poolLabel\" placeholder=\"标签(可选)\" /><button type=\"submit\" :disabled=\"busy || !poolKey.trim()\">加入</button></form>\n <label class=\"row\">轮换策略<select v-model=\"strategy\"><option value=\"fill_first\">fill_first</option><option value=\"round_robin\">round_robin</option><option value=\"least_used\">least_used</option><option value=\"random\">random</option></select>\n <button type=\"button\" :disabled=\"busy\" @click=\"saveStrategy\">保存</button></label>\n </div>\n </li>\n </ul>\n </div>\n\n <div v-if=\"mediaKeys.length\" class=\"block\"><h4>媒体专用凭据</h4><p class=\"hint\">这些密钥只供图片或视频使用。保存后,对应页面可以直接选用已授权的供应商。</p><ul class=\"providers\"><li v-for=\"field in mediaKeys\" :key=\"field.key\"><div class=\"head\"><strong>{{ field.prompt }}</strong> <code>{{ field.key }}</code><span :class=\"['badge', field.isSet ? 'ok' : '']\">{{ field.isSet ? '已配置' : '未配置' }}</span></div><p class=\"hint\">{{ field.uses.join('、') }}</p><form class=\"row\" @submit.prevent=\"saveMediaKey(field.key)\"><input v-model=\"mediaDraft[field.key]\" type=\"password\" autocomplete=\"new-password\" :placeholder=\"field.isSet ? `${field.key} 已设置,留空则不修改` : field.key\" :aria-label=\"field.prompt\" /><button type=\"submit\" :disabled=\"busy || !mediaDraft[field.key]?.trim()\">保存</button><button v-if=\"field.isSet\" type=\"button\" :disabled=\"busy\" @click=\"removeKey(field.key)\">移除</button></form></li></ul></div>\n <p v-if=\"!shown.length && !customConnections.length && !mediaKeys.length\" class=\"hint\">暂无匹配的连接。可添加供应商或自定义服务。</p>\n <details class=\"endpoint-section\"><summary>添加自定义模型服务</summary><form class=\"block\" @submit.prevent=\"saveEndpoint\">\n <h4>自定义 OpenAI 兼容服务</h4>\n <label>服务名称<input v-model=\"endpoint.name\" placeholder=\"名称\" /></label>\n <label>服务地址<input v-model=\"endpoint.base_url\" type=\"url\" placeholder=\"https://host/v1\" /></label>\n <label>默认模型<input v-model=\"endpoint.model\" placeholder=\"默认模型\" /></label>\n <label>API Key(可选)<input v-model=\"endpoint.api_key\" type=\"password\" autocomplete=\"new-password\" placeholder=\"API Key\" /></label>\n <label>接口协议<select v-model=\"endpoint.api_mode\"><option value=\"\">自动识别</option><option value=\"chat_completions\">chat_completions</option><option value=\"codex_responses\">codex_responses</option><option value=\"anthropic_messages\">anthropic_messages</option></select></label>\n <button type=\"submit\" :disabled=\"busy || !endpoint.name.trim() || !endpoint.base_url.trim()\">保存端点</button>\n </form></details>\n </template>\n </template>\n </section>\n</template>\n<style scoped>\n.hermes-providers{display:grid;gap:16px;max-width:760px}.note,.hint{color:var(--text-secondary);margin:0;line-height:1.6}.error{color:var(--danger,#c33)}\n.block{display:grid;gap:16px;border:0;border-top:1px solid var(--line);padding:20px 0}.block h4{margin:0}\n.row{display:flex;gap:8px;flex-wrap:wrap;align-items:center}.providers{list-style:none;margin:0;padding:0;display:grid;gap:16px}\n.providers>li{border-top:1px solid var(--line);padding-top:8px;display:grid;gap:6px}.head{display:flex;gap:8px;align-items:baseline;flex-wrap:wrap}.badge{font-size:12px;padding:1px 6px;border-radius:6px;border:1px solid var(--line)}.badge.ok{border-color:var(--accent)}\ninput,select,textarea,button{min-height:44px;padding:6px 10px;border:1px solid var(--line);border-radius:8px;background:var(--surface);color:var(--text-primary);font:inherit}button{cursor:pointer}button:disabled{opacity:.5;cursor:default}.link{border:0;background:none;padding:0;min-height:0;color:var(--accent);justify-self:start}\n.hermes-providers{max-width:none;font-size:14px}.defaults-form{display:grid;gap:0;min-width:0}.defaults-heading{margin-bottom:16px}.defaults-form h4{margin:0;font-size:18px;font-weight:650}.defaults-form p{margin:12px 0 0;font-size:14px;line-height:1.6;color:var(--text-secondary)}.setting-row{display:grid;grid-template-columns:minmax(0,1fr) minmax(200px,56%);align-items:center;gap:24px;padding:16px 0;border-bottom:1px solid var(--line)}.setting-row>span{display:grid;gap:7px}.setting-row strong{font-size:15px;font-weight:600}.setting-row small{font-size:13px;line-height:1.5;color:var(--text-secondary)}.setting-row input,.setting-row select{width:100%;box-sizing:border-box;padding:10px 12px}.defaults-status{display:flex;align-items:center;justify-content:space-between;gap:12px;margin:8px 0 8px 44%;font-size:13px;line-height:1.5;color:var(--text-secondary)}.defaults-status .configured{color:var(--success)}.defaults-status .configured:before{content:'';display:inline-block;width:9px;height:9px;border-radius:50%;background:currentColor;margin-right:8px}.defaults-status .refresh-models{min-height:44px;flex-shrink:0;padding:6px 8px;border:0;background:transparent;font-size:13px;display:inline-flex;align-items:center;gap:8px}.fallback-section{border-top:1px solid var(--line);padding-top:28px}.fallback-section details{margin-top:16px}.fallback-section summary{display:grid;grid-template-columns:minmax(0,1fr) minmax(200px,56%);align-items:center;gap:24px;min-height:48px;cursor:pointer;list-style:none}.fallback-section summary>.app-icon{position:absolute;right:14px;transform:rotate(180deg);color:var(--text-secondary)}.fallback-section summary{position:relative}.fallback-section summary>span:nth-child(2){display:block;border:1px solid var(--line);border-radius:8px;padding:12px 34px 12px 12px;color:var(--text-secondary)}.fallback-section label{display:grid;gap:10px;margin-top:18px}.fallback-section textarea{box-sizing:border-box;width:100%;resize:vertical}.fallback-section small{display:block;margin-top:10px;color:var(--text-secondary);line-height:1.6}.fallback-section details[open] summary>.app-icon{transform:rotate(-90deg)}.connection-heading{display:flex;align-items:center;justify-content:space-between;gap:16px}.endpoint-section summary{min-height:44px;line-height:44px;cursor:pointer}.endpoint-section label{display:grid;gap:8px}.hermes-providers :focus-visible{outline:2px solid var(--accent);outline-offset:2px}.hermes-providers input,.hermes-providers select,.hermes-providers textarea{min-width:0;max-width:100%;box-sizing:border-box}@media(max-width:600px){.setting-row,.fallback-section summary{grid-template-columns:1fr;gap:10px}.defaults-status{margin-left:0;flex-wrap:wrap}.fallback-section summary>.app-icon{bottom:14px}.head{align-items:center}.row input{flex:1;min-width:140px}.defaults-form h4{font-size:17px}}\n</style>\n","/** Hermes auxiliary model slots (config.yaml `auxiliary.<task>`), same set as the Hermes dashboard. */\nexport const HERMES_AUXILIARY_TASKS = [\n 'vision', 'compression', 'skills_hub', 'approval', 'mcp', 'title_generation', 'review', 'voice_chat',\n 'triage_specifier', 'kanban_decomposer', 'profile_describer', 'curator', 'memory_query_rewrite',\n] as const\nexport type HermesAuxiliaryTask = (typeof HERMES_AUXILIARY_TASKS)[number]\n\nexport const HERMES_AUXILIARY_LABELS: Record<HermesAuxiliaryTask, string> = {\n vision: '看图', compression: '上下文压缩', skills_hub: '技能中心', approval: '智能审批', mcp: 'MCP',\n title_generation: '会话标题', review: '后台复盘', voice_chat: '语音对话', triage_specifier: '任务分诊',\n kanban_decomposer: '看板拆解', profile_describer: '简介生成', curator: '技能整理', memory_query_rewrite: '记忆检索改写',\n}\n\n/** One slot override. `provider: \"auto\"` (or omitted) follows the main model, as in Hermes. */\nexport interface HermesAuxiliaryRoute {\n provider?: string\n model?: string\n base_url?: string\n reasoning_effort?: string | null\n}\nexport type HermesAuxiliaryOverrides = Partial<Record<HermesAuxiliaryTask, HermesAuxiliaryRoute | null>>\n/** Hermes `fallback_model` chain: tried in order when the main provider fails. */\nexport type HermesFallbackChain = Array<{ provider: string; model: string; base_url?: string }>\n","<script setup lang=\"ts\">\nimport { ref, watch, onBeforeUnmount } from \"vue\";\nimport { apiRequest } from \"@/api/client\";\nimport { createUuid } from \"@/utils/id\";\nconst props = defineProps<{\n agentId: string;\n scope: string;\n projectId?: string;\n}>();\nconst emit = defineEmits<{ \"dirty-change\": [dirty: boolean]; changed: [] }>();\nconst base = \"/api/app/workspace\";\ntype Doc = { path: string; content: string; hash: string };\ntype Revision = {\n id: string;\n path: string;\n before: string;\n after: string;\n afterHash: string;\n at: number;\n};\nconst files = ref<{ path: string; bytes: number }[]>([]),\n doc = ref<Doc>(),\n draft = ref(\"\"),\n newPath = ref(\"memory/notes.md\"),\n error = ref(\"\"),\n notice = ref(\"\"),\n busy = ref(false),\n history = ref<Revision[]>([]);\nlet generation = 0;\nconst scope = () => ({\n scope: props.scope,\n agentId: props.agentId,\n ...(props.scope === \"project\" ? { projectId: props.projectId } : {}),\n});\nconst query = (extra: Record<string, string> = {}) =>\n new URLSearchParams({ ...scope(), ...extra } as Record<string, string>);\nasync function action(fn: () => Promise<void>) {\n if (busy.value) return;\n busy.value = true;\n error.value = \"\";\n notice.value = \"\";\n try {\n await fn();\n } catch (e) {\n error.value = e instanceof Error ? e.message : \"操作失败\";\n } finally {\n busy.value = false;\n }\n}\nasync function load() {\n const epoch = ++generation;\n if (!props.agentId || (props.scope === \"project\" && !props.projectId)) {\n files.value = [];\n return;\n }\n try {\n const result = await apiRequest<{\n files: { path: string; bytes: number }[];\n }>(`${base}/memory-files?${query()}`);\n if (epoch === generation) files.value = result.files;\n } catch (e) {\n if (epoch === generation) error.value = String(e);\n }\n}\nasync function open(path: string) {\n await action(async () => {\n const epoch = generation;\n const result = await apiRequest<Doc>(\n `${base}/memory-file?${query({ path })}`,\n );\n if (epoch !== generation) return;\n doc.value = result;\n draft.value = result.content;\n history.value = [];\n });\n}\nasync function save() {\n if (!doc.value) return;\n await action(async () => {\n doc.value = await apiRequest<Doc>(base + \"/memory-file\", {\n method: \"PUT\",\n body: {\n ...scope(),\n requestId: createUuid(),\n path: doc.value!.path,\n content: draft.value,\n expectedHash: doc.value!.hash,\n },\n });\n draft.value = doc.value.content;\n notice.value = \"文件已保存,下一轮对话生效。\";\n emit(\"changed\");\n await load();\n });\n}\nasync function revisions() {\n await action(async () => {\n history.value = (\n await apiRequest<{ revisions: Revision[] }>(\n `${base}/memory-file-history?${query()}`,\n )\n ).revisions.filter((r) => r.path === doc.value?.path);\n });\n}\nasync function revert(r: Revision) {\n await action(async () => {\n doc.value = await apiRequest<Doc>(base + \"/memory-file-revert\", {\n method: \"POST\",\n body: {\n ...scope(),\n requestId: createUuid(),\n id: r.id,\n expectedHash: doc.value!.hash,\n },\n });\n draft.value = doc.value.content;\n notice.value = \"已撤销该次修改。\";\n await load();\n emit(\"changed\");\n });\n}\nwatch(\n () => [props.scope, props.agentId, props.projectId],\n () => {\n doc.value = undefined;\n draft.value = \"\";\n history.value = [];\n void load();\n },\n { immediate: true },\n);\nwatch(\n () => !!doc.value && draft.value !== doc.value.content,\n (v) => emit(\"dirty-change\", v),\n);\nonBeforeUnmount(() => {\n generation++;\n});\n</script>\n<template>\n <section class=\"memory-files\" aria-label=\"Markdown 记忆文件\">\n <h3>记忆文件</h3>\n <p>MEMORY.md 自动加载;主题和日记按需读取。可以直接编辑 Markdown。</p>\n <p v-if=\"error\" role=\"alert\">{{ error }}</p>\n <p v-if=\"notice\" role=\"status\">{{ notice }}</p>\n <template v-if=\"!doc\"\n ><div class=\"file-list\">\n <button\n v-for=\"file in files\"\n :key=\"file.path\"\n :disabled=\"busy\"\n @click=\"open(file.path)\"\n >\n {{ file.path }} · {{ file.bytes }} B\n </button>\n </div>\n <form @submit.prevent=\"open(newPath)\">\n <label\n >新文件路径<input\n v-model=\"newPath\"\n placeholder=\"memory/主题.md\"\n :disabled=\"busy\" /></label\n ><button :disabled=\"busy || !agentId\">创建或打开</button>\n </form></template\n >\n <template v-else\n ><label\n >{{ doc.path\n }}<textarea\n v-model=\"draft\"\n :disabled=\"busy\"\n rows=\"16\"\n spellcheck=\"false\"\n aria-label=\"记忆 Markdown 内容\"\n />\n </label>\n <div class=\"actions\">\n <button :disabled=\"busy || draft === doc.content\" @click=\"save\">\n 保存</button\n ><button\n :disabled=\"busy\"\n @click=\"\n doc = undefined;\n history = [];\n \"\n >\n 取消编辑</button\n ><button :disabled=\"busy\" @click=\"revisions\">修改历史</button>\n </div>\n <details v-for=\"revision in history\" :key=\"revision.id\">\n <summary>{{ new Date(revision.at).toLocaleString() }}</summary>\n <p>修改前</p>\n <pre>{{ revision.before }}</pre>\n <p>修改后</p>\n <pre>{{ revision.after }}</pre>\n <button\n :disabled=\"\n busy || revision.afterHash !== doc.hash || draft !== doc.content\n \"\n @click=\"revert(revision)\"\n >\n 撤销此修改\n </button>\n </details></template\n >\n </section>\n</template>\n<style scoped>\n.memory-files {\n display: grid;\n gap: 12px;\n margin-block: 20px;\n}\n.memory-files h3,\n.memory-files p {\n margin: 0;\n line-height: 1.6;\n}\n.memory-files p {\n color: var(--text-secondary);\n}\n.memory-files label {\n display: grid;\n gap: 8px;\n}\n.memory-files input,\n.memory-files textarea,\n.memory-files button {\n font: inherit;\n padding: 10px;\n border: 1px solid var(--line);\n border-radius: 8px;\n color: var(--text-primary);\n background: var(--surface);\n min-height: 44px;\n box-sizing: border-box;\n max-width: 100%;\n}\n.memory-files textarea {\n width: 100%;\n resize: vertical;\n font-family: monospace;\n}\n.file-list,\n.actions,\n.memory-files form {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n}\n.memory-files pre {\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n}\n.memory-files [role=\"alert\"] {\n color: var(--color-error, #d44);\n}\n</style>\n","<script setup lang=\"ts\">\nimport { ref, watch, onBeforeUnmount } from \"vue\";\nimport { apiRequest } from \"@/api/client\";\nimport { createUuid } from \"@/utils/id\";\nconst props = defineProps<{\n agentId: string;\n scope: string;\n projectId?: string;\n}>();\nconst emit = defineEmits<{ \"dirty-change\": [dirty: boolean]; changed: [] }>();\nconst base = \"/api/app/workspace\";\ntype Doc = { path: string; content: string; hash: string };\ntype Revision = {\n id: string;\n path: string;\n before: string;\n after: string;\n afterHash: string;\n at: number;\n};\nconst files = ref<{ path: string; bytes: number }[]>([]),\n doc = ref<Doc>(),\n draft = ref(\"\"),\n newPath = ref(\"memory/notes.md\"),\n error = ref(\"\"),\n notice = ref(\"\"),\n busy = ref(false),\n history = ref<Revision[]>([]);\nlet generation = 0;\nconst scope = () => ({\n scope: props.scope,\n agentId: props.agentId,\n ...(props.scope === \"project\" ? { projectId: props.projectId } : {}),\n});\nconst query = (extra: Record<string, string> = {}) =>\n new URLSearchParams({ ...scope(), ...extra } as Record<string, string>);\nasync function action(fn: () => Promise<void>) {\n if (busy.value) return;\n busy.value = true;\n error.value = \"\";\n notice.value = \"\";\n try {\n await fn();\n } catch (e) {\n error.value = e instanceof Error ? e.message : \"操作失败\";\n } finally {\n busy.value = false;\n }\n}\nasync function load() {\n const epoch = ++generation;\n if (!props.agentId || (props.scope === \"project\" && !props.projectId)) {\n files.value = [];\n return;\n }\n try {\n const result = await apiRequest<{\n files: { path: string; bytes: number }[];\n }>(`${base}/memory-files?${query()}`);\n if (epoch === generation) files.value = result.files;\n } catch (e) {\n if (epoch === generation) error.value = String(e);\n }\n}\nasync function open(path: string) {\n await action(async () => {\n const epoch = generation;\n const result = await apiRequest<Doc>(\n `${base}/memory-file?${query({ path })}`,\n );\n if (epoch !== generation) return;\n doc.value = result;\n draft.value = result.content;\n history.value = [];\n });\n}\nasync function save() {\n if (!doc.value) return;\n await action(async () => {\n doc.value = await apiRequest<Doc>(base + \"/memory-file\", {\n method: \"PUT\",\n body: {\n ...scope(),\n requestId: createUuid(),\n path: doc.value!.path,\n content: draft.value,\n expectedHash: doc.value!.hash,\n },\n });\n draft.value = doc.value.content;\n notice.value = \"文件已保存,下一轮对话生效。\";\n emit(\"changed\");\n await load();\n });\n}\nasync function revisions() {\n await action(async () => {\n history.value = (\n await apiRequest<{ revisions: Revision[] }>(\n `${base}/memory-file-history?${query()}`,\n )\n ).revisions.filter((r) => r.path === doc.value?.path);\n });\n}\nasync function revert(r: Revision) {\n await action(async () => {\n doc.value = await apiRequest<Doc>(base + \"/memory-file-revert\", {\n method: \"POST\",\n body: {\n ...scope(),\n requestId: createUuid(),\n id: r.id,\n expectedHash: doc.value!.hash,\n },\n });\n draft.value = doc.value.content;\n notice.value = \"已撤销该次修改。\";\n await load();\n emit(\"changed\");\n });\n}\nwatch(\n () => [props.scope, props.agentId, props.projectId],\n () => {\n doc.value = undefined;\n draft.value = \"\";\n history.value = [];\n void load();\n },\n { immediate: true },\n);\nwatch(\n () => !!doc.value && draft.value !== doc.value.content,\n (v) => emit(\"dirty-change\", v),\n);\nonBeforeUnmount(() => {\n generation++;\n});\n</script>\n<template>\n <section class=\"memory-files\" aria-label=\"Markdown 记忆文件\">\n <h3>记忆文件</h3>\n <p>MEMORY.md 自动加载;主题和日记按需读取。可以直接编辑 Markdown。</p>\n <p v-if=\"error\" role=\"alert\">{{ error }}</p>\n <p v-if=\"notice\" role=\"status\">{{ notice }}</p>\n <template v-if=\"!doc\"\n ><div class=\"file-list\">\n <button\n v-for=\"file in files\"\n :key=\"file.path\"\n :disabled=\"busy\"\n @click=\"open(file.path)\"\n >\n {{ file.path }} · {{ file.bytes }} B\n </button>\n </div>\n <form @submit.prevent=\"open(newPath)\">\n <label\n >新文件路径<input\n v-model=\"newPath\"\n placeholder=\"memory/主题.md\"\n :disabled=\"busy\" /></label\n ><button :disabled=\"busy || !agentId\">创建或打开</button>\n </form></template\n >\n <template v-else\n ><label\n >{{ doc.path\n }}<textarea\n v-model=\"draft\"\n :disabled=\"busy\"\n rows=\"16\"\n spellcheck=\"false\"\n aria-label=\"记忆 Markdown 内容\"\n />\n </label>\n <div class=\"actions\">\n <button :disabled=\"busy || draft === doc.content\" @click=\"save\">\n 保存</button\n ><button\n :disabled=\"busy\"\n @click=\"\n doc = undefined;\n history = [];\n \"\n >\n 取消编辑</button\n ><button :disabled=\"busy\" @click=\"revisions\">修改历史</button>\n </div>\n <details v-for=\"revision in history\" :key=\"revision.id\">\n <summary>{{ new Date(revision.at).toLocaleString() }}</summary>\n <p>修改前</p>\n <pre>{{ revision.before }}</pre>\n <p>修改后</p>\n <pre>{{ revision.after }}</pre>\n <button\n :disabled=\"\n busy || revision.afterHash !== doc.hash || draft !== doc.content\n \"\n @click=\"revert(revision)\"\n >\n 撤销此修改\n </button>\n </details></template\n >\n </section>\n</template>\n<style scoped>\n.memory-files {\n display: grid;\n gap: 12px;\n margin-block: 20px;\n}\n.memory-files h3,\n.memory-files p {\n margin: 0;\n line-height: 1.6;\n}\n.memory-files p {\n color: var(--text-secondary);\n}\n.memory-files label {\n display: grid;\n gap: 8px;\n}\n.memory-files input,\n.memory-files textarea,\n.memory-files button {\n font: inherit;\n padding: 10px;\n border: 1px solid var(--line);\n border-radius: 8px;\n color: var(--text-primary);\n background: var(--surface);\n min-height: 44px;\n box-sizing: border-box;\n max-width: 100%;\n}\n.memory-files textarea {\n width: 100%;\n resize: vertical;\n font-family: monospace;\n}\n.file-list,\n.actions,\n.memory-files form {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n}\n.memory-files pre {\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n}\n.memory-files [role=\"alert\"] {\n color: var(--color-error, #d44);\n}\n</style>\n","/** Execution acknowledgement and a real return delivery are distinct facts. */\nexport function communicationStatus(value: { status?: string; hasReply?: boolean; replyTo?: string }): string {\n if (value.status === 'failed') return '投递或执行失败'\n if (value.status === 'stopped') return '协作已停止'\n if (value.hasReply) return '已收到回复'\n if (value.replyTo) return '回复已投递'\n return ({ queued: '已投递 · 排队中', running: '正在处理', waiting: '等待补充信息', complete: '执行已结束 · 暂无回复' } as Record<string, string>)[value.status ?? ''] ?? '协作消息'\n}\nexport function goalStatus(status: string): string {\n return ({ queued: '排队中', pending: '待执行', failed: '执行失败', interrupted: '已中断', running: '进行中', review: '待复核', waiting: '需要补充信息', blocked: '遇到阻碍', complete: '已完成', cancelling: '正在停止', cancelled: '已停止' } as Record<string, string>)[status] ?? '状态待确认'\n}\nexport const activityLabels = { bot_created: '创建了 Bot', helper_created: '创建了临时助手', team_created: '组建了团队', assignment_created: '派发了任务' } as const\n/** Host-authored caption for a real Bot-to-Bot delivery. Outgoing rows are a\n * caption only (plus attachments); incoming rows keep the delivered body. */\nexport function communicationCaption(direction: 'outgoing' | 'incoming'): string {\n return direction === 'outgoing' ? '已发消息给' : '消息来自'\n}\nexport function communicationShowsBody(direction: 'outgoing' | 'incoming'): boolean {\n return direction === 'incoming'\n}\n","import { activityLabels, communicationStatus, goalStatus } from './collaborationPresentation.js'\n\nexport interface CollaborationPeer {\n id: string; fromAgentId: string; toAgentId?: string; targetGroupId?: string;\n fromName?: string; targetName?: string; content: string; status: string;\n hasReply?: boolean; replyTo?: string; error?: string; createdAt?: number;\n}\ninterface Assignment {\n id: string; agentId: string; title: string; brief?: string; status: string;\n result?: string | null; review?: string | null; createdAt?: number; updatedAt?: number;\n}\ninterface ActivityMessage {\n id: string; createdAt: number;\n activity?: { kind: keyof typeof activityLabels; actorName: string; targetName: string; description: string } | null;\n}\nexport interface CollaborationEvent {\n id: string; title: string; status: string; content: string; at: number;\n error?: string; peer?: CollaborationPeer;\n}\n/** Read projection only: assignment IDs own their events; retries never execute work. */\nexport function collaborationTimeline(input: {\n peers: CollaborationPeer[]; assignments: Assignment[]; activities?: ActivityMessage[];\n coordinatorId?: string; name: (id?: string) => string;\n}): CollaborationEvent[] {\n const events: CollaborationEvent[] = [];\n const leader = input.coordinatorId ? input.name(input.coordinatorId) : '负责人';\n for (const message of input.activities ?? []) {\n const a = message.activity;\n // Canonical assignments below cover dispatch, result and review without text matching.\n if (!a || (a.kind === 'assignment_created' && input.assignments.length)) continue;\n events.push({ id: `activity:${message.id}`, title: `${a.actorName} ${activityLabels[a.kind]} ${a.targetName}`, status: '已记录', content: a.description, at: message.createdAt });\n }\n for (const a of input.assignments) {\n const member = input.name(a.agentId);\n events.push({ id: `assignment:${a.id}:created`, title: `${leader} → ${member} · 派发任务`, status: goalStatus(a.status), content: [a.title, a.brief].filter(Boolean).join('\\n'), at: a.createdAt ?? 0 });\n if (a.result) events.push({ id: `assignment:${a.id}:result`, title: `${member} → ${leader} · 回传结果`, status: '已回传', content: `${a.title}\\n${a.result}`, at: a.updatedAt ?? a.createdAt ?? 0 });\n if (a.review) events.push({ id: `assignment:${a.id}:review`, title: `${leader} → ${member} · 复核意见`, status: goalStatus(a.status), content: a.review, at: a.updatedAt ?? a.createdAt ?? 0 });\n }\n for (const p of input.peers) events.push({\n id: `peer:${p.id}`, title: `${p.fromName || input.name(p.fromAgentId)} → ${p.targetName || (p.toAgentId ? input.name(p.toAgentId) : '群聊')}`,\n status: communicationStatus(p), content: p.content, at: p.createdAt ?? 0, error: p.error, peer: p,\n });\n return [...new Map(events.map(event => [event.id, event])).values()].sort((a, b) => a.at - b.at);\n}\n","<script setup lang=\"ts\">\nimport { computed, nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue'\nimport MemoryFilesPanel from './MemoryFilesPanel.vue'\nimport type { AgentAssignment, AgentGoal } from '@shared/agentTasks'\nimport { collaborationTimeline } from '@shared/collaborationTimeline'\nimport { apiRequest } from '@/api/client'\nimport { createUuid } from '@/utils/id'\nimport AppIcon from '@/components/common/AppIcon.vue'\nimport AgentAvatar from '@/components/common/AgentAvatar.vue'\nimport { ChevronForwardOutline } from '@vicons/ionicons5'\nimport type { WorkspaceAgent, WorkspaceConversation, WorkspaceMessage } from '@shared/workspace'\nimport type { MemoryScope, MemorySkipReason, WorkspaceMemory, WorkspaceMemoryJob, WorkspaceMemoryRevision, WorkspacePeerMessage, WorkspaceProject } from '@shared/workspaceKnowledge'\n\nconst props = defineProps<{ agents: WorkspaceAgent[]; conversations: WorkspaceConversation[]; conversationId?: string; taskId?: string; assignments?: AgentAssignment[]; goal?: AgentGoal; revision?: number; embedded?: boolean; initialTab?: 'projects' | 'user' | 'agent'; selectedAgentId?: string; hideAgentControls?: boolean }>()\nconst emit = defineEmits<{ changed: []; 'dirty-change': [dirty: boolean] }>()\nconst dialog = ref<HTMLDialogElement>(), opened = ref(false), busy = ref(false), error = ref(''), tab = ref('agent'), agentId = ref(''), projectId = ref(''), search = ref('')\nconst projects = ref<WorkspaceProject[]>([]), memories = ref<WorkspaceMemory[]>([]), peers = ref<WorkspacePeerMessage[]>([]), jobs = ref<WorkspaceMemoryJob[]>([]), revisions = ref<WorkspaceMemoryRevision[]>([])\nconst draft = ref<{ id?: string; expectedRevision?: number; agentId: string; content: string; tier: WorkspaceMemory['tier'] }>()\nconst projectDraft = ref<WorkspaceProject>()\nconst memoryTotal=ref(0), nextMemoryOffset=ref<number>(), loadedMore=ref(false)\nconst fileDirty=ref(false)\nconst activities = ref<WorkspaceMessage[]>([])\nlet generation = 0, timer: ReturnType<typeof setInterval> | undefined\nconst available = computed(() => props.agents.filter(a => !a.archived && !a.temporaryGoalId))\nconst currentAgent = computed(() => props.agents.find(a => a.id === agentId.value))\nconst currentProject = computed(() => projects.value.find(p => p.id === projectId.value))\nconst scope = computed(() => (['agent', 'user', 'project'].includes(tab.value) ? tab.value : 'agent') as MemoryScope)\nconst name = (id?: string) => props.agents.find(a => a.id === id)?.name ?? '原贡献者'\nconst collaboration = computed(() => collaborationTimeline({ peers: peers.value, activities: activities.value, assignments: props.assignments ?? [], coordinatorId: props.goal?.coordinatorId, name }))\nconst query = () => new URLSearchParams({ scope: scope.value, ...(tab.value === 'agent' && agentId.value ? { agentId: agentId.value } : {}), ...(tab.value === 'project' && projectId.value ? { projectId: projectId.value } : {}), ...(search.value ? { search: search.value } : {}) }).toString()\nconst stateNames: Record<string, string> = { queued: '已排队', pending: '待提炼', running: '处理中', waiting: '等待同伴', complete: '已完成', failed: '失败', stopped: '已停止', skipped: '已跳过' }\nconst skipReasonNames: Record<MemorySkipReason, string> = {\n source_missing: '找不到对应的来源消息', quote_mismatch: '引用与原文不一致', sensitive_content: '包含凭据等敏感内容',\n project_unbound: '项目记忆缺少关联项目', user_not_explicit: '缺少用户明确表达的长期信息', forgotten: '已遗忘的内容或来源不再保存', stale: '推理期间记忆已更新,本次旧提炼结果未应用',\n}\nfunction jobSummary(job: WorkspaceMemoryJob): string {\n if (job.status !== 'complete') return stateNames[job.status] ?? job.status\n const result = job.result\n if (!result) return '已结束(旧记录未统计保存结果)'\n if (!result.extractedCount) return '本轮没有可记录内容'\n if (result.writtenCount) return `已保存 ${result.writtenCount} 条记忆`\n if (result.replayedCount) return `重试已确认 ${result.replayedCount} 条记录`\n if (result.duplicateCount) return '未新增记忆,已有相同内容'\n return '候选记忆均未保存'\n}\nfunction skippedReasons(job: WorkspaceMemoryJob): string[] {\n return Object.entries(job.result?.skippedReasons ?? {}).filter(([, count]) => count > 0)\n .map(([reason, count]) => `${skipReasonNames[reason as MemorySkipReason] ?? '其他原因'}:${count} 条`)\n}\nasync function load(silent = false) {\n if (silent && loadedMore.value && tab.value !== 'collaboration') return\n const epoch = ++generation\n if (!silent) error.value = ''\n try {\n const projectResult = await apiRequest<{ projects: WorkspaceProject[] }>('/api/app/workspace/projects')\n if (epoch !== generation || !opened.value) return\n projects.value = projectResult.projects\n if (!projectId.value) projectId.value = projects.value.find(p => !p.archived)?.id ?? ''\n if (tab.value === 'collaboration') {\n const [result, milestones] = await Promise.all([\n apiRequest<{ messages: WorkspacePeerMessage[] }>(`/api/app/workspace/collaboration?${new URLSearchParams({ ...(props.conversationId ? { conversationId: props.conversationId } : {}), ...(props.taskId ? { taskId: props.taskId } : {}) })}`),\n props.conversationId ? apiRequest<{ messages: WorkspaceMessage[] }>(`/api/app/conversations/${encodeURIComponent(props.conversationId)}/activities${props.taskId ? `?taskId=${encodeURIComponent(props.taskId)}` : ''}`) : Promise.resolve({ messages: [] }),\n ])\n if (epoch === generation) { peers.value = result.messages; activities.value = milestones.messages }\n } else if (tab.value !== 'projects' && (tab.value !== 'project' || projectId.value)) {\n const result = await apiRequest<{ memories: WorkspaceMemory[]; total?: number; nextOffset?: number }>(`/api/app/workspace/memories?${query()}`)\n if (epoch === generation) { memories.value = result.memories; memoryTotal.value = result.total ?? result.memories.length; nextMemoryOffset.value = result.nextOffset; loadedMore.value = false }\n } else { memories.value = []; memoryTotal.value = 0; nextMemoryOffset.value = undefined; loadedMore.value = false }\n if (agentId.value) {\n const result = await apiRequest<{ jobs: WorkspaceMemoryJob[] }>(`/api/app/workspace/memory-jobs?agentId=${agentId.value}`)\n if (epoch === generation) jobs.value = result.jobs\n }\n } catch (cause) { if (epoch === generation) error.value = String(cause) }\n}\nasync function loadMoreMemories() {\n if (busy.value || nextMemoryOffset.value === undefined) return\n const epoch = generation, filter = query(), offset = nextMemoryOffset.value\n busy.value = true; error.value = ''\n try {\n const result = await apiRequest<{ memories: WorkspaceMemory[]; total: number; nextOffset?: number }>(`/api/app/workspace/memories?${filter}&offset=${offset}&limit=100`)\n if (epoch !== generation || !opened.value || filter !== query()) return\n const existing = new Set(memories.value.map(m => `${m.scope}:${m.agentId}:${m.id}`))\n memories.value.push(...result.memories.filter(m => !existing.has(`${m.scope}:${m.agentId}:${m.id}`)))\n memoryTotal.value = result.total; nextMemoryOffset.value = result.nextOffset; loadedMore.value = true\n } catch (cause) { if (epoch === generation) error.value = String(cause) } finally { busy.value = false }\n}\nasync function open(initial = 'agent', selectedAgent?: string, selectedProject?: string) {\n tab.value = initial; agentId.value = selectedAgent ?? available.value[0]?.id ?? ''; projectId.value = selectedProject ?? ''\n opened.value = true; draft.value = undefined; projectDraft.value = undefined; revisions.value = []; search.value = ''\n await nextTick(); if (!props.embedded) dialog.value?.showModal(); await load()\n clearInterval(timer); timer = setInterval(() => { if (!busy.value && !draft.value && !projectDraft.value) void load(true) }, 5000)\n}\nfunction close() { if(fileDirty.value){error.value='请先保存文件或取消编辑。';return} opened.value = false; generation++; clearInterval(timer); if (!props.embedded) dialog.value?.close() }\nfunction switchTab(value: string) { if(fileDirty.value)return; tab.value = value; draft.value = undefined; projectDraft.value = undefined; revisions.value = []; void load() }\nasync function perform(action: () => Promise<void>) {\n if (busy.value) return\n busy.value = true; error.value = ''\n try { await action(); emit('changed'); await load() } catch (cause) { error.value = String(cause) } finally { busy.value = false }\n}\nfunction newMemory(memory?: WorkspaceMemory) {\n revisions.value = []\n draft.value = memory ? { id: memory.id, expectedRevision: memory.revision, agentId: memory.agentId, content: memory.content, tier: memory.tier } : { agentId: agentId.value || available.value[0]?.id || '', content: '', tier: 'log' }\n}\nasync function saveMemory() {\n const value = draft.value\n if (!value?.content.trim()) { error.value = '请输入需要记住的事实'; return }\n await perform(async () => {\n await apiRequest('/api/app/workspace/memories', { method: 'POST', body: { requestId: createUuid(), scope: scope.value, ...(scope.value === 'project' ? { projectId: projectId.value } : {}), ...value } })\n draft.value = undefined\n })\n}\nasync function forget(memory: WorkspaceMemory) {\n await perform(async () => { await apiRequest('/api/app/workspace/memories/forget', { method: 'POST', body: { requestId: createUuid(), scope: memory.scope, agentId: memory.agentId, ...(memory.projectId ? { projectId: memory.projectId } : {}), id: memory.id, expectedRevision: memory.revision } }) })\n}\nasync function history(memory: WorkspaceMemory) {\n const query = new URLSearchParams({ scope: memory.scope, agentId: memory.agentId, ...(memory.projectId ? { projectId: memory.projectId } : {}) })\n await perform(async () => { revisions.value = (await apiRequest<{ revisions: WorkspaceMemoryRevision[] }>(`/api/app/workspace/memories/${memory.id}/revisions?${query}`)).revisions })\n}\nfunction editProject(project?: WorkspaceProject) {\n projectDraft.value = project ? { ...project, memberIds: [...project.memberIds], groupIds: [...project.groupIds] } : { id: '', name: '', description: '', memberIds: [], groupIds: [], revision: 0, archived: false, createdAt: 0, updatedAt: 0 }\n}\nasync function saveProject() {\n const value = projectDraft.value\n if (!value?.name.trim()) { error.value = '请输入项目名称'; return }\n await perform(async () => {\n const result = await apiRequest<{ project: WorkspaceProject }>('/api/app/workspace/projects', { method: 'POST', body: { requestId: createUuid(), ...(value.id ? { id: value.id, expectedRevision: value.revision } : {}), name: value.name, description: value.description, memberIds: value.memberIds, groupIds: value.groupIds, archived: value.archived } })\n projectId.value = result.project.id; projectDraft.value = undefined\n })\n}\nasync function setAgent(field: 'canCollaborate' | 'memoryEnabled', enabled: boolean) {\n await perform(async () => { await apiRequest(`/api/app/agents/${agentId.value}`, { method: 'PATCH', body: { [field]: enabled } }) })\n}\nonBeforeUnmount(() => { generation++; clearInterval(timer) })\nonMounted(() => { if (props.embedded) void open(props.initialTab ?? 'projects', props.selectedAgentId) })\nwatch(() => props.initialTab, value => { if (props.embedded && value) switchTab(value) })\nwatch(() => props.revision, () => { if (opened.value && !busy.value && !draft.value && !projectDraft.value) void load(true) })\nwatch(() => [props.conversationId, props.taskId], () => { generation++; peers.value = []; activities.value = []; if (opened.value && tab.value === 'collaboration') void load() })\nwatch(() => fileDirty.value || !!draft.value || !!projectDraft.value, value => emit('dirty-change', value))\ndefineExpose({ open, close })\n</script>\n\n<template>\n <component :is=\"embedded ? 'section' : 'dialog'\" ref=\"dialog\" class=\"knowledge-dialog\" :class=\"{ 'knowledge-dialog--embedded': embedded }\" :aria-labelledby=\"embedded ? undefined : 'knowledge-title'\" @cancel.prevent=\"close\" @close=\"opened = false\">\n <header v-if=\"!embedded\"><div><h2 id=\"knowledge-title\">Bot 记忆与协作</h2><p>管理长期事实、项目和同伴请求</p></div><button type=\"button\" @click=\"close\" aria-label=\"关闭记忆与协作\">关闭</button></header>\n <nav v-if=\"!embedded\" aria-label=\"记忆与项目分类\"><button v-for=\"item in [['agent','Bot 记忆'],['user','用户记忆'],['projects','项目'],['project','项目记忆'],['collaboration','协作']]\" :key=\"item[0]\" :aria-pressed=\"tab === item[0]\" @click=\"switchTab(item[0]!)\">{{ item[1] }}</button></nav>\n <div class=\"knowledge-body\" :aria-busy=\"busy\">\n <div v-if=\"embedded && tab === 'project'\" class=\"actions\"><button type=\"button\" @click=\"switchTab('projects')\">返回项目</button><h3>项目记忆</h3></div>\n <p v-if=\"error\" role=\"alert\" class=\"knowledge-error\">{{ error }}</p>\n <template v-if=\"tab === 'projects'\">\n <div v-if=\"embedded\" class=\"project-heading\"><div><h3>项目</h3><p>让同一项目的 Bot 共享决策与约定。</p></div><button v-if=\"!projectDraft\" type=\"button\" class=\"project-primary\" @click=\"editProject()\">新建项目</button></div>\n <button v-else-if=\"!projectDraft\" @click=\"editProject()\">新建项目</button>\n <form v-if=\"projectDraft\" class=\"knowledge-editor\" @submit.prevent=\"saveProject\">\n <h3>{{ projectDraft.id ? '编辑项目' : '新建项目' }}</h3>\n <label>名称<input v-model=\"projectDraft.name\" required maxlength=\"100\" /></label>\n <label>说明<textarea v-model=\"projectDraft.description\" rows=\"3\" maxlength=\"16000\" /></label>\n <fieldset><legend>项目成员</legend><label v-for=\"agent in available\" :key=\"agent.id\" class=\"check\"><input v-model=\"projectDraft.memberIds\" type=\"checkbox\" :value=\"agent.id\" />{{ agent.name }}</label></fieldset>\n <fieldset><legend>关联群聊</legend><p>群内所有 Bot 需要先加入此项目。</p><label v-for=\"group in conversations.filter(c => c.kind === 'group' && !c.archived)\" :key=\"group.id\" class=\"check\"><input v-model=\"projectDraft.groupIds\" type=\"checkbox\" :value=\"group.id\" :disabled=\"group.memberIds.some(id => !projectDraft!.memberIds.includes(id)) || !!group.projectId && group.projectId !== projectDraft.id\" />{{ group.name }}</label></fieldset>\n <label v-if=\"projectDraft.id\" class=\"check\"><input v-model=\"projectDraft.archived\" type=\"checkbox\" />归档项目</label>\n <div class=\"actions\"><button type=\"submit\" :disabled=\"busy\">保存项目</button><button type=\"button\" @click=\"projectDraft = undefined\">取消</button></div>\n </form>\n <template v-if=\"embedded && !projectDraft\">\n <div v-if=\"projects.length\" class=\"project-list\" aria-label=\"项目列表\"><button v-for=\"project in projects\" :key=\"project.id\" type=\"button\" :aria-pressed=\"projectId === project.id\" @click=\"projectId = project.id\"><AppIcon name=\"files\" :size=\"21\"/><span><strong>{{project.name}}{{project.archived ? ' · 已归档' : ''}}</strong><small>{{project.memberIds.length}} 位 Bot · {{project.groupIds.length}} 个群聊</small></span><ChevronForwardOutline class=\"project-chevron\" aria-hidden=\"true\"/></button></div>\n <section v-if=\"currentProject\" class=\"project-details\" aria-label=\"当前项目详情\">\n <h3>{{currentProject.name}}</h3><p v-if=\"currentProject.description\" class=\"project-description\">{{currentProject.description}}</p>\n <div class=\"project-detail-row\"><span>项目成员</span><div class=\"project-members\"><span v-for=\"id in currentProject.memberIds\" :key=\"id\"><AgentAvatar :name=\"name(id)\" :avatar=\"agents.find(a => a.id === id)?.avatar || ''\" :size=\"24\"/>{{name(id)}}</span><small v-if=\"!currentProject.memberIds.length\">尚无成员</small></div></div>\n <div class=\"project-detail-row\"><span>关联群聊</span><div>{{currentProject.groupIds.map(id => conversations.find(c => c.id === id)?.name ?? '原群聊').join('、') || '尚未关联群聊'}}</div></div>\n <div class=\"project-detail-row\"><span>项目记忆</span><div><button type=\"button\" @click=\"switchTab('project')\">查看记忆</button></div></div>\n <div class=\"project-detail-actions\"><button type=\"button\" class=\"project-primary\" @click=\"editProject(currentProject)\">编辑项目</button></div>\n </section>\n </template>\n <template v-else-if=\"!embedded\"><article v-for=\"project in projects\" :key=\"project.id\"><h3>{{ project.name }}{{ project.archived ? ' · 已归档' : '' }}</h3><p>{{ project.description || '暂无说明' }}</p><small>{{ project.memberIds.map(id => name(id)).join('、') || '尚无成员' }} · {{ project.groupIds.length }} 个群</small><div class=\"actions\"><button @click=\"editProject(project)\">编辑</button><button @click=\"projectId = project.id; switchTab('project')\">查看记忆</button></div></article></template>\n <p v-if=\"!projects.length && !projectDraft\" class=\"empty\">创建项目后,多个群可以共享该项目的决策和约定。</p>\n </template>\n <template v-else-if=\"tab === 'collaboration'\">\n <p class=\"scope-note\">{{ taskId ? '当前话题' : '当前聊天' }} · {{ collaboration.length }} 条协作记录</p>\n <article v-for=\"event in collaboration\" :key=\"event.id\"><details><summary>{{ event.title }} · {{ event.status }}</summary><p class=\"pre-wrap\">{{ event.content }}</p><small v-if=\"event.at\">{{ new Date(event.at).toLocaleString() }}</small><p v-if=\"event.error\" class=\"knowledge-error\">{{ event.error }}</p></details><button v-if=\"event.peer && ['queued','running','waiting'].includes(event.peer.status)\" :disabled=\"busy\" @click=\"perform(async () => { await apiRequest(`/api/app/workspace/collaboration/${encodeURIComponent(event.peer!.id)}/stop`, { method: 'POST' }) })\">停止此次协作</button></article>\n <p v-if=\"!collaboration.length\" class=\"empty\">暂无协作记录。你可以在聊天中让 Bot 联系同伴,或派发任务。</p>\n </template>\n <template v-else>\n <MemoryFilesPanel v-if=\"agentId && (scope !== 'project' || projectId)\" :agent-id=\"agentId\" :scope=\"scope\" :project-id=\"projectId\" @dirty-change=\"fileDirty=$event\" @changed=\"emit('changed');load()\" />\n <div class=\"filters\">\n <label v-if=\"['agent','user','project'].includes(tab) && !selectedAgentId\">记忆贡献 Bot<select :disabled=\"fileDirty\" v-model=\"agentId\" @change=\"draft = undefined; load()\"><option v-for=\"agent in available\" :key=\"agent.id\" :value=\"agent.id\">{{ agent.name }}</option></select></label>\n <label v-if=\"tab === 'project'\">项目<select :disabled=\"fileDirty\" v-model=\"projectId\" @change=\"draft = undefined; load()\"><option v-for=\"project in projects\" :key=\"project.id\" :value=\"project.id\">{{ project.name }}</option></select></label>\n <form @submit.prevent=\"load()\"><label>搜索记忆<input v-model=\"search\" type=\"search\" placeholder=\"搜索事实、偏好或决策\" /></label><button type=\"submit\">搜索</button></form>\n </div>\n <p class=\"scope-note\">{{ tab === 'agent' ? '仅此 Bot 使用,可跨单聊和群聊延续。' : tab === 'user' ? '同一账号的 Bot 共享,按贡献者保存。' : `仅「${currentProject?.name ?? '当前项目'}」成员读取。` }}</p>\n <template v-if=\"tab === 'agent' && currentAgent\"><label v-if=\"!hideAgentControls\" class=\"check\"><input type=\"checkbox\" :checked=\"currentAgent.memoryEnabled !== false\" :disabled=\"busy\" @change=\"setAgent('memoryEnabled', ($event.target as HTMLInputElement).checked)\" />自动记录长期事实</label><p v-if=\"currentAgent.memoryStatus === 'upgrade_required'\" role=\"status\">执行节点需要升级后才能启用隔离记忆;已保存的文件仍可管理。</p></template>\n <div v-if=\"tab !== 'project' || projectId\" class=\"actions\"><button @click=\"newMemory()\" :disabled=\"!available.length\">添加记忆</button><a :href=\"`/api/app/workspace/memory-export?${query()}`\" download=\"bot-memory.md\">导出 Markdown</a></div>\n <form v-if=\"draft\" class=\"knowledge-editor\" @submit.prevent=\"saveMemory\"><h3>{{ draft.id ? '编辑记忆' : '添加记忆' }}</h3><label v-if=\"!draft.id && tab !== 'agent'\">贡献 Bot<select v-model=\"draft.agentId\"><option v-for=\"agent in available.filter(a => tab !== 'project' || currentProject?.memberIds.includes(a.id))\" :key=\"agent.id\" :value=\"agent.id\">{{ agent.name }}</option></select></label><label>事实<textarea v-model=\"draft.content\" required rows=\"4\" maxlength=\"2000\" /></label><label>类别<select v-model=\"draft.tier\"><option value=\"profile\">长期事实</option><option value=\"log\">历史记录</option><option value=\"note\">补充笔记</option></select></label><div class=\"actions\"><button type=\"submit\" :disabled=\"busy\">保存</button><button type=\"button\" @click=\"draft = undefined\">取消</button></div></form>\n <article v-for=\"memory in memories\" :key=\"`${memory.scope}:${memory.agentId}:${memory.id}`\"><p class=\"pre-wrap\">{{ memory.content }}</p><p v-if=\"memory.conflict\" role=\"status\">同主题有不同贡献,请核对来源。</p><small>{{ name(memory.agentId) }} · {{ memory.origin === 'manual' ? '用户维护' : memory.origin === 'explicit' ? '明确保存' : '自动提炼' }} · {{ new Date(memory.updatedAt).toLocaleString() }} · 版本 {{ memory.revision }}</small><details v-if=\"memory.sources.length\"><summary>查看来源</summary><p v-for=\"source in memory.sources\" :key=\"source.messageId\"><a :href=\"`/conversations/${source.conversationId}${source.taskId ? `?taskId=${source.taskId}` : ''}`\">{{ source.quote || '查看原话题' }}</a><small v-if=\"source.at\"> · 来源 {{ new Date(source.at).toLocaleString() }}</small></p></details><div class=\"actions\"><button @click=\"newMemory(memory)\">编辑</button><button @click=\"history(memory)\" :disabled=\"busy\">修订记录</button><button @click=\"forget(memory)\" :disabled=\"busy\">遗忘</button></div></article>\n <div v-if=\"memories.length\" class=\"actions\"><small role=\"status\">已显示 {{ memories.length }} / {{ memoryTotal }} 条</small><button v-if=\"nextMemoryOffset !== undefined\" :disabled=\"busy\" @click=\"loadMoreMemories\">加载更多记忆</button><button v-if=\"loadedMore\" :disabled=\"busy\" @click=\"load()\">刷新结果</button></div>\n <p v-if=\"!memories.length && !draft\" class=\"empty\">暂无记忆。可手动添加,也可在对话中说明需要长期记住的事实。</p>\n <section v-if=\"revisions.length\" class=\"knowledge-editor\"><h3>修订记录</h3><article v-for=\"revision in revisions\" :key=\"revision.id\"><small>版本 {{ revision.revision }} · {{ revision.operation === 'forget' ? '遗忘' : '保存' }} · {{ new Date(revision.at).toLocaleString() }}</small><p>{{ revision.after?.content ?? revision.before?.content }}</p></article><button @click=\"revisions = []\">收起</button></section>\n <details v-if=\"tab === 'agent' && jobs.length\">\n <summary>后台提炼记录</summary>\n <article v-for=\"job in jobs\" :key=\"job.id\">\n <small>{{ new Date(job.createdAt).toLocaleString() }} · {{ jobSummary(job) }}</small>\n <p v-if=\"job.result\">本次提炼 {{ job.result.extractedCount }} 条 · 新增保存 {{ job.result.writtenCount }} 条 · 重复 {{ job.result.duplicateCount }} 条 · 重试确认 {{ job.result.replayedCount }} 条</p>\n <p v-for=\"reason in skippedReasons(job)\" :key=\"reason\">{{ reason }}</p>\n <p v-if=\"job.error\">{{ job.error }}</p>\n <button v-if=\"job.status === 'failed'\" :disabled=\"busy\" @click=\"perform(async () => { await apiRequest(`/api/app/workspace/memory-jobs/${job.id}/retry`, { method: 'POST' }) })\">重试</button>\n </article>\n </details>\n </template>\n </div>\n </component>\n</template>\n\n<style scoped>\n.knowledge-dialog{width:min(820px,calc(100vw - 24px));max-height:calc(100dvh - 32px);padding:0;border:1px solid var(--line);border-radius:18px;background:var(--surface);color:var(--text-primary)}\n.knowledge-dialog::backdrop{background:rgb(0 0 0 / .5)}header{display:flex;justify-content:space-between;align-items:center;gap:16px;padding:20px 24px;border-bottom:1px solid var(--line)}h2,h3,p{margin:0}header p,.scope-note,.empty,small{color:var(--text-secondary)}header p{margin-top:5px;font-size:13px}nav{display:flex;flex-wrap:wrap;gap:4px;padding:10px 20px;border-bottom:1px solid var(--line)}button,a{min-height:44px;display:inline-flex;align-items:center;justify-content:center;border:1px solid var(--line);border-radius:9px;padding:8px 12px;background:var(--surface);color:var(--text-primary);font:inherit;font-size:14px;cursor:pointer;text-decoration:none}button:hover,a:hover{background:var(--surface-hover)}button[aria-pressed=true]{background:var(--surface-hover);border-color:var(--accent);color:var(--accent)}button:disabled{opacity:.5;cursor:default}button:focus-visible,a:focus-visible,input:focus-visible,textarea:focus-visible,select:focus-visible,summary:focus-visible{outline:2px solid var(--accent);outline-offset:2px}.knowledge-body{display:grid;gap:16px;padding:20px 24px;max-height:calc(100dvh - 210px);overflow:auto;overscroll-behavior:contain}label{display:grid;gap:6px;font-size:14px}input:not([type=checkbox]),textarea,select{min-height:44px;padding:9px 10px;border:1px solid var(--line);border-radius:8px;background:var(--surface);color:var(--text-primary);font:inherit;box-sizing:border-box;width:100%}textarea{resize:vertical}.filters{display:flex;flex-wrap:wrap;align-items:end;gap:12px}.filters>label{min-width:160px}.filters form{display:flex;align-items:end;gap:8px;flex:1}.filters form label{flex:1}.actions{display:flex;flex-wrap:wrap;gap:8px;margin-top:10px}article{padding:16px;border:1px solid var(--line);border-radius:12px;display:grid;gap:9px}.knowledge-editor{display:grid;gap:12px;padding:16px;border:1px solid var(--accent);border-radius:12px}fieldset{border:1px solid var(--line);border-radius:10px;padding:12px;display:grid;gap:8px;max-height:240px;overflow:auto}.check{display:flex;align-items:center;min-height:44px;gap:9px}.check input{width:18px;height:18px;accent-color:var(--accent)}small,.scope-note{font-size:13px;line-height:1.5}.pre-wrap{white-space:pre-wrap;overflow-wrap:anywhere;line-height:1.6}.knowledge-error{color:var(--danger,#c0392b);white-space:pre-wrap}.empty{padding:24px 8px;text-align:center;line-height:1.6}summary{cursor:pointer;min-height:36px;line-height:1.6}details p{margin-top:8px}\n@media(max-width:520px){header{padding:16px}h2{font-size:19px}nav{padding:8px}nav button{flex:1;white-space:nowrap}.knowledge-body{padding:16px;max-height:calc(100dvh - 250px)}.filters{display:grid}.filters form{min-width:0}}\n.knowledge-dialog--embedded{width:100%;max-height:none;border:0;border-radius:0;background:transparent;min-width:0}.knowledge-dialog--embedded .knowledge-body{padding:0;max-height:none;overflow:visible}.knowledge-dialog--embedded .actions{align-items:center}\n.project-heading{display:flex;align-items:flex-start;justify-content:space-between;gap:20px;margin-bottom:8px}.project-heading h3{font-size:18px;font-weight:650}.project-heading p{font-size:13px;color:var(--text-secondary);margin-top:6px;line-height:1.6}.knowledge-dialog--embedded .project-primary{flex-shrink:0;padding:8px 16px;background:var(--accent);color:var(--text-on-solid);border-color:var(--accent);font-size:13px}.project-list{border:1px solid var(--line);border-radius:11px;overflow:hidden}.project-list button{display:flex;gap:20px;width:100%;padding:18px 22px;border:0;border-radius:0;text-align:left;justify-content:flex-start;min-height:76px}.project-list button+button{border-top:1px solid var(--line)}.project-list button[aria-pressed=true]{background:var(--settings-selected);color:var(--text-primary)}.project-list button>span{flex:1;min-width:0;display:grid;gap:4px}.project-list strong{font-size:15px;font-weight:600;overflow-wrap:anywhere}.project-list small{font-size:12px}.project-list .app-icon{color:var(--text-muted)}.project-details{background:var(--settings-panel);padding:20px;border-radius:12px}.project-details h3{font-size:17px;font-weight:650;margin-bottom:12px}.project-description{font-size:13px;color:var(--text-secondary);line-height:1.6;padding-bottom:12px;white-space:pre-wrap;overflow-wrap:anywhere}.project-detail-row{display:grid;grid-template-columns:104px minmax(0,1fr);align-items:center;gap:16px;min-height:48px;border-top:1px solid var(--line);font-size:14px}.project-detail-row>span{color:var(--text-secondary)}.project-detail-row>div{overflow-wrap:anywhere}.project-detail-row button{min-height:36px;background:var(--settings-selected);border:0;font-size:12px}.project-members{display:flex;gap:10px;flex-wrap:wrap;padding-block:10px}.project-members>span{display:inline-flex;align-items:center;gap:7px}.project-detail-actions{display:flex;justify-content:flex-end;margin-top:8px}.project-detail-actions .project-primary{min-height:36px}.knowledge-dialog--embedded article{border:0;background:var(--settings-panel)}@media(max-width:520px){.project-heading{gap:10px}.project-heading p{max-width:210px}.project-list button{padding:16px;gap:12px}.project-details{padding:16px}.project-detail-row{grid-template-columns:76px minmax(0,1fr);gap:10px}}\n</style>\n<style scoped>.project-chevron{width:17px;height:17px;flex-shrink:0;color:var(--text-muted)}</style>\n","<script setup lang=\"ts\">\nimport { computed, nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue'\nimport MemoryFilesPanel from './MemoryFilesPanel.vue'\nimport type { AgentAssignment, AgentGoal } from '@shared/agentTasks'\nimport { collaborationTimeline } from '@shared/collaborationTimeline'\nimport { apiRequest } from '@/api/client'\nimport { createUuid } from '@/utils/id'\nimport AppIcon from '@/components/common/AppIcon.vue'\nimport AgentAvatar from '@/components/common/AgentAvatar.vue'\nimport { ChevronForwardOutline } from '@vicons/ionicons5'\nimport type { WorkspaceAgent, WorkspaceConversation, WorkspaceMessage } from '@shared/workspace'\nimport type { MemoryScope, MemorySkipReason, WorkspaceMemory, WorkspaceMemoryJob, WorkspaceMemoryRevision, WorkspacePeerMessage, WorkspaceProject } from '@shared/workspaceKnowledge'\n\nconst props = defineProps<{ agents: WorkspaceAgent[]; conversations: WorkspaceConversation[]; conversationId?: string; taskId?: string; assignments?: AgentAssignment[]; goal?: AgentGoal; revision?: number; embedded?: boolean; initialTab?: 'projects' | 'user' | 'agent'; selectedAgentId?: string; hideAgentControls?: boolean }>()\nconst emit = defineEmits<{ changed: []; 'dirty-change': [dirty: boolean] }>()\nconst dialog = ref<HTMLDialogElement>(), opened = ref(false), busy = ref(false), error = ref(''), tab = ref('agent'), agentId = ref(''), projectId = ref(''), search = ref('')\nconst projects = ref<WorkspaceProject[]>([]), memories = ref<WorkspaceMemory[]>([]), peers = ref<WorkspacePeerMessage[]>([]), jobs = ref<WorkspaceMemoryJob[]>([]), revisions = ref<WorkspaceMemoryRevision[]>([])\nconst draft = ref<{ id?: string; expectedRevision?: number; agentId: string; content: string; tier: WorkspaceMemory['tier'] }>()\nconst projectDraft = ref<WorkspaceProject>()\nconst memoryTotal=ref(0), nextMemoryOffset=ref<number>(), loadedMore=ref(false)\nconst fileDirty=ref(false)\nconst activities = ref<WorkspaceMessage[]>([])\nlet generation = 0, timer: ReturnType<typeof setInterval> | undefined\nconst available = computed(() => props.agents.filter(a => !a.archived && !a.temporaryGoalId))\nconst currentAgent = computed(() => props.agents.find(a => a.id === agentId.value))\nconst currentProject = computed(() => projects.value.find(p => p.id === projectId.value))\nconst scope = computed(() => (['agent', 'user', 'project'].includes(tab.value) ? tab.value : 'agent') as MemoryScope)\nconst name = (id?: string) => props.agents.find(a => a.id === id)?.name ?? '原贡献者'\nconst collaboration = computed(() => collaborationTimeline({ peers: peers.value, activities: activities.value, assignments: props.assignments ?? [], coordinatorId: props.goal?.coordinatorId, name }))\nconst query = () => new URLSearchParams({ scope: scope.value, ...(tab.value === 'agent' && agentId.value ? { agentId: agentId.value } : {}), ...(tab.value === 'project' && projectId.value ? { projectId: projectId.value } : {}), ...(search.value ? { search: search.value } : {}) }).toString()\nconst stateNames: Record<string, string> = { queued: '已排队', pending: '待提炼', running: '处理中', waiting: '等待同伴', complete: '已完成', failed: '失败', stopped: '已停止', skipped: '已跳过' }\nconst skipReasonNames: Record<MemorySkipReason, string> = {\n source_missing: '找不到对应的来源消息', quote_mismatch: '引用与原文不一致', sensitive_content: '包含凭据等敏感内容',\n project_unbound: '项目记忆缺少关联项目', user_not_explicit: '缺少用户明确表达的长期信息', forgotten: '已遗忘的内容或来源不再保存', stale: '推理期间记忆已更新,本次旧提炼结果未应用',\n}\nfunction jobSummary(job: WorkspaceMemoryJob): string {\n if (job.status !== 'complete') return stateNames[job.status] ?? job.status\n const result = job.result\n if (!result) return '已结束(旧记录未统计保存结果)'\n if (!result.extractedCount) return '本轮没有可记录内容'\n if (result.writtenCount) return `已保存 ${result.writtenCount} 条记忆`\n if (result.replayedCount) return `重试已确认 ${result.replayedCount} 条记录`\n if (result.duplicateCount) return '未新增记忆,已有相同内容'\n return '候选记忆均未保存'\n}\nfunction skippedReasons(job: WorkspaceMemoryJob): string[] {\n return Object.entries(job.result?.skippedReasons ?? {}).filter(([, count]) => count > 0)\n .map(([reason, count]) => `${skipReasonNames[reason as MemorySkipReason] ?? '其他原因'}:${count} 条`)\n}\nasync function load(silent = false) {\n if (silent && loadedMore.value && tab.value !== 'collaboration') return\n const epoch = ++generation\n if (!silent) error.value = ''\n try {\n const projectResult = await apiRequest<{ projects: WorkspaceProject[] }>('/api/app/workspace/projects')\n if (epoch !== generation || !opened.value) return\n projects.value = projectResult.projects\n if (!projectId.value) projectId.value = projects.value.find(p => !p.archived)?.id ?? ''\n if (tab.value === 'collaboration') {\n const [result, milestones] = await Promise.all([\n apiRequest<{ messages: WorkspacePeerMessage[] }>(`/api/app/workspace/collaboration?${new URLSearchParams({ ...(props.conversationId ? { conversationId: props.conversationId } : {}), ...(props.taskId ? { taskId: props.taskId } : {}) })}`),\n props.conversationId ? apiRequest<{ messages: WorkspaceMessage[] }>(`/api/app/conversations/${encodeURIComponent(props.conversationId)}/activities${props.taskId ? `?taskId=${encodeURIComponent(props.taskId)}` : ''}`) : Promise.resolve({ messages: [] }),\n ])\n if (epoch === generation) { peers.value = result.messages; activities.value = milestones.messages }\n } else if (tab.value !== 'projects' && (tab.value !== 'project' || projectId.value)) {\n const result = await apiRequest<{ memories: WorkspaceMemory[]; total?: number; nextOffset?: number }>(`/api/app/workspace/memories?${query()}`)\n if (epoch === generation) { memories.value = result.memories; memoryTotal.value = result.total ?? result.memories.length; nextMemoryOffset.value = result.nextOffset; loadedMore.value = false }\n } else { memories.value = []; memoryTotal.value = 0; nextMemoryOffset.value = undefined; loadedMore.value = false }\n if (agentId.value) {\n const result = await apiRequest<{ jobs: WorkspaceMemoryJob[] }>(`/api/app/workspace/memory-jobs?agentId=${agentId.value}`)\n if (epoch === generation) jobs.value = result.jobs\n }\n } catch (cause) { if (epoch === generation) error.value = String(cause) }\n}\nasync function loadMoreMemories() {\n if (busy.value || nextMemoryOffset.value === undefined) return\n const epoch = generation, filter = query(), offset = nextMemoryOffset.value\n busy.value = true; error.value = ''\n try {\n const result = await apiRequest<{ memories: WorkspaceMemory[]; total: number; nextOffset?: number }>(`/api/app/workspace/memories?${filter}&offset=${offset}&limit=100`)\n if (epoch !== generation || !opened.value || filter !== query()) return\n const existing = new Set(memories.value.map(m => `${m.scope}:${m.agentId}:${m.id}`))\n memories.value.push(...result.memories.filter(m => !existing.has(`${m.scope}:${m.agentId}:${m.id}`)))\n memoryTotal.value = result.total; nextMemoryOffset.value = result.nextOffset; loadedMore.value = true\n } catch (cause) { if (epoch === generation) error.value = String(cause) } finally { busy.value = false }\n}\nasync function open(initial = 'agent', selectedAgent?: string, selectedProject?: string) {\n tab.value = initial; agentId.value = selectedAgent ?? available.value[0]?.id ?? ''; projectId.value = selectedProject ?? ''\n opened.value = true; draft.value = undefined; projectDraft.value = undefined; revisions.value = []; search.value = ''\n await nextTick(); if (!props.embedded) dialog.value?.showModal(); await load()\n clearInterval(timer); timer = setInterval(() => { if (!busy.value && !draft.value && !projectDraft.value) void load(true) }, 5000)\n}\nfunction close() { if(fileDirty.value){error.value='请先保存文件或取消编辑。';return} opened.value = false; generation++; clearInterval(timer); if (!props.embedded) dialog.value?.close() }\nfunction switchTab(value: string) { if(fileDirty.value)return; tab.value = value; draft.value = undefined; projectDraft.value = undefined; revisions.value = []; void load() }\nasync function perform(action: () => Promise<void>) {\n if (busy.value) return\n busy.value = true; error.value = ''\n try { await action(); emit('changed'); await load() } catch (cause) { error.value = String(cause) } finally { busy.value = false }\n}\nfunction newMemory(memory?: WorkspaceMemory) {\n revisions.value = []\n draft.value = memory ? { id: memory.id, expectedRevision: memory.revision, agentId: memory.agentId, content: memory.content, tier: memory.tier } : { agentId: agentId.value || available.value[0]?.id || '', content: '', tier: 'log' }\n}\nasync function saveMemory() {\n const value = draft.value\n if (!value?.content.trim()) { error.value = '请输入需要记住的事实'; return }\n await perform(async () => {\n await apiRequest('/api/app/workspace/memories', { method: 'POST', body: { requestId: createUuid(), scope: scope.value, ...(scope.value === 'project' ? { projectId: projectId.value } : {}), ...value } })\n draft.value = undefined\n })\n}\nasync function forget(memory: WorkspaceMemory) {\n await perform(async () => { await apiRequest('/api/app/workspace/memories/forget', { method: 'POST', body: { requestId: createUuid(), scope: memory.scope, agentId: memory.agentId, ...(memory.projectId ? { projectId: memory.projectId } : {}), id: memory.id, expectedRevision: memory.revision } }) })\n}\nasync function history(memory: WorkspaceMemory) {\n const query = new URLSearchParams({ scope: memory.scope, agentId: memory.agentId, ...(memory.projectId ? { projectId: memory.projectId } : {}) })\n await perform(async () => { revisions.value = (await apiRequest<{ revisions: WorkspaceMemoryRevision[] }>(`/api/app/workspace/memories/${memory.id}/revisions?${query}`)).revisions })\n}\nfunction editProject(project?: WorkspaceProject) {\n projectDraft.value = project ? { ...project, memberIds: [...project.memberIds], groupIds: [...project.groupIds] } : { id: '', name: '', description: '', memberIds: [], groupIds: [], revision: 0, archived: false, createdAt: 0, updatedAt: 0 }\n}\nasync function saveProject() {\n const value = projectDraft.value\n if (!value?.name.trim()) { error.value = '请输入项目名称'; return }\n await perform(async () => {\n const result = await apiRequest<{ project: WorkspaceProject }>('/api/app/workspace/projects', { method: 'POST', body: { requestId: createUuid(), ...(value.id ? { id: value.id, expectedRevision: value.revision } : {}), name: value.name, description: value.description, memberIds: value.memberIds, groupIds: value.groupIds, archived: value.archived } })\n projectId.value = result.project.id; projectDraft.value = undefined\n })\n}\nasync function setAgent(field: 'canCollaborate' | 'memoryEnabled', enabled: boolean) {\n await perform(async () => { await apiRequest(`/api/app/agents/${agentId.value}`, { method: 'PATCH', body: { [field]: enabled } }) })\n}\nonBeforeUnmount(() => { generation++; clearInterval(timer) })\nonMounted(() => { if (props.embedded) void open(props.initialTab ?? 'projects', props.selectedAgentId) })\nwatch(() => props.initialTab, value => { if (props.embedded && value) switchTab(value) })\nwatch(() => props.revision, () => { if (opened.value && !busy.value && !draft.value && !projectDraft.value) void load(true) })\nwatch(() => [props.conversationId, props.taskId], () => { generation++; peers.value = []; activities.value = []; if (opened.value && tab.value === 'collaboration') void load() })\nwatch(() => fileDirty.value || !!draft.value || !!projectDraft.value, value => emit('dirty-change', value))\ndefineExpose({ open, close })\n</script>\n\n<template>\n <component :is=\"embedded ? 'section' : 'dialog'\" ref=\"dialog\" class=\"knowledge-dialog\" :class=\"{ 'knowledge-dialog--embedded': embedded }\" :aria-labelledby=\"embedded ? undefined : 'knowledge-title'\" @cancel.prevent=\"close\" @close=\"opened = false\">\n <header v-if=\"!embedded\"><div><h2 id=\"knowledge-title\">Bot 记忆与协作</h2><p>管理长期事实、项目和同伴请求</p></div><button type=\"button\" @click=\"close\" aria-label=\"关闭记忆与协作\">关闭</button></header>\n <nav v-if=\"!embedded\" aria-label=\"记忆与项目分类\"><button v-for=\"item in [['agent','Bot 记忆'],['user','用户记忆'],['projects','项目'],['project','项目记忆'],['collaboration','协作']]\" :key=\"item[0]\" :aria-pressed=\"tab === item[0]\" @click=\"switchTab(item[0]!)\">{{ item[1] }}</button></nav>\n <div class=\"knowledge-body\" :aria-busy=\"busy\">\n <div v-if=\"embedded && tab === 'project'\" class=\"actions\"><button type=\"button\" @click=\"switchTab('projects')\">返回项目</button><h3>项目记忆</h3></div>\n <p v-if=\"error\" role=\"alert\" class=\"knowledge-error\">{{ error }}</p>\n <template v-if=\"tab === 'projects'\">\n <div v-if=\"embedded\" class=\"project-heading\"><div><h3>项目</h3><p>让同一项目的 Bot 共享决策与约定。</p></div><button v-if=\"!projectDraft\" type=\"button\" class=\"project-primary\" @click=\"editProject()\">新建项目</button></div>\n <button v-else-if=\"!projectDraft\" @click=\"editProject()\">新建项目</button>\n <form v-if=\"projectDraft\" class=\"knowledge-editor\" @submit.prevent=\"saveProject\">\n <h3>{{ projectDraft.id ? '编辑项目' : '新建项目' }}</h3>\n <label>名称<input v-model=\"projectDraft.name\" required maxlength=\"100\" /></label>\n <label>说明<textarea v-model=\"projectDraft.description\" rows=\"3\" maxlength=\"16000\" /></label>\n <fieldset><legend>项目成员</legend><label v-for=\"agent in available\" :key=\"agent.id\" class=\"check\"><input v-model=\"projectDraft.memberIds\" type=\"checkbox\" :value=\"agent.id\" />{{ agent.name }}</label></fieldset>\n <fieldset><legend>关联群聊</legend><p>群内所有 Bot 需要先加入此项目。</p><label v-for=\"group in conversations.filter(c => c.kind === 'group' && !c.archived)\" :key=\"group.id\" class=\"check\"><input v-model=\"projectDraft.groupIds\" type=\"checkbox\" :value=\"group.id\" :disabled=\"group.memberIds.some(id => !projectDraft!.memberIds.includes(id)) || !!group.projectId && group.projectId !== projectDraft.id\" />{{ group.name }}</label></fieldset>\n <label v-if=\"projectDraft.id\" class=\"check\"><input v-model=\"projectDraft.archived\" type=\"checkbox\" />归档项目</label>\n <div class=\"actions\"><button type=\"submit\" :disabled=\"busy\">保存项目</button><button type=\"button\" @click=\"projectDraft = undefined\">取消</button></div>\n </form>\n <template v-if=\"embedded && !projectDraft\">\n <div v-if=\"projects.length\" class=\"project-list\" aria-label=\"项目列表\"><button v-for=\"project in projects\" :key=\"project.id\" type=\"button\" :aria-pressed=\"projectId === project.id\" @click=\"projectId = project.id\"><AppIcon name=\"files\" :size=\"21\"/><span><strong>{{project.name}}{{project.archived ? ' · 已归档' : ''}}</strong><small>{{project.memberIds.length}} 位 Bot · {{project.groupIds.length}} 个群聊</small></span><ChevronForwardOutline class=\"project-chevron\" aria-hidden=\"true\"/></button></div>\n <section v-if=\"currentProject\" class=\"project-details\" aria-label=\"当前项目详情\">\n <h3>{{currentProject.name}}</h3><p v-if=\"currentProject.description\" class=\"project-description\">{{currentProject.description}}</p>\n <div class=\"project-detail-row\"><span>项目成员</span><div class=\"project-members\"><span v-for=\"id in currentProject.memberIds\" :key=\"id\"><AgentAvatar :name=\"name(id)\" :avatar=\"agents.find(a => a.id === id)?.avatar || ''\" :size=\"24\"/>{{name(id)}}</span><small v-if=\"!currentProject.memberIds.length\">尚无成员</small></div></div>\n <div class=\"project-detail-row\"><span>关联群聊</span><div>{{currentProject.groupIds.map(id => conversations.find(c => c.id === id)?.name ?? '原群聊').join('、') || '尚未关联群聊'}}</div></div>\n <div class=\"project-detail-row\"><span>项目记忆</span><div><button type=\"button\" @click=\"switchTab('project')\">查看记忆</button></div></div>\n <div class=\"project-detail-actions\"><button type=\"button\" class=\"project-primary\" @click=\"editProject(currentProject)\">编辑项目</button></div>\n </section>\n </template>\n <template v-else-if=\"!embedded\"><article v-for=\"project in projects\" :key=\"project.id\"><h3>{{ project.name }}{{ project.archived ? ' · 已归档' : '' }}</h3><p>{{ project.description || '暂无说明' }}</p><small>{{ project.memberIds.map(id => name(id)).join('、') || '尚无成员' }} · {{ project.groupIds.length }} 个群</small><div class=\"actions\"><button @click=\"editProject(project)\">编辑</button><button @click=\"projectId = project.id; switchTab('project')\">查看记忆</button></div></article></template>\n <p v-if=\"!projects.length && !projectDraft\" class=\"empty\">创建项目后,多个群可以共享该项目的决策和约定。</p>\n </template>\n <template v-else-if=\"tab === 'collaboration'\">\n <p class=\"scope-note\">{{ taskId ? '当前话题' : '当前聊天' }} · {{ collaboration.length }} 条协作记录</p>\n <article v-for=\"event in collaboration\" :key=\"event.id\"><details><summary>{{ event.title }} · {{ event.status }}</summary><p class=\"pre-wrap\">{{ event.content }}</p><small v-if=\"event.at\">{{ new Date(event.at).toLocaleString() }}</small><p v-if=\"event.error\" class=\"knowledge-error\">{{ event.error }}</p></details><button v-if=\"event.peer && ['queued','running','waiting'].includes(event.peer.status)\" :disabled=\"busy\" @click=\"perform(async () => { await apiRequest(`/api/app/workspace/collaboration/${encodeURIComponent(event.peer!.id)}/stop`, { method: 'POST' }) })\">停止此次协作</button></article>\n <p v-if=\"!collaboration.length\" class=\"empty\">暂无协作记录。你可以在聊天中让 Bot 联系同伴,或派发任务。</p>\n </template>\n <template v-else>\n <MemoryFilesPanel v-if=\"agentId && (scope !== 'project' || projectId)\" :agent-id=\"agentId\" :scope=\"scope\" :project-id=\"projectId\" @dirty-change=\"fileDirty=$event\" @changed=\"emit('changed');load()\" />\n <div class=\"filters\">\n <label v-if=\"['agent','user','project'].includes(tab) && !selectedAgentId\">记忆贡献 Bot<select :disabled=\"fileDirty\" v-model=\"agentId\" @change=\"draft = undefined; load()\"><option v-for=\"agent in available\" :key=\"agent.id\" :value=\"agent.id\">{{ agent.name }}</option></select></label>\n <label v-if=\"tab === 'project'\">项目<select :disabled=\"fileDirty\" v-model=\"projectId\" @change=\"draft = undefined; load()\"><option v-for=\"project in projects\" :key=\"project.id\" :value=\"project.id\">{{ project.name }}</option></select></label>\n <form @submit.prevent=\"load()\"><label>搜索记忆<input v-model=\"search\" type=\"search\" placeholder=\"搜索事实、偏好或决策\" /></label><button type=\"submit\">搜索</button></form>\n </div>\n <p class=\"scope-note\">{{ tab === 'agent' ? '仅此 Bot 使用,可跨单聊和群聊延续。' : tab === 'user' ? '同一账号的 Bot 共享,按贡献者保存。' : `仅「${currentProject?.name ?? '当前项目'}」成员读取。` }}</p>\n <template v-if=\"tab === 'agent' && currentAgent\"><label v-if=\"!hideAgentControls\" class=\"check\"><input type=\"checkbox\" :checked=\"currentAgent.memoryEnabled !== false\" :disabled=\"busy\" @change=\"setAgent('memoryEnabled', ($event.target as HTMLInputElement).checked)\" />自动记录长期事实</label><p v-if=\"currentAgent.memoryStatus === 'upgrade_required'\" role=\"status\">执行节点需要升级后才能启用隔离记忆;已保存的文件仍可管理。</p></template>\n <div v-if=\"tab !== 'project' || projectId\" class=\"actions\"><button @click=\"newMemory()\" :disabled=\"!available.length\">添加记忆</button><a :href=\"`/api/app/workspace/memory-export?${query()}`\" download=\"bot-memory.md\">导出 Markdown</a></div>\n <form v-if=\"draft\" class=\"knowledge-editor\" @submit.prevent=\"saveMemory\"><h3>{{ draft.id ? '编辑记忆' : '添加记忆' }}</h3><label v-if=\"!draft.id && tab !== 'agent'\">贡献 Bot<select v-model=\"draft.agentId\"><option v-for=\"agent in available.filter(a => tab !== 'project' || currentProject?.memberIds.includes(a.id))\" :key=\"agent.id\" :value=\"agent.id\">{{ agent.name }}</option></select></label><label>事实<textarea v-model=\"draft.content\" required rows=\"4\" maxlength=\"2000\" /></label><label>类别<select v-model=\"draft.tier\"><option value=\"profile\">长期事实</option><option value=\"log\">历史记录</option><option value=\"note\">补充笔记</option></select></label><div class=\"actions\"><button type=\"submit\" :disabled=\"busy\">保存</button><button type=\"button\" @click=\"draft = undefined\">取消</button></div></form>\n <article v-for=\"memory in memories\" :key=\"`${memory.scope}:${memory.agentId}:${memory.id}`\"><p class=\"pre-wrap\">{{ memory.content }}</p><p v-if=\"memory.conflict\" role=\"status\">同主题有不同贡献,请核对来源。</p><small>{{ name(memory.agentId) }} · {{ memory.origin === 'manual' ? '用户维护' : memory.origin === 'explicit' ? '明确保存' : '自动提炼' }} · {{ new Date(memory.updatedAt).toLocaleString() }} · 版本 {{ memory.revision }}</small><details v-if=\"memory.sources.length\"><summary>查看来源</summary><p v-for=\"source in memory.sources\" :key=\"source.messageId\"><a :href=\"`/conversations/${source.conversationId}${source.taskId ? `?taskId=${source.taskId}` : ''}`\">{{ source.quote || '查看原话题' }}</a><small v-if=\"source.at\"> · 来源 {{ new Date(source.at).toLocaleString() }}</small></p></details><div class=\"actions\"><button @click=\"newMemory(memory)\">编辑</button><button @click=\"history(memory)\" :disabled=\"busy\">修订记录</button><button @click=\"forget(memory)\" :disabled=\"busy\">遗忘</button></div></article>\n <div v-if=\"memories.length\" class=\"actions\"><small role=\"status\">已显示 {{ memories.length }} / {{ memoryTotal }} 条</small><button v-if=\"nextMemoryOffset !== undefined\" :disabled=\"busy\" @click=\"loadMoreMemories\">加载更多记忆</button><button v-if=\"loadedMore\" :disabled=\"busy\" @click=\"load()\">刷新结果</button></div>\n <p v-if=\"!memories.length && !draft\" class=\"empty\">暂无记忆。可手动添加,也可在对话中说明需要长期记住的事实。</p>\n <section v-if=\"revisions.length\" class=\"knowledge-editor\"><h3>修订记录</h3><article v-for=\"revision in revisions\" :key=\"revision.id\"><small>版本 {{ revision.revision }} · {{ revision.operation === 'forget' ? '遗忘' : '保存' }} · {{ new Date(revision.at).toLocaleString() }}</small><p>{{ revision.after?.content ?? revision.before?.content }}</p></article><button @click=\"revisions = []\">收起</button></section>\n <details v-if=\"tab === 'agent' && jobs.length\">\n <summary>后台提炼记录</summary>\n <article v-for=\"job in jobs\" :key=\"job.id\">\n <small>{{ new Date(job.createdAt).toLocaleString() }} · {{ jobSummary(job) }}</small>\n <p v-if=\"job.result\">本次提炼 {{ job.result.extractedCount }} 条 · 新增保存 {{ job.result.writtenCount }} 条 · 重复 {{ job.result.duplicateCount }} 条 · 重试确认 {{ job.result.replayedCount }} 条</p>\n <p v-for=\"reason in skippedReasons(job)\" :key=\"reason\">{{ reason }}</p>\n <p v-if=\"job.error\">{{ job.error }}</p>\n <button v-if=\"job.status === 'failed'\" :disabled=\"busy\" @click=\"perform(async () => { await apiRequest(`/api/app/workspace/memory-jobs/${job.id}/retry`, { method: 'POST' }) })\">重试</button>\n </article>\n </details>\n </template>\n </div>\n </component>\n</template>\n\n<style scoped>\n.knowledge-dialog{width:min(820px,calc(100vw - 24px));max-height:calc(100dvh - 32px);padding:0;border:1px solid var(--line);border-radius:18px;background:var(--surface);color:var(--text-primary)}\n.knowledge-dialog::backdrop{background:rgb(0 0 0 / .5)}header{display:flex;justify-content:space-between;align-items:center;gap:16px;padding:20px 24px;border-bottom:1px solid var(--line)}h2,h3,p{margin:0}header p,.scope-note,.empty,small{color:var(--text-secondary)}header p{margin-top:5px;font-size:13px}nav{display:flex;flex-wrap:wrap;gap:4px;padding:10px 20px;border-bottom:1px solid var(--line)}button,a{min-height:44px;display:inline-flex;align-items:center;justify-content:center;border:1px solid var(--line);border-radius:9px;padding:8px 12px;background:var(--surface);color:var(--text-primary);font:inherit;font-size:14px;cursor:pointer;text-decoration:none}button:hover,a:hover{background:var(--surface-hover)}button[aria-pressed=true]{background:var(--surface-hover);border-color:var(--accent);color:var(--accent)}button:disabled{opacity:.5;cursor:default}button:focus-visible,a:focus-visible,input:focus-visible,textarea:focus-visible,select:focus-visible,summary:focus-visible{outline:2px solid var(--accent);outline-offset:2px}.knowledge-body{display:grid;gap:16px;padding:20px 24px;max-height:calc(100dvh - 210px);overflow:auto;overscroll-behavior:contain}label{display:grid;gap:6px;font-size:14px}input:not([type=checkbox]),textarea,select{min-height:44px;padding:9px 10px;border:1px solid var(--line);border-radius:8px;background:var(--surface);color:var(--text-primary);font:inherit;box-sizing:border-box;width:100%}textarea{resize:vertical}.filters{display:flex;flex-wrap:wrap;align-items:end;gap:12px}.filters>label{min-width:160px}.filters form{display:flex;align-items:end;gap:8px;flex:1}.filters form label{flex:1}.actions{display:flex;flex-wrap:wrap;gap:8px;margin-top:10px}article{padding:16px;border:1px solid var(--line);border-radius:12px;display:grid;gap:9px}.knowledge-editor{display:grid;gap:12px;padding:16px;border:1px solid var(--accent);border-radius:12px}fieldset{border:1px solid var(--line);border-radius:10px;padding:12px;display:grid;gap:8px;max-height:240px;overflow:auto}.check{display:flex;align-items:center;min-height:44px;gap:9px}.check input{width:18px;height:18px;accent-color:var(--accent)}small,.scope-note{font-size:13px;line-height:1.5}.pre-wrap{white-space:pre-wrap;overflow-wrap:anywhere;line-height:1.6}.knowledge-error{color:var(--danger,#c0392b);white-space:pre-wrap}.empty{padding:24px 8px;text-align:center;line-height:1.6}summary{cursor:pointer;min-height:36px;line-height:1.6}details p{margin-top:8px}\n@media(max-width:520px){header{padding:16px}h2{font-size:19px}nav{padding:8px}nav button{flex:1;white-space:nowrap}.knowledge-body{padding:16px;max-height:calc(100dvh - 250px)}.filters{display:grid}.filters form{min-width:0}}\n.knowledge-dialog--embedded{width:100%;max-height:none;border:0;border-radius:0;background:transparent;min-width:0}.knowledge-dialog--embedded .knowledge-body{padding:0;max-height:none;overflow:visible}.knowledge-dialog--embedded .actions{align-items:center}\n.project-heading{display:flex;align-items:flex-start;justify-content:space-between;gap:20px;margin-bottom:8px}.project-heading h3{font-size:18px;font-weight:650}.project-heading p{font-size:13px;color:var(--text-secondary);margin-top:6px;line-height:1.6}.knowledge-dialog--embedded .project-primary{flex-shrink:0;padding:8px 16px;background:var(--accent);color:var(--text-on-solid);border-color:var(--accent);font-size:13px}.project-list{border:1px solid var(--line);border-radius:11px;overflow:hidden}.project-list button{display:flex;gap:20px;width:100%;padding:18px 22px;border:0;border-radius:0;text-align:left;justify-content:flex-start;min-height:76px}.project-list button+button{border-top:1px solid var(--line)}.project-list button[aria-pressed=true]{background:var(--settings-selected);color:var(--text-primary)}.project-list button>span{flex:1;min-width:0;display:grid;gap:4px}.project-list strong{font-size:15px;font-weight:600;overflow-wrap:anywhere}.project-list small{font-size:12px}.project-list .app-icon{color:var(--text-muted)}.project-details{background:var(--settings-panel);padding:20px;border-radius:12px}.project-details h3{font-size:17px;font-weight:650;margin-bottom:12px}.project-description{font-size:13px;color:var(--text-secondary);line-height:1.6;padding-bottom:12px;white-space:pre-wrap;overflow-wrap:anywhere}.project-detail-row{display:grid;grid-template-columns:104px minmax(0,1fr);align-items:center;gap:16px;min-height:48px;border-top:1px solid var(--line);font-size:14px}.project-detail-row>span{color:var(--text-secondary)}.project-detail-row>div{overflow-wrap:anywhere}.project-detail-row button{min-height:36px;background:var(--settings-selected);border:0;font-size:12px}.project-members{display:flex;gap:10px;flex-wrap:wrap;padding-block:10px}.project-members>span{display:inline-flex;align-items:center;gap:7px}.project-detail-actions{display:flex;justify-content:flex-end;margin-top:8px}.project-detail-actions .project-primary{min-height:36px}.knowledge-dialog--embedded article{border:0;background:var(--settings-panel)}@media(max-width:520px){.project-heading{gap:10px}.project-heading p{max-width:210px}.project-list button{padding:16px;gap:12px}.project-details{padding:16px}.project-detail-row{grid-template-columns:76px minmax(0,1fr);gap:10px}}\n</style>\n<style scoped>.project-chevron{width:17px;height:17px;flex-shrink:0;color:var(--text-muted)}</style>\n"],"x_google_ignoreList":[0],"mappings":"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"}
|