@winspan/claude-forge 8.33.2 → 8.33.5
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/dist/cli/commands/daemon.d.ts.map +1 -1
- package/dist/cli/commands/daemon.js +32 -11
- package/dist/cli/commands/daemon.js.map +1 -1
- package/dist/daemon/routing-observer.js +1 -1
- package/dist/daemon/routing-observer.js.map +1 -1
- package/dist/engine/conventions/routing.yaml +11 -0
- package/dist/web/routes/ai.d.ts.map +1 -1
- package/dist/web/routes/ai.js +2 -7
- package/dist/web/routes/ai.js.map +1 -1
- package/dist/web/routes/execution-trace.d.ts +8 -0
- package/dist/web/routes/execution-trace.d.ts.map +1 -1
- package/dist/web/routes/execution-trace.js +30 -1
- package/dist/web/routes/execution-trace.js.map +1 -1
- package/dist/web/routes/routing.d.ts.map +1 -1
- package/dist/web/routes/routing.js +11 -1
- package/dist/web/routes/routing.js.map +1 -1
- package/dist/web/static/assets/{AIConfig-Dw13rVtT.js → AIConfig-BbwRuWzm.js} +2 -2
- package/dist/web/static/assets/{AIConfig-Dw13rVtT.js.map → AIConfig-BbwRuWzm.js.map} +1 -1
- package/dist/web/static/assets/{Agents-D1p3JhQs.js → Agents-FyKzsN-g.js} +2 -2
- package/dist/web/static/assets/{Agents-D1p3JhQs.js.map → Agents-FyKzsN-g.js.map} +1 -1
- package/dist/web/static/assets/{Dashboard-qUCxXFSI.js → Dashboard-Ciyyw6ph.js} +2 -2
- package/dist/web/static/assets/{Dashboard-qUCxXFSI.js.map → Dashboard-Ciyyw6ph.js.map} +1 -1
- package/dist/web/static/assets/{Drawer-DeKukfwJ.js → Drawer-DOUcx6m1.js} +2 -2
- package/dist/web/static/assets/{Drawer-DeKukfwJ.js.map → Drawer-DOUcx6m1.js.map} +1 -1
- package/dist/web/static/assets/{Events-DqzBTrly.js → Events-C2OCOKAD.js} +2 -2
- package/dist/web/static/assets/{Events-DqzBTrly.js.map → Events-C2OCOKAD.js.map} +1 -1
- package/dist/web/static/assets/ExecutionTrace-BsWSpu2v.js +3 -0
- package/dist/web/static/assets/ExecutionTrace-BsWSpu2v.js.map +1 -0
- package/dist/web/static/assets/{Methodologies-Br5KOWuF.js → Methodologies-DwYLXc8o.js} +2 -2
- package/dist/web/static/assets/{Methodologies-Br5KOWuF.js.map → Methodologies-DwYLXc8o.js.map} +1 -1
- package/dist/web/static/assets/{MethodologyDetail-Do1taSKM.js → MethodologyDetail-rV3W1utf.js} +2 -2
- package/dist/web/static/assets/{MethodologyDetail-Do1taSKM.js.map → MethodologyDetail-rV3W1utf.js.map} +1 -1
- package/dist/web/static/assets/{Routing-CFmM7JuB.js → Routing-BW3eGD-8.js} +2 -2
- package/dist/web/static/assets/{Routing-CFmM7JuB.js.map → Routing-BW3eGD-8.js.map} +1 -1
- package/dist/web/static/assets/{SessionDetail-DzTue2xK.js → SessionDetail-Cbd7Jwox.js} +2 -2
- package/dist/web/static/assets/{SessionDetail-DzTue2xK.js.map → SessionDetail-Cbd7Jwox.js.map} +1 -1
- package/dist/web/static/assets/{Sessions-DOd65EkN.js → Sessions-CFpFk-5I.js} +2 -2
- package/dist/web/static/assets/{Sessions-DOd65EkN.js.map → Sessions-CFpFk-5I.js.map} +1 -1
- package/dist/web/static/assets/{Skills-zacj_uSW.js → Skills-BkbegTV1.js} +2 -2
- package/dist/web/static/assets/{Skills-zacj_uSW.js.map → Skills-BkbegTV1.js.map} +1 -1
- package/dist/web/static/assets/{export-CEzDNM66.js → export-CbQTOt71.js} +2 -2
- package/dist/web/static/assets/{export-CEzDNM66.js.map → export-CbQTOt71.js.map} +1 -1
- package/dist/web/static/assets/{index-BVpUTHdp.js → index-CIRlno4E.js} +3 -3
- package/dist/web/static/assets/{index-BVpUTHdp.js.map → index-CIRlno4E.js.map} +1 -1
- package/dist/web/static/assets/index-N1EByy_h.css +1 -0
- package/dist/web/static/assets/{lucide-DjB4fWNj.js → lucide-BanPULT1.js} +35 -40
- package/dist/web/static/assets/lucide-BanPULT1.js.map +1 -0
- package/dist/web/static/index.html +3 -3
- package/package.json +1 -1
- package/dist/web/static/assets/ExecutionTrace-Z-zlH0KH.js +0 -2
- package/dist/web/static/assets/ExecutionTrace-Z-zlH0KH.js.map +0 -1
- package/dist/web/static/assets/index-Drpf7sLl.css +0 -1
- package/dist/web/static/assets/lucide-DjB4fWNj.js.map +0 -1
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import{r as y,j as e}from"./react-vendor-CSp-GLFF.js";import{b as D,u as k}from"./query-C99w429o.js";import{d as E}from"./vendor-CMMjVdZs.js";import{D as M}from"./Drawer-DOUcx6m1.js";import{C as b}from"./CodeBlock--H53gk46.js";import{S as A,g as J,d as L,a as q}from"./export-CbQTOt71.js";import{u as W}from"./index-CIRlno4E.js";import{W as $,l as B,D as O,A as R}from"./lucide-BanPULT1.js";import{f as T}from"./date-fns-CZ_bHujz.js";import"./syntax-highlighter-44FakypI.js";import"./react-router-I-HqunH7.js";async function G(m){let l="/api/routing/events?limit=200";m==="obeyed"?l+="&obeyed=1":m==="refused"?l+="&obeyed=0":m==="unknown"&&(l+="&obeyed=null");const h=await fetch(l);if(!h.ok)throw new Error("Failed to fetch");return h.json()}const V=[{value:"",label:"全部"},{value:"obeyed",label:"✓ 遵守"},{value:"refused",label:"✗ 违抗"},{value:"unknown",label:"? 未判定"}],H={obeyed:{label:"✓ 遵守",className:"bg-green-100 text-green-800 border border-green-200",title:"调用了推荐的 agent"},disobeyed:{label:"✗ 违抗",className:"bg-red-100 text-red-800 border border-red-200",title:"使用了其他工具而非推荐 agent"},investigation_only:{label:"◎ 仅侦察",className:"bg-orange-100 text-orange-800 border border-orange-200",title:"只做了代码调查(Read/Grep/Glob),未调用推荐 agent"},timeout:{label:"⏱ 超时",className:"bg-gray-100 text-gray-700 border border-gray-200",title:"30 秒内未检测到任何工具调用"},no_action:{label:"— 纯对话",className:"bg-gray-100 text-gray-600 border border-gray-200",title:"未使用任何工具(纯文字回答)"},not_applicable:{label:"· 未适用",className:"bg-gray-50 text-gray-500 border border-gray-200",title:"此消息未触发 agent 推荐,不涉及遵守判定"}};function F({verdict:m}){const l=H[m]??H.not_applicable;return e.jsx("span",{className:E("inline-flex items-center px-2 py-0.5 rounded text-xs whitespace-nowrap",l.className),title:l.title,children:l.label})}function K({events:m,routingTimestamp:l}){const[h,S]=y.useState(new Set),[n,N]=y.useState(!0),u=m.filter(t=>t.hook_type==="PostToolUse"&&t.tool_name),v=new Set(["Read","Grep","Glob"]),a=u.filter(t=>t.tool_name&&v.has(t.tool_name)),r=u.filter(t=>t.tool_name&&!v.has(t.tool_name)),o=t=>v.has(t)?"🔍":["Edit","Write","MultiEdit"].includes(t)?"✏️":t==="Bash"?"⚙️":["Agent","Task"].includes(t)?"🤖":"📦",j=t=>{S(c=>{const x=new Set(c);return x.has(t)?x.delete(t):x.add(t),x})},f=t=>{if(!t)return null;try{return JSON.parse(t)}catch{return null}};return e.jsxs("div",{className:"space-y-3",children:[a.length>0&&e.jsxs("div",{className:"border border-gray-200 rounded-lg p-3",children:[e.jsxs("button",{onClick:()=>N(!n),className:"flex items-center gap-2 text-sm text-gray-700 hover:text-gray-900 w-full",children:[e.jsxs("span",{children:["🔍 侦察 × ",a.length," 次"]}),e.jsx("span",{className:"text-xs text-gray-500",children:n?"(展开)":"(收起)"})]}),!n&&e.jsx("div",{className:"mt-2 space-y-2 pl-4 border-l-2 border-gray-200",children:a.map(t=>{const c=((new Date(t.timestamp).getTime()-l)/1e3).toFixed(1),x=f(t.tool_input),d=f(t.tool_output),g=h.has(t.event_id),_=d==null?void 0:d.error;return e.jsxs("div",{className:"text-xs",children:[e.jsxs("button",{onClick:()=>j(t.event_id),className:"flex items-center gap-2 hover:bg-gray-50 p-1 rounded w-full text-left",children:[e.jsxs("span",{className:"text-gray-400 font-mono",children:[c,"s"]}),e.jsx("span",{children:o(t.tool_name)}),e.jsx("span",{className:"font-medium",children:t.tool_name}),_?e.jsx("span",{className:"text-red-600",children:"✗"}):e.jsx("span",{className:"text-green-600",children:"•"})]}),g&&e.jsxs("div",{className:"mt-1 ml-4 space-y-1",children:[x&&e.jsxs("div",{children:[e.jsx("div",{className:"text-gray-500 mb-0.5",children:"Input:"}),e.jsx(b,{data:x,language:"json",maxHeight:"150px"})]}),d&&e.jsxs("div",{children:[e.jsx("div",{className:"text-gray-500 mb-0.5",children:"Output:"}),e.jsx(b,{data:d,language:"json",maxHeight:"150px"})]})]})]},t.event_id)})})]}),e.jsx("div",{className:"space-y-2 pl-4 border-l-2 border-indigo-200",children:r.map(t=>{const c=((new Date(t.timestamp).getTime()-l)/1e3).toFixed(1),x=f(t.tool_input),d=f(t.tool_output),g=h.has(t.event_id),_=d==null?void 0:d.error;return e.jsxs("div",{className:"text-sm",children:[e.jsxs("button",{onClick:()=>j(t.event_id),className:"flex items-center gap-2 hover:bg-gray-50 p-2 rounded w-full text-left",children:[e.jsxs("span",{className:"text-gray-400 font-mono text-xs",children:[c,"s"]}),e.jsx("span",{children:o(t.tool_name)}),e.jsx("span",{className:"font-medium",children:t.tool_name}),_?e.jsx("span",{className:"text-red-600",children:"✗"}):e.jsx("span",{className:"text-green-600",children:"•"})]}),g&&e.jsxs("div",{className:"mt-2 ml-8 space-y-2",children:[x&&e.jsxs("div",{children:[e.jsx("div",{className:"text-xs text-gray-500 mb-1",children:"Input:"}),e.jsx(b,{data:x,language:"json",maxHeight:"200px"})]}),d&&e.jsxs("div",{children:[e.jsx("div",{className:"text-xs text-gray-500 mb-1",children:"Output:"}),e.jsx(b,{data:d,language:"json",maxHeight:"200px"})]})]})]},t.event_id)})}),u.length===0&&e.jsx("div",{className:"text-center text-gray-500 text-sm py-8",children:"此次执行未产生工具调用记录"})]})}function P({events:m}){const[l,h]=y.useState(new Set),S=new Set(["Edit","Write","MultiEdit","Bash"]),n=m.filter(a=>a.hook_type==="PostToolUse"&&a.tool_name&&S.has(a.tool_name)),N=a=>{h(r=>{const o=new Set(r);return o.has(a)?o.delete(a):o.add(a),o})},u=a=>{if(!a)return null;try{return JSON.parse(a)}catch{return null}},v=a=>a?a.split(`
|
|
2
|
+
`).length:0;return e.jsxs("div",{className:"space-y-3",children:[n.map(a=>{const r=u(a.tool_input),o=u(a.tool_output),j=l.has(a.event_id);if(a.tool_name==="Bash"){const f=(r==null?void 0:r.command)||"",t=(o==null?void 0:o.stdout)||"",c=(o==null?void 0:o.stderr)||"";return e.jsxs("div",{className:"border border-gray-200 rounded-lg overflow-hidden",children:[e.jsxs("button",{onClick:()=>N(a.event_id),className:"w-full px-4 py-3 bg-gray-50 hover:bg-gray-100 text-left flex items-center gap-2",children:[e.jsx("span",{children:"⚙️"}),e.jsxs("span",{className:"font-mono text-sm flex-1 truncate",children:["$ ",f]}),e.jsx("span",{className:"text-xs text-gray-500",children:j?"收起":"展开"})]}),j&&e.jsxs("div",{className:"p-4 space-y-2",children:[t&&e.jsxs("div",{children:[e.jsx("div",{className:"text-xs text-gray-500 mb-1",children:"stdout:"}),e.jsx(b,{data:t,language:"bash",maxHeight:"300px"})]}),c&&e.jsxs("div",{children:[e.jsx("div",{className:"text-xs text-gray-500 mb-1",children:"stderr:"}),e.jsx(b,{data:c,language:"bash",maxHeight:"300px"})]})]})]},a.event_id)}if(["Edit","Write","MultiEdit"].includes(a.tool_name)){const f=(r==null?void 0:r.file_path)||"(unknown)",t=(r==null?void 0:r.old_string)||"",c=(r==null?void 0:r.new_string)||(r==null?void 0:r.content)||"",x=a.tool_name==="Write"||!t,d=v(c),g=v(t);return e.jsxs("div",{className:"border border-gray-200 rounded-lg overflow-hidden",children:[e.jsxs("button",{onClick:()=>N(a.event_id),className:"w-full px-4 py-3 bg-gray-50 hover:bg-gray-100 text-left flex items-center gap-2",children:[e.jsx("span",{children:"📄"}),e.jsx("span",{className:"font-mono text-sm flex-1 truncate",children:f}),e.jsx("span",{className:"text-xs px-2 py-0.5 rounded bg-blue-100 text-blue-700",children:x?"+新增":"~修改"}),!x&&e.jsxs("span",{className:"text-xs text-gray-500",children:["+",d,"/-",g]}),e.jsx("span",{className:"text-xs text-gray-500",children:j?"收起":"展开"})]}),j&&e.jsxs("div",{className:"p-4 space-y-2",children:[t&&e.jsxs("div",{children:[e.jsx("div",{className:"text-xs text-gray-500 mb-1",children:"Before:"}),e.jsx(b,{data:t,language:"typescript",maxHeight:"200px"})]}),c&&e.jsxs("div",{children:[e.jsx("div",{className:"text-xs text-gray-500 mb-1",children:x?"Content:":"After:"}),e.jsx(b,{data:c,language:"typescript",maxHeight:"200px"})]})]})]},a.event_id)}return null}),n.length===0&&e.jsx("div",{className:"text-center text-gray-500 text-sm py-8",children:"此次执行未产生文件改动"})]})}async function Q(m){const l=await fetch(`/api/execution-trace/${m}`);if(!l.ok)throw new Error("Failed to fetch execution detail");return l.json()}function re(){const[m,l]=y.useState(""),[h,S]=y.useState(""),[n,N]=y.useState(null),[u,v]=y.useState("basic"),[a,r]=y.useState(!1),[o,j]=y.useState(!1),f=W(),t=D();y.useEffect(()=>{const s=new EventSource("/api/execution-trace/stream");return s.onopen=()=>r(!0),s.onerror=()=>r(!1),s.onmessage=i=>{try{JSON.parse(i.data).type==="execution-status"&&t.invalidateQueries({queryKey:["routing-events"]})}catch{}},()=>{s.close(),r(!1)}},[t]);const{data:c,isLoading:x}=k({queryKey:["routing-events",m],queryFn:()=>G(m),refetchInterval:1e4}),{data:d}=k({queryKey:["execution-detail",n==null?void 0:n.id],queryFn:()=>Q(n.id),enabled:n!==null}),g=y.useMemo(()=>{if(!c)return[];if(!h.trim())return c;const s=h.toLowerCase();return c.filter(i=>{var C,p,w;return((C=i.prompt)==null?void 0:C.toLowerCase().includes(s))||((p=i.routed_to_name)==null?void 0:p.toLowerCase().includes(s))||((w=i.first_tool_name)==null?void 0:w.toLowerCase().includes(s))})},[c,h]),_=s=>{const i=J();if(s==="json")L(`routing-events-${i}.json`,g);else{const C=g.map(p=>{let w={};try{w=JSON.parse(p.intent_json||"{}")}catch{}return{id:p.id,ts:p.ts?T(p.ts,"yyyy-MM-dd HH:mm:ss"):"",prompt:p.prompt,taskType:w.taskType||"",complexity:w.complexity||"",routed_to:p.routed_to_name||"",obeyed:p.obeyed===1?"yes":p.obeyed===0?"no":"",first_tool:p.first_tool_name||"",duration_ms:p.total_execution_ms||"",refusal_reason:p.refusal_reason||""}});q(`routing-events-${i}.csv`,C)}f.success(`已导出 ${g.length} 条追踪记录`),j(!1)};return e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center justify-between mb-4 flex-wrap gap-3",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"text-2xl font-bold text-gray-900",children:"执行追踪"}),e.jsx("div",{className:"flex items-center gap-2 mt-1",children:a?e.jsxs(e.Fragment,{children:[e.jsx($,{className:"h-3 w-3 text-green-500"}),e.jsx("span",{className:"text-xs text-green-600",children:"实时流已连接"})]}):e.jsxs(e.Fragment,{children:[e.jsx(B,{className:"h-3 w-3 text-gray-400"}),e.jsx("span",{className:"text-xs text-gray-500",children:"实时流未连接"})]})})]}),e.jsxs("div",{className:"flex items-center gap-2 flex-wrap",children:[e.jsx(A,{value:h,onChange:S,placeholder:"搜索 prompt / agent / tool...",className:"w-56"}),e.jsx("div",{className:"flex items-center gap-1",children:V.map(s=>e.jsx("button",{onClick:()=>l(s.value),className:E("px-2.5 py-1.5 text-xs rounded-md",m===s.value?"bg-indigo-100 text-indigo-700":"bg-white text-gray-600 border border-gray-300 hover:bg-gray-50"),children:s.label},s.value))}),e.jsxs("div",{className:"relative",children:[e.jsxs("button",{onClick:()=>j(s=>!s),disabled:g.length===0,className:"inline-flex items-center gap-1 px-3 py-1.5 text-sm bg-white border border-gray-300 rounded-md hover:bg-gray-50 disabled:opacity-50",children:[e.jsx(O,{className:"h-4 w-4"}),"导出"]}),o&&e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"fixed inset-0 z-10",onClick:()=>j(!1)}),e.jsxs("div",{className:"absolute right-0 mt-1 bg-white border border-gray-200 rounded-md shadow-lg z-20",children:[e.jsx("button",{onClick:()=>_("json"),className:"block w-full text-left px-4 py-2 text-sm hover:bg-gray-50",children:"导出为 JSON"}),e.jsx("button",{onClick:()=>_("csv"),className:"block w-full text-left px-4 py-2 text-sm hover:bg-gray-50",children:"导出为 CSV"})]})]})]})]})]}),e.jsxs("div",{className:"text-sm text-gray-500 mb-3",children:["显示 ",g.length," 条 ",h&&"(已过滤)"]}),e.jsx("div",{className:"bg-white rounded-lg shadow overflow-hidden",children:x?e.jsx("div",{className:"p-6",children:"加载中..."}):e.jsxs("table",{className:"min-w-full divide-y divide-gray-200",children:[e.jsx("thead",{className:"bg-gray-50",children:e.jsxs("tr",{children:[e.jsx("th",{className:"px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase",children:"时间"}),e.jsx("th",{className:"px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase",children:"提示"}),e.jsx("th",{className:"px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase",children:"路由到"}),e.jsx("th",{className:"px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase",children:"遵守"}),e.jsx("th",{className:"px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase",children:"首工具"}),e.jsx("th",{className:"px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase",children:"耗时"})]})}),e.jsxs("tbody",{className:"bg-white divide-y divide-gray-200",children:[g.map(s=>{let i={};try{i=JSON.parse(s.intent_json||"{}")}catch{}return e.jsxs("tr",{className:"hover:bg-gray-50 cursor-pointer",onClick:()=>N(s),children:[e.jsx("td",{className:"px-4 py-2 whitespace-nowrap text-xs font-mono text-gray-500",children:T(s.ts,"MM-dd HH:mm:ss")}),e.jsxs("td",{className:"px-4 py-2 max-w-xs",children:[e.jsx("p",{className:"text-xs text-gray-700 truncate",title:s.prompt,children:s.prompt}),e.jsxs("p",{className:"text-xs text-gray-400 mt-0.5",children:[i.taskType," / ",i.complexity]})]}),e.jsx("td",{className:"px-4 py-2 whitespace-nowrap",children:s.routed_to_name?e.jsx("span",{className:"px-2 py-0.5 text-xs font-medium bg-indigo-100 text-indigo-700 rounded",children:s.routed_to_name}):e.jsx("span",{className:"text-xs text-gray-400",children:"未路由"})}),e.jsx("td",{className:"px-4 py-2 whitespace-nowrap",children:e.jsx(F,{verdict:s.verdict})}),e.jsx("td",{className:"px-4 py-2 whitespace-nowrap text-xs text-gray-700",children:s.first_tool_name||"-"}),e.jsx("td",{className:"px-4 py-2 whitespace-nowrap text-xs font-mono text-gray-500",children:s.total_execution_ms?`${(s.total_execution_ms/1e3).toFixed(1)}s`:"-"})]},s.id)}),g.length===0&&e.jsx("tr",{children:e.jsxs("td",{colSpan:6,className:"px-4 py-12 text-center text-gray-500",children:[e.jsx(R,{className:"h-12 w-12 text-gray-300 mx-auto mb-2"}),h?"无匹配结果":"暂无追踪记录"]})})]})]})}),e.jsx(M,{open:n!==null,onClose:()=>{N(null),v("basic")},title:"Agent 执行详情",children:n&&d&&(()=>{let s={};try{s=JSON.parse(n.intent_json||"{}")}catch{}return e.jsxs("div",{className:"space-y-4",children:[e.jsx("div",{className:"flex gap-2 border-b border-gray-200 pb-2",children:["basic","timeline","artifacts"].map(i=>e.jsxs("button",{onClick:()=>v(i),className:E("px-3 py-1.5 text-sm rounded-md transition-colors",u===i?"bg-indigo-100 text-indigo-700 font-medium":"text-gray-600 hover:bg-gray-100"),children:[i==="basic"&&"基本",i==="timeline"&&"过程",i==="artifacts"&&"产物"]},i))}),u==="basic"&&e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{children:[e.jsx("div",{className:"text-xs text-gray-500 mb-1",children:"用户提示"}),e.jsx("div",{className:"bg-purple-50 rounded p-3 text-sm text-gray-800 whitespace-pre-wrap",children:n.prompt})]}),e.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[e.jsxs("div",{children:[e.jsx("div",{className:"text-xs text-gray-500 mb-1",children:"路由结果"}),e.jsx("div",{className:"text-sm font-medium",children:n.routed_to_name||"未路由"})]}),e.jsxs("div",{children:[e.jsx("div",{className:"text-xs text-gray-500 mb-1",children:"遵守状态"}),e.jsx("div",{children:e.jsx(F,{verdict:n.verdict})})]})]}),e.jsxs("div",{children:[e.jsx("div",{className:"text-xs text-gray-500 mb-1",children:"意图分类"}),e.jsx(b,{data:s,language:"json",maxHeight:"200px"})]}),e.jsxs("div",{className:"grid grid-cols-2 gap-3 text-sm",children:[e.jsxs("div",{children:[e.jsx("div",{className:"text-xs text-gray-500 mb-1",children:"首工具"}),e.jsx("div",{className:"font-mono",children:n.first_tool_name||"-"})]}),e.jsxs("div",{children:[e.jsx("div",{className:"text-xs text-gray-500 mb-1",children:"分类耗时"}),e.jsxs("div",{className:"font-mono",children:[n.classification_ms,"ms"]})]}),e.jsxs("div",{children:[e.jsx("div",{className:"text-xs text-gray-500 mb-1",children:"总执行时间"}),e.jsx("div",{className:"font-mono",children:n.total_execution_ms?`${(n.total_execution_ms/1e3).toFixed(2)}s`:"-"})]}),e.jsxs("div",{children:[e.jsx("div",{className:"text-xs text-gray-500 mb-1",children:"完成原因"}),e.jsx("div",{children:n.completion_reason||"-"})]})]}),n.refusal_reason&&e.jsxs("div",{children:[e.jsx("div",{className:"text-xs text-gray-500 mb-1",children:"违抗原因"}),e.jsx("div",{className:"bg-red-50 rounded p-3 text-sm text-red-700",children:n.refusal_reason})]}),e.jsxs("div",{children:[e.jsx("div",{className:"text-xs text-gray-500 mb-1",children:"Session"}),e.jsx("div",{className:"text-xs font-mono text-gray-700",children:n.session_id})]})]}),u==="timeline"&&e.jsx(K,{events:d.events,routingTimestamp:n.ts}),u==="artifacts"&&e.jsx(P,{events:d.events})]})})()})]})}export{re as default};
|
|
3
|
+
//# sourceMappingURL=ExecutionTrace-BsWSpu2v.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ExecutionTrace-BsWSpu2v.js","sources":["../../src/pages/ExecutionTrace.tsx"],"sourcesContent":["import { useQuery, useQueryClient } from '@tanstack/react-query'\nimport { useState, useEffect, useMemo } from 'react'\nimport { format } from 'date-fns'\nimport { Activity, Wifi, WifiOff, Download } from 'lucide-react'\nimport clsx from 'clsx'\nimport Drawer from '../components/Drawer'\nimport CodeBlock from '../components/CodeBlock'\nimport SearchInput from '../components/SearchInput'\nimport { downloadJSON, downloadCSV, getTimestamp } from '../utils/export'\nimport { useToast } from '../components/Toast'\n\ninterface RoutingEvent {\n id: number\n session_id: string\n project_path: string\n ts: number\n prompt: string\n intent_json: string\n routed_to_type: string\n routed_to_name: string\n is_forced: number\n obeyed: number | null\n classification_ms: number\n fallback_used: number\n refusal_reason: string | null\n first_tool_name: string | null\n first_tool_ts: number | null\n completed_ts: number | null\n total_execution_ms: number | null\n completion_reason: string | null\n verdict: 'obeyed' | 'disobeyed' | 'investigation_only' | 'timeout' | 'no_action' | 'not_applicable'\n}\n\ninterface ExecutionDetail {\n routing: {\n id: number\n sessionId: string\n routeRequestId: string | null\n prompt: string\n timestamp: number\n intent: any\n routedToType: string | null\n routedToName: string | null\n obeyed: number | null\n verdict: RoutingEvent['verdict']\n classificationMs: number | null\n fallbackUsed: boolean\n refusalReason: string | null\n firstTool: string | null\n firstToolTs: number | null\n completedTs: number | null\n totalExecutionMs: number | null\n completionReason: string | null\n taskChain: any[]\n }\n events: Array<{\n event_id: string\n timestamp: string\n hook_type: string\n tool_name: string | null\n user_prompt: string | null\n tool_input: string | null\n tool_output: string | null\n }>\n injections: Array<{\n injection_type: string\n content: string\n timestamp: string\n }>\n agentCalls: Array<{\n toolEventId: number\n tool: string\n subagent: string | null\n startedTs: number\n allowed: boolean\n error: string | null\n completedTs: number | null\n completedEventId: string | null\n status: string\n }>\n}\n\nasync function fetchRoutingEvents(filter?: string): Promise<RoutingEvent[]> {\n let url = '/api/routing/events?limit=200'\n if (filter === 'obeyed') url += '&obeyed=1'\n else if (filter === 'refused') url += '&obeyed=0'\n else if (filter === 'unknown') url += '&obeyed=null'\n const res = await fetch(url)\n if (!res.ok) throw new Error('Failed to fetch')\n return res.json()\n}\n\nconst filters = [\n { value: '', label: '全部' },\n { value: 'obeyed', label: '✓ 遵守' },\n { value: 'refused', label: '✗ 违抗' },\n { value: 'unknown', label: '? 未判定' },\n]\n\ntype Verdict = RoutingEvent['verdict']\n\nconst VERDICT_META: Record<Verdict, { label: string; className: string; title: string }> = {\n obeyed: {\n label: '✓ 遵守',\n className: 'bg-green-100 text-green-800 border border-green-200',\n title: '调用了推荐的 agent',\n },\n disobeyed: {\n label: '✗ 违抗',\n className: 'bg-red-100 text-red-800 border border-red-200',\n title: '使用了其他工具而非推荐 agent',\n },\n investigation_only: {\n label: '◎ 仅侦察',\n className: 'bg-orange-100 text-orange-800 border border-orange-200',\n title: '只做了代码调查(Read/Grep/Glob),未调用推荐 agent',\n },\n timeout: {\n label: '⏱ 超时',\n className: 'bg-gray-100 text-gray-700 border border-gray-200',\n title: '30 秒内未检测到任何工具调用',\n },\n no_action: {\n label: '— 纯对话',\n className: 'bg-gray-100 text-gray-600 border border-gray-200',\n title: '未使用任何工具(纯文字回答)',\n },\n not_applicable: {\n label: '· 未适用',\n className: 'bg-gray-50 text-gray-500 border border-gray-200',\n title: '此消息未触发 agent 推荐,不涉及遵守判定',\n },\n}\n\nfunction VerdictBadge({ verdict }: { verdict: Verdict }) {\n const meta = VERDICT_META[verdict] ?? VERDICT_META.not_applicable\n return (\n <span\n className={clsx('inline-flex items-center px-2 py-0.5 rounded text-xs whitespace-nowrap', meta.className)}\n title={meta.title}\n >\n {meta.label}\n </span>\n )\n}\n\nfunction AgentTimeline({ events, routingTimestamp }: { events: ExecutionDetail['events']; routingTimestamp: number }) {\n const [expandedNodes, setExpandedNodes] = useState<Set<string>>(new Set())\n const [collapsedInvestigation, setCollapsedInvestigation] = useState(true)\n\n const postToolUseEvents = events.filter(e => e.hook_type === 'PostToolUse' && e.tool_name)\n\n const investigationTools = new Set(['Read', 'Grep', 'Glob'])\n const investigationEvents = postToolUseEvents.filter(e => e.tool_name && investigationTools.has(e.tool_name))\n const otherEvents = postToolUseEvents.filter(e => e.tool_name && !investigationTools.has(e.tool_name))\n\n const getToolIcon = (toolName: string) => {\n if (investigationTools.has(toolName)) return '🔍'\n if (['Edit', 'Write', 'MultiEdit'].includes(toolName)) return '✏️'\n if (toolName === 'Bash') return '⚙️'\n if (['Agent', 'Task'].includes(toolName)) return '🤖'\n return '📦'\n }\n\n const toggleNode = (eventId: string) => {\n setExpandedNodes(prev => {\n const next = new Set(prev)\n if (next.has(eventId)) next.delete(eventId)\n else next.add(eventId)\n return next\n })\n }\n\n const parseToolData = (jsonStr: string | null) => {\n if (!jsonStr) return null\n try {\n return JSON.parse(jsonStr)\n } catch {\n return null\n }\n }\n\n return (\n <div className=\"space-y-3\">\n {investigationEvents.length > 0 && (\n <div className=\"border border-gray-200 rounded-lg p-3\">\n <button\n onClick={() => setCollapsedInvestigation(!collapsedInvestigation)}\n className=\"flex items-center gap-2 text-sm text-gray-700 hover:text-gray-900 w-full\"\n >\n <span>🔍 侦察 × {investigationEvents.length} 次</span>\n <span className=\"text-xs text-gray-500\">\n {collapsedInvestigation ? '(展开)' : '(收起)'}\n </span>\n </button>\n {!collapsedInvestigation && (\n <div className=\"mt-2 space-y-2 pl-4 border-l-2 border-gray-200\">\n {investigationEvents.map(e => {\n const offsetSec = ((new Date(e.timestamp).getTime() - routingTimestamp) / 1000).toFixed(1)\n const toolInput = parseToolData(e.tool_input)\n const toolOutput = parseToolData(e.tool_output)\n const isExpanded = expandedNodes.has(e.event_id)\n const hasError = toolOutput?.error\n\n return (\n <div key={e.event_id} className=\"text-xs\">\n <button\n onClick={() => toggleNode(e.event_id)}\n className=\"flex items-center gap-2 hover:bg-gray-50 p-1 rounded w-full text-left\"\n >\n <span className=\"text-gray-400 font-mono\">{offsetSec}s</span>\n <span>{getToolIcon(e.tool_name!)}</span>\n <span className=\"font-medium\">{e.tool_name}</span>\n {hasError ? (\n <span className=\"text-red-600\">✗</span>\n ) : (\n <span className=\"text-green-600\">•</span>\n )}\n </button>\n {isExpanded && (\n <div className=\"mt-1 ml-4 space-y-1\">\n {toolInput && (\n <div>\n <div className=\"text-gray-500 mb-0.5\">Input:</div>\n <CodeBlock data={toolInput} language=\"json\" maxHeight=\"150px\" />\n </div>\n )}\n {toolOutput && (\n <div>\n <div className=\"text-gray-500 mb-0.5\">Output:</div>\n <CodeBlock data={toolOutput} language=\"json\" maxHeight=\"150px\" />\n </div>\n )}\n </div>\n )}\n </div>\n )\n })}\n </div>\n )}\n </div>\n )}\n\n <div className=\"space-y-2 pl-4 border-l-2 border-indigo-200\">\n {otherEvents.map(e => {\n const offsetSec = ((new Date(e.timestamp).getTime() - routingTimestamp) / 1000).toFixed(1)\n const toolInput = parseToolData(e.tool_input)\n const toolOutput = parseToolData(e.tool_output)\n const isExpanded = expandedNodes.has(e.event_id)\n const hasError = toolOutput?.error\n\n return (\n <div key={e.event_id} className=\"text-sm\">\n <button\n onClick={() => toggleNode(e.event_id)}\n className=\"flex items-center gap-2 hover:bg-gray-50 p-2 rounded w-full text-left\"\n >\n <span className=\"text-gray-400 font-mono text-xs\">{offsetSec}s</span>\n <span>{getToolIcon(e.tool_name!)}</span>\n <span className=\"font-medium\">{e.tool_name}</span>\n {hasError ? (\n <span className=\"text-red-600\">✗</span>\n ) : (\n <span className=\"text-green-600\">•</span>\n )}\n </button>\n {isExpanded && (\n <div className=\"mt-2 ml-8 space-y-2\">\n {toolInput && (\n <div>\n <div className=\"text-xs text-gray-500 mb-1\">Input:</div>\n <CodeBlock data={toolInput} language=\"json\" maxHeight=\"200px\" />\n </div>\n )}\n {toolOutput && (\n <div>\n <div className=\"text-xs text-gray-500 mb-1\">Output:</div>\n <CodeBlock data={toolOutput} language=\"json\" maxHeight=\"200px\" />\n </div>\n )}\n </div>\n )}\n </div>\n )\n })}\n </div>\n\n {postToolUseEvents.length === 0 && (\n <div className=\"text-center text-gray-500 text-sm py-8\">\n 此次执行未产生工具调用记录\n </div>\n )}\n </div>\n )\n}\n\nfunction ArtifactCards({ events }: { events: ExecutionDetail['events'] }) {\n const [expandedCards, setExpandedCards] = useState<Set<string>>(new Set())\n\n const artifactTools = new Set(['Edit', 'Write', 'MultiEdit', 'Bash'])\n const artifactEvents = events.filter(e =>\n e.hook_type === 'PostToolUse' && e.tool_name && artifactTools.has(e.tool_name)\n )\n\n const toggleCard = (eventId: string) => {\n setExpandedCards(prev => {\n const next = new Set(prev)\n if (next.has(eventId)) next.delete(eventId)\n else next.add(eventId)\n return next\n })\n }\n\n const parseToolData = (jsonStr: string | null) => {\n if (!jsonStr) return null\n try {\n return JSON.parse(jsonStr)\n } catch {\n return null\n }\n }\n\n const countLines = (str: string | undefined) => {\n if (!str) return 0\n return str.split('\\n').length\n }\n\n return (\n <div className=\"space-y-3\">\n {artifactEvents.map(e => {\n const toolInput = parseToolData(e.tool_input)\n const toolOutput = parseToolData(e.tool_output)\n const isExpanded = expandedCards.has(e.event_id)\n\n if (e.tool_name === 'Bash') {\n const command = toolInput?.command || ''\n const stdout = toolOutput?.stdout || ''\n const stderr = toolOutput?.stderr || ''\n\n return (\n <div key={e.event_id} className=\"border border-gray-200 rounded-lg overflow-hidden\">\n <button\n onClick={() => toggleCard(e.event_id)}\n className=\"w-full px-4 py-3 bg-gray-50 hover:bg-gray-100 text-left flex items-center gap-2\"\n >\n <span>⚙️</span>\n <span className=\"font-mono text-sm flex-1 truncate\">$ {command}</span>\n <span className=\"text-xs text-gray-500\">{isExpanded ? '收起' : '展开'}</span>\n </button>\n {isExpanded && (\n <div className=\"p-4 space-y-2\">\n {stdout && (\n <div>\n <div className=\"text-xs text-gray-500 mb-1\">stdout:</div>\n <CodeBlock data={stdout} language=\"bash\" maxHeight=\"300px\" />\n </div>\n )}\n {stderr && (\n <div>\n <div className=\"text-xs text-gray-500 mb-1\">stderr:</div>\n <CodeBlock data={stderr} language=\"bash\" maxHeight=\"300px\" />\n </div>\n )}\n </div>\n )}\n </div>\n )\n }\n\n if (['Edit', 'Write', 'MultiEdit'].includes(e.tool_name!)) {\n const filePath = toolInput?.file_path || '(unknown)'\n const oldString = toolInput?.old_string || ''\n const newString = toolInput?.new_string || toolInput?.content || ''\n const isNew = e.tool_name === 'Write' || !oldString\n const addedLines = countLines(newString)\n const removedLines = countLines(oldString)\n\n return (\n <div key={e.event_id} className=\"border border-gray-200 rounded-lg overflow-hidden\">\n <button\n onClick={() => toggleCard(e.event_id)}\n className=\"w-full px-4 py-3 bg-gray-50 hover:bg-gray-100 text-left flex items-center gap-2\"\n >\n <span>📄</span>\n <span className=\"font-mono text-sm flex-1 truncate\">{filePath}</span>\n <span className=\"text-xs px-2 py-0.5 rounded bg-blue-100 text-blue-700\">\n {isNew ? '+新增' : '~修改'}\n </span>\n {!isNew && (\n <span className=\"text-xs text-gray-500\">\n +{addedLines}/-{removedLines}\n </span>\n )}\n <span className=\"text-xs text-gray-500\">{isExpanded ? '收起' : '展开'}</span>\n </button>\n {isExpanded && (\n <div className=\"p-4 space-y-2\">\n {oldString && (\n <div>\n <div className=\"text-xs text-gray-500 mb-1\">Before:</div>\n <CodeBlock data={oldString} language=\"typescript\" maxHeight=\"200px\" />\n </div>\n )}\n {newString && (\n <div>\n <div className=\"text-xs text-gray-500 mb-1\">{isNew ? 'Content:' : 'After:'}</div>\n <CodeBlock data={newString} language=\"typescript\" maxHeight=\"200px\" />\n </div>\n )}\n </div>\n )}\n </div>\n )\n }\n\n return null\n })}\n\n {artifactEvents.length === 0 && (\n <div className=\"text-center text-gray-500 text-sm py-8\">\n 此次执行未产生文件改动\n </div>\n )}\n </div>\n )\n}\n\nasync function fetchExecutionDetail(id: number): Promise<ExecutionDetail> {\n const res = await fetch(`/api/execution-trace/${id}`)\n if (!res.ok) throw new Error('Failed to fetch execution detail')\n return res.json()\n}\n\nexport default function ExecutionTrace() {\n const [filter, setFilter] = useState('')\n const [search, setSearch] = useState('')\n const [selectedEvent, setSelectedEvent] = useState<RoutingEvent | null>(null)\n const [activeTab, setActiveTab] = useState<'basic' | 'timeline' | 'artifacts'>('basic')\n const [sseConnected, setSseConnected] = useState(false)\n const [showExportMenu, setShowExportMenu] = useState(false)\n const toast = useToast()\n const queryClient = useQueryClient()\n\n useEffect(() => {\n const eventSource = new EventSource('/api/execution-trace/stream')\n eventSource.onopen = () => setSseConnected(true)\n eventSource.onerror = () => setSseConnected(false)\n eventSource.onmessage = (e) => {\n try {\n const data = JSON.parse(e.data)\n if (data.type === 'execution-status') {\n queryClient.invalidateQueries({ queryKey: ['routing-events'] })\n }\n } catch { /* ignore */ }\n }\n return () => {\n eventSource.close()\n setSseConnected(false)\n }\n }, [queryClient])\n\n const { data: events, isLoading } = useQuery({\n queryKey: ['routing-events', filter],\n queryFn: () => fetchRoutingEvents(filter),\n refetchInterval: 10000,\n })\n\n const { data: executionDetail } = useQuery({\n queryKey: ['execution-detail', selectedEvent?.id],\n queryFn: () => fetchExecutionDetail(selectedEvent!.id),\n enabled: selectedEvent !== null,\n })\n\n const filteredEvents = useMemo(() => {\n if (!events) return []\n if (!search.trim()) return events\n const q = search.toLowerCase()\n return events.filter(e =>\n e.prompt?.toLowerCase().includes(q) ||\n e.routed_to_name?.toLowerCase().includes(q) ||\n e.first_tool_name?.toLowerCase().includes(q)\n )\n }, [events, search])\n\n const handleExport = (exportFormat: 'json' | 'csv') => {\n const ts = getTimestamp()\n if (exportFormat === 'json') {\n downloadJSON(`routing-events-${ts}.json`, filteredEvents)\n } else {\n const flat = filteredEvents.map(e => {\n let intent: { taskType?: string; complexity?: string } = {}\n try { intent = JSON.parse(e.intent_json || '{}') } catch { /* ignore */ }\n return {\n id: e.id,\n ts: e.ts ? format(e.ts, 'yyyy-MM-dd HH:mm:ss') : '',\n prompt: e.prompt,\n taskType: intent.taskType || '',\n complexity: intent.complexity || '',\n routed_to: e.routed_to_name || '',\n obeyed: e.obeyed === 1 ? 'yes' : e.obeyed === 0 ? 'no' : '',\n first_tool: e.first_tool_name || '',\n duration_ms: e.total_execution_ms || '',\n refusal_reason: e.refusal_reason || '',\n }\n })\n downloadCSV(`routing-events-${ts}.csv`, flat)\n }\n toast.success(`已导出 ${filteredEvents.length} 条追踪记录`)\n setShowExportMenu(false)\n }\n\n return (\n <div>\n <div className=\"flex items-center justify-between mb-4 flex-wrap gap-3\">\n <div>\n <h1 className=\"text-2xl font-bold text-gray-900\">执行追踪</h1>\n <div className=\"flex items-center gap-2 mt-1\">\n {sseConnected ? (\n <>\n <Wifi className=\"h-3 w-3 text-green-500\" />\n <span className=\"text-xs text-green-600\">实时流已连接</span>\n </>\n ) : (\n <>\n <WifiOff className=\"h-3 w-3 text-gray-400\" />\n <span className=\"text-xs text-gray-500\">实时流未连接</span>\n </>\n )}\n </div>\n </div>\n <div className=\"flex items-center gap-2 flex-wrap\">\n <SearchInput\n value={search}\n onChange={setSearch}\n placeholder=\"搜索 prompt / agent / tool...\"\n className=\"w-56\"\n />\n <div className=\"flex items-center gap-1\">\n {filters.map((f) => (\n <button\n key={f.value}\n onClick={() => setFilter(f.value)}\n className={clsx(\n 'px-2.5 py-1.5 text-xs rounded-md',\n filter === f.value\n ? 'bg-indigo-100 text-indigo-700'\n : 'bg-white text-gray-600 border border-gray-300 hover:bg-gray-50'\n )}\n >\n {f.label}\n </button>\n ))}\n </div>\n <div className=\"relative\">\n <button\n onClick={() => setShowExportMenu(v => !v)}\n disabled={filteredEvents.length === 0}\n className=\"inline-flex items-center gap-1 px-3 py-1.5 text-sm bg-white border border-gray-300 rounded-md hover:bg-gray-50 disabled:opacity-50\"\n >\n <Download className=\"h-4 w-4\" />\n 导出\n </button>\n {showExportMenu && (\n <>\n <div className=\"fixed inset-0 z-10\" onClick={() => setShowExportMenu(false)} />\n <div className=\"absolute right-0 mt-1 bg-white border border-gray-200 rounded-md shadow-lg z-20\">\n <button\n onClick={() => handleExport('json')}\n className=\"block w-full text-left px-4 py-2 text-sm hover:bg-gray-50\"\n >\n 导出为 JSON\n </button>\n <button\n onClick={() => handleExport('csv')}\n className=\"block w-full text-left px-4 py-2 text-sm hover:bg-gray-50\"\n >\n 导出为 CSV\n </button>\n </div>\n </>\n )}\n </div>\n </div>\n </div>\n\n <div className=\"text-sm text-gray-500 mb-3\">\n 显示 {filteredEvents.length} 条 {search && `(已过滤)`}\n </div>\n\n <div className=\"bg-white rounded-lg shadow overflow-hidden\">\n {isLoading ? (\n <div className=\"p-6\">加载中...</div>\n ) : (\n <table className=\"min-w-full divide-y divide-gray-200\">\n <thead className=\"bg-gray-50\">\n <tr>\n <th className=\"px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase\">时间</th>\n <th className=\"px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase\">提示</th>\n <th className=\"px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase\">路由到</th>\n <th className=\"px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase\">遵守</th>\n <th className=\"px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase\">首工具</th>\n <th className=\"px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase\">耗时</th>\n </tr>\n </thead>\n <tbody className=\"bg-white divide-y divide-gray-200\">\n {filteredEvents.map((e) => {\n let intent: any = {}\n try { intent = JSON.parse(e.intent_json || '{}') } catch { /* ignore */ }\n return (\n <tr\n key={e.id}\n className=\"hover:bg-gray-50 cursor-pointer\"\n onClick={() => setSelectedEvent(e)}\n >\n <td className=\"px-4 py-2 whitespace-nowrap text-xs font-mono text-gray-500\">\n {format(e.ts, 'MM-dd HH:mm:ss')}\n </td>\n <td className=\"px-4 py-2 max-w-xs\">\n <p className=\"text-xs text-gray-700 truncate\" title={e.prompt}>{e.prompt}</p>\n <p className=\"text-xs text-gray-400 mt-0.5\">\n {intent.taskType} / {intent.complexity}\n </p>\n </td>\n <td className=\"px-4 py-2 whitespace-nowrap\">\n {e.routed_to_name ? (\n <span className=\"px-2 py-0.5 text-xs font-medium bg-indigo-100 text-indigo-700 rounded\">\n {e.routed_to_name}\n </span>\n ) : (\n <span className=\"text-xs text-gray-400\">未路由</span>\n )}\n </td>\n <td className=\"px-4 py-2 whitespace-nowrap\">\n <VerdictBadge verdict={e.verdict} />\n </td>\n <td className=\"px-4 py-2 whitespace-nowrap text-xs text-gray-700\">\n {e.first_tool_name || '-'}\n </td>\n <td className=\"px-4 py-2 whitespace-nowrap text-xs font-mono text-gray-500\">\n {e.total_execution_ms ? `${(e.total_execution_ms / 1000).toFixed(1)}s` : '-'}\n </td>\n </tr>\n )\n })}\n {filteredEvents.length === 0 && (\n <tr>\n <td colSpan={6} className=\"px-4 py-12 text-center text-gray-500\">\n <Activity className=\"h-12 w-12 text-gray-300 mx-auto mb-2\" />\n {search ? '无匹配结果' : '暂无追踪记录'}\n </td>\n </tr>\n )}\n </tbody>\n </table>\n )}\n </div>\n\n <Drawer\n open={selectedEvent !== null}\n onClose={() => {\n setSelectedEvent(null)\n setActiveTab('basic')\n }}\n title=\"Agent 执行详情\"\n >\n {selectedEvent && executionDetail && (() => {\n let intent: any = {}\n try { intent = JSON.parse(selectedEvent.intent_json || '{}') } catch { /* ignore */ }\n\n return (\n <div className=\"space-y-4\">\n <div className=\"flex gap-2 border-b border-gray-200 pb-2\">\n {(['basic', 'timeline', 'artifacts'] as const).map(tab => (\n <button\n key={tab}\n onClick={() => setActiveTab(tab)}\n className={clsx(\n 'px-3 py-1.5 text-sm rounded-md transition-colors',\n activeTab === tab\n ? 'bg-indigo-100 text-indigo-700 font-medium'\n : 'text-gray-600 hover:bg-gray-100'\n )}\n >\n {tab === 'basic' && '基本'}\n {tab === 'timeline' && '过程'}\n {tab === 'artifacts' && '产物'}\n </button>\n ))}\n </div>\n\n {activeTab === 'basic' && (\n <div className=\"space-y-4\">\n <div>\n <div className=\"text-xs text-gray-500 mb-1\">用户提示</div>\n <div className=\"bg-purple-50 rounded p-3 text-sm text-gray-800 whitespace-pre-wrap\">\n {selectedEvent.prompt}\n </div>\n </div>\n\n <div className=\"grid grid-cols-2 gap-3\">\n <div>\n <div className=\"text-xs text-gray-500 mb-1\">路由结果</div>\n <div className=\"text-sm font-medium\">\n {selectedEvent.routed_to_name || '未路由'}\n </div>\n </div>\n <div>\n <div className=\"text-xs text-gray-500 mb-1\">遵守状态</div>\n <div><VerdictBadge verdict={selectedEvent.verdict} /></div>\n </div>\n </div>\n\n <div>\n <div className=\"text-xs text-gray-500 mb-1\">意图分类</div>\n <CodeBlock data={intent} language=\"json\" maxHeight=\"200px\" />\n </div>\n\n <div className=\"grid grid-cols-2 gap-3 text-sm\">\n <div>\n <div className=\"text-xs text-gray-500 mb-1\">首工具</div>\n <div className=\"font-mono\">{selectedEvent.first_tool_name || '-'}</div>\n </div>\n <div>\n <div className=\"text-xs text-gray-500 mb-1\">分类耗时</div>\n <div className=\"font-mono\">{selectedEvent.classification_ms}ms</div>\n </div>\n <div>\n <div className=\"text-xs text-gray-500 mb-1\">总执行时间</div>\n <div className=\"font-mono\">\n {selectedEvent.total_execution_ms\n ? `${(selectedEvent.total_execution_ms / 1000).toFixed(2)}s`\n : '-'}\n </div>\n </div>\n <div>\n <div className=\"text-xs text-gray-500 mb-1\">完成原因</div>\n <div>{selectedEvent.completion_reason || '-'}</div>\n </div>\n </div>\n\n {selectedEvent.refusal_reason && (\n <div>\n <div className=\"text-xs text-gray-500 mb-1\">违抗原因</div>\n <div className=\"bg-red-50 rounded p-3 text-sm text-red-700\">\n {selectedEvent.refusal_reason}\n </div>\n </div>\n )}\n\n <div>\n <div className=\"text-xs text-gray-500 mb-1\">Session</div>\n <div className=\"text-xs font-mono text-gray-700\">{selectedEvent.session_id}</div>\n </div>\n </div>\n )}\n\n {activeTab === 'timeline' && (\n <AgentTimeline\n events={executionDetail.events}\n routingTimestamp={selectedEvent.ts}\n />\n )}\n\n {activeTab === 'artifacts' && (\n <ArtifactCards events={executionDetail.events} />\n )}\n </div>\n )\n })()}\n </Drawer>\n </div>\n )\n}\n"],"names":["fetchRoutingEvents","filter","url","res","filters","VERDICT_META","VerdictBadge","verdict","meta","jsx","clsx","AgentTimeline","events","routingTimestamp","expandedNodes","setExpandedNodes","useState","collapsedInvestigation","setCollapsedInvestigation","postToolUseEvents","e","investigationTools","investigationEvents","otherEvents","getToolIcon","toolName","toggleNode","eventId","prev","next","parseToolData","jsonStr","jsxs","offsetSec","toolInput","toolOutput","isExpanded","hasError","CodeBlock","ArtifactCards","expandedCards","setExpandedCards","artifactTools","artifactEvents","toggleCard","countLines","str","command","stdout","stderr","filePath","oldString","newString","isNew","addedLines","removedLines","fetchExecutionDetail","id","ExecutionTrace","setFilter","search","setSearch","selectedEvent","setSelectedEvent","activeTab","setActiveTab","sseConnected","setSseConnected","showExportMenu","setShowExportMenu","toast","useToast","queryClient","useQueryClient","useEffect","eventSource","isLoading","useQuery","executionDetail","filteredEvents","useMemo","q","_a","_b","_c","handleExport","exportFormat","ts","getTimestamp","downloadJSON","flat","intent","format","downloadCSV","Fragment","Wifi","WifiOff","SearchInput","f","v","Download","Activity","Drawer","tab"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import{r as b,j as e}from"./react-vendor-CSp-GLFF.js";import{b as q,u as C,c as E}from"./query-C99w429o.js";import{b as M,L as $}from"./react-router-I-HqunH7.js";import{d as p}from"./vendor-CMMjVdZs.js";import{u as D,a as F}from"./index-
|
|
1
|
+
import{r as b,j as e}from"./react-vendor-CSp-GLFF.js";import{b as q,u as C,c as E}from"./query-C99w429o.js";import{b as M,L as $}from"./react-router-I-HqunH7.js";import{d as p}from"./vendor-CMMjVdZs.js";import{u as D,a as F}from"./index-CIRlno4E.js";import{a as A}from"./auth-Bnf8ZcqN.js";import{P as K,G as S,C as T,m as P,g as Q,c as O,e as R,d as H,n as B,o as L,f as _}from"./lucide-BanPULT1.js";import{a as U,z as X}from"./date-fns-CZ_bHujz.js";import"./syntax-highlighter-44FakypI.js";async function z(){const t=await fetch("/api/methodology-executions?limit=50");if(!t.ok)throw new Error("Failed to fetch");return t.json()}async function G(){const t=await fetch("/api/methodologies");if(!t.ok)throw new Error("Failed to fetch methodologies");return t.json()}async function J(){const t=await fetch("/api/worker-auth-status");if(!t.ok)throw new Error("Failed to fetch worker auth status");return t.json()}async function Y(t){const a=await A(`/api/methodology-executions/${t}/cancel`,{method:"POST"});if(!a.ok){const o=await a.json().catch(()=>({}));throw new Error(o.error||"Cancel failed")}}async function W(t){if(!(await A(`/api/methodology-executions/${t}`,{method:"DELETE"})).ok)throw new Error("Delete failed")}async function V(t){const a=await A("/api/methodology-executions",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)});if(!a.ok){const o=await a.json().catch(()=>({})),i=new Error(o.error||`Start failed (HTTP ${a.status})`);throw typeof o.code=="string"&&(i.code=o.code),i}return a.json()}const Z={"harness-engineering":"Harness Engineering",bmad:"BMad (敏捷开发)"};function ce(){const t=q(),a=D(),o=F(),i=M(),[j,d]=b.useState(!1),{data:r,isLoading:g,error:f}=C({queryKey:["methodology-executions"],queryFn:z,refetchInterval:5e3}),{data:c}=C({queryKey:["methodologies"],queryFn:G}),{data:N}=C({queryKey:["worker-auth-status"],queryFn:J,staleTime:3e4}),m=E({mutationFn:Y,onSuccess:()=>{a.success("方法论执行已取消"),t.invalidateQueries({queryKey:["methodology-executions"]})},onError:s=>a.error(`取消失败: ${s.message}`)}),y=E({mutationFn:W,onSuccess:()=>{a.success("记录已删除"),t.invalidateQueries({queryKey:["methodology-executions"]})},onError:s=>a.error(`删除失败: ${s.message}`)}),x=E({mutationFn:V,onSuccess:s=>{a.success(`已启动执行 #${s.id}`),d(!1),t.invalidateQueries({queryKey:["methodology-executions"]}),t.invalidateQueries({queryKey:["worker-auth-status"]})},onError:async s=>{const l=s.message||"";if(s.code==="AUTH_REQUIRED"||l.includes("Background mode requires")||l.includes("AUTH_REQUIRED")){t.invalidateQueries({queryKey:["worker-auth-status"]}),await o({title:"需要配置 Claude API",message:`后台模式需要 Claude API 认证(ANTHROPIC_API_KEY 或 OAuth)。
|
|
2
2
|
请先在 AI 配置页设置后再启动执行。
|
|
3
3
|
|
|
4
4
|
详细信息:${l}`,confirmText:"去 AI 配置",cancelText:"留在此页",variant:"warning"})&&(d(!1),i("/ai-config"));return}a.error(`启动失败: ${l}`)}}),h=async s=>{await o({title:"取消方法论执行",message:"确定要取消这个运行中的方法论吗?已完成的阶段不会受影响,但当前进行中的阶段将停止。",confirmText:"确认取消",variant:"warning"})&&m.mutate(s)},w=async s=>{await o({title:"删除执行记录",message:"确定要删除这条方法论执行记录吗?此操作不可恢复。",confirmText:"删除",variant:"danger"})&&y.mutate(s)};if(g)return e.jsxs("div",{children:[e.jsx("h1",{className:"text-2xl font-bold text-gray-900 mb-6",children:"方法论执行"}),e.jsx("div",{className:"bg-white rounded-lg shadow p-6",children:e.jsx("p",{className:"text-gray-600",children:"加载中..."})})]});if(f)return e.jsxs("div",{children:[e.jsx("h1",{className:"text-2xl font-bold text-gray-900 mb-6",children:"方法论执行"}),e.jsx("div",{className:"bg-white rounded-lg shadow p-6",children:e.jsxs("p",{className:"text-red-600",children:["加载失败: ",f.message]})})]});const u=(r==null?void 0:r.filter(s=>s.status==="running").length)||0,n=(r==null?void 0:r.filter(s=>s.status==="completed").length)||0;return e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center justify-between mb-6",children:[e.jsx("h1",{className:"text-2xl font-bold text-gray-900",children:"方法论执行"}),e.jsxs("div",{className:"flex items-center gap-4 text-sm",children:[e.jsxs("span",{className:"text-gray-500",children:["共 ",(r==null?void 0:r.length)||0," 个实例"]}),u>0&&e.jsxs("span",{className:"text-blue-600",children:["· 运行中 ",u]}),n>0&&e.jsxs("span",{className:"text-green-600",children:["· 已完成 ",n]}),e.jsxs("button",{onClick:()=>d(!0),className:"ml-3 inline-flex items-center gap-1 px-3 py-1.5 text-sm bg-indigo-600 text-white rounded-md hover:bg-indigo-700",children:[e.jsx(K,{className:"h-4 w-4"})," 新建执行"]})]})]}),j&&e.jsx(ee,{methodologies:c??[],authStatus:N??null,onCancel:()=>d(!1),onSubmit:s=>x.mutate(s),onGoToAIConfig:()=>{d(!1),i("/ai-config")},submitting:x.isPending}),e.jsxs("div",{className:"space-y-4",children:[r==null?void 0:r.map(s=>{const l=JSON.parse(s.plan_json),v=l.phases[s.current_phase_index],I=s.status==="completed"?100:Math.round(s.current_phase_index/l.phases.length*100);return e.jsx("div",{className:"bg-white rounded-lg shadow",children:e.jsxs("div",{className:"p-6 flex items-start justify-between gap-4",children:[e.jsxs($,{to:`/methodologies/${s.id}`,className:"flex-1 min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-3 mb-2",children:[e.jsx(S,{className:"h-5 w-5 text-indigo-600 flex-shrink-0"}),e.jsx("h3",{className:"text-lg font-semibold text-gray-900",children:Z[s.methodology_id]||s.methodology_id}),e.jsxs("span",{className:p("px-2 py-1 text-xs font-medium rounded-full",s.status==="running"&&"bg-blue-100 text-blue-700",s.status==="completed"&&"bg-green-100 text-green-700",s.status==="failed"&&"bg-red-100 text-red-700",s.status==="cancelled"&&"bg-gray-100 text-gray-600"),children:[s.status==="running"&&"运行中",s.status==="completed"&&"已完成",s.status==="failed"&&"失败",s.status==="cancelled"&&"已取消"]}),s.mode&&e.jsxs("span",{className:p("inline-flex items-center gap-1 px-2 py-1 text-xs font-medium rounded-full",s.mode==="background"?"bg-purple-100 text-purple-700":"bg-sky-100 text-sky-700"),title:s.mode==="background"?"独立 claude -p 子进程":"主会话内执行",children:[s.mode==="background"?e.jsx(T,{className:"h-3 w-3"}):e.jsx(P,{className:"h-3 w-3"}),s.mode==="background"?"后台":"前台"]})]}),e.jsxs("p",{className:"text-sm text-gray-600 mb-3 font-mono",children:["Session: ",s.session_id.slice(0,12),"..."]}),e.jsx("div",{className:"w-full bg-gray-200 rounded-full h-1.5 mb-3",children:e.jsx("div",{className:p("h-1.5 rounded-full transition-all",s.status==="completed"?"bg-green-500":s.status==="cancelled"?"bg-gray-400":"bg-indigo-600"),style:{width:`${I}%`}})}),e.jsxs("div",{className:"flex items-center gap-4 text-sm text-gray-500",children:[e.jsxs("div",{className:"flex items-center gap-1",children:[e.jsx(Q,{className:"h-4 w-4"}),U(s.started_at,{addSuffix:!0,locale:X})]}),s.status==="running"&&v&&e.jsxs("div",{className:"flex items-center gap-1",children:[e.jsx(O,{className:"h-4 w-4"}),"Phase ",s.current_phase_index+1,"/",l.phases.length,": ",v.id]}),s.status==="completed"&&e.jsxs("div",{className:"flex items-center gap-1 text-green-600",children:[e.jsx(R,{className:"h-4 w-4"}),"完成 ",l.phases.length," 个阶段"]}),s.status==="cancelled"&&e.jsxs("div",{className:"flex items-center gap-1 text-gray-500",children:[e.jsx(H,{className:"h-4 w-4"}),"已取消于 Phase ",s.current_phase_index+1]})]})]}),e.jsxs("div",{className:"flex items-center gap-1 flex-shrink-0",children:[s.status==="running"&&e.jsx("button",{onClick:k=>{k.preventDefault(),h(s.id)},className:"p-2 text-orange-600 hover:bg-orange-50 rounded-md",title:"取消执行",children:e.jsx(B,{className:"h-4 w-4"})}),s.status!=="running"&&e.jsx("button",{onClick:k=>{k.preventDefault(),w(s.id)},className:"p-2 text-gray-500 hover:bg-red-50 hover:text-red-600 rounded-md",title:"删除记录",children:e.jsx(L,{className:"h-4 w-4"})})]})]})},s.id)}),(!r||r.length===0)&&e.jsxs("div",{className:"bg-white rounded-lg shadow p-12 text-center",children:[e.jsx(S,{className:"h-12 w-12 text-gray-400 mx-auto mb-4"}),e.jsx("p",{className:"text-gray-600",children:"暂无方法论执行记录"}),e.jsx("p",{className:"text-xs text-gray-500 mt-2",children:'当你输入复杂任务(如"重构 XXX 模块")时,系统会自动匹配方法论并生成执行计划'})]})]})]})}function ee({methodologies:t,authStatus:a,submitting:o,onSubmit:i,onCancel:j,onGoToAIConfig:d}){var u;const r=`manual-${Date.now().toString(36)}`,[g,f]=b.useState(r),[c,N]=b.useState(((u=t[0])==null?void 0:u.id)??""),[m,y]=b.useState("background"),x=a!==null&&a.available===!1,h=x&&m==="background",w=n=>{n.preventDefault(),!(!g.trim()||!c)&&(h||i({session_id:g.trim(),methodology_id:c,mode:m}))};return e.jsx("div",{className:"fixed inset-0 z-50 flex items-center justify-center bg-black/40 p-4",children:e.jsxs("form",{onSubmit:w,className:"w-full max-w-md bg-white rounded-lg shadow-xl border border-gray-200",children:[e.jsxs("div",{className:"px-5 py-4 border-b border-gray-100",children:[e.jsx("h2",{className:"text-lg font-semibold text-gray-900",children:"新建方法论执行"}),e.jsx("p",{className:"text-xs text-gray-500 mt-0.5",children:"选择方法论模板和执行模式"})]}),e.jsxs("div",{className:"px-5 py-4 space-y-4 text-sm",children:[e.jsxs("label",{className:"block",children:[e.jsx("span",{className:"text-gray-700",children:"方法论"}),e.jsxs("select",{className:"mt-1 w-full border border-gray-300 rounded-md px-2 py-1.5",value:c,onChange:n=>N(n.target.value),required:!0,children:[t.length===0&&e.jsx("option",{value:"",children:"(未发现方法论)"}),t.map(n=>e.jsx("option",{value:n.id,children:n.name||n.id},n.id))]})]}),e.jsxs("label",{className:"block",children:[e.jsx("span",{className:"text-gray-700",children:"Session ID"}),e.jsx("input",{type:"text",className:"mt-1 w-full border border-gray-300 rounded-md px-2 py-1.5 font-mono text-xs",value:g,onChange:n=>f(n.target.value),required:!0}),e.jsx("span",{className:"mt-1 block text-xs text-gray-500",children:"后台模式下用于追踪;建议保留默认或自定义一个可识别值"})]}),e.jsxs("div",{children:[e.jsx("span",{className:"text-gray-700",children:"执行模式"}),e.jsxs("div",{className:"mt-2 grid grid-cols-2 gap-2",children:[e.jsxs("button",{type:"button",onClick:()=>y("background"),className:p("rounded-md border px-3 py-2 text-left",m==="background"?"border-indigo-500 bg-indigo-50":"border-gray-200 hover:border-gray-300",x&&"ring-1 ring-amber-200"),children:[e.jsxs("div",{className:"flex items-center gap-2 font-medium text-gray-900",children:[e.jsx(T,{className:"h-4 w-4 text-purple-600"})," 后台",x&&e.jsx("span",{className:"ml-auto text-[10px] font-normal text-amber-700 bg-amber-100 px-1.5 py-0.5 rounded",children:"需先配置 API"})]}),e.jsx("p",{className:"text-xs text-gray-500 mt-1",children:"独立 claude -p 子进程,无需用户在主会话输入"})]}),e.jsxs("button",{type:"button",onClick:()=>y("foreground"),className:p("rounded-md border px-3 py-2 text-left",m==="foreground"?"border-indigo-500 bg-indigo-50":"border-gray-200 hover:border-gray-300"),children:[e.jsxs("div",{className:"flex items-center gap-2 font-medium text-gray-900",children:[e.jsx(P,{className:"h-4 w-4 text-sky-600"})," 前台"]}),e.jsxs("p",{className:"text-xs text-amber-700 mt-1 flex items-start gap-1",children:[e.jsx(_,{className:"h-3.5 w-3.5 mt-0.5 shrink-0"}),e.jsxs("span",{children:["需要你在主会话里输入任意内容才会推进;期间可用 ",e.jsx("code",{className:"px-1 rounded bg-amber-50",children:"/forge methodology status"})," 查看"]})]})]})]})]}),h&&e.jsx("div",{className:"rounded-md border border-amber-300 bg-amber-50 px-3 py-2 text-xs text-amber-800",children:e.jsxs("div",{className:"flex items-start gap-2",children:[e.jsx(_,{className:"h-4 w-4 mt-0.5 shrink-0 text-amber-600"}),e.jsxs("div",{className:"flex-1 space-y-1",children:[e.jsx("div",{className:"font-medium",children:"后台模式需要 Claude API 认证"}),e.jsxs("div",{className:"text-amber-700",children:["未检测到 ",e.jsx("code",{className:"px-1 rounded bg-amber-100",children:"ANTHROPIC_API_KEY"})," 或 OAuth 凭据",a!=null&&a.message?`(${a.message})`:"","。 请先在 AI 配置页完成设置,或切换到前台模式。"]}),e.jsx("button",{type:"button",onClick:d,className:"mt-1 inline-flex items-center gap-1 px-2 py-1 text-xs font-medium text-white bg-amber-600 rounded hover:bg-amber-700",children:"去 AI 配置"})]})]})})]}),e.jsxs("div",{className:"px-5 py-3 border-t border-gray-100 flex justify-end gap-2",children:[e.jsx("button",{type:"button",onClick:j,className:"px-3 py-1.5 text-sm text-gray-700 hover:bg-gray-100 rounded-md",children:"取消"}),e.jsx("button",{type:"submit",disabled:o||!c||h,title:h?"后台模式需要先配置 Claude API":void 0,className:"inline-flex items-center gap-1 px-3 py-1.5 text-sm bg-indigo-600 text-white rounded-md hover:bg-indigo-700 disabled:opacity-50 disabled:cursor-not-allowed",children:o?"启动中...":"启动"})]})]})})}export{ce as default};
|
|
5
|
-
//# sourceMappingURL=Methodologies-
|
|
5
|
+
//# sourceMappingURL=Methodologies-DwYLXc8o.js.map
|
package/dist/web/static/assets/{Methodologies-Br5KOWuF.js.map → Methodologies-DwYLXc8o.js.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Methodologies-Br5KOWuF.js","sources":["../../src/pages/Methodologies.tsx"],"sourcesContent":["import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'\nimport { Link, useNavigate } from 'react-router-dom'\nimport { useState } from 'react'\nimport { formatDistanceToNow } from 'date-fns'\nimport { zhCN } from 'date-fns/locale'\nimport { GitBranch, Clock, CheckCircle, AlertCircle, XCircle, Trash2, StopCircle, Plus, Monitor, Cpu, AlertTriangle } from 'lucide-react'\nimport clsx from 'clsx'\nimport { useToast } from '../components/Toast'\nimport { useConfirm } from '../components/Confirm'\nimport { authFetch } from '../utils/auth'\n\ninterface MethodologyExecution {\n id: number\n session_id: string\n methodology_id: string\n plan_json: string\n current_phase_index: number\n status: 'running' | 'completed' | 'failed' | 'cancelled'\n mode?: 'foreground' | 'background'\n worker_pid?: number | null\n worker_session_id?: string | null\n started_at: number\n completed_at: number | null\n}\n\ninterface MethodologyMeta {\n id: string\n name: string\n description?: string\n}\n\ninterface WorkerAuthStatus {\n available: boolean\n method: 'api-key-env' | 'oauth-token' | 'keychain' | 'unknown' | 'none'\n message: string\n}\n\nasync function fetchMethodologyExecutions(): Promise<MethodologyExecution[]> {\n const res = await fetch('/api/methodology-executions?limit=50')\n if (!res.ok) throw new Error('Failed to fetch')\n return res.json()\n}\n\nasync function fetchMethodologies(): Promise<MethodologyMeta[]> {\n const res = await fetch('/api/methodologies')\n if (!res.ok) throw new Error('Failed to fetch methodologies')\n return res.json()\n}\n\nasync function fetchWorkerAuthStatus(): Promise<WorkerAuthStatus> {\n const res = await fetch('/api/worker-auth-status')\n if (!res.ok) throw new Error('Failed to fetch worker auth status')\n return res.json()\n}\n\nasync function cancelExecution(id: number): Promise<void> {\n const res = await authFetch(`/api/methodology-executions/${id}/cancel`, { method: 'POST' })\n if (!res.ok) {\n const data = await res.json().catch(() => ({}))\n throw new Error(data.error || 'Cancel failed')\n }\n}\n\nasync function deleteExecution(id: number): Promise<void> {\n const res = await authFetch(`/api/methodology-executions/${id}`, { method: 'DELETE' })\n if (!res.ok) throw new Error('Delete failed')\n}\n\nasync function startExecution(payload: {\n session_id: string\n methodology_id: string\n mode: 'foreground' | 'background'\n}): Promise<{ id: number }> {\n const res = await authFetch('/api/methodology-executions', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(payload),\n })\n if (!res.ok) {\n const data = await res.json().catch(() => ({}))\n const err = new Error(data.error || `Start failed (HTTP ${res.status})`) as Error & { code?: string }\n if (typeof data.code === 'string') err.code = data.code\n throw err\n }\n return res.json()\n}\n\nconst methodologyNames: Record<string, string> = {\n 'harness-engineering': 'Harness Engineering',\n 'bmad': 'BMad (敏捷开发)',\n}\n\nexport default function Methodologies() {\n const queryClient = useQueryClient()\n const toast = useToast()\n const confirm = useConfirm()\n const navigate = useNavigate()\n const [showStart, setShowStart] = useState(false)\n\n const { data: executions, isLoading, error } = useQuery({\n queryKey: ['methodology-executions'],\n queryFn: fetchMethodologyExecutions,\n refetchInterval: 5000,\n })\n\n const { data: methodologies } = useQuery({\n queryKey: ['methodologies'],\n queryFn: fetchMethodologies,\n })\n\n const { data: authStatus } = useQuery({\n queryKey: ['worker-auth-status'],\n queryFn: fetchWorkerAuthStatus,\n // 只在打开 Modal 时或进入页面时查一次;后续可手动刷新\n staleTime: 30_000,\n })\n\n const cancelMutation = useMutation({\n mutationFn: cancelExecution,\n onSuccess: () => {\n toast.success('方法论执行已取消')\n queryClient.invalidateQueries({ queryKey: ['methodology-executions'] })\n },\n onError: (e: Error) => toast.error(`取消失败: ${e.message}`),\n })\n\n const deleteMutation = useMutation({\n mutationFn: deleteExecution,\n onSuccess: () => {\n toast.success('记录已删除')\n queryClient.invalidateQueries({ queryKey: ['methodology-executions'] })\n },\n onError: (e: Error) => toast.error(`删除失败: ${e.message}`),\n })\n\n const startMutation = useMutation({\n mutationFn: startExecution,\n onSuccess: (data) => {\n toast.success(`已启动执行 #${data.id}`)\n setShowStart(false)\n queryClient.invalidateQueries({ queryKey: ['methodology-executions'] })\n // 成功启动后顺手刷新 auth 状态(虽然理论上没变,但保持一致)\n queryClient.invalidateQueries({ queryKey: ['worker-auth-status'] })\n },\n onError: async (e: Error & { code?: string }) => {\n const msg = e.message || ''\n const isAuthError =\n e.code === 'AUTH_REQUIRED' ||\n msg.includes('Background mode requires') ||\n msg.includes('AUTH_REQUIRED')\n if (isAuthError) {\n // 提前刷一下认证状态,确保 Modal 下次打开时 banner 即时更新\n queryClient.invalidateQueries({ queryKey: ['worker-auth-status'] })\n const go = await confirm({\n title: '需要配置 Claude API',\n message:\n '后台模式需要 Claude API 认证(ANTHROPIC_API_KEY 或 OAuth)。\\n' +\n '请先在 AI 配置页设置后再启动执行。\\n\\n' +\n `详细信息:${msg}`,\n confirmText: '去 AI 配置',\n cancelText: '留在此页',\n variant: 'warning',\n })\n if (go) {\n setShowStart(false)\n navigate('/ai-config')\n }\n return\n }\n toast.error(`启动失败: ${msg}`)\n },\n })\n\n const handleCancel = async (id: number) => {\n const ok = await confirm({\n title: '取消方法论执行',\n message: '确定要取消这个运行中的方法论吗?已完成的阶段不会受影响,但当前进行中的阶段将停止。',\n confirmText: '确认取消',\n variant: 'warning',\n })\n if (ok) cancelMutation.mutate(id)\n }\n\n const handleDelete = async (id: number) => {\n const ok = await confirm({\n title: '删除执行记录',\n message: '确定要删除这条方法论执行记录吗?此操作不可恢复。',\n confirmText: '删除',\n variant: 'danger',\n })\n if (ok) deleteMutation.mutate(id)\n }\n\n if (isLoading) {\n return (\n <div>\n <h1 className=\"text-2xl font-bold text-gray-900 mb-6\">方法论执行</h1>\n <div className=\"bg-white rounded-lg shadow p-6\">\n <p className=\"text-gray-600\">加载中...</p>\n </div>\n </div>\n )\n }\n\n if (error) {\n return (\n <div>\n <h1 className=\"text-2xl font-bold text-gray-900 mb-6\">方法论执行</h1>\n <div className=\"bg-white rounded-lg shadow p-6\">\n <p className=\"text-red-600\">加载失败: {(error as Error).message}</p>\n </div>\n </div>\n )\n }\n\n const runningCount = executions?.filter(e => e.status === 'running').length || 0\n const completedCount = executions?.filter(e => e.status === 'completed').length || 0\n\n return (\n <div>\n <div className=\"flex items-center justify-between mb-6\">\n <h1 className=\"text-2xl font-bold text-gray-900\">方法论执行</h1>\n <div className=\"flex items-center gap-4 text-sm\">\n <span className=\"text-gray-500\">共 {executions?.length || 0} 个实例</span>\n {runningCount > 0 && <span className=\"text-blue-600\">· 运行中 {runningCount}</span>}\n {completedCount > 0 && <span className=\"text-green-600\">· 已完成 {completedCount}</span>}\n <button\n onClick={() => setShowStart(true)}\n className=\"ml-3 inline-flex items-center gap-1 px-3 py-1.5 text-sm bg-indigo-600 text-white rounded-md hover:bg-indigo-700\"\n >\n <Plus className=\"h-4 w-4\" /> 新建执行\n </button>\n </div>\n </div>\n\n {showStart && (\n <StartExecutionModal\n methodologies={methodologies ?? []}\n authStatus={authStatus ?? null}\n onCancel={() => setShowStart(false)}\n onSubmit={(payload) => startMutation.mutate(payload)}\n onGoToAIConfig={() => {\n setShowStart(false)\n navigate('/ai-config')\n }}\n submitting={startMutation.isPending}\n />\n )}\n\n <div className=\"space-y-4\">\n {executions?.map((execution) => {\n const plan = JSON.parse(execution.plan_json)\n const currentPhase = plan.phases[execution.current_phase_index]\n const progress = execution.status === 'completed'\n ? 100\n : Math.round((execution.current_phase_index / plan.phases.length) * 100)\n\n return (\n <div key={execution.id} className=\"bg-white rounded-lg shadow\">\n <div className=\"p-6 flex items-start justify-between gap-4\">\n <Link to={`/methodologies/${execution.id}`} className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-3 mb-2\">\n <GitBranch className=\"h-5 w-5 text-indigo-600 flex-shrink-0\" />\n <h3 className=\"text-lg font-semibold text-gray-900\">\n {methodologyNames[execution.methodology_id] || execution.methodology_id}\n </h3>\n <span className={clsx(\n 'px-2 py-1 text-xs font-medium rounded-full',\n execution.status === 'running' && 'bg-blue-100 text-blue-700',\n execution.status === 'completed' && 'bg-green-100 text-green-700',\n execution.status === 'failed' && 'bg-red-100 text-red-700',\n execution.status === 'cancelled' && 'bg-gray-100 text-gray-600'\n )}>\n {execution.status === 'running' && '运行中'}\n {execution.status === 'completed' && '已完成'}\n {execution.status === 'failed' && '失败'}\n {execution.status === 'cancelled' && '已取消'}\n </span>\n {execution.mode && (\n <span\n className={clsx(\n 'inline-flex items-center gap-1 px-2 py-1 text-xs font-medium rounded-full',\n execution.mode === 'background'\n ? 'bg-purple-100 text-purple-700'\n : 'bg-sky-100 text-sky-700'\n )}\n title={execution.mode === 'background' ? '独立 claude -p 子进程' : '主会话内执行'}\n >\n {execution.mode === 'background' ? <Cpu className=\"h-3 w-3\" /> : <Monitor className=\"h-3 w-3\" />}\n {execution.mode === 'background' ? '后台' : '前台'}\n </span>\n )}\n </div>\n\n <p className=\"text-sm text-gray-600 mb-3 font-mono\">\n Session: {execution.session_id.slice(0, 12)}...\n </p>\n\n {/* Progress bar */}\n <div className=\"w-full bg-gray-200 rounded-full h-1.5 mb-3\">\n <div\n className={clsx(\n 'h-1.5 rounded-full transition-all',\n execution.status === 'completed' ? 'bg-green-500' :\n execution.status === 'cancelled' ? 'bg-gray-400' : 'bg-indigo-600'\n )}\n style={{ width: `${progress}%` }}\n />\n </div>\n\n <div className=\"flex items-center gap-4 text-sm text-gray-500\">\n <div className=\"flex items-center gap-1\">\n <Clock className=\"h-4 w-4\" />\n {formatDistanceToNow(execution.started_at, { addSuffix: true, locale: zhCN })}\n </div>\n {execution.status === 'running' && currentPhase && (\n <div className=\"flex items-center gap-1\">\n <AlertCircle className=\"h-4 w-4\" />\n Phase {execution.current_phase_index + 1}/{plan.phases.length}: {currentPhase.id}\n </div>\n )}\n {execution.status === 'completed' && (\n <div className=\"flex items-center gap-1 text-green-600\">\n <CheckCircle className=\"h-4 w-4\" />\n 完成 {plan.phases.length} 个阶段\n </div>\n )}\n {execution.status === 'cancelled' && (\n <div className=\"flex items-center gap-1 text-gray-500\">\n <XCircle className=\"h-4 w-4\" />\n 已取消于 Phase {execution.current_phase_index + 1}\n </div>\n )}\n </div>\n </Link>\n\n {/* Actions */}\n <div className=\"flex items-center gap-1 flex-shrink-0\">\n {execution.status === 'running' && (\n <button\n onClick={(e) => {\n e.preventDefault()\n handleCancel(execution.id)\n }}\n className=\"p-2 text-orange-600 hover:bg-orange-50 rounded-md\"\n title=\"取消执行\"\n >\n <StopCircle className=\"h-4 w-4\" />\n </button>\n )}\n {execution.status !== 'running' && (\n <button\n onClick={(e) => { e.preventDefault(); handleDelete(execution.id) }}\n className=\"p-2 text-gray-500 hover:bg-red-50 hover:text-red-600 rounded-md\"\n title=\"删除记录\"\n >\n <Trash2 className=\"h-4 w-4\" />\n </button>\n )}\n </div>\n </div>\n </div>\n )\n })}\n\n {(!executions || executions.length === 0) && (\n <div className=\"bg-white rounded-lg shadow p-12 text-center\">\n <GitBranch className=\"h-12 w-12 text-gray-400 mx-auto mb-4\" />\n <p className=\"text-gray-600\">暂无方法论执行记录</p>\n <p className=\"text-xs text-gray-500 mt-2\">\n 当你输入复杂任务(如\"重构 XXX 模块\")时,系统会自动匹配方法论并生成执行计划\n </p>\n </div>\n )}\n </div>\n </div>\n )\n}\n\ninterface StartExecutionModalProps {\n methodologies: MethodologyMeta[]\n authStatus: WorkerAuthStatus | null\n submitting: boolean\n onSubmit: (payload: { session_id: string; methodology_id: string; mode: 'foreground' | 'background' }) => void\n onCancel: () => void\n onGoToAIConfig: () => void\n}\n\nfunction StartExecutionModal({ methodologies, authStatus, submitting, onSubmit, onCancel, onGoToAIConfig }: StartExecutionModalProps) {\n const defaultSession = `manual-${Date.now().toString(36)}`\n const [sessionId, setSessionId] = useState(defaultSession)\n const [methodologyId, setMethodologyId] = useState(methodologies[0]?.id ?? '')\n const [mode, setMode] = useState<'foreground' | 'background'>('background')\n\n const authMissing = authStatus !== null && authStatus.available === false\n const blockedByAuth = authMissing && mode === 'background'\n\n const submit = (e: React.FormEvent) => {\n e.preventDefault()\n if (!sessionId.trim() || !methodologyId) return\n if (blockedByAuth) return\n onSubmit({ session_id: sessionId.trim(), methodology_id: methodologyId, mode })\n }\n\n return (\n <div className=\"fixed inset-0 z-50 flex items-center justify-center bg-black/40 p-4\">\n <form\n onSubmit={submit}\n className=\"w-full max-w-md bg-white rounded-lg shadow-xl border border-gray-200\"\n >\n <div className=\"px-5 py-4 border-b border-gray-100\">\n <h2 className=\"text-lg font-semibold text-gray-900\">新建方法论执行</h2>\n <p className=\"text-xs text-gray-500 mt-0.5\">选择方法论模板和执行模式</p>\n </div>\n\n <div className=\"px-5 py-4 space-y-4 text-sm\">\n <label className=\"block\">\n <span className=\"text-gray-700\">方法论</span>\n <select\n className=\"mt-1 w-full border border-gray-300 rounded-md px-2 py-1.5\"\n value={methodologyId}\n onChange={(e) => setMethodologyId(e.target.value)}\n required\n >\n {methodologies.length === 0 && <option value=\"\">(未发现方法论)</option>}\n {methodologies.map(m => (\n <option key={m.id} value={m.id}>{m.name || m.id}</option>\n ))}\n </select>\n </label>\n\n <label className=\"block\">\n <span className=\"text-gray-700\">Session ID</span>\n <input\n type=\"text\"\n className=\"mt-1 w-full border border-gray-300 rounded-md px-2 py-1.5 font-mono text-xs\"\n value={sessionId}\n onChange={(e) => setSessionId(e.target.value)}\n required\n />\n <span className=\"mt-1 block text-xs text-gray-500\">\n 后台模式下用于追踪;建议保留默认或自定义一个可识别值\n </span>\n </label>\n\n <div>\n <span className=\"text-gray-700\">执行模式</span>\n <div className=\"mt-2 grid grid-cols-2 gap-2\">\n <button\n type=\"button\"\n onClick={() => setMode('background')}\n className={clsx(\n 'rounded-md border px-3 py-2 text-left',\n mode === 'background'\n ? 'border-indigo-500 bg-indigo-50'\n : 'border-gray-200 hover:border-gray-300',\n authMissing && 'ring-1 ring-amber-200'\n )}\n >\n <div className=\"flex items-center gap-2 font-medium text-gray-900\">\n <Cpu className=\"h-4 w-4 text-purple-600\" /> 后台\n {authMissing && (\n <span className=\"ml-auto text-[10px] font-normal text-amber-700 bg-amber-100 px-1.5 py-0.5 rounded\">\n 需先配置 API\n </span>\n )}\n </div>\n <p className=\"text-xs text-gray-500 mt-1\">\n 独立 claude -p 子进程,无需用户在主会话输入\n </p>\n </button>\n <button\n type=\"button\"\n onClick={() => setMode('foreground')}\n className={clsx(\n 'rounded-md border px-3 py-2 text-left',\n mode === 'foreground'\n ? 'border-indigo-500 bg-indigo-50'\n : 'border-gray-200 hover:border-gray-300'\n )}\n >\n <div className=\"flex items-center gap-2 font-medium text-gray-900\">\n <Monitor className=\"h-4 w-4 text-sky-600\" /> 前台\n </div>\n <p className=\"text-xs text-amber-700 mt-1 flex items-start gap-1\">\n <AlertTriangle className=\"h-3.5 w-3.5 mt-0.5 shrink-0\" />\n <span>需要你在主会话里输入任意内容才会推进;期间可用 <code className=\"px-1 rounded bg-amber-50\">/forge methodology status</code> 查看</span>\n </p>\n </button>\n </div>\n </div>\n\n {blockedByAuth && (\n <div className=\"rounded-md border border-amber-300 bg-amber-50 px-3 py-2 text-xs text-amber-800\">\n <div className=\"flex items-start gap-2\">\n <AlertTriangle className=\"h-4 w-4 mt-0.5 shrink-0 text-amber-600\" />\n <div className=\"flex-1 space-y-1\">\n <div className=\"font-medium\">后台模式需要 Claude API 认证</div>\n <div className=\"text-amber-700\">\n 未检测到 <code className=\"px-1 rounded bg-amber-100\">ANTHROPIC_API_KEY</code> 或 OAuth 凭据\n {authStatus?.message ? `(${authStatus.message})` : ''}。\n 请先在 AI 配置页完成设置,或切换到前台模式。\n </div>\n <button\n type=\"button\"\n onClick={onGoToAIConfig}\n className=\"mt-1 inline-flex items-center gap-1 px-2 py-1 text-xs font-medium text-white bg-amber-600 rounded hover:bg-amber-700\"\n >\n 去 AI 配置\n </button>\n </div>\n </div>\n </div>\n )}\n </div>\n\n <div className=\"px-5 py-3 border-t border-gray-100 flex justify-end gap-2\">\n <button\n type=\"button\"\n onClick={onCancel}\n className=\"px-3 py-1.5 text-sm text-gray-700 hover:bg-gray-100 rounded-md\"\n >\n 取消\n </button>\n <button\n type=\"submit\"\n disabled={submitting || !methodologyId || blockedByAuth}\n title={blockedByAuth ? '后台模式需要先配置 Claude API' : undefined}\n className=\"inline-flex items-center gap-1 px-3 py-1.5 text-sm bg-indigo-600 text-white rounded-md hover:bg-indigo-700 disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n {submitting ? '启动中...' : '启动'}\n </button>\n </div>\n </form>\n </div>\n )\n}\n"],"names":["fetchMethodologyExecutions","res","fetchMethodologies","fetchWorkerAuthStatus","cancelExecution","id","authFetch","data","deleteExecution","startExecution","payload","err","methodologyNames","Methodologies","queryClient","useQueryClient","toast","useToast","confirm","useConfirm","navigate","useNavigate","showStart","setShowStart","useState","executions","isLoading","error","useQuery","methodologies","authStatus","cancelMutation","useMutation","e","deleteMutation","startMutation","msg","handleCancel","handleDelete","jsx","jsxs","runningCount","completedCount","Plus","StartExecutionModal","execution","plan","currentPhase","progress","Link","GitBranch","clsx","Cpu","Monitor","Clock","formatDistanceToNow","zhCN","AlertCircle","CheckCircle","XCircle","StopCircle","Trash2","submitting","onSubmit","onCancel","onGoToAIConfig","defaultSession","sessionId","setSessionId","methodologyId","setMethodologyId","_a","mode","setMode","authMissing","blockedByAuth","submit","m","AlertTriangle"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Methodologies-DwYLXc8o.js","sources":["../../src/pages/Methodologies.tsx"],"sourcesContent":["import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'\nimport { Link, useNavigate } from 'react-router-dom'\nimport { useState } from 'react'\nimport { formatDistanceToNow } from 'date-fns'\nimport { zhCN } from 'date-fns/locale'\nimport { GitBranch, Clock, CheckCircle, AlertCircle, XCircle, Trash2, StopCircle, Plus, Monitor, Cpu, AlertTriangle } from 'lucide-react'\nimport clsx from 'clsx'\nimport { useToast } from '../components/Toast'\nimport { useConfirm } from '../components/Confirm'\nimport { authFetch } from '../utils/auth'\n\ninterface MethodologyExecution {\n id: number\n session_id: string\n methodology_id: string\n plan_json: string\n current_phase_index: number\n status: 'running' | 'completed' | 'failed' | 'cancelled'\n mode?: 'foreground' | 'background'\n worker_pid?: number | null\n worker_session_id?: string | null\n started_at: number\n completed_at: number | null\n}\n\ninterface MethodologyMeta {\n id: string\n name: string\n description?: string\n}\n\ninterface WorkerAuthStatus {\n available: boolean\n method: 'api-key-env' | 'oauth-token' | 'keychain' | 'unknown' | 'none'\n message: string\n}\n\nasync function fetchMethodologyExecutions(): Promise<MethodologyExecution[]> {\n const res = await fetch('/api/methodology-executions?limit=50')\n if (!res.ok) throw new Error('Failed to fetch')\n return res.json()\n}\n\nasync function fetchMethodologies(): Promise<MethodologyMeta[]> {\n const res = await fetch('/api/methodologies')\n if (!res.ok) throw new Error('Failed to fetch methodologies')\n return res.json()\n}\n\nasync function fetchWorkerAuthStatus(): Promise<WorkerAuthStatus> {\n const res = await fetch('/api/worker-auth-status')\n if (!res.ok) throw new Error('Failed to fetch worker auth status')\n return res.json()\n}\n\nasync function cancelExecution(id: number): Promise<void> {\n const res = await authFetch(`/api/methodology-executions/${id}/cancel`, { method: 'POST' })\n if (!res.ok) {\n const data = await res.json().catch(() => ({}))\n throw new Error(data.error || 'Cancel failed')\n }\n}\n\nasync function deleteExecution(id: number): Promise<void> {\n const res = await authFetch(`/api/methodology-executions/${id}`, { method: 'DELETE' })\n if (!res.ok) throw new Error('Delete failed')\n}\n\nasync function startExecution(payload: {\n session_id: string\n methodology_id: string\n mode: 'foreground' | 'background'\n}): Promise<{ id: number }> {\n const res = await authFetch('/api/methodology-executions', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(payload),\n })\n if (!res.ok) {\n const data = await res.json().catch(() => ({}))\n const err = new Error(data.error || `Start failed (HTTP ${res.status})`) as Error & { code?: string }\n if (typeof data.code === 'string') err.code = data.code\n throw err\n }\n return res.json()\n}\n\nconst methodologyNames: Record<string, string> = {\n 'harness-engineering': 'Harness Engineering',\n 'bmad': 'BMad (敏捷开发)',\n}\n\nexport default function Methodologies() {\n const queryClient = useQueryClient()\n const toast = useToast()\n const confirm = useConfirm()\n const navigate = useNavigate()\n const [showStart, setShowStart] = useState(false)\n\n const { data: executions, isLoading, error } = useQuery({\n queryKey: ['methodology-executions'],\n queryFn: fetchMethodologyExecutions,\n refetchInterval: 5000,\n })\n\n const { data: methodologies } = useQuery({\n queryKey: ['methodologies'],\n queryFn: fetchMethodologies,\n })\n\n const { data: authStatus } = useQuery({\n queryKey: ['worker-auth-status'],\n queryFn: fetchWorkerAuthStatus,\n // 只在打开 Modal 时或进入页面时查一次;后续可手动刷新\n staleTime: 30_000,\n })\n\n const cancelMutation = useMutation({\n mutationFn: cancelExecution,\n onSuccess: () => {\n toast.success('方法论执行已取消')\n queryClient.invalidateQueries({ queryKey: ['methodology-executions'] })\n },\n onError: (e: Error) => toast.error(`取消失败: ${e.message}`),\n })\n\n const deleteMutation = useMutation({\n mutationFn: deleteExecution,\n onSuccess: () => {\n toast.success('记录已删除')\n queryClient.invalidateQueries({ queryKey: ['methodology-executions'] })\n },\n onError: (e: Error) => toast.error(`删除失败: ${e.message}`),\n })\n\n const startMutation = useMutation({\n mutationFn: startExecution,\n onSuccess: (data) => {\n toast.success(`已启动执行 #${data.id}`)\n setShowStart(false)\n queryClient.invalidateQueries({ queryKey: ['methodology-executions'] })\n // 成功启动后顺手刷新 auth 状态(虽然理论上没变,但保持一致)\n queryClient.invalidateQueries({ queryKey: ['worker-auth-status'] })\n },\n onError: async (e: Error & { code?: string }) => {\n const msg = e.message || ''\n const isAuthError =\n e.code === 'AUTH_REQUIRED' ||\n msg.includes('Background mode requires') ||\n msg.includes('AUTH_REQUIRED')\n if (isAuthError) {\n // 提前刷一下认证状态,确保 Modal 下次打开时 banner 即时更新\n queryClient.invalidateQueries({ queryKey: ['worker-auth-status'] })\n const go = await confirm({\n title: '需要配置 Claude API',\n message:\n '后台模式需要 Claude API 认证(ANTHROPIC_API_KEY 或 OAuth)。\\n' +\n '请先在 AI 配置页设置后再启动执行。\\n\\n' +\n `详细信息:${msg}`,\n confirmText: '去 AI 配置',\n cancelText: '留在此页',\n variant: 'warning',\n })\n if (go) {\n setShowStart(false)\n navigate('/ai-config')\n }\n return\n }\n toast.error(`启动失败: ${msg}`)\n },\n })\n\n const handleCancel = async (id: number) => {\n const ok = await confirm({\n title: '取消方法论执行',\n message: '确定要取消这个运行中的方法论吗?已完成的阶段不会受影响,但当前进行中的阶段将停止。',\n confirmText: '确认取消',\n variant: 'warning',\n })\n if (ok) cancelMutation.mutate(id)\n }\n\n const handleDelete = async (id: number) => {\n const ok = await confirm({\n title: '删除执行记录',\n message: '确定要删除这条方法论执行记录吗?此操作不可恢复。',\n confirmText: '删除',\n variant: 'danger',\n })\n if (ok) deleteMutation.mutate(id)\n }\n\n if (isLoading) {\n return (\n <div>\n <h1 className=\"text-2xl font-bold text-gray-900 mb-6\">方法论执行</h1>\n <div className=\"bg-white rounded-lg shadow p-6\">\n <p className=\"text-gray-600\">加载中...</p>\n </div>\n </div>\n )\n }\n\n if (error) {\n return (\n <div>\n <h1 className=\"text-2xl font-bold text-gray-900 mb-6\">方法论执行</h1>\n <div className=\"bg-white rounded-lg shadow p-6\">\n <p className=\"text-red-600\">加载失败: {(error as Error).message}</p>\n </div>\n </div>\n )\n }\n\n const runningCount = executions?.filter(e => e.status === 'running').length || 0\n const completedCount = executions?.filter(e => e.status === 'completed').length || 0\n\n return (\n <div>\n <div className=\"flex items-center justify-between mb-6\">\n <h1 className=\"text-2xl font-bold text-gray-900\">方法论执行</h1>\n <div className=\"flex items-center gap-4 text-sm\">\n <span className=\"text-gray-500\">共 {executions?.length || 0} 个实例</span>\n {runningCount > 0 && <span className=\"text-blue-600\">· 运行中 {runningCount}</span>}\n {completedCount > 0 && <span className=\"text-green-600\">· 已完成 {completedCount}</span>}\n <button\n onClick={() => setShowStart(true)}\n className=\"ml-3 inline-flex items-center gap-1 px-3 py-1.5 text-sm bg-indigo-600 text-white rounded-md hover:bg-indigo-700\"\n >\n <Plus className=\"h-4 w-4\" /> 新建执行\n </button>\n </div>\n </div>\n\n {showStart && (\n <StartExecutionModal\n methodologies={methodologies ?? []}\n authStatus={authStatus ?? null}\n onCancel={() => setShowStart(false)}\n onSubmit={(payload) => startMutation.mutate(payload)}\n onGoToAIConfig={() => {\n setShowStart(false)\n navigate('/ai-config')\n }}\n submitting={startMutation.isPending}\n />\n )}\n\n <div className=\"space-y-4\">\n {executions?.map((execution) => {\n const plan = JSON.parse(execution.plan_json)\n const currentPhase = plan.phases[execution.current_phase_index]\n const progress = execution.status === 'completed'\n ? 100\n : Math.round((execution.current_phase_index / plan.phases.length) * 100)\n\n return (\n <div key={execution.id} className=\"bg-white rounded-lg shadow\">\n <div className=\"p-6 flex items-start justify-between gap-4\">\n <Link to={`/methodologies/${execution.id}`} className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-3 mb-2\">\n <GitBranch className=\"h-5 w-5 text-indigo-600 flex-shrink-0\" />\n <h3 className=\"text-lg font-semibold text-gray-900\">\n {methodologyNames[execution.methodology_id] || execution.methodology_id}\n </h3>\n <span className={clsx(\n 'px-2 py-1 text-xs font-medium rounded-full',\n execution.status === 'running' && 'bg-blue-100 text-blue-700',\n execution.status === 'completed' && 'bg-green-100 text-green-700',\n execution.status === 'failed' && 'bg-red-100 text-red-700',\n execution.status === 'cancelled' && 'bg-gray-100 text-gray-600'\n )}>\n {execution.status === 'running' && '运行中'}\n {execution.status === 'completed' && '已完成'}\n {execution.status === 'failed' && '失败'}\n {execution.status === 'cancelled' && '已取消'}\n </span>\n {execution.mode && (\n <span\n className={clsx(\n 'inline-flex items-center gap-1 px-2 py-1 text-xs font-medium rounded-full',\n execution.mode === 'background'\n ? 'bg-purple-100 text-purple-700'\n : 'bg-sky-100 text-sky-700'\n )}\n title={execution.mode === 'background' ? '独立 claude -p 子进程' : '主会话内执行'}\n >\n {execution.mode === 'background' ? <Cpu className=\"h-3 w-3\" /> : <Monitor className=\"h-3 w-3\" />}\n {execution.mode === 'background' ? '后台' : '前台'}\n </span>\n )}\n </div>\n\n <p className=\"text-sm text-gray-600 mb-3 font-mono\">\n Session: {execution.session_id.slice(0, 12)}...\n </p>\n\n {/* Progress bar */}\n <div className=\"w-full bg-gray-200 rounded-full h-1.5 mb-3\">\n <div\n className={clsx(\n 'h-1.5 rounded-full transition-all',\n execution.status === 'completed' ? 'bg-green-500' :\n execution.status === 'cancelled' ? 'bg-gray-400' : 'bg-indigo-600'\n )}\n style={{ width: `${progress}%` }}\n />\n </div>\n\n <div className=\"flex items-center gap-4 text-sm text-gray-500\">\n <div className=\"flex items-center gap-1\">\n <Clock className=\"h-4 w-4\" />\n {formatDistanceToNow(execution.started_at, { addSuffix: true, locale: zhCN })}\n </div>\n {execution.status === 'running' && currentPhase && (\n <div className=\"flex items-center gap-1\">\n <AlertCircle className=\"h-4 w-4\" />\n Phase {execution.current_phase_index + 1}/{plan.phases.length}: {currentPhase.id}\n </div>\n )}\n {execution.status === 'completed' && (\n <div className=\"flex items-center gap-1 text-green-600\">\n <CheckCircle className=\"h-4 w-4\" />\n 完成 {plan.phases.length} 个阶段\n </div>\n )}\n {execution.status === 'cancelled' && (\n <div className=\"flex items-center gap-1 text-gray-500\">\n <XCircle className=\"h-4 w-4\" />\n 已取消于 Phase {execution.current_phase_index + 1}\n </div>\n )}\n </div>\n </Link>\n\n {/* Actions */}\n <div className=\"flex items-center gap-1 flex-shrink-0\">\n {execution.status === 'running' && (\n <button\n onClick={(e) => {\n e.preventDefault()\n handleCancel(execution.id)\n }}\n className=\"p-2 text-orange-600 hover:bg-orange-50 rounded-md\"\n title=\"取消执行\"\n >\n <StopCircle className=\"h-4 w-4\" />\n </button>\n )}\n {execution.status !== 'running' && (\n <button\n onClick={(e) => { e.preventDefault(); handleDelete(execution.id) }}\n className=\"p-2 text-gray-500 hover:bg-red-50 hover:text-red-600 rounded-md\"\n title=\"删除记录\"\n >\n <Trash2 className=\"h-4 w-4\" />\n </button>\n )}\n </div>\n </div>\n </div>\n )\n })}\n\n {(!executions || executions.length === 0) && (\n <div className=\"bg-white rounded-lg shadow p-12 text-center\">\n <GitBranch className=\"h-12 w-12 text-gray-400 mx-auto mb-4\" />\n <p className=\"text-gray-600\">暂无方法论执行记录</p>\n <p className=\"text-xs text-gray-500 mt-2\">\n 当你输入复杂任务(如\"重构 XXX 模块\")时,系统会自动匹配方法论并生成执行计划\n </p>\n </div>\n )}\n </div>\n </div>\n )\n}\n\ninterface StartExecutionModalProps {\n methodologies: MethodologyMeta[]\n authStatus: WorkerAuthStatus | null\n submitting: boolean\n onSubmit: (payload: { session_id: string; methodology_id: string; mode: 'foreground' | 'background' }) => void\n onCancel: () => void\n onGoToAIConfig: () => void\n}\n\nfunction StartExecutionModal({ methodologies, authStatus, submitting, onSubmit, onCancel, onGoToAIConfig }: StartExecutionModalProps) {\n const defaultSession = `manual-${Date.now().toString(36)}`\n const [sessionId, setSessionId] = useState(defaultSession)\n const [methodologyId, setMethodologyId] = useState(methodologies[0]?.id ?? '')\n const [mode, setMode] = useState<'foreground' | 'background'>('background')\n\n const authMissing = authStatus !== null && authStatus.available === false\n const blockedByAuth = authMissing && mode === 'background'\n\n const submit = (e: React.FormEvent) => {\n e.preventDefault()\n if (!sessionId.trim() || !methodologyId) return\n if (blockedByAuth) return\n onSubmit({ session_id: sessionId.trim(), methodology_id: methodologyId, mode })\n }\n\n return (\n <div className=\"fixed inset-0 z-50 flex items-center justify-center bg-black/40 p-4\">\n <form\n onSubmit={submit}\n className=\"w-full max-w-md bg-white rounded-lg shadow-xl border border-gray-200\"\n >\n <div className=\"px-5 py-4 border-b border-gray-100\">\n <h2 className=\"text-lg font-semibold text-gray-900\">新建方法论执行</h2>\n <p className=\"text-xs text-gray-500 mt-0.5\">选择方法论模板和执行模式</p>\n </div>\n\n <div className=\"px-5 py-4 space-y-4 text-sm\">\n <label className=\"block\">\n <span className=\"text-gray-700\">方法论</span>\n <select\n className=\"mt-1 w-full border border-gray-300 rounded-md px-2 py-1.5\"\n value={methodologyId}\n onChange={(e) => setMethodologyId(e.target.value)}\n required\n >\n {methodologies.length === 0 && <option value=\"\">(未发现方法论)</option>}\n {methodologies.map(m => (\n <option key={m.id} value={m.id}>{m.name || m.id}</option>\n ))}\n </select>\n </label>\n\n <label className=\"block\">\n <span className=\"text-gray-700\">Session ID</span>\n <input\n type=\"text\"\n className=\"mt-1 w-full border border-gray-300 rounded-md px-2 py-1.5 font-mono text-xs\"\n value={sessionId}\n onChange={(e) => setSessionId(e.target.value)}\n required\n />\n <span className=\"mt-1 block text-xs text-gray-500\">\n 后台模式下用于追踪;建议保留默认或自定义一个可识别值\n </span>\n </label>\n\n <div>\n <span className=\"text-gray-700\">执行模式</span>\n <div className=\"mt-2 grid grid-cols-2 gap-2\">\n <button\n type=\"button\"\n onClick={() => setMode('background')}\n className={clsx(\n 'rounded-md border px-3 py-2 text-left',\n mode === 'background'\n ? 'border-indigo-500 bg-indigo-50'\n : 'border-gray-200 hover:border-gray-300',\n authMissing && 'ring-1 ring-amber-200'\n )}\n >\n <div className=\"flex items-center gap-2 font-medium text-gray-900\">\n <Cpu className=\"h-4 w-4 text-purple-600\" /> 后台\n {authMissing && (\n <span className=\"ml-auto text-[10px] font-normal text-amber-700 bg-amber-100 px-1.5 py-0.5 rounded\">\n 需先配置 API\n </span>\n )}\n </div>\n <p className=\"text-xs text-gray-500 mt-1\">\n 独立 claude -p 子进程,无需用户在主会话输入\n </p>\n </button>\n <button\n type=\"button\"\n onClick={() => setMode('foreground')}\n className={clsx(\n 'rounded-md border px-3 py-2 text-left',\n mode === 'foreground'\n ? 'border-indigo-500 bg-indigo-50'\n : 'border-gray-200 hover:border-gray-300'\n )}\n >\n <div className=\"flex items-center gap-2 font-medium text-gray-900\">\n <Monitor className=\"h-4 w-4 text-sky-600\" /> 前台\n </div>\n <p className=\"text-xs text-amber-700 mt-1 flex items-start gap-1\">\n <AlertTriangle className=\"h-3.5 w-3.5 mt-0.5 shrink-0\" />\n <span>需要你在主会话里输入任意内容才会推进;期间可用 <code className=\"px-1 rounded bg-amber-50\">/forge methodology status</code> 查看</span>\n </p>\n </button>\n </div>\n </div>\n\n {blockedByAuth && (\n <div className=\"rounded-md border border-amber-300 bg-amber-50 px-3 py-2 text-xs text-amber-800\">\n <div className=\"flex items-start gap-2\">\n <AlertTriangle className=\"h-4 w-4 mt-0.5 shrink-0 text-amber-600\" />\n <div className=\"flex-1 space-y-1\">\n <div className=\"font-medium\">后台模式需要 Claude API 认证</div>\n <div className=\"text-amber-700\">\n 未检测到 <code className=\"px-1 rounded bg-amber-100\">ANTHROPIC_API_KEY</code> 或 OAuth 凭据\n {authStatus?.message ? `(${authStatus.message})` : ''}。\n 请先在 AI 配置页完成设置,或切换到前台模式。\n </div>\n <button\n type=\"button\"\n onClick={onGoToAIConfig}\n className=\"mt-1 inline-flex items-center gap-1 px-2 py-1 text-xs font-medium text-white bg-amber-600 rounded hover:bg-amber-700\"\n >\n 去 AI 配置\n </button>\n </div>\n </div>\n </div>\n )}\n </div>\n\n <div className=\"px-5 py-3 border-t border-gray-100 flex justify-end gap-2\">\n <button\n type=\"button\"\n onClick={onCancel}\n className=\"px-3 py-1.5 text-sm text-gray-700 hover:bg-gray-100 rounded-md\"\n >\n 取消\n </button>\n <button\n type=\"submit\"\n disabled={submitting || !methodologyId || blockedByAuth}\n title={blockedByAuth ? '后台模式需要先配置 Claude API' : undefined}\n className=\"inline-flex items-center gap-1 px-3 py-1.5 text-sm bg-indigo-600 text-white rounded-md hover:bg-indigo-700 disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n {submitting ? '启动中...' : '启动'}\n </button>\n </div>\n </form>\n </div>\n )\n}\n"],"names":["fetchMethodologyExecutions","res","fetchMethodologies","fetchWorkerAuthStatus","cancelExecution","id","authFetch","data","deleteExecution","startExecution","payload","err","methodologyNames","Methodologies","queryClient","useQueryClient","toast","useToast","confirm","useConfirm","navigate","useNavigate","showStart","setShowStart","useState","executions","isLoading","error","useQuery","methodologies","authStatus","cancelMutation","useMutation","e","deleteMutation","startMutation","msg","handleCancel","handleDelete","jsx","jsxs","runningCount","completedCount","Plus","StartExecutionModal","execution","plan","currentPhase","progress","Link","GitBranch","clsx","Cpu","Monitor","Clock","formatDistanceToNow","zhCN","AlertCircle","CheckCircle","XCircle","StopCircle","Trash2","submitting","onSubmit","onCancel","onGoToAIConfig","defaultSession","sessionId","setSessionId","methodologyId","setMethodologyId","_a","mode","setMode","authMissing","blockedByAuth","submit","m","AlertTriangle"],"mappings":"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"}
|
package/dist/web/static/assets/{MethodologyDetail-Do1taSKM.js → MethodologyDetail-rV3W1utf.js}
RENAMED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{j as e,r as N}from"./react-vendor-CSp-GLFF.js";import{c as M,L as b}from"./react-router-I-HqunH7.js";import{u as S}from"./query-C99w429o.js";import{d as x}from"./vendor-CMMjVdZs.js";import{q as w,j as v,C as H,n as A,A as L,c as _,e as q,r as D,g as F,U as P,s as k}from"./lucide-DjB4fWNj.js";import{f as y,a as R,z as $}from"./date-fns-CZ_bHujz.js";async function z(l){const s=await fetch(`/api/methodology-executions/${l}`);if(!s.ok)throw new Error("Failed to fetch");return s.json()}const B={"harness-engineering":"Harness Engineering",bmad:"BMad (敏捷开发)"};function Q(){const{id:l}=M(),{data:s,isLoading:u,error:m}=S({queryKey:["methodology-execution",l],queryFn:()=>z(l),enabled:!!l,refetchInterval:t=>{const n=t.state.data;return(n==null?void 0:n.status)==="running"?3e3:!1}}),i=J(l,(s==null?void 0:s.status)==="running");if(u)return e.jsx("div",{className:"flex items-center justify-center py-12",children:e.jsx(w,{className:"h-8 w-8 animate-spin text-indigo-600"})});if(m||!s)return e.jsxs("div",{className:"bg-white rounded-lg shadow p-6",children:[e.jsxs("p",{className:"text-red-600",children:["加载失败: ",(m==null?void 0:m.message)||"未知错误"]}),e.jsxs(b,{to:"/methodologies",className:"mt-4 inline-flex items-center text-indigo-600 hover:text-indigo-700",children:[e.jsx(v,{className:"h-4 w-4 mr-1"}),"返回列表"]})]});const{plan:d,phases:j,current_phase_index:c,status:r}=s,g=r==="completed"?100:Math.round(c/d.phases.length*100);return e.jsxs("div",{children:[e.jsxs("div",{className:"mb-6",children:[e.jsxs(b,{to:"/methodologies",className:"inline-flex items-center text-sm text-gray-500 hover:text-gray-700 mb-4",children:[e.jsx(v,{className:"h-4 w-4 mr-1"}),"返回列表"]}),e.jsxs("div",{className:"flex items-start justify-between",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"text-2xl font-bold text-gray-900",children:B[s.methodology_id]||s.methodology_id}),e.jsxs("p",{className:"text-sm text-gray-500 mt-1",children:["Session: ",s.session_id]})]}),e.jsxs("span",{className:x("px-3 py-1 text-sm font-medium rounded-full",r==="running"&&"bg-blue-100 text-blue-700",r==="completed"&&"bg-green-100 text-green-700",r==="failed"&&"bg-red-100 text-red-700"),children:[r==="running"&&"运行中",r==="completed"&&"已完成",r==="failed"&&"失败"]})]})]}),e.jsxs("div",{className:"bg-white rounded-lg shadow p-6 mb-6",children:[e.jsxs("div",{className:"flex items-center justify-between mb-2",children:[e.jsx("h3",{className:"text-sm font-medium text-gray-700",children:"执行进度"}),e.jsxs("div",{className:"flex items-center gap-2 text-sm text-gray-500",children:[s.mode&&e.jsxs("span",{className:x("inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-xs",s.mode==="background"?"bg-purple-100 text-purple-700":"bg-sky-100 text-sky-700"),children:[s.mode==="background"?e.jsx(H,{className:"h-3 w-3"}):e.jsx(A,{className:"h-3 w-3"}),s.mode==="background"?"后台":"前台"]}),e.jsxs("span",{children:[g,"%"]})]})]}),e.jsx("div",{className:"w-full bg-gray-200 rounded-full h-2",children:e.jsx("div",{className:x("h-2 rounded-full transition-all duration-500",r==="completed"?"bg-green-500":"bg-indigo-600"),style:{width:`${g}%`}})}),e.jsxs("div",{className:"grid grid-cols-3 gap-4 mt-4 pt-4 border-t",children:[e.jsxs("div",{children:[e.jsx("div",{className:"text-xs text-gray-500",children:"开始时间"}),e.jsx("div",{className:"text-sm font-medium",children:y(s.started_at,"MM-dd HH:mm:ss")})]}),e.jsxs("div",{children:[e.jsx("div",{className:"text-xs text-gray-500",children:"阶段"}),e.jsxs("div",{className:"text-sm font-medium",children:[c+(r==="completed"?0:1)," / ",d.phases.length]})]}),e.jsxs("div",{children:[e.jsx("div",{className:"text-xs text-gray-500",children:r==="completed"?"完成时间":"已运行"}),e.jsx("div",{className:"text-sm font-medium",children:r==="completed"&&s.completed_at?y(s.completed_at,"MM-dd HH:mm:ss"):R(s.started_at,{addSuffix:!1,locale:$})})]})]}),(s.worker_pid||s.worker_session_id)&&e.jsxs("div",{className:"mt-3 pt-3 border-t text-xs text-gray-500 flex gap-4",children:[s.worker_pid?e.jsxs("span",{children:["worker PID: ",e.jsx("span",{className:"font-mono",children:s.worker_pid})]}):null,s.worker_session_id?e.jsxs("span",{children:["worker session: ",e.jsxs("span",{className:"font-mono",children:[String(s.worker_session_id).slice(0,18),"…"]})]}):null]})]}),(r==="running"||i.length>0)&&e.jsxs("div",{className:"bg-white rounded-lg shadow p-6 mb-6",children:[e.jsxs("h3",{className:"flex items-center text-sm font-medium text-gray-700 mb-3",children:[e.jsx(L,{className:"h-4 w-4 mr-2 text-indigo-600"}),"实时事件流",e.jsxs("span",{className:"ml-2 text-xs text-gray-400",children:["(最近 ",i.length," 条)"]})]}),i.length===0?e.jsx("p",{className:"text-xs text-gray-500",children:r==="running"?"等待 worker 输出…":"暂无事件"}):e.jsx("ol",{className:"space-y-1 text-xs font-mono max-h-64 overflow-auto",children:i.map((t,n)=>e.jsxs("li",{className:"flex items-start gap-2",children:[e.jsx("span",{className:"text-gray-400 flex-shrink-0 w-16",children:y(t.timestamp,"HH:mm:ss")}),e.jsx("span",{className:x("px-1.5 rounded text-[10px] font-medium flex-shrink-0",t.type==="phase-start"&&"bg-indigo-100 text-indigo-700",t.type==="phase-finish"&&"bg-green-100 text-green-700",t.type==="phase-log"&&"bg-gray-100 text-gray-700",t.type==="error"&&"bg-red-100 text-red-700",t.type==="done"&&"bg-gray-200 text-gray-700"),children:t.type}),e.jsxs("span",{className:"text-gray-700 truncate",children:[t.phase_id?`phase=${t.phase_id} `:"",t.payload?JSON.stringify(t.payload).slice(0,180):""]})]},n))})]}),e.jsxs("div",{className:"bg-white rounded-lg shadow p-6 mb-6",children:[e.jsxs("h3",{className:"flex items-center text-sm font-medium text-gray-700 mb-3",children:[e.jsx(_,{className:"h-4 w-4 mr-2 text-indigo-600"}),"执行计划 (AI 生成)"]}),e.jsx("p",{className:"text-sm text-gray-600 leading-relaxed",children:d.rationale})]}),e.jsxs("div",{className:"bg-white rounded-lg shadow p-6",children:[e.jsx("h3",{className:"text-lg font-semibold text-gray-900 mb-4",children:"执行阶段"}),e.jsx("div",{className:"space-y-4",children:d.phases.map((t,n)=>{const a=j.find(o=>o.phase_index===n),h=n<c||n===c&&r==="completed"||(a==null?void 0:a.status)==="completed",p=n===c&&r==="running"&&(a==null?void 0:a.status)==="running",f=n>c&&!p;return e.jsxs("div",{className:"relative",children:[n<d.phases.length-1&&e.jsx("div",{className:x("absolute left-4 top-10 w-0.5 h-full -z-10",h?"bg-green-300":"bg-gray-200")}),e.jsxs("div",{className:"flex gap-4",children:[e.jsx("div",{className:"flex-shrink-0",children:h?e.jsx("div",{className:"w-8 h-8 rounded-full bg-green-100 flex items-center justify-center",children:e.jsx(q,{className:"h-5 w-5 text-green-600"})}):p?e.jsx("div",{className:"w-8 h-8 rounded-full bg-blue-100 flex items-center justify-center",children:e.jsx(w,{className:"h-5 w-5 text-blue-600 animate-spin"})}):e.jsx("div",{className:"w-8 h-8 rounded-full bg-gray-100 flex items-center justify-center",children:e.jsx(D,{className:"h-5 w-5 text-gray-400"})})}),e.jsx("div",{className:x("flex-1 pb-4",f&&"opacity-50"),children:e.jsxs("div",{className:"bg-gray-50 rounded-lg p-4 border border-gray-200",children:[e.jsxs("div",{className:"flex items-center justify-between mb-2",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsxs("span",{className:"text-sm font-semibold text-gray-900",children:["阶段 ",n+1,": ",t.id]}),e.jsxs("span",{className:x("px-2 py-0.5 text-xs font-medium rounded",h&&"bg-green-100 text-green-700",p&&"bg-blue-100 text-blue-700",f&&"bg-gray-100 text-gray-600"),children:[h&&"已完成",p&&"运行中",f&&"待执行"]})]}),(a==null?void 0:a.duration_ms)&&e.jsxs("span",{className:"text-xs text-gray-500",children:[e.jsx(F,{className:"inline h-3 w-3 mr-1"}),(a.duration_ms/1e3).toFixed(1),"s"]})]}),e.jsxs("div",{className:"flex items-center gap-2 mb-3 text-xs text-gray-600",children:[e.jsx(P,{className:"h-3 w-3"}),e.jsxs("span",{children:["Agent: ",e.jsx("strong",{children:t.agent})]})]}),e.jsx("p",{className:"text-xs text-gray-500 italic mb-3",children:t.rationale}),e.jsxs("div",{className:"bg-white rounded p-3 border border-gray-200",children:[e.jsxs("div",{className:"flex items-center gap-1 text-xs text-gray-500 mb-1",children:[e.jsx(k,{className:"h-3 w-3"}),"Prompt"]}),e.jsx("p",{className:"text-xs text-gray-700 leading-relaxed",children:t.prompt})]}),t.artifacts&&t.artifacts.length>0&&e.jsxs("div",{className:"mt-3",children:[e.jsx("div",{className:"text-xs text-gray-500 mb-1",children:"预期产物"}),e.jsx("div",{className:"flex flex-wrap gap-1",children:t.artifacts.map((o,C)=>e.jsxs("span",{className:"px-2 py-0.5 text-xs bg-indigo-50 text-indigo-700 rounded",children:[o.pattern||o.type,o.required&&" *"]},C))})]}),(a==null?void 0:a.output_text)&&e.jsxs("details",{className:"mt-3 bg-white rounded border border-gray-200",children:[e.jsxs("summary",{className:"px-3 py-1.5 cursor-pointer text-xs text-gray-600 hover:bg-gray-50",children:[e.jsx(k,{className:"inline h-3 w-3 mr-1"})," 输出(",a.output_text.length," 字符)"]}),e.jsx("pre",{className:"px-3 py-2 text-xs text-gray-800 whitespace-pre-wrap break-words max-h-64 overflow-auto",children:a.output_text})]}),(a==null?void 0:a.error_message)&&e.jsxs("div",{className:"mt-3 bg-red-50 border border-red-200 rounded p-2",children:[e.jsxs("div",{className:"flex items-center gap-1 text-xs font-medium text-red-700 mb-1",children:[e.jsx(_,{className:"h-3 w-3"})," 错误"]}),e.jsx("pre",{className:"text-xs text-red-800 whitespace-pre-wrap break-words",children:a.error_message})]}),(a==null?void 0:a.stream_log_path)&&e.jsxs("div",{className:"mt-2 text-[11px] text-gray-400",children:["日志: ",e.jsx("span",{className:"font-mono",children:a.stream_log_path})]})]})})]})]},n)})})]})]})}function J(l,s){const[u,m]=N.useState([]),i=N.useRef(null);return N.useEffect(()=>{var c;if(!l||!s){(c=i.current)==null||c.close(),i.current=null;return}const d=new EventSource(`/api/methodology-executions/events?execution_id=${l}`);i.current=d;const j=r=>{try{const g=JSON.parse(r.data);m(t=>{const n=[...t,g];return n.length>100&&n.splice(0,n.length-100),n})}catch{}};return["phase-start","phase-log","phase-finish","done","error"].forEach(r=>{d.addEventListener(r,j)}),()=>{d.close(),i.current=null}},[l,s]),u}export{Q as default};
|
|
2
|
-
//# sourceMappingURL=MethodologyDetail-
|
|
1
|
+
import{j as e,r as N}from"./react-vendor-CSp-GLFF.js";import{c as M,L as b}from"./react-router-I-HqunH7.js";import{u as S}from"./query-C99w429o.js";import{d as x}from"./vendor-CMMjVdZs.js";import{p as w,j as v,C as H,m as A,A as L,c as _,e as q,q as D,g as F,U as P,r as k}from"./lucide-BanPULT1.js";import{f as y,a as R,z as $}from"./date-fns-CZ_bHujz.js";async function z(l){const s=await fetch(`/api/methodology-executions/${l}`);if(!s.ok)throw new Error("Failed to fetch");return s.json()}const B={"harness-engineering":"Harness Engineering",bmad:"BMad (敏捷开发)"};function Q(){const{id:l}=M(),{data:s,isLoading:u,error:m}=S({queryKey:["methodology-execution",l],queryFn:()=>z(l),enabled:!!l,refetchInterval:t=>{const n=t.state.data;return(n==null?void 0:n.status)==="running"?3e3:!1}}),i=J(l,(s==null?void 0:s.status)==="running");if(u)return e.jsx("div",{className:"flex items-center justify-center py-12",children:e.jsx(w,{className:"h-8 w-8 animate-spin text-indigo-600"})});if(m||!s)return e.jsxs("div",{className:"bg-white rounded-lg shadow p-6",children:[e.jsxs("p",{className:"text-red-600",children:["加载失败: ",(m==null?void 0:m.message)||"未知错误"]}),e.jsxs(b,{to:"/methodologies",className:"mt-4 inline-flex items-center text-indigo-600 hover:text-indigo-700",children:[e.jsx(v,{className:"h-4 w-4 mr-1"}),"返回列表"]})]});const{plan:d,phases:j,current_phase_index:c,status:r}=s,g=r==="completed"?100:Math.round(c/d.phases.length*100);return e.jsxs("div",{children:[e.jsxs("div",{className:"mb-6",children:[e.jsxs(b,{to:"/methodologies",className:"inline-flex items-center text-sm text-gray-500 hover:text-gray-700 mb-4",children:[e.jsx(v,{className:"h-4 w-4 mr-1"}),"返回列表"]}),e.jsxs("div",{className:"flex items-start justify-between",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"text-2xl font-bold text-gray-900",children:B[s.methodology_id]||s.methodology_id}),e.jsxs("p",{className:"text-sm text-gray-500 mt-1",children:["Session: ",s.session_id]})]}),e.jsxs("span",{className:x("px-3 py-1 text-sm font-medium rounded-full",r==="running"&&"bg-blue-100 text-blue-700",r==="completed"&&"bg-green-100 text-green-700",r==="failed"&&"bg-red-100 text-red-700"),children:[r==="running"&&"运行中",r==="completed"&&"已完成",r==="failed"&&"失败"]})]})]}),e.jsxs("div",{className:"bg-white rounded-lg shadow p-6 mb-6",children:[e.jsxs("div",{className:"flex items-center justify-between mb-2",children:[e.jsx("h3",{className:"text-sm font-medium text-gray-700",children:"执行进度"}),e.jsxs("div",{className:"flex items-center gap-2 text-sm text-gray-500",children:[s.mode&&e.jsxs("span",{className:x("inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-xs",s.mode==="background"?"bg-purple-100 text-purple-700":"bg-sky-100 text-sky-700"),children:[s.mode==="background"?e.jsx(H,{className:"h-3 w-3"}):e.jsx(A,{className:"h-3 w-3"}),s.mode==="background"?"后台":"前台"]}),e.jsxs("span",{children:[g,"%"]})]})]}),e.jsx("div",{className:"w-full bg-gray-200 rounded-full h-2",children:e.jsx("div",{className:x("h-2 rounded-full transition-all duration-500",r==="completed"?"bg-green-500":"bg-indigo-600"),style:{width:`${g}%`}})}),e.jsxs("div",{className:"grid grid-cols-3 gap-4 mt-4 pt-4 border-t",children:[e.jsxs("div",{children:[e.jsx("div",{className:"text-xs text-gray-500",children:"开始时间"}),e.jsx("div",{className:"text-sm font-medium",children:y(s.started_at,"MM-dd HH:mm:ss")})]}),e.jsxs("div",{children:[e.jsx("div",{className:"text-xs text-gray-500",children:"阶段"}),e.jsxs("div",{className:"text-sm font-medium",children:[c+(r==="completed"?0:1)," / ",d.phases.length]})]}),e.jsxs("div",{children:[e.jsx("div",{className:"text-xs text-gray-500",children:r==="completed"?"完成时间":"已运行"}),e.jsx("div",{className:"text-sm font-medium",children:r==="completed"&&s.completed_at?y(s.completed_at,"MM-dd HH:mm:ss"):R(s.started_at,{addSuffix:!1,locale:$})})]})]}),(s.worker_pid||s.worker_session_id)&&e.jsxs("div",{className:"mt-3 pt-3 border-t text-xs text-gray-500 flex gap-4",children:[s.worker_pid?e.jsxs("span",{children:["worker PID: ",e.jsx("span",{className:"font-mono",children:s.worker_pid})]}):null,s.worker_session_id?e.jsxs("span",{children:["worker session: ",e.jsxs("span",{className:"font-mono",children:[String(s.worker_session_id).slice(0,18),"…"]})]}):null]})]}),(r==="running"||i.length>0)&&e.jsxs("div",{className:"bg-white rounded-lg shadow p-6 mb-6",children:[e.jsxs("h3",{className:"flex items-center text-sm font-medium text-gray-700 mb-3",children:[e.jsx(L,{className:"h-4 w-4 mr-2 text-indigo-600"}),"实时事件流",e.jsxs("span",{className:"ml-2 text-xs text-gray-400",children:["(最近 ",i.length," 条)"]})]}),i.length===0?e.jsx("p",{className:"text-xs text-gray-500",children:r==="running"?"等待 worker 输出…":"暂无事件"}):e.jsx("ol",{className:"space-y-1 text-xs font-mono max-h-64 overflow-auto",children:i.map((t,n)=>e.jsxs("li",{className:"flex items-start gap-2",children:[e.jsx("span",{className:"text-gray-400 flex-shrink-0 w-16",children:y(t.timestamp,"HH:mm:ss")}),e.jsx("span",{className:x("px-1.5 rounded text-[10px] font-medium flex-shrink-0",t.type==="phase-start"&&"bg-indigo-100 text-indigo-700",t.type==="phase-finish"&&"bg-green-100 text-green-700",t.type==="phase-log"&&"bg-gray-100 text-gray-700",t.type==="error"&&"bg-red-100 text-red-700",t.type==="done"&&"bg-gray-200 text-gray-700"),children:t.type}),e.jsxs("span",{className:"text-gray-700 truncate",children:[t.phase_id?`phase=${t.phase_id} `:"",t.payload?JSON.stringify(t.payload).slice(0,180):""]})]},n))})]}),e.jsxs("div",{className:"bg-white rounded-lg shadow p-6 mb-6",children:[e.jsxs("h3",{className:"flex items-center text-sm font-medium text-gray-700 mb-3",children:[e.jsx(_,{className:"h-4 w-4 mr-2 text-indigo-600"}),"执行计划 (AI 生成)"]}),e.jsx("p",{className:"text-sm text-gray-600 leading-relaxed",children:d.rationale})]}),e.jsxs("div",{className:"bg-white rounded-lg shadow p-6",children:[e.jsx("h3",{className:"text-lg font-semibold text-gray-900 mb-4",children:"执行阶段"}),e.jsx("div",{className:"space-y-4",children:d.phases.map((t,n)=>{const a=j.find(o=>o.phase_index===n),h=n<c||n===c&&r==="completed"||(a==null?void 0:a.status)==="completed",p=n===c&&r==="running"&&(a==null?void 0:a.status)==="running",f=n>c&&!p;return e.jsxs("div",{className:"relative",children:[n<d.phases.length-1&&e.jsx("div",{className:x("absolute left-4 top-10 w-0.5 h-full -z-10",h?"bg-green-300":"bg-gray-200")}),e.jsxs("div",{className:"flex gap-4",children:[e.jsx("div",{className:"flex-shrink-0",children:h?e.jsx("div",{className:"w-8 h-8 rounded-full bg-green-100 flex items-center justify-center",children:e.jsx(q,{className:"h-5 w-5 text-green-600"})}):p?e.jsx("div",{className:"w-8 h-8 rounded-full bg-blue-100 flex items-center justify-center",children:e.jsx(w,{className:"h-5 w-5 text-blue-600 animate-spin"})}):e.jsx("div",{className:"w-8 h-8 rounded-full bg-gray-100 flex items-center justify-center",children:e.jsx(D,{className:"h-5 w-5 text-gray-400"})})}),e.jsx("div",{className:x("flex-1 pb-4",f&&"opacity-50"),children:e.jsxs("div",{className:"bg-gray-50 rounded-lg p-4 border border-gray-200",children:[e.jsxs("div",{className:"flex items-center justify-between mb-2",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsxs("span",{className:"text-sm font-semibold text-gray-900",children:["阶段 ",n+1,": ",t.id]}),e.jsxs("span",{className:x("px-2 py-0.5 text-xs font-medium rounded",h&&"bg-green-100 text-green-700",p&&"bg-blue-100 text-blue-700",f&&"bg-gray-100 text-gray-600"),children:[h&&"已完成",p&&"运行中",f&&"待执行"]})]}),(a==null?void 0:a.duration_ms)&&e.jsxs("span",{className:"text-xs text-gray-500",children:[e.jsx(F,{className:"inline h-3 w-3 mr-1"}),(a.duration_ms/1e3).toFixed(1),"s"]})]}),e.jsxs("div",{className:"flex items-center gap-2 mb-3 text-xs text-gray-600",children:[e.jsx(P,{className:"h-3 w-3"}),e.jsxs("span",{children:["Agent: ",e.jsx("strong",{children:t.agent})]})]}),e.jsx("p",{className:"text-xs text-gray-500 italic mb-3",children:t.rationale}),e.jsxs("div",{className:"bg-white rounded p-3 border border-gray-200",children:[e.jsxs("div",{className:"flex items-center gap-1 text-xs text-gray-500 mb-1",children:[e.jsx(k,{className:"h-3 w-3"}),"Prompt"]}),e.jsx("p",{className:"text-xs text-gray-700 leading-relaxed",children:t.prompt})]}),t.artifacts&&t.artifacts.length>0&&e.jsxs("div",{className:"mt-3",children:[e.jsx("div",{className:"text-xs text-gray-500 mb-1",children:"预期产物"}),e.jsx("div",{className:"flex flex-wrap gap-1",children:t.artifacts.map((o,C)=>e.jsxs("span",{className:"px-2 py-0.5 text-xs bg-indigo-50 text-indigo-700 rounded",children:[o.pattern||o.type,o.required&&" *"]},C))})]}),(a==null?void 0:a.output_text)&&e.jsxs("details",{className:"mt-3 bg-white rounded border border-gray-200",children:[e.jsxs("summary",{className:"px-3 py-1.5 cursor-pointer text-xs text-gray-600 hover:bg-gray-50",children:[e.jsx(k,{className:"inline h-3 w-3 mr-1"})," 输出(",a.output_text.length," 字符)"]}),e.jsx("pre",{className:"px-3 py-2 text-xs text-gray-800 whitespace-pre-wrap break-words max-h-64 overflow-auto",children:a.output_text})]}),(a==null?void 0:a.error_message)&&e.jsxs("div",{className:"mt-3 bg-red-50 border border-red-200 rounded p-2",children:[e.jsxs("div",{className:"flex items-center gap-1 text-xs font-medium text-red-700 mb-1",children:[e.jsx(_,{className:"h-3 w-3"})," 错误"]}),e.jsx("pre",{className:"text-xs text-red-800 whitespace-pre-wrap break-words",children:a.error_message})]}),(a==null?void 0:a.stream_log_path)&&e.jsxs("div",{className:"mt-2 text-[11px] text-gray-400",children:["日志: ",e.jsx("span",{className:"font-mono",children:a.stream_log_path})]})]})})]})]},n)})})]})]})}function J(l,s){const[u,m]=N.useState([]),i=N.useRef(null);return N.useEffect(()=>{var c;if(!l||!s){(c=i.current)==null||c.close(),i.current=null;return}const d=new EventSource(`/api/methodology-executions/events?execution_id=${l}`);i.current=d;const j=r=>{try{const g=JSON.parse(r.data);m(t=>{const n=[...t,g];return n.length>100&&n.splice(0,n.length-100),n})}catch{}};return["phase-start","phase-log","phase-finish","done","error"].forEach(r=>{d.addEventListener(r,j)}),()=>{d.close(),i.current=null}},[l,s]),u}export{Q as default};
|
|
2
|
+
//# sourceMappingURL=MethodologyDetail-rV3W1utf.js.map
|