Files
kefu/deploy/knowledge-v2-20260916/payload/admin-web/apps/web-antd/dist/js/agents-B34lWKK9.js
T
2026-09-21 10:34:06 +08:00

1 line
13 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import{D as e,E as t,On as n,_ as r,b as i,bt as a,ct as o,g as s,gn as c,k as ee,mt as l,o as u,qt as d,tr as f,v as p,vn as m,y as h}from"./runtime-core.esm-bundler-DkysjgTd.js";import{t as g}from"./objectSpread2-BmonrgTA.js";import{n as _}from"./objectWithoutProperties-BjoYlK0I.js";import{t as v}from"./use-access-CQdD7p8C.js";import{t as te}from"./table--97p0aBW.js";import{n as y,t as b}from"./form-CZK1ilUa.js";import{t as x}from"./select-DyNDAEL2.js";import{M as S,b as ne,o as re,r as ie,x as C}from"./console-BEstjdZV.js";import{a as w}from"./config-provider-D1kcLCP5.js";import{t as T}from"./alert-CkUknOsQ.js";import{t as ae}from"./popconfirm-BqMuKaMZ.js";import{t as E}from"./button-B2y2NpJm.js";import{t as D}from"./tag-BFecLZmQ.js";import{r as O,t as k}from"./input-DgEff0DC.js";import{t as oe}from"./input-number-B39v8Wj_.js";import{t as se}from"./modal-Ju-U4s3Q.js";import{t as A}from"./switch-CtSw_Hgg.js";var ce={class:`p-5`},le={class:`grid grid-cols-1 gap-x-6 md:grid-cols-2`},ue={class:`flex items-center gap-3`},de={key:1,class:`text-xs text-gray-500`},fe={key:0,class:`text-xs text-gray-400`},pe={key:2,class:`text-xs text-gray-400`},me={key:0,class:`mt-3 text-xs text-gray-500`},j={class:`grid grid-cols-1 gap-x-6 md:grid-cols-2`},M={class:`mb-2 flex items-start gap-3`},N={class:`w-44 shrink-0`},P={class:`w-64 shrink-0`},F={class:`mb-2 text-xs text-gray-500`},I={class:`grid grid-cols-1 gap-x-6 md:grid-cols-2`},L=ee({__name:`agents`,setup(ee){let{hasAccessByCodes:L}=v(),R=s(()=>L([`agent:write`])),z=m(!1),B=m([]),V=m(null),H=m(!1),U=m(``),W=c({mode:`single`,primary_id:``,active_ids:[]}),G=()=>({id:``,name:``,role:``,description:``,persona:``,keywords:[],rules:[],enabled:!0,priority:100}),K=c(G()),he=[{value:`guide`,label:`补充指令(告诉模型该怎么答)`},{value:`forbid`,label:`禁止措辞(回复里出现就换掉)`},{value:`reply`,label:`固定口径(命中就直接这么回)`}],ge={guide:`写一句给模型的补充要求。关键词留空 = 每一轮都注入;填了关键词 = 客户这句话命中才注入(规则多了以后靠这个控制提示词长度)。`,forbid:`关键词是**回复里**不许出现的词。命中就换成下面的兜底话术;兜底留空时客户端会用内置的那句正常人话顶上。`,reply:`关键词命中**客户这句话**时,直接发下面这句,不再问模型。口径必须一字不差的场景用它。`},_e=s(()=>B.value.filter(e=>e.enabled)),q=s(()=>_e.value.map(e=>({value:e.id,label:`${e.name}(${e.role})`})));function ve(){return J.apply(this,arguments)}function J(){return J=_(function*(){z.value=!0;try{let e=yield re();B.value=e.agents,V.value=e.plan,Object.assign(W,{mode:e.plan.mode||`single`,primary_id:e.plan.primary_id||``,active_ids:[...e.plan.active_ids||[]]})}finally{z.value=!1}}),J.apply(this,arguments)}function ye(){U.value=``,Object.assign(K,G()),H.value=!0}function be(e){U.value=e.id,Object.assign(K,g(g({},e),{},{keywords:[...e.keywords],rules:e.rules.map(e=>g(g({},e),{},{keywords:[...e.keywords]}))})),H.value=!0}function xe(){var e;(e=K.rules)==null||e.push({label:``,type:`guide`,keywords:[],instruction:``,reply:``,enabled:!0})}function Se(e){var t;(t=K.rules)==null||t.splice(e,1)}function Ce(){var e;if(!((e=K.name)!=null&&e.trim()))return`智能体名称不能为空`;for(let[e,t]of(K.rules||[]).entries()){let n=`第 ${e+1} 条规则`;if(!t.label.trim())return`${n}没有填名称`;if(t.type===`guide`&&!t.instruction.trim())return`${n}是补充指令,必须填要告诉模型的话`;if(t.type!==`guide`&&t.keywords.length===0)return`${n}至少要有一个关键词,否则永远不会命中`;if(t.type===`reply`&&!t.reply.trim())return`${n}是固定口径,必须填要发给客户的话术`}return``}function we(){return Y.apply(this,arguments)}function Y(){return Y=_(function*(){let e=Ce();if(e){w.warning(e);return}let t=yield ne(g({},K));B.value=t.agents,V.value=t.plan,H.value=!1,w.success(U.value?`已更新`:`已新增`)}),Y.apply(this,arguments)}function Te(e){return X.apply(this,arguments)}function X(){return X=_(function*(e){let t=yield ie(e.id);B.value=t.agents,V.value=t.plan,w.success(`已删除`)}),X.apply(this,arguments)}function Z(){return Q.apply(this,arguments)}function Q(){return Q=_(function*(){if(W.mode===`single`&&!W.primary_id){w.warning(`单角色模式要选一个当前生效的智能体`);return}if(W.mode===`collaborate`&&W.active_ids.length<2){w.warning(`协作模式至少要有两个在岗智能体,否则就是单角色`);return}let e=yield C(g({},W));V.value=e.plan,w.success(`已保存为 v${e.version},客户端下次同步配置时生效`)}),Q.apply(this,arguments)}let Ee=[{title:`名称`,dataIndex:`name`,key:`name`,width:160},{title:`角色`,dataIndex:`role`,key:`role`,width:130},{title:`职责`,dataIndex:`description`,key:`description`},{title:`负责话题`,dataIndex:`keywords`,key:`keywords`},{title:`规则`,dataIndex:`rules`,key:`rules`,width:100},{title:`在岗`,key:`onduty`,width:110},{title:`状态`,dataIndex:`enabled`,key:`enabled`,width:90},{title:`操作`,key:`action`,width:130}];function $(e){return V.value?V.value.primary_id===e.id?`主答`:V.value.active_ids.includes(e.id)?`在岗`:``:``}return o(ve),(o,s)=>(l(),i(`div`,ce,[e(n(T),{class:`mb-4`,type:`info`,"show-icon":``,message:`智能体决定「用什么身份、按什么规矩说话」,模型清单决定「用哪个模型」`,description:`这两件事的变更频率差一个数量级:模型半年动一次,话术一周动三次。改这里不用动模型,也不用给客户端发版——保存后随配置下发。`}),e(n(S),{title:`启用与协作`,class:`mb-4`,loading:z.value},{default:d(()=>[s[13]||(s[13]=r(`p`,{class:`mb-3 text-xs text-gray-500`},` 单角色 = 只上一个,切换就是换这里选的那个;协作 = 多个同时在场,客户这句话 命中谁的「负责话题」就由谁主答,其余角色的禁止措辞仍然全体生效。 不论哪种模式,客户看到的永远是同一个人——不会自报角色名,也不会出现「转给同事」。 `,-1)),e(n(b),{model:W,layout:`vertical`},{default:d(()=>[r(`div`,le,[e(n(y),{label:`模式`},{default:d(()=>[e(n(x),{value:W.mode,"onUpdate:value":s[0]||(s[0]=e=>W.mode=e),disabled:!R.value,options:[{value:`single`,label:`单角色(切换到某一个)`},{value:`collaborate`,label:`协作(多个同时在场)`}]},null,8,[`value`,`disabled`])]),_:1}),e(n(y),{label:`主答智能体(没命中任何话题时由它回)`},{default:d(()=>[e(n(x),{value:W.primary_id,"onUpdate:value":s[1]||(s[1]=e=>W.primary_id=e),disabled:!R.value,options:q.value,placeholder:`选一个`},null,8,[`value`,`disabled`,`options`])]),_:1})]),W.mode===`collaborate`?(l(),p(n(y),{key:0,label:`在岗智能体(至少两个;主答会自动排在最前)`},{default:d(()=>[e(n(x),{value:W.active_ids,"onUpdate:value":s[2]||(s[2]=e=>W.active_ids=e),mode:`multiple`,disabled:!R.value,options:q.value},null,8,[`value`,`disabled`,`options`])]),_:1})):h(``,!0),r(`div`,ue,[R.value?(l(),p(n(E),{key:0,type:`primary`,onClick:Z},{default:d(()=>[...s[12]||(s[12]=[t(` 保存为新版本 `,-1)])]),_:1})):h(``,!0),V.value?(l(),i(`span`,de,[t(` 当前 v`+f(V.value.version)+` `,1),V.value.updated_at?(l(),i(u,{key:0},[t(`· `+f(V.value.updated_at),1)],64)):h(``,!0)])):h(``,!0)])]),_:1},8,[`model`])]),_:1},8,[`loading`]),e(n(S),{title:`智能体`},{extra:d(()=>[R.value?(l(),p(n(E),{key:0,type:`primary`,onClick:ye},{default:d(()=>[...s[14]||(s[14]=[t(` 新增智能体 `,-1)])]),_:1})):h(``,!0)]),default:d(()=>[e(n(te),{columns:Ee,"data-source":B.value,loading:z.value,"row-key":`id`,size:`small`,pagination:!1},{bodyCell:d(({column:r,record:o})=>[r.key===`keywords`?(l(),i(u,{key:0},[(l(!0),i(u,null,a(o.keywords,e=>(l(),p(n(D),{key:e,class:`mb-1`},{default:d(()=>[t(f(e),1)]),_:2},1024))),128)),o.keywords.length===0?(l(),i(`span`,fe,` 不认领话题 `)):h(``,!0)],64)):r.key===`rules`?(l(),i(u,{key:1},[t(f(o.rules.length)+` 条 `,1)],64)):r.key===`onduty`?(l(),i(u,{key:2},[$(o)===`主答`?(l(),p(n(D),{key:0,color:`green`},{default:d(()=>[...s[15]||(s[15]=[t(`主答`,-1)])]),_:1})):$(o)===`在岗`?(l(),p(n(D),{key:1,color:`blue`},{default:d(()=>[...s[16]||(s[16]=[t(`在岗`,-1)])]),_:1})):(l(),i(`span`,pe,`未上岗`))],64)):r.key===`enabled`?(l(),p(n(D),{key:3,color:o.enabled?`green`:`default`},{default:d(()=>[t(f(o.enabled?`已启用`:`已停用`),1)]),_:2},1032,[`color`])):r.key===`action`?(l(),i(u,{key:4},[e(n(E),{type:`link`,size:`small`,disabled:!R.value,onClick:e=>be(o)},{default:d(()=>[...s[17]||(s[17]=[t(` 编辑 `,-1)])]),_:1},8,[`disabled`,`onClick`]),e(n(ae),{title:`确定删除这个智能体?`,onConfirm:e=>Te(o)},{default:d(()=>[e(n(E),{type:`link`,size:`small`,danger:``,disabled:!R.value},{default:d(()=>[...s[18]||(s[18]=[t(` 删除 `,-1)])]),_:1},8,[`disabled`])]),_:1},8,[`onConfirm`])],64)):h(``,!0)]),_:1},8,[`data-source`,`loading`]),B.value.length===0&&!z.value?(l(),i(`p`,me,` 还没有智能体——客户端会沿用内置人设,行为和没有这套东西时一样。 `)):h(``,!0)]),_:1}),e(n(se),{open:H.value,"onUpdate:open":s[11]||(s[11]=e=>H.value=e),title:U.value?`编辑智能体:${K.name}`:`新增智能体`,width:`760px`,onOk:we},{default:d(()=>[e(n(b),{model:K,layout:`vertical`,class:`pt-2`},{default:d(()=>[r(`div`,j,[e(n(y),{label:`名称`},{default:d(()=>[e(n(k),{value:K.name,"onUpdate:value":s[3]||(s[3]=e=>K.name=e),placeholder:`客户经理`},null,8,[`value`])]),_:1}),e(n(y),{label:`角色标签(留空同名称)`},{default:d(()=>[e(n(k),{value:K.role,"onUpdate:value":s[4]||(s[4]=e=>K.role=e),placeholder:`客户经理 / 糖尿病专科医生`},null,8,[`value`])]),_:1})]),e(n(y),{label:`ID(留空自动生成,之后不可改)`},{default:d(()=>[e(n(k),{value:K.id,"onUpdate:value":s[5]||(s[5]=e=>K.id=e),disabled:!!U.value,placeholder:`customer-manager`},null,8,[`value`,`disabled`])]),_:1}),e(n(y),{label:`职责(一句话,写给人看的)`},{default:d(()=>[e(n(k),{value:K.description,"onUpdate:value":s[6]||(s[6]=e=>K.description=e),placeholder:`挂号预约、面诊链接、订单物流、投诉退款`},null,8,[`value`])]),_:1}),e(n(y),{label:`负责话题(协作时按它认领本轮;留空 = 不主动认领)`},{default:d(()=>[e(n(x),{value:K.keywords,"onUpdate:value":s[7]||(s[7]=e=>K.keywords=e),mode:`tags`,placeholder:`输入后回车,可以加多个`,style:{width:`100%`}},null,8,[`value`])]),_:1}),e(n(y),{label:`人设(这个角色怎么说话、管哪一摊事)`},{default:d(()=>[e(n(O),{value:K.persona,"onUpdate:value":s[8]||(s[8]=e=>K.persona=e),rows:5,placeholder:`你负责流程类事情:挂号预约、面诊安排、订单物流、投诉退款……`},null,8,[`value`]),s[19]||(s[19]=r(`p`,{class:`mt-1 text-xs text-gray-500`},` 追加在内置人设后面,压过默认的表达习惯。不用重复写「像真人一样说话」 这种通用要求,内置人设里已经有了——这里只写这个角色特有的部分。 `,-1))]),_:1}),e(n(y),{label:`规则`},{default:d(()=>[(l(!0),i(u,null,a(K.rules,(a,o)=>(l(),i(`div`,{key:o,class:`mb-3 rounded border border-dashed p-3`},[r(`div`,M,[r(`div`,N,[e(n(k),{value:a.label,"onUpdate:value":e=>a.label=e,placeholder:`规则名称`},null,8,[`value`,`onUpdate:value`])]),r(`div`,P,[e(n(x),{value:a.type,"onUpdate:value":e=>a.type=e,options:he,style:{width:`100%`}},null,8,[`value`,`onUpdate:value`])]),e(n(A),{checked:a.enabled,"onUpdate:checked":e=>a.enabled=e,class:`mt-1 shrink-0`},null,8,[`checked`,`onUpdate:checked`]),e(n(E),{danger:``,type:`link`,size:`small`,class:`shrink-0`,onClick:e=>Se(o)},{default:d(()=>[...s[20]||(s[20]=[t(` 删除 `,-1)])]),_:1},8,[`onClick`])]),r(`p`,F,f(ge[a.type]),1),e(n(x),{value:a.keywords,"onUpdate:value":e=>a.keywords=e,mode:`tags`,class:`mb-2`,placeholder:a.type===`forbid`?`回复里不许出现的词,回车分隔`:`触发关键词,回车分隔`,style:{width:`100%`}},null,8,[`value`,`onUpdate:value`,`placeholder`]),a.type===`guide`?(l(),p(n(O),{key:0,value:a.instruction,"onUpdate:value":e=>a.instruction=e,rows:2,placeholder:`要告诉模型的话,例如:客户只发数字时按血糖值理解,严禁说这是系统编码。`},null,8,[`value`,`onUpdate:value`])):(l(),p(n(O),{key:1,value:a.reply,"onUpdate:value":e=>a.reply=e,rows:2,placeholder:a.type===`reply`?`命中后直接发给客户的话术`:`命中禁止措辞后的兜底话术(留空则用客户端内置的那句)`},null,8,[`value`,`onUpdate:value`,`placeholder`]))]))),128)),e(n(E),{size:`small`,onClick:xe},{default:d(()=>[...s[21]||(s[21]=[t(`+ 新增规则`,-1)])]),_:1})]),_:1}),r(`div`,I,[e(n(y),{label:`优先级(数字越小越靠前)`},{default:d(()=>[e(n(oe),{value:K.priority,"onUpdate:value":s[9]||(s[9]=e=>K.priority=e),min:1,max:999},null,8,[`value`])]),_:1}),e(n(y),{label:`启用`},{default:d(()=>[e(n(A),{checked:K.enabled,"onUpdate:checked":s[10]||(s[10]=e=>K.enabled=e)},null,8,[`checked`])]),_:1})])]),_:1},8,[`model`])]),_:1},8,[`open`,`title`])]))}});export{L as default};