@jagreehal/workflow 1.6.0 → 1.7.0
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/README.md +255 -19
- package/dist/core.cjs +1 -1
- package/dist/core.cjs.map +1 -1
- package/dist/core.d.cts +60 -7
- package/dist/core.d.ts +60 -7
- package/dist/core.js +1 -1
- package/dist/core.js.map +1 -1
- package/dist/index.cjs +5 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +5 -5
- package/dist/index.js.map +1 -1
- package/dist/visualize.cjs +1188 -6
- package/dist/visualize.cjs.map +1 -1
- package/dist/visualize.d.cts +467 -1
- package/dist/visualize.d.ts +467 -1
- package/dist/visualize.js +1188 -6
- package/dist/visualize.js.map +1 -1
- package/dist/workflow.cjs +1 -1
- package/dist/workflow.cjs.map +1 -1
- package/dist/workflow.d.cts +50 -0
- package/dist/workflow.d.ts +50 -0
- package/dist/workflow.js +1 -1
- package/dist/workflow.js.map +1 -1
- package/docs/advanced.md +368 -3
- package/package.json +1 -1
package/dist/visualize.cjs
CHANGED
|
@@ -1,7 +1,1189 @@
|
|
|
1
|
-
"use strict";var X=Object.defineProperty;var fe=Object.getOwnPropertyDescriptor;var he=Object.getOwnPropertyNames;var me=Object.prototype.hasOwnProperty;var ge=(e,n)=>{for(var t in n)X(e,t,{get:n[t],enumerable:!0})},$e=(e,n,t,r)=>{if(n&&typeof n=="object"||typeof n=="function")for(let s of he(n))!me.call(e,s)&&s!==t&&X(e,s,{get:()=>n[s],enumerable:!(r=fe(n,s))||r.enumerable});return e};var ke=e=>$e(X({},"__esModule",{value:!0}),e);var Ae={};ge(Ae,{asciiRenderer:()=>W,createEventCollector:()=>Ve,createIRBuilder:()=>F,createLiveVisualizer:()=>le,createParallelDetector:()=>re,createVisualizer:()=>H,defaultColorScheme:()=>M,detectParallelGroups:()=>z,hasChildren:()=>Se,isDecisionNode:()=>A,isParallelNode:()=>P,isRaceNode:()=>V,isSequenceNode:()=>ye,isStepNode:()=>C,mermaidRenderer:()=>j,trackDecision:()=>Y,trackIf:()=>ue,trackSwitch:()=>pe,visualizeEvents:()=>Pe});module.exports=ke(Ae);function N(e){if(e<1e3)return`${Math.round(e)}ms`;if(e<6e4)return`${(e/1e3).toFixed(1).replace(/\.0$/,"")}s`;let n=Math.floor(e/6e4),t=Math.round(e%6e4/1e3);return t===0?`${n}m`:`${n}m ${t}s`}function Q(){return`node_${Date.now()}_${Math.random().toString(36).slice(2,8)}`}function we(e){for(let n of e)if((n.type==="parallel"||n.type==="race"||n.type==="sequence")&&!n.id.startsWith("detected_")||"decisionId"in n)return!0;return!1}function z(e,n={}){if(we(e))return e;let{minOverlapMs:t=0,maxGapMs:r=5}=n,s=[],o=[];for(let c=0;c<e.length;c++){let a=e[c];a.type==="step"&&a.startTs!==void 0?s.push({node:a,startTs:a.startTs,endTs:a.endTs??a.startTs+(a.durationMs??0),originalIndex:c}):o.push({node:a,originalIndex:c})}if(s.length<=1)return e;s.sort((c,a)=>c.startTs-a.startTs);let u=[],h=[s[0]];for(let c=1;c<s.length;c++){let a=s[c],l=Math.min(...h.map(y=>y.startTs)),g=Math.max(...h.map(y=>y.endTs)),$=a.startTs<=l+r,k=a.startTs<g;if(!$&&!k){u.push(h),h=[a];continue}let w=k?Math.min(a.endTs,g)-a.startTs:0;$||w>=t?h.push(a):(u.push(h),h=[a])}u.push(h);let p=[];for(let c of u){let a=Math.min(...c.map(l=>l.originalIndex));if(c.length===1)p.push({node:c[0].node,position:a});else{let l=c.map(w=>w.node),g=Math.min(...c.map(w=>w.startTs)),$=Math.max(...c.map(w=>w.endTs)),k={type:"parallel",id:`detected_parallel_${g}`,name:`${l.length} parallel steps`,state:be(l),mode:"all",children:l,startTs:g,endTs:$,durationMs:$-g};p.push({node:k,position:a})}}for(let{node:c,originalIndex:a}of o)p.push({node:c,position:a});return p.sort((c,a)=>c.position-a.position),p.map(c=>c.node)}function be(e){return e.some(o=>o.state==="error")?"error":e.some(o=>o.state==="running")?"running":e.some(o=>o.state==="pending")?"pending":(e.every(o=>o.state==="success"||o.state==="cached"),"success")}function re(e={}){return{detect:n=>z(n,e)}}function F(e={}){let{detectParallel:n=!0,parallelDetection:t}=e,r,s,o="pending",u,h,p=new Map,c=[],a=[],l=[],g=Date.now(),$=g;function k(i){return i.stepId??i.stepKey??i.name??Q()}function w(i){if(a.length>0){let d=a[a.length-1];for(let E of d.branches.values())if(E.taken){E.children.push(i),$=Date.now();return}let m=Array.from(d.branches.values())[0];if(m){m.children.push(i),$=Date.now();return}}c.length>0?c[c.length-1].children.push(i):l.push(i),$=Date.now()}function y(i){switch(i.type){case"workflow_start":r=i.workflowId,s=i.ts,o="running",g=Date.now(),$=g;break;case"workflow_success":o="success",h=i.durationMs,$=Date.now();break;case"workflow_error":o="error",u=i.error,h=i.durationMs,$=Date.now();break;case"step_start":{let d=k(i);p.set(d,{id:d,name:i.name,key:i.stepKey,startTs:i.ts,retryCount:0,timedOut:!1}),$=Date.now();break}case"step_success":{let d=k(i),m=p.get(d);if(m){let E={type:"step",id:m.id,name:m.name,key:m.key,state:"success",startTs:m.startTs,endTs:i.ts,durationMs:i.durationMs,...m.retryCount>0&&{retryCount:m.retryCount},...m.timedOut&&{timedOut:!0,timeoutMs:m.timeoutMs}};w(E),p.delete(d)}break}case"step_error":{let d=k(i),m=p.get(d);if(m){let E={type:"step",id:m.id,name:m.name,key:m.key,state:"error",startTs:m.startTs,endTs:i.ts,durationMs:i.durationMs,error:i.error,...m.retryCount>0&&{retryCount:m.retryCount},...m.timedOut&&{timedOut:!0,timeoutMs:m.timeoutMs}};w(E),p.delete(d)}break}case"step_aborted":{let d=k(i),m=p.get(d);if(m){let E={type:"step",id:m.id,name:m.name,key:m.key,state:"aborted",startTs:m.startTs,endTs:i.ts,durationMs:i.durationMs,...m.retryCount>0&&{retryCount:m.retryCount},...m.timedOut&&{timedOut:!0,timeoutMs:m.timeoutMs}};w(E),p.delete(d)}break}case"step_cache_hit":{let m={type:"step",id:k(i),name:i.name,key:i.stepKey,state:"cached",startTs:i.ts,endTs:i.ts,durationMs:0};w(m);break}case"step_cache_miss":break;case"step_complete":break;case"step_timeout":{let d=k(i),m=p.get(d);m&&(m.timedOut=!0,m.timeoutMs=i.timeoutMs),$=Date.now();break}case"step_retry":{let d=k(i),m=p.get(d);m&&(m.retryCount=(i.attempt??1)-1),$=Date.now();break}case"step_retries_exhausted":$=Date.now();break;case"step_skipped":{let m={type:"step",id:k(i),name:i.name,key:i.stepKey,state:"skipped",startTs:i.ts,endTs:i.ts,durationMs:0};w(m);break}}}function x(i){if(i.type==="scope_start")c.push({id:i.scopeId,name:i.name,type:i.scopeType,startTs:i.ts,children:[]}),$=Date.now();else if(i.type==="scope_end"){let d=c.pop();if(d){let m=d.type==="race"?{type:"race",id:d.id,name:d.name,state:R(d.children),startTs:d.startTs,endTs:i.ts,durationMs:i.durationMs,children:d.children,winnerId:i.winnerId}:{type:"parallel",id:d.id,name:d.name,state:R(d.children),startTs:d.startTs,endTs:i.ts,durationMs:i.durationMs,children:d.children,mode:d.type==="allSettled"?"allSettled":"all"};w(m)}}}function T(i){if(i.type==="decision_start")a.push({id:i.decisionId,name:i.name,condition:i.condition,decisionValue:i.decisionValue,startTs:i.ts,branches:new Map}),$=Date.now();else if(i.type==="decision_branch"){let d=a[a.length-1];if(d&&d.id===i.decisionId){let m=i.branchLabel,E=d.branches.get(m);E?E.taken=i.taken:d.branches.set(m,{label:i.branchLabel,condition:i.condition,taken:i.taken,children:[]}),$=Date.now()}}else if(i.type==="decision_end"){let d=a.pop();if(d&&d.id===i.decisionId){let m=Array.from(d.branches.values()),E={type:"decision",id:d.id,name:d.name,state:R(m.flatMap(I=>I.taken?I.children:[])),startTs:d.startTs,endTs:i.ts,durationMs:i.durationMs,condition:d.condition,decisionValue:d.decisionValue,branchTaken:i.branchTaken??d.branchTaken,branches:m};w(E)}}}function R(i){return i.length===0?"success":i.some(I=>I.state==="error")?"error":i.every(I=>I.state==="success"||I.state==="cached")?"success":i.some(I=>I.state==="running")?"running":"pending"}function b(){let i=[...l];for(let[,d]of p)i.push({type:"step",id:d.id,name:d.name,key:d.key,state:"running",startTs:d.startTs,...d.retryCount>0&&{retryCount:d.retryCount},...d.timedOut&&{timedOut:!0,timeoutMs:d.timeoutMs}});return i}function O(){let i=b();return n&&(i=z(i,t)),{root:{type:"workflow",id:r??Q(),workflowId:r??"unknown",state:o,startTs:s,durationMs:h,children:i,error:u},metadata:{createdAt:g,lastUpdatedAt:$}}}function B(){r=void 0,s=void 0,o="pending",u=void 0,h=void 0,p.clear(),c.length=0,a.length=0,l=[],g=Date.now(),$=g}return{handleEvent:y,handleScopeEvent:x,handleDecisionEvent:T,getIR:O,reset:B,get hasActiveSteps(){return p.size>0},get state(){return o}}}function C(e){return e.type==="step"}function ye(e){return e.type==="sequence"}function P(e){return e.type==="parallel"}function V(e){return e.type==="race"}function A(e){return e.type==="decision"}function Se(e){return"children"in e||e.type==="decision"&&"branches"in e}var ee="\x1B[0m",ve="\x1B[1m",ie="\x1B[2m",Ee="\x1B[31m",xe="\x1B[32m",De="\x1B[33m",Ie="\x1B[34m",oe="\x1B[90m",Ne="\x1B[37m";function q(e,n){return n?`${n}${e}${ee}`:e}function G(e){return`${ve}${e}${ee}`}function v(e){return`${ie}${e}${ee}`}var M={pending:Ne,running:De,success:xe,error:Ee,aborted:oe,cached:Ie,skipped:ie+oe};function Te(e){switch(e){case"pending":return"\u25CB";case"running":return"\u27F3";case"success":return"\u2713";case"error":return"\u2717";case"aborted":return"\u2298";case"cached":return"\u21BA";case"skipped":return"\u2298"}}function U(e,n){let t=Te(e);return q(t,n[e])}function te(e,n,t){return q(e,t[n])}function se(e){return e.replace(/\x1b\[[0-9;]*m/g,"")}var f={topLeft:"\u250C",topRight:"\u2510",bottomLeft:"\u2514",bottomRight:"\u2518",horizontal:"\u2500",vertical:"\u2502",teeRight:"\u251C",teeLeft:"\u2524",teeDown:"\u252C",teeUp:"\u2534",cross:"\u253C"};function ae(e,n){let t=se(e).length,r=Math.max(0,n-t);return e+" ".repeat(r)}function Re(e,n){if(!n)return f.horizontal.repeat(e);let t=` ${n} `,r=e-t.length;if(r<4)return f.horizontal.repeat(e);let s=2,o=r-s;return f.horizontal.repeat(s)+t+f.horizontal.repeat(o)}function W(){return{name:"ascii",supportsLive:!0,render(e,n){let t={...M,...n.colors},r=n.terminalWidth??60,s=r-4,o=[],u=e.root.name??"workflow",h=G(u);o.push(`${f.topLeft}${Re(r-2,h)}${f.topRight}`),o.push(`${f.vertical}${" ".repeat(r-2)}${f.vertical}`);let p=J(e.root.children,n,t,0);for(let c of p)o.push(`${f.vertical} ${ae(c,s)}${f.vertical}`);if(o.push(`${f.vertical}${" ".repeat(r-2)}${f.vertical}`),e.root.durationMs!==void 0&&n.showTimings){let c=e.root.state==="success"?"Completed":"Failed",l=`${te(c,e.root.state,t)} in ${N(e.root.durationMs)}`;o.push(`${f.vertical} ${ae(l,s)}${f.vertical}`),o.push(`${f.vertical}${" ".repeat(r-2)}${f.vertical}`)}return o.push(`${f.bottomLeft}${f.horizontal.repeat(r-2)}${f.bottomRight}`),o.join(`
|
|
2
|
-
`)}}}function J(e,n,t,r){let s=[];for(let o of e)C(o)?s.push(ne(o,n,t)):P(o)?s.push(...Oe(o,n,t,r)):V(o)?s.push(...Me(o,n,t,r)):A(o)&&s.push(...Ce(o,n,t,r));return s}function ne(e,n,t){let r=U(e.state,t),s=e.name??e.key??"step",o=te(s,e.state,t),u=`${r} ${o}`;if(n.showKeys&&e.key&&(u+=v(` [key: ${e.key}]`)),e.input!==void 0){let h=typeof e.input=="string"?e.input:JSON.stringify(e.input).slice(0,30);u+=v(` [in: ${h}${h.length>=30?"...":""}]`)}if(e.output!==void 0&&e.state==="success"){let h=typeof e.output=="string"?e.output:JSON.stringify(e.output).slice(0,30);u+=v(` [out: ${h}${h.length>=30?"...":""}]`)}if(n.showTimings&&e.durationMs!==void 0&&(u+=v(` [${N(e.durationMs)}]`)),e.retryCount!==void 0&&e.retryCount>0&&(u+=v(` [${e.retryCount} ${e.retryCount===1?"retry":"retries"}]`)),e.timedOut){let h=e.timeoutMs!==void 0?` ${e.timeoutMs}ms`:"";u+=v(` [timeout${h}]`)}return u}function Oe(e,n,t,r){let s=[],o=" ".repeat(r),u=U(e.state,t),h=e.name??"parallel",p=e.mode==="allSettled"?" (allSettled)":"";if(s.push(`${o}${f.teeRight}${f.teeDown}${f.horizontal} ${u} ${G(h)}${p}`),e.children.length===0)s.push(`${o}${f.vertical} ${v("(operations not individually tracked)")}`),s.push(`${o}${f.vertical} ${v("(wrap each operation with step() to see individual steps)")}`);else for(let c=0;c<e.children.length;c++){let a=e.children[c],g=c===e.children.length-1?`${o}${f.vertical} ${f.bottomLeft}`:`${o}${f.vertical} ${f.teeRight}`;if(C(a))s.push(`${g} ${ne(a,n,t)}`);else{let $=J([a],n,t,r+1);for(let k of $)s.push(`${o}${f.vertical} ${k}`)}}return n.showTimings&&e.durationMs!==void 0&&s.push(`${o}${f.bottomLeft}${f.horizontal}${f.horizontal} ${v(`[${N(e.durationMs)}]`)}`),s}function Me(e,n,t,r){let s=[],o=" ".repeat(r),u=U(e.state,t),h=e.name??"race";if(s.push(`${o}${f.teeRight}\u26A1 ${u} ${G(h)}`),e.children.length===0)s.push(`${o}${f.vertical} ${v("(operations not individually tracked)")}`),s.push(`${o}${f.vertical} ${v("(wrap each operation with step() to see individual steps)")}`);else for(let p=0;p<e.children.length;p++){let c=e.children[p],l=p===e.children.length-1?`${o}${f.vertical} ${f.bottomLeft}`:`${o}${f.vertical} ${f.teeRight}`,$=e.winnerId&&c.id===e.winnerId?v(" (winner)"):"";if(C(c))s.push(`${l} ${ne(c,n,t)}${$}`);else{let k=J([c],n,t,r+1);for(let w of k)s.push(`${o}${f.vertical} ${w}`)}}return n.showTimings&&e.durationMs!==void 0&&s.push(`${o}${f.bottomLeft}${f.horizontal}${f.horizontal} ${v(`[${N(e.durationMs)}]`)}`),s}function Ce(e,n,t,r){let s=[],o=" ".repeat(r),u=U(e.state,t),h=e.name??"decision",p=e.condition?v(` (${e.condition})`):"",c=e.decisionValue!==void 0?v(` = ${String(e.decisionValue)}`):"",a=e.branchTaken!==void 0?v(` \u2192 ${String(e.branchTaken)}`):"";s.push(`${o}${f.teeRight}${f.teeDown}${f.horizontal} ${u} ${G(h)}${p}${c}${a}`);for(let l=0;l<e.branches.length;l++){let g=e.branches[l],k=l===e.branches.length-1?`${o}${f.vertical} ${f.bottomLeft}`:`${o}${f.vertical} ${f.teeRight}`,w=g.taken?"\u2713":"\u2298",y=g.taken?t.success:t.skipped,x=q(`${w} ${g.label}`,y),T=g.condition?v(` (${g.condition})`):"";if(s.push(`${k} ${x}${T}`),g.children.length>0){let R=J(g.children,n,t,r+1);for(let b of R)s.push(`${o}${f.vertical} ${b}`)}else g.taken||s.push(`${o}${f.vertical} ${v("(skipped)")}`)}return n.showTimings&&e.durationMs!==void 0&&s.push(`${o}${f.bottomLeft}${f.horizontal}${f.horizontal} ${v(`[${N(e.durationMs)}]`)}`),s}function _e(){return[" classDef pending fill:#f3f4f6,stroke:#9ca3af,stroke-width:2px,color:#374151"," classDef running fill:#fef3c7,stroke:#f59e0b,stroke-width:3px,color:#92400e"," classDef success fill:#d1fae5,stroke:#10b981,stroke-width:3px,color:#065f46"," classDef error fill:#fee2e2,stroke:#ef4444,stroke-width:3px,color:#991b1b"," classDef aborted fill:#f3f4f6,stroke:#6b7280,stroke-width:2px,color:#4b5563,stroke-dasharray: 5 5"," classDef cached fill:#dbeafe,stroke:#3b82f6,stroke-width:3px,color:#1e40af"," classDef skipped fill:#f9fafb,stroke:#d1d5db,stroke-width:2px,color:#6b7280,stroke-dasharray: 5 5"]}var ce=0;function K(e="node"){return`${e}_${++ce}`}function We(){ce=0}function D(e){return e.replace(/[{}[\]()]/g,"").replace(/[<>]/g,"").replace(/"/g,"'").trim()}function de(e){return D(e).replace(/[[\]]/g,"")}function j(){return{name:"mermaid",supportsLive:!1,render(e,n){We();let t=[];t.push("flowchart TD");let r="start";t.push(` ${r}(("\u25B6 Start"))`);let s=r;for(let o of e.root.children){let u=Z(o,n,t);t.push(` ${s} --> ${u.entryId}`),s=u.exitId}if(e.root.state==="success"||e.root.state==="error"){let o="finish",u=e.root.state==="success"?"\u2713":"\u2717",h=e.root.state==="success"?"Done":"Failed",p=`(("${u} ${h}"))`,c=e.root.state==="success"?":::success":":::error";t.push(` ${o}${p}${c}`),t.push(` ${s} --> ${o}`)}return t.push(""),t.push(..._e()),t.join(`
|
|
3
|
-
`)}}}function
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
"use strict";var Je=Object.create;var ae=Object.defineProperty;var Ye=Object.getOwnPropertyDescriptor;var Xe=Object.getOwnPropertyNames;var Ze=Object.getPrototypeOf,Qe=Object.prototype.hasOwnProperty;var et=(e,n)=>{for(var t in n)ae(e,t,{get:n[t],enumerable:!0})},Ie=(e,n,t,a)=>{if(n&&typeof n=="object"||typeof n=="function")for(let o of Xe(n))!Qe.call(e,o)&&o!==t&&ae(e,o,{get:()=>n[o],enumerable:!(a=Ye(n,o))||a.enumerable});return e};var tt=(e,n,t)=>(t=e!=null?Je(Ze(e)):{},Ie(n||!e||!e.__esModule?ae(t,"default",{value:e,enumerable:!0}):t,e)),nt=e=>Ie(ae({},"__esModule",{value:!0}),e);var Ft={};et(Ft,{asciiRenderer:()=>Z,createDevServer:()=>qe,createEventCollector:()=>zt,createIRBuilder:()=>j,createLiveVisualizer:()=>Ue,createParallelDetector:()=>De,createPerformanceAnalyzer:()=>le,createTimeTravelController:()=>he,createVisualizer:()=>ve,defaultColorScheme:()=>U,detectParallelGroups:()=>te,getHeatLevel:()=>de,hasChildren:()=>at,htmlRenderer:()=>Ve,isDecisionNode:()=>X,isParallelNode:()=>K,isRaceNode:()=>Y,isSequenceNode:()=>it,isStepNode:()=>V,mermaidRenderer:()=>ie,renderToHTML:()=>fe,trackDecision:()=>me,trackIf:()=>je,trackSwitch:()=>Ke,visualizeEvents:()=>At});module.exports=nt(Ft);function H(e){if(e<1e3)return`${Math.round(e)}ms`;if(e<6e4)return`${(e/1e3).toFixed(1).replace(/\.0$/,"")}s`;let n=Math.floor(e/6e4),t=Math.round(e%6e4/1e3);return t===0?`${n}m`:`${n}m ${t}s`}function we(){return`node_${Date.now()}_${Math.random().toString(36).slice(2,8)}`}function rt(e){for(let n of e)if((n.type==="parallel"||n.type==="race"||n.type==="sequence")&&!n.id.startsWith("detected_")||"decisionId"in n)return!0;return!1}function te(e,n={}){if(rt(e))return e;let{minOverlapMs:t=0,maxGapMs:a=5}=n,o=[],r=[];for(let u=0;u<e.length;u++){let s=e[u];s.type==="step"&&s.startTs!==void 0?o.push({node:s,startTs:s.startTs,endTs:s.endTs??s.startTs+(s.durationMs??0),originalIndex:u}):r.push({node:s,originalIndex:u})}if(o.length<=1)return e;o.sort((u,s)=>u.startTs-s.startTs);let c=[],p=[o[0]];for(let u=1;u<o.length;u++){let s=o[u],l=Math.min(...p.map(R=>R.startTs)),f=Math.max(...p.map(R=>R.endTs)),h=s.startTs<=l+a,k=s.startTs<f;if(!h&&!k){c.push(p),p=[s];continue}let v=k?Math.min(s.endTs,f)-s.startTs:0;h||v>=t?p.push(s):(c.push(p),p=[s])}c.push(p);let d=[];for(let u of c){let s=Math.min(...u.map(l=>l.originalIndex));if(u.length===1)d.push({node:u[0].node,position:s});else{let l=u.map(v=>v.node),f=Math.min(...u.map(v=>v.startTs)),h=Math.max(...u.map(v=>v.endTs)),k={type:"parallel",id:`detected_parallel_${f}`,name:`${l.length} parallel steps`,state:ot(l),mode:"all",children:l,startTs:f,endTs:h,durationMs:h-f};d.push({node:k,position:s})}}for(let{node:u,originalIndex:s}of r)d.push({node:u,position:s});return d.sort((u,s)=>u.position-s.position),d.map(u=>u.node)}function ot(e){return e.some(r=>r.state==="error")?"error":e.some(r=>r.state==="running")?"running":e.some(r=>r.state==="pending")?"pending":(e.every(r=>r.state==="success"||r.state==="cached"),"success")}function De(e={}){return{detect:n=>te(n,e)}}function j(e={}){let{detectParallel:n=!0,parallelDetection:t,enableSnapshots:a=!1,maxSnapshots:o=1e3}=e,r,c,p="pending",d,u,s=new Map,l=[],f=[],h=[],k=Date.now(),v=k,R={onAfterStep:new Map},T=[],B=0;function O(i){return i.stepId??i.stepKey??i.name??we()}function g(i){if(f.length>0){let m=f[f.length-1];for(let P of m.branches.values())if(P.taken){P.children.push(i),v=Date.now();return}let b=Array.from(m.branches.values())[0];if(b){b.children.push(i),v=Date.now();return}}l.length>0?l[l.length-1].children.push(i):h.push(i),v=Date.now()}function I(i){if(!a)return;let m=M(),b=new Map;for(let[F,J]of s)b.set(F,{id:J.id,name:J.name,key:J.key,startTs:J.startTs,retryCount:J.retryCount,timedOut:J.timedOut,timeoutMs:J.timeoutMs});let P={id:`snapshot_${B}`,eventIndex:B,event:structuredClone(i),ir:structuredClone(m),timestamp:Date.now(),activeSteps:b};T.push(P),T.length>o&&T.shift(),B++}function w(i){switch(i.type){case"workflow_start":r=i.workflowId,c=i.ts,p="running",k=Date.now(),v=k,R.onAfterStep=new Map;break;case"workflow_success":p="success",u=i.durationMs,v=Date.now();break;case"workflow_error":p="error",d=i.error,u=i.durationMs,v=Date.now();break;case"step_start":{let m=O(i);s.set(m,{id:m,name:i.name,key:i.stepKey,startTs:i.ts,retryCount:0,timedOut:!1}),v=Date.now();break}case"step_success":{let m=O(i),b=s.get(m);if(b){let P={type:"step",id:b.id,name:b.name,key:b.key,state:"success",startTs:b.startTs,endTs:i.ts,durationMs:i.durationMs,...b.retryCount>0&&{retryCount:b.retryCount},...b.timedOut&&{timedOut:!0,timeoutMs:b.timeoutMs}};g(P),s.delete(m)}break}case"step_error":{let m=O(i),b=s.get(m);if(b){let P={type:"step",id:b.id,name:b.name,key:b.key,state:"error",startTs:b.startTs,endTs:i.ts,durationMs:i.durationMs,error:i.error,...b.retryCount>0&&{retryCount:b.retryCount},...b.timedOut&&{timedOut:!0,timeoutMs:b.timeoutMs}};g(P),s.delete(m)}break}case"step_aborted":{let m=O(i),b=s.get(m);if(b){let P={type:"step",id:b.id,name:b.name,key:b.key,state:"aborted",startTs:b.startTs,endTs:i.ts,durationMs:i.durationMs,...b.retryCount>0&&{retryCount:b.retryCount},...b.timedOut&&{timedOut:!0,timeoutMs:b.timeoutMs}};g(P),s.delete(m)}break}case"step_cache_hit":{let b={type:"step",id:O(i),name:i.name,key:i.stepKey,state:"cached",startTs:i.ts,endTs:i.ts,durationMs:0};g(b);break}case"step_cache_miss":break;case"step_complete":break;case"step_timeout":{let m=O(i),b=s.get(m);b&&(b.timedOut=!0,b.timeoutMs=i.timeoutMs),v=Date.now();break}case"step_retry":{let m=O(i),b=s.get(m);b&&(b.retryCount=(i.attempt??1)-1),v=Date.now();break}case"step_retries_exhausted":v=Date.now();break;case"step_skipped":{let b={type:"step",id:O(i),name:i.name,key:i.stepKey,state:"skipped",startTs:i.ts,endTs:i.ts,durationMs:0};g(b);break}case"hook_should_run":{let m={type:"shouldRun",state:"success",ts:i.ts,durationMs:i.durationMs,context:{result:i.result,skipped:i.skipped}};R.shouldRun=m,v=Date.now();break}case"hook_should_run_error":{let m={type:"shouldRun",state:"error",ts:i.ts,durationMs:i.durationMs,error:i.error};R.shouldRun=m,v=Date.now();break}case"hook_before_start":{let m={type:"onBeforeStart",state:"success",ts:i.ts,durationMs:i.durationMs,context:{result:i.result,skipped:i.skipped}};R.onBeforeStart=m,v=Date.now();break}case"hook_before_start_error":{let m={type:"onBeforeStart",state:"error",ts:i.ts,durationMs:i.durationMs,error:i.error};R.onBeforeStart=m,v=Date.now();break}case"hook_after_step":{let m={type:"onAfterStep",state:"success",ts:i.ts,durationMs:i.durationMs,context:{stepKey:i.stepKey}};R.onAfterStep.set(i.stepKey,m),v=Date.now();break}case"hook_after_step_error":{let m={type:"onAfterStep",state:"error",ts:i.ts,durationMs:i.durationMs,error:i.error,context:{stepKey:i.stepKey}};R.onAfterStep.set(i.stepKey,m),v=Date.now();break}}I(i)}function $(i){if(i.type==="scope_start")l.push({id:i.scopeId,name:i.name,type:i.scopeType,startTs:i.ts,children:[]}),v=Date.now();else if(i.type==="scope_end"){let m=l.pop();if(m){let b=m.type==="race"?{type:"race",id:m.id,name:m.name,state:C(m.children),startTs:m.startTs,endTs:i.ts,durationMs:i.durationMs,children:m.children,winnerId:i.winnerId}:{type:"parallel",id:m.id,name:m.name,state:C(m.children),startTs:m.startTs,endTs:i.ts,durationMs:i.durationMs,children:m.children,mode:m.type==="allSettled"?"allSettled":"all"};g(b)}}}function W(i){if(i.type==="decision_start")f.push({id:i.decisionId,name:i.name,condition:i.condition,decisionValue:i.decisionValue,startTs:i.ts,branches:new Map}),v=Date.now();else if(i.type==="decision_branch"){let m=f[f.length-1];if(m&&m.id===i.decisionId){let b=i.branchLabel,P=m.branches.get(b);P?P.taken=i.taken:m.branches.set(b,{label:i.branchLabel,condition:i.condition,taken:i.taken,children:[]}),v=Date.now()}}else if(i.type==="decision_end"){let m=f.pop();if(m&&m.id===i.decisionId){let b=Array.from(m.branches.values()),P={type:"decision",id:m.id,name:m.name,state:C(b.flatMap(F=>F.taken?F.children:[])),startTs:m.startTs,endTs:i.ts,durationMs:i.durationMs,condition:m.condition,decisionValue:m.decisionValue,branchTaken:i.branchTaken??m.branchTaken,branches:b};g(P)}}}function C(i){return i.length===0?"success":i.some(F=>F.state==="error")?"error":i.every(F=>F.state==="success"||F.state==="cached")?"success":i.some(F=>F.state==="running")?"running":"pending"}function D(){let i=[...h];for(let[,m]of s)i.push({type:"step",id:m.id,name:m.name,key:m.key,state:"running",startTs:m.startTs,...m.retryCount>0&&{retryCount:m.retryCount},...m.timedOut&&{timedOut:!0,timeoutMs:m.timeoutMs}});return i}function M(){let i=D();n&&(i=te(i,t));let m={type:"workflow",id:r??we(),workflowId:r??"unknown",state:p,startTs:c,durationMs:u,children:i,error:d},b=R.shouldRun!==void 0||R.onBeforeStart!==void 0||R.onAfterStep.size>0;return{root:m,metadata:{createdAt:k,lastUpdatedAt:v},...b&&{hooks:R}}}function N(){r=void 0,c=void 0,p="pending",d=void 0,u=void 0,s.clear(),l.length=0,f.length=0,h=[],k=Date.now(),v=k,R={onAfterStep:new Map},T.length=0,B=0}function S(){return[...T]}function x(i){return T[i]}function E(i){return T[i]?.ir}function L(){T.length=0,B=0}return{handleEvent:w,handleScopeEvent:$,handleDecisionEvent:W,getIR:M,reset:N,getSnapshots:S,getSnapshotAt:x,getIRAt:E,clearSnapshots:L,get hasActiveSteps(){return s.size>0},get state(){return p},get snapshotCount(){return T.length},get snapshotsEnabled(){return a}}}function V(e){return e.type==="step"}function it(e){return e.type==="sequence"}function K(e){return e.type==="parallel"}function Y(e){return e.type==="race"}function X(e){return e.type==="decision"}function at(e){return"children"in e||e.type==="decision"&&"branches"in e}var be="\x1B[0m",st="\x1B[1m",Ne="\x1B[2m",ct="\x1B[31m",dt="\x1B[32m",lt="\x1B[33m",ut="\x1B[34m",Te="\x1B[90m",pt="\x1B[37m";function G(e,n){return n?`${n}${e}${be}`:e}function ne(e){return`${st}${e}${be}`}function _(e){return`${Ne}${e}${be}`}var U={pending:pt,running:lt,success:dt,error:ct,aborted:Te,cached:ut,skipped:Ne+Te};function ft(e){switch(e){case"pending":return"\u25CB";case"running":return"\u27F3";case"success":return"\u2713";case"error":return"\u2717";case"aborted":return"\u2298";case"cached":return"\u21BA";case"skipped":return"\u2298"}}function re(e,n){let t=ft(e);return G(t,n[e])}function ye(e,n,t){return G(e,t[n])}function Me(e){return e.replace(/\x1b\[[0-9;]*m/g,"")}var y={topLeft:"\u250C",topRight:"\u2510",bottomLeft:"\u2514",bottomRight:"\u2518",horizontal:"\u2500",vertical:"\u2502",teeRight:"\u251C",teeLeft:"\u2524",teeDown:"\u252C",teeUp:"\u2534",cross:"\u253C"},Q={cold:"\x1B[34m",cool:"\x1B[36m",neutral:"",warm:"\x1B[33m",hot:"\x1B[31m",critical:"\x1B[41m"},mt="\x1B[0m";function ht(e){return e<.2?Q.cold:e<.4?Q.cool:e<.6?Q.neutral:e<.8?Q.warm:e<.95?Q.hot:Q.critical}function _e(e,n){let t=ht(n);return t?`${t}${e}${mt}`:e}var Ce="\u2581\u2582\u2583\u2584\u2585\u2586\u2587\u2588";function gt(e,n=10){if(e.length===0)return"";let t=e.slice(-n),a=Math.min(...t),r=Math.max(...t)-a||1;return t.map(c=>{let p=(c-a)/r,d=Math.floor(p*(Ce.length-1));return Ce[d]}).join("")}function ke(e,n){let t=Me(e).length,a=Math.max(0,n-t);return e+" ".repeat(a)}function vt(e,n){if(!n)return y.horizontal.repeat(e);let t=` ${n} `,a=e-t.length;if(a<4)return y.horizontal.repeat(e);let o=2,r=a-o;return y.horizontal.repeat(o)+t+y.horizontal.repeat(r)}function Oe(e,n,t){let a=e.state==="success"?G("\u2699",t.success):G("\u26A0",t.error),o=e.durationMs!==void 0?_(` [${H(e.durationMs)}]`):"",r="";e.type==="shouldRun"&&e.context?.skipped?r=_(" \u2192 workflow skipped"):e.type==="shouldRun"&&e.context?.result===!0?r=_(" \u2192 proceed"):e.type==="onBeforeStart"&&e.context?.skipped?r=_(" \u2192 workflow skipped"):e.type==="onAfterStep"&&e.context?.stepKey&&(r=_(` (${e.context.stepKey})`));let c=e.state==="error"&&e.error?_(` error: ${String(e.error)}`):"";return`${a} ${_(n)}${r}${o}${c}`}function wt(e,n){let t=[];return e.shouldRun&&t.push(Oe(e.shouldRun,"shouldRun",n)),e.onBeforeStart&&t.push(Oe(e.onBeforeStart,"onBeforeStart",n)),t.length>0&&t.push(_("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")),t}function Z(){return{name:"ascii",supportsLive:!0,render(e,n){let t={...U,...n.colors},a=n.terminalWidth??60,o=a-4,r=[],c=e.root.name??"workflow",p=ne(c);if(r.push(`${y.topLeft}${vt(a-2,p)}${y.topRight}`),r.push(`${y.vertical}${" ".repeat(a-2)}${y.vertical}`),e.hooks){let u=wt(e.hooks,t);for(let s of u)r.push(`${y.vertical} ${ke(s,o)}${y.vertical}`)}let d=se(e.root.children,n,t,0,e.hooks);for(let u of d)r.push(`${y.vertical} ${ke(u,o)}${y.vertical}`);if(r.push(`${y.vertical}${" ".repeat(a-2)}${y.vertical}`),e.root.durationMs!==void 0&&n.showTimings){let u=e.root.state==="success"?"Completed":"Failed",l=`${ye(u,e.root.state,t)} in ${H(e.root.durationMs)}`;r.push(`${y.vertical} ${ke(l,o)}${y.vertical}`),r.push(`${y.vertical}${" ".repeat(a-2)}${y.vertical}`)}return r.push(`${y.bottomLeft}${y.horizontal.repeat(a-2)}${y.bottomRight}`),r.join(`
|
|
2
|
+
`)}}}function se(e,n,t,a,o){let r=[];for(let c of e)V(c)?r.push(Se(c,n,t,o)):K(c)?r.push(...bt(c,n,t,a,o)):Y(c)?r.push(...yt(c,n,t,a,o)):X(c)&&r.push(...kt(c,n,t,a,o));return r}function Se(e,n,t,a){let o=re(e.state,t),r=e.name??e.key??"step",c=n,p=e.name??e.id,d=c.showHeatmap&&c.heatmapData?c.heatmapData.heat.get(e.id)??c.heatmapData.heat.get(p):void 0,u;d!==void 0?u=_e(r,d):u=ye(r,e.state,t);let s=`${o} ${u}`;if(n.showKeys&&e.key&&(s+=_(` [key: ${e.key}]`)),e.input!==void 0){let l=typeof e.input=="string"?e.input:JSON.stringify(e.input).slice(0,30);s+=_(` [in: ${l}${l.length>=30?"...":""}]`)}if(e.output!==void 0&&e.state==="success"){let l=typeof e.output=="string"?e.output:JSON.stringify(e.output).slice(0,30);s+=_(` [out: ${l}${l.length>=30?"...":""}]`)}if(n.showTimings&&e.durationMs!==void 0){let l=H(e.durationMs),f=d!==void 0?_e(`[${l}]`,d):_(`[${l}]`);s+=` ${f}`}if(c.showSparklines&&c.timingHistory){let l=c.timingHistory.get(p);l&&l.length>1&&(s+=` ${_(gt(l))}`)}if(e.retryCount!==void 0&&e.retryCount>0&&(s+=_(` [${e.retryCount} ${e.retryCount===1?"retry":"retries"}]`)),e.timedOut){let l=e.timeoutMs!==void 0?` ${e.timeoutMs}ms`:"";s+=_(` [timeout${l}]`)}if(a&&e.key&&a.onAfterStep.has(e.key)){let l=a.onAfterStep.get(e.key),f=l.state==="success"?G("\u2699",t.success):G("\u26A0",t.error),h=l.durationMs!==void 0?_(` ${H(l.durationMs)}`):"";s+=` ${f}${h}`}return s}function bt(e,n,t,a,o){let r=[],c=" ".repeat(a),p=re(e.state,t),d=e.name??"parallel",u=e.mode==="allSettled"?" (allSettled)":"";if(r.push(`${c}${y.teeRight}${y.teeDown}${y.horizontal} ${p} ${ne(d)}${u}`),e.children.length===0)r.push(`${c}${y.vertical} ${_("(operations not individually tracked)")}`),r.push(`${c}${y.vertical} ${_("(wrap each operation with step() to see individual steps)")}`);else for(let s=0;s<e.children.length;s++){let l=e.children[s],h=s===e.children.length-1?`${c}${y.vertical} ${y.bottomLeft}`:`${c}${y.vertical} ${y.teeRight}`;if(V(l))r.push(`${h} ${Se(l,n,t,o)}`);else{let k=se([l],n,t,a+1,o);for(let v of k)r.push(`${c}${y.vertical} ${v}`)}}return n.showTimings&&e.durationMs!==void 0&&r.push(`${c}${y.bottomLeft}${y.horizontal}${y.horizontal} ${_(`[${H(e.durationMs)}]`)}`),r}function yt(e,n,t,a,o){let r=[],c=" ".repeat(a),p=re(e.state,t),d=e.name??"race";if(r.push(`${c}${y.teeRight}\u26A1 ${p} ${ne(d)}`),e.children.length===0)r.push(`${c}${y.vertical} ${_("(operations not individually tracked)")}`),r.push(`${c}${y.vertical} ${_("(wrap each operation with step() to see individual steps)")}`);else for(let u=0;u<e.children.length;u++){let s=e.children[u],f=u===e.children.length-1?`${c}${y.vertical} ${y.bottomLeft}`:`${c}${y.vertical} ${y.teeRight}`,k=e.winnerId&&s.id===e.winnerId?_(" (winner)"):"";if(V(s))r.push(`${f} ${Se(s,n,t,o)}${k}`);else{let v=se([s],n,t,a+1,o);for(let R of v)r.push(`${c}${y.vertical} ${R}`)}}return n.showTimings&&e.durationMs!==void 0&&r.push(`${c}${y.bottomLeft}${y.horizontal}${y.horizontal} ${_(`[${H(e.durationMs)}]`)}`),r}function kt(e,n,t,a,o){let r=[],c=" ".repeat(a),p=re(e.state,t),d=e.name??"decision",u=e.condition?_(` (${e.condition})`):"",s=e.decisionValue!==void 0?_(` = ${String(e.decisionValue)}`):"",l=e.branchTaken!==void 0?_(` \u2192 ${String(e.branchTaken)}`):"";r.push(`${c}${y.teeRight}${y.teeDown}${y.horizontal} ${p} ${ne(d)}${u}${s}${l}`);for(let f=0;f<e.branches.length;f++){let h=e.branches[f],v=f===e.branches.length-1?`${c}${y.vertical} ${y.bottomLeft}`:`${c}${y.vertical} ${y.teeRight}`,R=h.taken?"\u2713":"\u2298",T=h.taken?t.success:t.skipped,B=G(`${R} ${h.label}`,T),O=h.condition?_(` (${h.condition})`):"";if(r.push(`${v} ${B}${O}`),h.children.length>0){let g=se(h.children,n,t,a+1,o);for(let I of g)r.push(`${c}${y.vertical} ${I}`)}else h.taken||r.push(`${c}${y.vertical} ${_("(skipped)")}`)}return n.showTimings&&e.durationMs!==void 0&&r.push(`${c}${y.bottomLeft}${y.horizontal}${y.horizontal} ${_(`[${H(e.durationMs)}]`)}`),r}function xe(e){let n=[];for(let t of e)if(n.push(t),"children"in t&&Array.isArray(t.children)&&n.push(...xe(t.children)),"branches"in t)for(let a of t.branches)n.push(...xe(a.children));return n}function ce(e,n){if(e.length===0)return 0;let t=Math.floor(e.length*n);return e[Math.min(t,e.length-1)]}function de(e){return e<.2?"cold":e<.4?"cool":e<.6?"neutral":e<.8?"warm":e<.95?"hot":"critical"}function le(){let e=new Map,n=new Map,t=new Map,a=new Map,o=[];function r(g){return g.name??g.stepKey??g.stepId??"unknown"}function c(g){let I=new Map;for(let w of g)switch(w.type){case"step_start":{let $=r(w);I.set($,{retried:!1,timedOut:!1});break}case"step_retry":{let $=r(w),W=I.get($);W&&(W.retried=!0);break}case"step_timeout":{let $=r(w),W=I.get($);W&&(W.timedOut=!0);let C=a.get($)??{timedOut:0,total:0};C.timedOut++,C.total++,a.set($,C);break}case"step_success":{let $=r(w),W=I.get($),C=e.get($)??[];C.push(w.durationMs),e.set($,C);let D=n.get($)??{retried:0,total:0};D.total++,W?.retried&&D.retried++,n.set($,D);let M=t.get($)??{errors:0,total:0};M.total++,t.set($,M),I.delete($);break}case"step_error":{let $=r(w),W=I.get($),C=e.get($)??[];C.push(w.durationMs),e.set($,C);let D=n.get($)??{retried:0,total:0};D.total++,W?.retried&&D.retried++,n.set($,D);let M=t.get($)??{errors:0,total:0};M.total++,M.errors++,t.set($,M),I.delete($);break}}}function p(g){c(g.events)}function d(g){o.push(g)}function u(g){o.length>0&&(c(o),o=[])}function s(g){let I=e.get(g);if(!I||I.length===0)return;let w=[...I].sort((S,x)=>S-x),W=w.reduce((S,x)=>S+x,0)/w.length,C=w.reduce((S,x)=>S+(x-W)**2,0)/w.length,D=n.get(g)??{retried:0,total:1},M=t.get(g)??{errors:0,total:1},N=a.get(g)??{timedOut:0,total:1};return{nodeId:g,avgDurationMs:W,minDurationMs:w[0],maxDurationMs:w[w.length-1],stdDevMs:Math.sqrt(C),samples:w.length,retryRate:D.total>0?D.retried/D.total:0,timeoutRate:N.total>0?N.timedOut/N.total:0,errorRate:M.total>0?M.errors/M.total:0,percentiles:{p50:ce(w,.5),p90:ce(w,.9),p95:ce(w,.95),p99:ce(w,.99)}}}function l(g){return s(g)}function f(g,I="duration"){let w=new Map,$=xe(g.root.children),W=[];for(let x of $){let E=x.name??x.id,L=s(E);if(L){let i;switch(I){case"duration":i=L.avgDurationMs;break;case"retryRate":i=L.retryRate;break;case"errorRate":i=L.errorRate;break}W.push({id:x.id,value:i})}}if(W.length===0)return{heat:w,metric:I,stats:{min:0,max:0,mean:0,threshold:0}};let C=W.map(x=>x.value),D=Math.min(...C),M=Math.max(...C),N=C.reduce((x,E)=>x+E,0)/C.length,S=M-D||1;for(let{id:x,value:E}of W)w.set(x,(E-D)/S);return{heat:w,metric:I,stats:{min:D,max:M,mean:N,threshold:N+(M-N)*.5}}}function h(){let g=new Map;for(let I of e.keys()){let w=s(I);w&&g.set(I,w)}return g}function k(g=10){return[...h().values()].sort((w,$)=>$.avgDurationMs-w.avgDurationMs).slice(0,g)}function v(g=10){return[...h().values()].filter(w=>w.errorRate>0).sort((w,$)=>$.errorRate-w.errorRate).slice(0,g)}function R(g=10){return[...h().values()].filter(w=>w.retryRate>0).sort((w,$)=>$.retryRate-w.retryRate).slice(0,g)}function T(){return JSON.stringify({timingData:Object.fromEntries(e),retryData:Object.fromEntries(n),errorData:Object.fromEntries(t),timeoutData:Object.fromEntries(a)})}function B(g){let I=JSON.parse(g);e.clear(),n.clear(),t.clear(),a.clear();for(let[w,$]of Object.entries(I.timingData??{}))e.set(w,$);for(let[w,$]of Object.entries(I.retryData??{}))n.set(w,$);for(let[w,$]of Object.entries(I.errorData??{}))t.set(w,$);for(let[w,$]of Object.entries(I.timeoutData??{}))a.set(w,$)}function O(){e.clear(),n.clear(),t.clear(),a.clear(),o=[]}return{addRun:p,addEvent:d,finalizeRun:u,getNodePerformance:l,getHeatmap:f,getSlowestNodes:k,getErrorProneNodes:v,getRetryProneNodes:R,getAllPerformance:h,exportData:T,importData:B,clear:O}}function St(){return[" classDef pending fill:#f3f4f6,stroke:#9ca3af,stroke-width:2px,color:#374151"," classDef running fill:#fef3c7,stroke:#f59e0b,stroke-width:3px,color:#92400e"," classDef success fill:#d1fae5,stroke:#10b981,stroke-width:3px,color:#065f46"," classDef error fill:#fee2e2,stroke:#ef4444,stroke-width:3px,color:#991b1b"," classDef aborted fill:#f3f4f6,stroke:#6b7280,stroke-width:2px,color:#4b5563,stroke-dasharray: 5 5"," classDef cached fill:#dbeafe,stroke:#3b82f6,stroke-width:3px,color:#1e40af"," classDef skipped fill:#f9fafb,stroke:#d1d5db,stroke-width:2px,color:#6b7280,stroke-dasharray: 5 5"]}function xt(){return[" classDef heat_cold fill:#dbeafe,stroke:#3b82f6,stroke-width:2px,color:#1e40af"," classDef heat_cool fill:#ccfbf1,stroke:#14b8a6,stroke-width:2px,color:#0f766e"," classDef heat_neutral fill:#f3f4f6,stroke:#6b7280,stroke-width:2px,color:#374151"," classDef heat_warm fill:#fef3c7,stroke:#f59e0b,stroke-width:2px,color:#92400e"," classDef heat_hot fill:#fed7aa,stroke:#f97316,stroke-width:3px,color:#c2410c"," classDef heat_critical fill:#fecaca,stroke:#ef4444,stroke-width:3px,color:#b91c1c"]}function $t(e){return`heat_${e}`}function Rt(){return[" classDef hook_success fill:#e0f2fe,stroke:#0284c7,stroke-width:2px,color:#0c4a6e"," classDef hook_error fill:#fef2f2,stroke:#dc2626,stroke-width:2px,color:#7f1d1d"]}function Et(e,n,t){let a;if(e.shouldRun){let o="hook_shouldRun",r=e.shouldRun.state==="success"?"hook_success":"hook_error",c=e.shouldRun.state==="success"?"\u2699":"\u26A0",p=t.showTimings&&e.shouldRun.durationMs!==void 0?` ${H(e.shouldRun.durationMs)}`:"",d=e.shouldRun.context?.skipped?"\\nskipped workflow":e.shouldRun.context?.result===!0?"\\nproceed":"";n.push(` ${o}[["${c} shouldRun${d}${p}"]]:::${r}`),a=o}if(e.onBeforeStart){let o="hook_beforeStart",r=e.onBeforeStart.state==="success"?"hook_success":"hook_error",c=e.onBeforeStart.state==="success"?"\u2699":"\u26A0",p=t.showTimings&&e.onBeforeStart.durationMs!==void 0?` ${H(e.onBeforeStart.durationMs)}`:"",d=e.onBeforeStart.context?.skipped?"\\nskipped workflow":"";n.push(` ${o}[["${c} onBeforeStart${d}${p}"]]:::${r}`),a&&n.push(` ${a} --> ${o}`),a=o}return{lastHookId:a}}var We=0;function oe(e="node"){return`${e}_${++We}`}function It(){We=0}function z(e){return e.replace(/[{}[\]()]/g,"").replace(/[<>]/g,"").replace(/"/g,"'").trim()}function Le(e){return z(e).replace(/[[\]]/g,"")}function ie(){return{name:"mermaid",supportsLive:!1,render(e,n){It();let t=[],a=n;t.push("flowchart TD");let o;e.hooks&&(o=Et(e.hooks,t,n).lastHookId);let r="start";t.push(` ${r}(("\u25B6 Start"))`),o&&t.push(` ${o} --> ${r}`);let c=r;for(let p of e.root.children){let d=ue(p,n,t,a,e.hooks);t.push(` ${c} --> ${d.entryId}`),c=d.exitId}if(e.root.state==="success"||e.root.state==="error"){let p="finish",d=e.root.state==="success"?"\u2713":"\u2717",u=e.root.state==="success"?"Done":"Failed",s=`(("${d} ${u}"))`,l=e.root.state==="success"?":::success":":::error";t.push(` ${p}${s}${l}`),t.push(` ${c} --> ${p}`)}return t.push(""),t.push(...St()),a.showHeatmap&&t.push(...xt()),e.hooks&&t.push(...Rt()),t.join(`
|
|
3
|
+
`)}}}function ue(e,n,t,a,o){if(V(e))return Dt(e,n,t,a,o);if(K(e))return Tt(e,n,t,a,o);if(Y(e))return Nt(e,n,t,a,o);if(X(e))return Mt(e,n,t,a,o);let r=oe("unknown");return t.push(` ${r}[Unknown Node]`),{entryId:r,exitId:r}}function Dt(e,n,t,a,o){let r=e.key?`step_${e.key.replace(/[^a-zA-Z0-9]/g,"_")}`:oe("step"),c=z(e.name??e.key??"Step"),p=n.showTimings&&e.durationMs!==void 0?` ${H(e.durationMs)}`:"",d="";switch(e.state){case"success":d="\u2713 ";break;case"error":d="\u2717 ";break;case"cached":d="\u{1F4BE} ";break;case"running":d="\u23F3 ";break;case"skipped":d="\u2298 ";break}let u="";if(e.input!==void 0){let T=typeof e.input=="string"?z(e.input):z(JSON.stringify(e.input).slice(0,20));u+=`\\nin: ${T}`}if(e.output!==void 0&&e.state==="success"){let T=typeof e.output=="string"?z(e.output):z(JSON.stringify(e.output).slice(0,20));u+=`\\nout: ${T}`}let s="";if(e.retryCount!==void 0&&e.retryCount>0&&(s+=`\\n\u21BB ${e.retryCount} retr${e.retryCount===1?"y":"ies"}`),e.timedOut){let T=e.timeoutMs!==void 0?`${e.timeoutMs}ms`:"";s+=`\\n\u23F1 timeout ${T}`}let l="";if(o&&e.key&&o.onAfterStep.has(e.key)){let T=o.onAfterStep.get(e.key),B=T.state==="success"?"\u2699":"\u26A0",O=n.showTimings&&T.durationMs!==void 0?` ${H(T.durationMs)}`:"";l=`\\n${B} hook${O}`}let f=(d+c+u+s+l+p).trim(),h,k=e.name??e.id,v=a?.showHeatmap&&a.heatmapData?a.heatmapData.heat.get(e.id)??a.heatmapData.heat.get(k):void 0;if(v!==void 0){let T=de(v);h=$t(T)}else h=e.state;let R;switch(e.state){case"error":R=`{{${f}}}`;break;case"cached":R=`[(${f})]`;break;case"skipped":R=`[${f}]:::skipped`;break;default:R=`[${f}]`}return t.push(` ${r}${R}:::${h}`),{entryId:r,exitId:r}}function Tt(e,n,t,a,o){let r=oe("parallel"),c=`${r}_fork`,p=`${r}_join`,d=Le(e.name??"Parallel"),u=e.mode==="allSettled"?" (allSettled)":"";if(e.children.length===0){let f=r,h=z(`${d}${u}`),k="operations not individually tracked",v=n.showTimings&&e.durationMs!==void 0?` ${H(e.durationMs)}`:"";return t.push(` ${f}[${h}${v}\\n${k}]:::${e.state}`),{entryId:f,exitId:f}}t.push(` subgraph ${r}["${d}${u}"]`),t.push(" direction TB"),t.push(` ${c}{"\u26A1 Fork"}`);let s=[];for(let f of e.children){let h=ue(f,n,t,a,o);t.push(` ${c} --> ${h.entryId}`),s.push(h.exitId)}t.push(` ${p}{"\u2713 Join"}`);for(let f of s)t.push(` ${f} --> ${p}`);t.push(" end");let l=e.state;return t.push(` class ${r} ${l}`),{entryId:c,exitId:p}}function Nt(e,n,t,a,o){let r=oe("race"),c=`${r}_start`,p=`${r}_end`,d=Le(e.name??"Race");if(e.children.length===0){let f=r,h=z(d),k="operations not individually tracked",v=n.showTimings&&e.durationMs!==void 0?` ${H(e.durationMs)}`:"";return t.push(` ${f}[\u26A1 ${h}${v}\\n${k}]:::${e.state}`),{entryId:f,exitId:f}}t.push(` subgraph ${r}["\u26A1 ${d}"]`),t.push(" direction TB"),t.push(` ${c}(("\u{1F3C1} Start"))`);let u=[],s;for(let f of e.children){let h=ue(f,n,t,a,o),k=V(f)&&e.winnerId===f.id;t.push(` ${c} --> ${h.entryId}`),k&&(s=h.exitId),u.push({exitId:h.exitId,isWinner:k})}t.push(` ${p}(("\u2713 First"))`);for(let{exitId:f,isWinner:h}of u)h&&s?t.push(` ${f} ==>|\u{1F3C6} Winner| ${p}`):e.winnerId?t.push(` ${f} -. cancelled .-> ${p}`):t.push(` ${f} --> ${p}`);t.push(" end");let l=e.state;return t.push(` class ${r} ${l}`),{entryId:c,exitId:p}}function Mt(e,n,t,a,o){let r=e.key?`decision_${e.key.replace(/[^a-zA-Z0-9]/g,"_")}`:oe("decision"),c=z(e.condition??"condition"),p=e.decisionValue!==void 0?` = ${z(String(e.decisionValue)).slice(0,30)}`:"",d=`${c}${p}`.trim();t.push(` ${r}{${d}}`);let u=[],s;for(let l of e.branches){let f=`${r}_${l.label.replace(/[^a-zA-Z0-9]/g,"_")}`,h=z(l.label),k=l.taken?`${h} \u2713`:`${h} skipped`,v=l.taken?":::success":":::skipped";t.push(` ${f}[${k}]${v}`);let R=l.condition?`|${z(l.condition).replace(/\|/g,"")}|`:"";if(t.push(` ${r} -->${R} ${f}`),l.children.length>0){let T=f;for(let B of l.children){let O=ue(B,n,t,a,o);t.push(` ${T} --> ${O.entryId}`),T=O.exitId}u.push(T),l.taken&&(s=T)}else u.push(f),l.taken&&(s=f)}return s?{entryId:r,exitId:s}:{entryId:r,exitId:r}}function Be(e){let n={bg:"#ffffff",bgSecondary:"#f8f9fa",text:"#212529",textMuted:"#6c757d",border:"#dee2e6",primary:"#0d6efd",success:"#198754",error:"#dc3545",warning:"#ffc107",info:"#0dcaf0",muted:"#6c757d",nodePending:"#e9ecef",nodeRunning:"#fff3cd",nodeSuccess:"#d1e7dd",nodeError:"#f8d7da",nodeAborted:"#e9ecef",nodeCached:"#cfe2ff",nodeSkipped:"#f8f9fa",heatCold:"#0d6efd",heatCool:"#0dcaf0",heatNeutral:"#6c757d",heatWarm:"#ffc107",heatHot:"#fd7e14",heatCritical:"#dc3545"},t={bg:"#212529",bgSecondary:"#343a40",text:"#f8f9fa",textMuted:"#adb5bd",border:"#495057",primary:"#0d6efd",success:"#198754",error:"#dc3545",warning:"#ffc107",info:"#0dcaf0",muted:"#6c757d",nodePending:"#495057",nodeRunning:"#664d03",nodeSuccess:"#0f5132",nodeError:"#842029",nodeAborted:"#495057",nodeCached:"#084298",nodeSkipped:"#343a40",heatCold:"#0d6efd",heatCool:"#0dcaf0",heatNeutral:"#6c757d",heatWarm:"#ffc107",heatHot:"#fd7e14",heatCritical:"#dc3545"},a=r=>`
|
|
4
|
+
--bg: ${r.bg};
|
|
5
|
+
--bg-secondary: ${r.bgSecondary};
|
|
6
|
+
--text: ${r.text};
|
|
7
|
+
--text-muted: ${r.textMuted};
|
|
8
|
+
--border: ${r.border};
|
|
9
|
+
--primary: ${r.primary};
|
|
10
|
+
--success: ${r.success};
|
|
11
|
+
--error: ${r.error};
|
|
12
|
+
--warning: ${r.warning};
|
|
13
|
+
--info: ${r.info};
|
|
14
|
+
--muted: ${r.muted};
|
|
15
|
+
--node-pending: ${r.nodePending};
|
|
16
|
+
--node-running: ${r.nodeRunning};
|
|
17
|
+
--node-success: ${r.nodeSuccess};
|
|
18
|
+
--node-error: ${r.nodeError};
|
|
19
|
+
--node-aborted: ${r.nodeAborted};
|
|
20
|
+
--node-cached: ${r.nodeCached};
|
|
21
|
+
--node-skipped: ${r.nodeSkipped};
|
|
22
|
+
--heat-cold: ${r.heatCold};
|
|
23
|
+
--heat-cool: ${r.heatCool};
|
|
24
|
+
--heat-neutral: ${r.heatNeutral};
|
|
25
|
+
--heat-warm: ${r.heatWarm};
|
|
26
|
+
--heat-hot: ${r.heatHot};
|
|
27
|
+
--heat-critical: ${r.heatCritical};
|
|
28
|
+
`,o;return e==="auto"?o=`
|
|
29
|
+
:root {
|
|
30
|
+
${a(n)}
|
|
31
|
+
}
|
|
32
|
+
@media (prefers-color-scheme: dark) {
|
|
33
|
+
:root {
|
|
34
|
+
${a(t)}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
`:e==="dark"?o=`
|
|
38
|
+
:root {
|
|
39
|
+
${a(t)}
|
|
40
|
+
}
|
|
41
|
+
`:o=`
|
|
42
|
+
:root {
|
|
43
|
+
${a(n)}
|
|
44
|
+
}
|
|
45
|
+
`,`
|
|
46
|
+
${o}
|
|
47
|
+
|
|
48
|
+
* {
|
|
49
|
+
box-sizing: border-box;
|
|
50
|
+
margin: 0;
|
|
51
|
+
padding: 0;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
body {
|
|
55
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
|
56
|
+
background-color: var(--bg);
|
|
57
|
+
color: var(--text);
|
|
58
|
+
line-height: 1.5;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.workflow-visualizer {
|
|
62
|
+
display: flex;
|
|
63
|
+
flex-direction: column;
|
|
64
|
+
height: 100vh;
|
|
65
|
+
overflow: hidden;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/* Header */
|
|
69
|
+
.wv-header {
|
|
70
|
+
display: flex;
|
|
71
|
+
align-items: center;
|
|
72
|
+
justify-content: space-between;
|
|
73
|
+
padding: 12px 20px;
|
|
74
|
+
background-color: var(--bg-secondary);
|
|
75
|
+
border-bottom: 1px solid var(--border);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.wv-header h1 {
|
|
79
|
+
font-size: 1.25rem;
|
|
80
|
+
font-weight: 600;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
.wv-controls {
|
|
84
|
+
display: flex;
|
|
85
|
+
gap: 8px;
|
|
86
|
+
align-items: center;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.wv-btn {
|
|
90
|
+
display: inline-flex;
|
|
91
|
+
align-items: center;
|
|
92
|
+
justify-content: center;
|
|
93
|
+
padding: 6px 12px;
|
|
94
|
+
font-size: 0.875rem;
|
|
95
|
+
font-weight: 500;
|
|
96
|
+
border: 1px solid var(--border);
|
|
97
|
+
border-radius: 6px;
|
|
98
|
+
background-color: var(--bg);
|
|
99
|
+
color: var(--text);
|
|
100
|
+
cursor: pointer;
|
|
101
|
+
transition: all 0.15s ease;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
.wv-btn:hover {
|
|
105
|
+
background-color: var(--bg-secondary);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.wv-btn:disabled {
|
|
109
|
+
opacity: 0.5;
|
|
110
|
+
cursor: not-allowed;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
.wv-btn--primary {
|
|
114
|
+
background-color: var(--primary);
|
|
115
|
+
border-color: var(--primary);
|
|
116
|
+
color: white;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.wv-btn--primary:hover {
|
|
120
|
+
opacity: 0.9;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.wv-btn--icon {
|
|
124
|
+
padding: 6px;
|
|
125
|
+
min-width: 32px;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/* Main content area */
|
|
129
|
+
.wv-main {
|
|
130
|
+
display: flex;
|
|
131
|
+
flex: 1;
|
|
132
|
+
overflow: hidden;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/* Diagram container */
|
|
136
|
+
.wv-diagram {
|
|
137
|
+
flex: 1;
|
|
138
|
+
position: relative;
|
|
139
|
+
overflow: hidden;
|
|
140
|
+
background-color: var(--bg);
|
|
141
|
+
background-image:
|
|
142
|
+
radial-gradient(circle, var(--border) 1px, transparent 1px);
|
|
143
|
+
background-size: 20px 20px;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
.wv-diagram svg {
|
|
147
|
+
width: 100%;
|
|
148
|
+
height: 100%;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/* SVG Node styles */
|
|
152
|
+
.wv-node {
|
|
153
|
+
cursor: pointer;
|
|
154
|
+
transition: transform 0.15s ease;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
.wv-node:hover {
|
|
158
|
+
transform: scale(1.02);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
.wv-node rect,
|
|
162
|
+
.wv-node circle {
|
|
163
|
+
stroke: var(--border);
|
|
164
|
+
stroke-width: 2;
|
|
165
|
+
transition: all 0.2s ease;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
.wv-node--pending rect { fill: var(--node-pending); }
|
|
169
|
+
.wv-node--running rect { fill: var(--node-running); stroke: var(--warning); }
|
|
170
|
+
.wv-node--success rect { fill: var(--node-success); stroke: var(--success); }
|
|
171
|
+
.wv-node--error rect { fill: var(--node-error); stroke: var(--error); }
|
|
172
|
+
.wv-node--aborted rect { fill: var(--node-aborted); }
|
|
173
|
+
.wv-node--cached rect { fill: var(--node-cached); stroke: var(--info); }
|
|
174
|
+
.wv-node--skipped rect { fill: var(--node-skipped); opacity: 0.6; }
|
|
175
|
+
|
|
176
|
+
.wv-node--selected rect {
|
|
177
|
+
stroke: var(--primary);
|
|
178
|
+
stroke-width: 3;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
.wv-node text {
|
|
182
|
+
fill: var(--text);
|
|
183
|
+
font-size: 12px;
|
|
184
|
+
font-weight: 500;
|
|
185
|
+
dominant-baseline: middle;
|
|
186
|
+
text-anchor: middle;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
.wv-node .wv-node-timing {
|
|
190
|
+
fill: var(--text-muted);
|
|
191
|
+
font-size: 10px;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/* Edge styles */
|
|
195
|
+
.wv-edge {
|
|
196
|
+
fill: none;
|
|
197
|
+
stroke: var(--border);
|
|
198
|
+
stroke-width: 2;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
.wv-edge--active {
|
|
202
|
+
stroke: var(--success);
|
|
203
|
+
stroke-width: 2.5;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
.wv-edge-arrow {
|
|
207
|
+
fill: var(--border);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/* Parallel/Race container */
|
|
211
|
+
.wv-container {
|
|
212
|
+
fill: transparent;
|
|
213
|
+
stroke: var(--border);
|
|
214
|
+
stroke-dasharray: 5 3;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
.wv-container--parallel { stroke: var(--info); }
|
|
218
|
+
.wv-container--race { stroke: var(--warning); }
|
|
219
|
+
|
|
220
|
+
.wv-container-label {
|
|
221
|
+
fill: var(--text-muted);
|
|
222
|
+
font-size: 10px;
|
|
223
|
+
font-weight: 600;
|
|
224
|
+
text-transform: uppercase;
|
|
225
|
+
letter-spacing: 0.5px;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/* Heatmap overlay */
|
|
229
|
+
.wv-node--heat-cold rect { fill: var(--heat-cold) !important; opacity: 0.7; }
|
|
230
|
+
.wv-node--heat-cool rect { fill: var(--heat-cool) !important; opacity: 0.7; }
|
|
231
|
+
.wv-node--heat-neutral rect { fill: var(--heat-neutral) !important; opacity: 0.7; }
|
|
232
|
+
.wv-node--heat-warm rect { fill: var(--heat-warm) !important; opacity: 0.7; }
|
|
233
|
+
.wv-node--heat-hot rect { fill: var(--heat-hot) !important; opacity: 0.7; }
|
|
234
|
+
.wv-node--heat-critical rect { fill: var(--heat-critical) !important; opacity: 0.85; }
|
|
235
|
+
|
|
236
|
+
/* Timeline scrubber */
|
|
237
|
+
.wv-timeline {
|
|
238
|
+
height: 80px;
|
|
239
|
+
padding: 12px 20px;
|
|
240
|
+
background-color: var(--bg-secondary);
|
|
241
|
+
border-top: 1px solid var(--border);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
.wv-timeline-track {
|
|
245
|
+
position: relative;
|
|
246
|
+
height: 24px;
|
|
247
|
+
background-color: var(--bg);
|
|
248
|
+
border-radius: 4px;
|
|
249
|
+
overflow: hidden;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
.wv-timeline-progress {
|
|
253
|
+
position: absolute;
|
|
254
|
+
top: 0;
|
|
255
|
+
left: 0;
|
|
256
|
+
height: 100%;
|
|
257
|
+
background-color: var(--primary);
|
|
258
|
+
opacity: 0.3;
|
|
259
|
+
transition: width 0.1s ease;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
.wv-timeline-marker {
|
|
263
|
+
position: absolute;
|
|
264
|
+
top: 0;
|
|
265
|
+
width: 3px;
|
|
266
|
+
height: 100%;
|
|
267
|
+
background-color: var(--primary);
|
|
268
|
+
cursor: ew-resize;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
.wv-timeline-events {
|
|
272
|
+
display: flex;
|
|
273
|
+
gap: 2px;
|
|
274
|
+
height: 100%;
|
|
275
|
+
align-items: center;
|
|
276
|
+
padding: 4px;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
.wv-timeline-event {
|
|
280
|
+
width: 4px;
|
|
281
|
+
height: 16px;
|
|
282
|
+
border-radius: 2px;
|
|
283
|
+
background-color: var(--muted);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
.wv-timeline-event--success { background-color: var(--success); }
|
|
287
|
+
.wv-timeline-event--error { background-color: var(--error); }
|
|
288
|
+
.wv-timeline-event--running { background-color: var(--warning); }
|
|
289
|
+
|
|
290
|
+
.wv-timeline-controls {
|
|
291
|
+
display: flex;
|
|
292
|
+
gap: 8px;
|
|
293
|
+
margin-top: 8px;
|
|
294
|
+
align-items: center;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
.wv-timeline-time {
|
|
298
|
+
font-size: 0.75rem;
|
|
299
|
+
color: var(--text-muted);
|
|
300
|
+
font-family: monospace;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/* Inspector panel */
|
|
304
|
+
.wv-inspector {
|
|
305
|
+
width: 320px;
|
|
306
|
+
background-color: var(--bg-secondary);
|
|
307
|
+
border-left: 1px solid var(--border);
|
|
308
|
+
overflow-y: auto;
|
|
309
|
+
transition: width 0.2s ease;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
.wv-inspector--collapsed {
|
|
313
|
+
width: 0;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
.wv-inspector-header {
|
|
317
|
+
display: flex;
|
|
318
|
+
align-items: center;
|
|
319
|
+
justify-content: space-between;
|
|
320
|
+
padding: 12px 16px;
|
|
321
|
+
border-bottom: 1px solid var(--border);
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
.wv-inspector-header h2 {
|
|
325
|
+
font-size: 0.875rem;
|
|
326
|
+
font-weight: 600;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
.wv-inspector-content {
|
|
330
|
+
padding: 16px;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
.wv-inspector-section {
|
|
334
|
+
margin-bottom: 20px;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
.wv-inspector-section h3 {
|
|
338
|
+
font-size: 0.75rem;
|
|
339
|
+
font-weight: 600;
|
|
340
|
+
text-transform: uppercase;
|
|
341
|
+
letter-spacing: 0.5px;
|
|
342
|
+
color: var(--text-muted);
|
|
343
|
+
margin-bottom: 8px;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
.wv-inspector-row {
|
|
347
|
+
display: flex;
|
|
348
|
+
justify-content: space-between;
|
|
349
|
+
padding: 4px 0;
|
|
350
|
+
font-size: 0.875rem;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
.wv-inspector-label {
|
|
354
|
+
color: var(--text-muted);
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
.wv-inspector-value {
|
|
358
|
+
font-weight: 500;
|
|
359
|
+
font-family: monospace;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
.wv-inspector-value--success { color: var(--success); }
|
|
363
|
+
.wv-inspector-value--error { color: var(--error); }
|
|
364
|
+
.wv-inspector-value--running { color: var(--warning); }
|
|
365
|
+
|
|
366
|
+
/* Status badge */
|
|
367
|
+
.wv-badge {
|
|
368
|
+
display: inline-flex;
|
|
369
|
+
align-items: center;
|
|
370
|
+
padding: 2px 8px;
|
|
371
|
+
font-size: 0.75rem;
|
|
372
|
+
font-weight: 500;
|
|
373
|
+
border-radius: 4px;
|
|
374
|
+
text-transform: capitalize;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
.wv-badge--pending { background-color: var(--node-pending); }
|
|
378
|
+
.wv-badge--running { background-color: var(--node-running); color: #664d03; }
|
|
379
|
+
.wv-badge--success { background-color: var(--node-success); color: #0f5132; }
|
|
380
|
+
.wv-badge--error { background-color: var(--node-error); color: #842029; }
|
|
381
|
+
.wv-badge--cached { background-color: var(--node-cached); color: #084298; }
|
|
382
|
+
|
|
383
|
+
/* Live indicator */
|
|
384
|
+
.wv-live {
|
|
385
|
+
display: flex;
|
|
386
|
+
align-items: center;
|
|
387
|
+
gap: 6px;
|
|
388
|
+
padding: 4px 10px;
|
|
389
|
+
background-color: var(--error);
|
|
390
|
+
color: white;
|
|
391
|
+
font-size: 0.75rem;
|
|
392
|
+
font-weight: 600;
|
|
393
|
+
border-radius: 4px;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
.wv-live-dot {
|
|
397
|
+
width: 8px;
|
|
398
|
+
height: 8px;
|
|
399
|
+
background-color: white;
|
|
400
|
+
border-radius: 50%;
|
|
401
|
+
animation: wv-pulse 1.5s infinite;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
@keyframes wv-pulse {
|
|
405
|
+
0%, 100% { opacity: 1; }
|
|
406
|
+
50% { opacity: 0.5; }
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
/* Performance stats */
|
|
410
|
+
.wv-perf-bar {
|
|
411
|
+
height: 8px;
|
|
412
|
+
background-color: var(--bg);
|
|
413
|
+
border-radius: 4px;
|
|
414
|
+
overflow: hidden;
|
|
415
|
+
margin-top: 4px;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
.wv-perf-bar-fill {
|
|
419
|
+
height: 100%;
|
|
420
|
+
border-radius: 4px;
|
|
421
|
+
transition: width 0.3s ease;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
.wv-perf-bar-fill--cold { background-color: var(--heat-cold); }
|
|
425
|
+
.wv-perf-bar-fill--cool { background-color: var(--heat-cool); }
|
|
426
|
+
.wv-perf-bar-fill--neutral { background-color: var(--heat-neutral); }
|
|
427
|
+
.wv-perf-bar-fill--warm { background-color: var(--heat-warm); }
|
|
428
|
+
.wv-perf-bar-fill--hot { background-color: var(--heat-hot); }
|
|
429
|
+
.wv-perf-bar-fill--critical { background-color: var(--heat-critical); }
|
|
430
|
+
|
|
431
|
+
/* Tooltip */
|
|
432
|
+
.wv-tooltip {
|
|
433
|
+
position: fixed;
|
|
434
|
+
padding: 8px 12px;
|
|
435
|
+
background-color: var(--text);
|
|
436
|
+
color: var(--bg);
|
|
437
|
+
font-size: 0.75rem;
|
|
438
|
+
border-radius: 4px;
|
|
439
|
+
pointer-events: none;
|
|
440
|
+
z-index: 1000;
|
|
441
|
+
max-width: 300px;
|
|
442
|
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
/* Loading state */
|
|
446
|
+
.wv-loading {
|
|
447
|
+
display: flex;
|
|
448
|
+
align-items: center;
|
|
449
|
+
justify-content: center;
|
|
450
|
+
height: 100%;
|
|
451
|
+
color: var(--text-muted);
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
.wv-spinner {
|
|
455
|
+
width: 24px;
|
|
456
|
+
height: 24px;
|
|
457
|
+
border: 3px solid var(--border);
|
|
458
|
+
border-top-color: var(--primary);
|
|
459
|
+
border-radius: 50%;
|
|
460
|
+
animation: wv-spin 1s linear infinite;
|
|
461
|
+
margin-right: 8px;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
@keyframes wv-spin {
|
|
465
|
+
to { transform: rotate(360deg); }
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
/* Empty state */
|
|
469
|
+
.wv-empty {
|
|
470
|
+
display: flex;
|
|
471
|
+
flex-direction: column;
|
|
472
|
+
align-items: center;
|
|
473
|
+
justify-content: center;
|
|
474
|
+
height: 100%;
|
|
475
|
+
color: var(--text-muted);
|
|
476
|
+
text-align: center;
|
|
477
|
+
padding: 40px;
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
.wv-empty svg {
|
|
481
|
+
width: 64px;
|
|
482
|
+
height: 64px;
|
|
483
|
+
margin-bottom: 16px;
|
|
484
|
+
opacity: 0.5;
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
/* Responsive */
|
|
488
|
+
@media (max-width: 768px) {
|
|
489
|
+
.wv-inspector {
|
|
490
|
+
position: fixed;
|
|
491
|
+
right: 0;
|
|
492
|
+
top: 0;
|
|
493
|
+
bottom: 0;
|
|
494
|
+
z-index: 100;
|
|
495
|
+
box-shadow: -4px 0 12px rgba(0, 0, 0, 0.1);
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
.wv-timeline {
|
|
499
|
+
height: auto;
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
`}function He(e){return`
|
|
503
|
+
(function() {
|
|
504
|
+
'use strict';
|
|
505
|
+
|
|
506
|
+
// State
|
|
507
|
+
let selectedNodeId = null;
|
|
508
|
+
let transform = { x: 0, y: 0, scale: 1 };
|
|
509
|
+
let isDragging = false;
|
|
510
|
+
let dragStart = { x: 0, y: 0 };
|
|
511
|
+
let ws = null;
|
|
512
|
+
let snapshots = [];
|
|
513
|
+
let currentSnapshotIndex = -1;
|
|
514
|
+
let isPlaying = false;
|
|
515
|
+
let playbackSpeed = 1;
|
|
516
|
+
let heatmapEnabled = false;
|
|
517
|
+
let heatmapMetric = 'duration';
|
|
518
|
+
|
|
519
|
+
// DOM elements
|
|
520
|
+
const diagram = document.getElementById('diagram');
|
|
521
|
+
const svg = diagram?.querySelector('svg');
|
|
522
|
+
const inspector = document.getElementById('inspector');
|
|
523
|
+
const timeline = document.getElementById('timeline');
|
|
524
|
+
|
|
525
|
+
// Initialize
|
|
526
|
+
document.addEventListener('DOMContentLoaded', init);
|
|
527
|
+
|
|
528
|
+
function init() {
|
|
529
|
+
${e.interactive?"setupInteractivity();":""}
|
|
530
|
+
${e.timeTravel?"setupTimeTravel();":""}
|
|
531
|
+
${e.wsUrl?`setupWebSocket('${e.wsUrl}');`:""}
|
|
532
|
+
${e.heatmap?"setupHeatmap();":""}
|
|
533
|
+
setupKeyboardShortcuts();
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
// Interactivity
|
|
537
|
+
function setupInteractivity() {
|
|
538
|
+
if (!diagram || !svg) return;
|
|
539
|
+
|
|
540
|
+
// Zoom with mouse wheel
|
|
541
|
+
diagram.addEventListener('wheel', (e) => {
|
|
542
|
+
e.preventDefault();
|
|
543
|
+
const delta = e.deltaY > 0 ? 0.9 : 1.1;
|
|
544
|
+
const rect = diagram.getBoundingClientRect();
|
|
545
|
+
const x = e.clientX - rect.left;
|
|
546
|
+
const y = e.clientY - rect.top;
|
|
547
|
+
|
|
548
|
+
// Zoom towards cursor position
|
|
549
|
+
transform.scale *= delta;
|
|
550
|
+
transform.scale = Math.max(0.1, Math.min(5, transform.scale));
|
|
551
|
+
transform.x = x - (x - transform.x) * delta;
|
|
552
|
+
transform.y = y - (y - transform.y) * delta;
|
|
553
|
+
|
|
554
|
+
applyTransform();
|
|
555
|
+
});
|
|
556
|
+
|
|
557
|
+
// Pan with drag
|
|
558
|
+
diagram.addEventListener('mousedown', (e) => {
|
|
559
|
+
if (e.target === diagram || e.target === svg) {
|
|
560
|
+
isDragging = true;
|
|
561
|
+
dragStart = { x: e.clientX - transform.x, y: e.clientY - transform.y };
|
|
562
|
+
diagram.style.cursor = 'grabbing';
|
|
563
|
+
}
|
|
564
|
+
});
|
|
565
|
+
|
|
566
|
+
document.addEventListener('mousemove', (e) => {
|
|
567
|
+
if (!isDragging) return;
|
|
568
|
+
transform.x = e.clientX - dragStart.x;
|
|
569
|
+
transform.y = e.clientY - dragStart.y;
|
|
570
|
+
applyTransform();
|
|
571
|
+
});
|
|
572
|
+
|
|
573
|
+
document.addEventListener('mouseup', () => {
|
|
574
|
+
isDragging = false;
|
|
575
|
+
if (diagram) diagram.style.cursor = 'grab';
|
|
576
|
+
});
|
|
577
|
+
|
|
578
|
+
// Node selection
|
|
579
|
+
document.querySelectorAll('.wv-node').forEach((node) => {
|
|
580
|
+
node.addEventListener('click', (e) => {
|
|
581
|
+
e.stopPropagation();
|
|
582
|
+
selectNode(node.dataset.nodeId);
|
|
583
|
+
});
|
|
584
|
+
});
|
|
585
|
+
|
|
586
|
+
// Deselect on background click
|
|
587
|
+
diagram.addEventListener('click', (e) => {
|
|
588
|
+
if (e.target === diagram || e.target === svg) {
|
|
589
|
+
selectNode(null);
|
|
590
|
+
}
|
|
591
|
+
});
|
|
592
|
+
|
|
593
|
+
// Zoom buttons
|
|
594
|
+
document.getElementById('zoom-in')?.addEventListener('click', () => zoom(1.2));
|
|
595
|
+
document.getElementById('zoom-out')?.addEventListener('click', () => zoom(0.8));
|
|
596
|
+
document.getElementById('zoom-reset')?.addEventListener('click', resetZoom);
|
|
597
|
+
|
|
598
|
+
// Set initial cursor
|
|
599
|
+
diagram.style.cursor = 'grab';
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
function applyTransform() {
|
|
603
|
+
if (!svg) return;
|
|
604
|
+
const g = svg.querySelector('g.wv-root');
|
|
605
|
+
if (g) {
|
|
606
|
+
g.setAttribute('transform', 'translate(' + transform.x + ',' + transform.y + ') scale(' + transform.scale + ')');
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
function zoom(factor) {
|
|
611
|
+
if (!diagram) return;
|
|
612
|
+
const rect = diagram.getBoundingClientRect();
|
|
613
|
+
const centerX = rect.width / 2;
|
|
614
|
+
const centerY = rect.height / 2;
|
|
615
|
+
|
|
616
|
+
transform.scale *= factor;
|
|
617
|
+
transform.scale = Math.max(0.1, Math.min(5, transform.scale));
|
|
618
|
+
transform.x = centerX - (centerX - transform.x) * factor;
|
|
619
|
+
transform.y = centerY - (centerY - transform.y) * factor;
|
|
620
|
+
|
|
621
|
+
applyTransform();
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
function resetZoom() {
|
|
625
|
+
transform = { x: 0, y: 0, scale: 1 };
|
|
626
|
+
applyTransform();
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
function selectNode(nodeId) {
|
|
630
|
+
// Remove previous selection
|
|
631
|
+
document.querySelectorAll('.wv-node--selected').forEach((n) => {
|
|
632
|
+
n.classList.remove('wv-node--selected');
|
|
633
|
+
});
|
|
634
|
+
|
|
635
|
+
selectedNodeId = nodeId;
|
|
636
|
+
|
|
637
|
+
if (nodeId) {
|
|
638
|
+
const node = document.querySelector('[data-node-id="' + nodeId + '"]');
|
|
639
|
+
if (node) {
|
|
640
|
+
node.classList.add('wv-node--selected');
|
|
641
|
+
updateInspector(nodeId);
|
|
642
|
+
}
|
|
643
|
+
} else {
|
|
644
|
+
clearInspector();
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
function updateInspector(nodeId) {
|
|
649
|
+
const content = document.getElementById('inspector-content');
|
|
650
|
+
if (!content) return;
|
|
651
|
+
|
|
652
|
+
const nodeData = window.__WORKFLOW_DATA__?.nodes?.[nodeId];
|
|
653
|
+
if (!nodeData) {
|
|
654
|
+
// Clear and add empty message using safe DOM methods
|
|
655
|
+
while (content.firstChild) content.removeChild(content.firstChild);
|
|
656
|
+
const p = document.createElement('p');
|
|
657
|
+
p.className = 'wv-empty';
|
|
658
|
+
p.textContent = 'No data available';
|
|
659
|
+
content.appendChild(p);
|
|
660
|
+
return;
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
renderInspectorContent(content, nodeData);
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
function renderInspectorContent(container, node) {
|
|
667
|
+
// Clear container using safe DOM method
|
|
668
|
+
while (container.firstChild) container.removeChild(container.firstChild);
|
|
669
|
+
|
|
670
|
+
// Node Info section
|
|
671
|
+
const infoSection = createSection('Node Info');
|
|
672
|
+
infoSection.appendChild(createRow('Name', node.name || node.id));
|
|
673
|
+
infoSection.appendChild(createRow('Type', node.type));
|
|
674
|
+
|
|
675
|
+
// State badge
|
|
676
|
+
const stateRow = document.createElement('div');
|
|
677
|
+
stateRow.className = 'wv-inspector-row';
|
|
678
|
+
const stateLabel = document.createElement('span');
|
|
679
|
+
stateLabel.className = 'wv-inspector-label';
|
|
680
|
+
stateLabel.textContent = 'State';
|
|
681
|
+
const stateBadge = document.createElement('span');
|
|
682
|
+
stateBadge.className = 'wv-badge wv-badge--' + node.state;
|
|
683
|
+
stateBadge.textContent = node.state;
|
|
684
|
+
stateRow.appendChild(stateLabel);
|
|
685
|
+
stateRow.appendChild(stateBadge);
|
|
686
|
+
infoSection.appendChild(stateRow);
|
|
687
|
+
|
|
688
|
+
if (node.key) {
|
|
689
|
+
infoSection.appendChild(createRow('Key', node.key));
|
|
690
|
+
}
|
|
691
|
+
container.appendChild(infoSection);
|
|
692
|
+
|
|
693
|
+
// Timing section
|
|
694
|
+
if (node.durationMs !== undefined) {
|
|
695
|
+
const timingSection = createSection('Timing');
|
|
696
|
+
timingSection.appendChild(createRow('Duration', formatDuration(node.durationMs)));
|
|
697
|
+
if (node.startTs) {
|
|
698
|
+
timingSection.appendChild(createRow('Started', new Date(node.startTs).toLocaleTimeString()));
|
|
699
|
+
}
|
|
700
|
+
container.appendChild(timingSection);
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
// Retries section
|
|
704
|
+
if (node.retryCount !== undefined && node.retryCount > 0) {
|
|
705
|
+
const retrySection = createSection('Retries');
|
|
706
|
+
retrySection.appendChild(createRow('Retry Count', String(node.retryCount)));
|
|
707
|
+
container.appendChild(retrySection);
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
// Error section
|
|
711
|
+
if (node.error) {
|
|
712
|
+
const errorSection = createSection('Error');
|
|
713
|
+
const pre = document.createElement('pre');
|
|
714
|
+
pre.style.cssText = 'font-size:11px;overflow:auto;max-height:150px;background:var(--bg);padding:8px;border-radius:4px;';
|
|
715
|
+
pre.textContent = String(node.error);
|
|
716
|
+
errorSection.appendChild(pre);
|
|
717
|
+
container.appendChild(errorSection);
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
function createSection(title) {
|
|
722
|
+
const section = document.createElement('div');
|
|
723
|
+
section.className = 'wv-inspector-section';
|
|
724
|
+
const h3 = document.createElement('h3');
|
|
725
|
+
h3.textContent = title;
|
|
726
|
+
section.appendChild(h3);
|
|
727
|
+
return section;
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
function createRow(label, value) {
|
|
731
|
+
const row = document.createElement('div');
|
|
732
|
+
row.className = 'wv-inspector-row';
|
|
733
|
+
const labelSpan = document.createElement('span');
|
|
734
|
+
labelSpan.className = 'wv-inspector-label';
|
|
735
|
+
labelSpan.textContent = label;
|
|
736
|
+
const valueSpan = document.createElement('span');
|
|
737
|
+
valueSpan.className = 'wv-inspector-value';
|
|
738
|
+
valueSpan.textContent = value;
|
|
739
|
+
row.appendChild(labelSpan);
|
|
740
|
+
row.appendChild(valueSpan);
|
|
741
|
+
return row;
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
function clearInspector() {
|
|
745
|
+
const content = document.getElementById('inspector-content');
|
|
746
|
+
if (content) {
|
|
747
|
+
while (content.firstChild) content.removeChild(content.firstChild);
|
|
748
|
+
const p = document.createElement('p');
|
|
749
|
+
p.className = 'wv-empty';
|
|
750
|
+
p.textContent = 'Select a node to inspect';
|
|
751
|
+
content.appendChild(p);
|
|
752
|
+
}
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
// Time Travel
|
|
756
|
+
function setupTimeTravel() {
|
|
757
|
+
const playBtn = document.getElementById('tt-play');
|
|
758
|
+
const pauseBtn = document.getElementById('tt-pause');
|
|
759
|
+
const prevBtn = document.getElementById('tt-prev');
|
|
760
|
+
const nextBtn = document.getElementById('tt-next');
|
|
761
|
+
const speedSelect = document.getElementById('tt-speed');
|
|
762
|
+
const slider = document.getElementById('tt-slider');
|
|
763
|
+
|
|
764
|
+
playBtn?.addEventListener('click', play);
|
|
765
|
+
pauseBtn?.addEventListener('click', pause);
|
|
766
|
+
prevBtn?.addEventListener('click', stepBackward);
|
|
767
|
+
nextBtn?.addEventListener('click', stepForward);
|
|
768
|
+
speedSelect?.addEventListener('change', (e) => {
|
|
769
|
+
playbackSpeed = parseFloat(e.target.value);
|
|
770
|
+
});
|
|
771
|
+
slider?.addEventListener('input', (e) => {
|
|
772
|
+
seek(parseInt(e.target.value, 10));
|
|
773
|
+
});
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
function play() {
|
|
777
|
+
if (snapshots.length === 0) return;
|
|
778
|
+
isPlaying = true;
|
|
779
|
+
updatePlaybackUI();
|
|
780
|
+
playNext();
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
function pause() {
|
|
784
|
+
isPlaying = false;
|
|
785
|
+
updatePlaybackUI();
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
function playNext() {
|
|
789
|
+
if (!isPlaying) return;
|
|
790
|
+
if (currentSnapshotIndex < snapshots.length - 1) {
|
|
791
|
+
const current = snapshots[currentSnapshotIndex];
|
|
792
|
+
const next = snapshots[currentSnapshotIndex + 1];
|
|
793
|
+
const delay = (next.timestamp - current.timestamp) / playbackSpeed;
|
|
794
|
+
|
|
795
|
+
setTimeout(() => {
|
|
796
|
+
stepForward();
|
|
797
|
+
playNext();
|
|
798
|
+
}, Math.max(16, delay));
|
|
799
|
+
} else {
|
|
800
|
+
pause();
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
function stepForward() {
|
|
805
|
+
if (currentSnapshotIndex < snapshots.length - 1) {
|
|
806
|
+
seek(currentSnapshotIndex + 1);
|
|
807
|
+
}
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
function stepBackward() {
|
|
811
|
+
if (currentSnapshotIndex > 0) {
|
|
812
|
+
seek(currentSnapshotIndex - 1);
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
function seek(index) {
|
|
817
|
+
if (index < 0 || index >= snapshots.length) return;
|
|
818
|
+
currentSnapshotIndex = index;
|
|
819
|
+
updateTimelineUI();
|
|
820
|
+
|
|
821
|
+
// Request IR update from server or use cached
|
|
822
|
+
if (ws && ws.readyState === WebSocket.OPEN) {
|
|
823
|
+
ws.send(JSON.stringify({ type: 'time_travel_seek', payload: { index } }));
|
|
824
|
+
} else if (snapshots[index]?.ir) {
|
|
825
|
+
renderIR(snapshots[index].ir);
|
|
826
|
+
}
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
function updatePlaybackUI() {
|
|
830
|
+
const playBtn = document.getElementById('tt-play');
|
|
831
|
+
const pauseBtn = document.getElementById('tt-pause');
|
|
832
|
+
|
|
833
|
+
if (playBtn) playBtn.style.display = isPlaying ? 'none' : 'inline-flex';
|
|
834
|
+
if (pauseBtn) pauseBtn.style.display = isPlaying ? 'inline-flex' : 'none';
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
function updateTimelineUI() {
|
|
838
|
+
const slider = document.getElementById('tt-slider');
|
|
839
|
+
const timeDisplay = document.getElementById('tt-time');
|
|
840
|
+
|
|
841
|
+
if (slider) {
|
|
842
|
+
slider.max = String(Math.max(0, snapshots.length - 1));
|
|
843
|
+
slider.value = String(currentSnapshotIndex);
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
if (timeDisplay) {
|
|
847
|
+
timeDisplay.textContent = (currentSnapshotIndex + 1) + ' / ' + snapshots.length;
|
|
848
|
+
}
|
|
849
|
+
}
|
|
850
|
+
|
|
851
|
+
// WebSocket
|
|
852
|
+
function setupWebSocket(url) {
|
|
853
|
+
ws = new WebSocket(url);
|
|
854
|
+
|
|
855
|
+
ws.onopen = () => {
|
|
856
|
+
console.log('[Visualizer] Connected to server');
|
|
857
|
+
showLiveIndicator(true);
|
|
858
|
+
};
|
|
859
|
+
|
|
860
|
+
ws.onclose = () => {
|
|
861
|
+
console.log('[Visualizer] Disconnected from server');
|
|
862
|
+
showLiveIndicator(false);
|
|
863
|
+
// Attempt reconnect after 2 seconds
|
|
864
|
+
setTimeout(() => setupWebSocket(url), 2000);
|
|
865
|
+
};
|
|
866
|
+
|
|
867
|
+
ws.onmessage = (event) => {
|
|
868
|
+
try {
|
|
869
|
+
const msg = JSON.parse(event.data);
|
|
870
|
+
handleServerMessage(msg);
|
|
871
|
+
} catch (e) {
|
|
872
|
+
console.error('[Visualizer] Failed to parse message:', e);
|
|
873
|
+
}
|
|
874
|
+
};
|
|
875
|
+
|
|
876
|
+
ws.onerror = (error) => {
|
|
877
|
+
console.error('[Visualizer] WebSocket error:', error);
|
|
878
|
+
};
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
function handleServerMessage(msg) {
|
|
882
|
+
switch (msg.type) {
|
|
883
|
+
case 'ir_update':
|
|
884
|
+
renderIR(msg.payload);
|
|
885
|
+
break;
|
|
886
|
+
case 'snapshot':
|
|
887
|
+
snapshots.push(msg.payload);
|
|
888
|
+
currentSnapshotIndex = snapshots.length - 1;
|
|
889
|
+
updateTimelineUI();
|
|
890
|
+
break;
|
|
891
|
+
case 'snapshots_list':
|
|
892
|
+
snapshots = msg.payload;
|
|
893
|
+
currentSnapshotIndex = snapshots.length - 1;
|
|
894
|
+
updateTimelineUI();
|
|
895
|
+
break;
|
|
896
|
+
case 'performance_data':
|
|
897
|
+
window.__PERFORMANCE_DATA__ = msg.payload;
|
|
898
|
+
if (heatmapEnabled) applyHeatmap();
|
|
899
|
+
break;
|
|
900
|
+
case 'workflow_complete':
|
|
901
|
+
showLiveIndicator(false);
|
|
902
|
+
break;
|
|
903
|
+
case 'time_travel_state':
|
|
904
|
+
currentSnapshotIndex = msg.payload.currentIndex;
|
|
905
|
+
isPlaying = msg.payload.isPlaying;
|
|
906
|
+
playbackSpeed = msg.payload.playbackSpeed;
|
|
907
|
+
updateTimelineUI();
|
|
908
|
+
updatePlaybackUI();
|
|
909
|
+
break;
|
|
910
|
+
}
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
function showLiveIndicator(show) {
|
|
914
|
+
const indicator = document.getElementById('live-indicator');
|
|
915
|
+
if (indicator) {
|
|
916
|
+
indicator.style.display = show ? 'flex' : 'none';
|
|
917
|
+
}
|
|
918
|
+
}
|
|
919
|
+
|
|
920
|
+
// Heatmap
|
|
921
|
+
function setupHeatmap() {
|
|
922
|
+
const toggle = document.getElementById('heatmap-toggle');
|
|
923
|
+
const metricSelect = document.getElementById('heatmap-metric');
|
|
924
|
+
|
|
925
|
+
toggle?.addEventListener('click', () => {
|
|
926
|
+
heatmapEnabled = !heatmapEnabled;
|
|
927
|
+
toggle.classList.toggle('wv-btn--primary', heatmapEnabled);
|
|
928
|
+
if (heatmapEnabled) {
|
|
929
|
+
applyHeatmap();
|
|
930
|
+
} else {
|
|
931
|
+
removeHeatmap();
|
|
932
|
+
}
|
|
933
|
+
});
|
|
934
|
+
|
|
935
|
+
metricSelect?.addEventListener('change', (e) => {
|
|
936
|
+
heatmapMetric = e.target.value;
|
|
937
|
+
if (heatmapEnabled) applyHeatmap();
|
|
938
|
+
});
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
function applyHeatmap() {
|
|
942
|
+
const perfData = window.__PERFORMANCE_DATA__;
|
|
943
|
+
if (!perfData) return;
|
|
944
|
+
|
|
945
|
+
document.querySelectorAll('.wv-node').forEach((node) => {
|
|
946
|
+
const nodeId = node.dataset.nodeId;
|
|
947
|
+
const heat = perfData.heat?.[nodeId];
|
|
948
|
+
|
|
949
|
+
// Remove existing heat classes
|
|
950
|
+
node.classList.remove(
|
|
951
|
+
'wv-node--heat-cold',
|
|
952
|
+
'wv-node--heat-cool',
|
|
953
|
+
'wv-node--heat-neutral',
|
|
954
|
+
'wv-node--heat-warm',
|
|
955
|
+
'wv-node--heat-hot',
|
|
956
|
+
'wv-node--heat-critical'
|
|
957
|
+
);
|
|
958
|
+
|
|
959
|
+
if (heat !== undefined) {
|
|
960
|
+
const level = getHeatLevel(heat);
|
|
961
|
+
node.classList.add('wv-node--heat-' + level);
|
|
962
|
+
}
|
|
963
|
+
});
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
function removeHeatmap() {
|
|
967
|
+
document.querySelectorAll('.wv-node').forEach((node) => {
|
|
968
|
+
node.classList.remove(
|
|
969
|
+
'wv-node--heat-cold',
|
|
970
|
+
'wv-node--heat-cool',
|
|
971
|
+
'wv-node--heat-neutral',
|
|
972
|
+
'wv-node--heat-warm',
|
|
973
|
+
'wv-node--heat-hot',
|
|
974
|
+
'wv-node--heat-critical'
|
|
975
|
+
);
|
|
976
|
+
});
|
|
977
|
+
}
|
|
978
|
+
|
|
979
|
+
function getHeatLevel(heat) {
|
|
980
|
+
if (heat < 0.2) return 'cold';
|
|
981
|
+
if (heat < 0.4) return 'cool';
|
|
982
|
+
if (heat < 0.6) return 'neutral';
|
|
983
|
+
if (heat < 0.8) return 'warm';
|
|
984
|
+
if (heat < 0.95) return 'hot';
|
|
985
|
+
return 'critical';
|
|
986
|
+
}
|
|
987
|
+
|
|
988
|
+
// Keyboard shortcuts
|
|
989
|
+
function setupKeyboardShortcuts() {
|
|
990
|
+
document.addEventListener('keydown', (e) => {
|
|
991
|
+
// Don't trigger shortcuts when typing in inputs
|
|
992
|
+
if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA') return;
|
|
993
|
+
|
|
994
|
+
switch (e.key) {
|
|
995
|
+
case ' ':
|
|
996
|
+
e.preventDefault();
|
|
997
|
+
isPlaying ? pause() : play();
|
|
998
|
+
break;
|
|
999
|
+
case 'ArrowLeft':
|
|
1000
|
+
e.preventDefault();
|
|
1001
|
+
stepBackward();
|
|
1002
|
+
break;
|
|
1003
|
+
case 'ArrowRight':
|
|
1004
|
+
e.preventDefault();
|
|
1005
|
+
stepForward();
|
|
1006
|
+
break;
|
|
1007
|
+
case '0':
|
|
1008
|
+
resetZoom();
|
|
1009
|
+
break;
|
|
1010
|
+
case '+':
|
|
1011
|
+
case '=':
|
|
1012
|
+
zoom(1.2);
|
|
1013
|
+
break;
|
|
1014
|
+
case '-':
|
|
1015
|
+
zoom(0.8);
|
|
1016
|
+
break;
|
|
1017
|
+
case 'h':
|
|
1018
|
+
${e.heatmap?"document.getElementById('heatmap-toggle')?.click();":""}
|
|
1019
|
+
break;
|
|
1020
|
+
case 'Escape':
|
|
1021
|
+
selectNode(null);
|
|
1022
|
+
break;
|
|
1023
|
+
}
|
|
1024
|
+
});
|
|
1025
|
+
}
|
|
1026
|
+
|
|
1027
|
+
// Render functions
|
|
1028
|
+
function renderIR(ir) {
|
|
1029
|
+
// Store node data for inspector
|
|
1030
|
+
window.__WORKFLOW_DATA__ = {
|
|
1031
|
+
nodes: flattenNodes(ir.root.children).reduce((acc, n) => {
|
|
1032
|
+
acc[n.id] = n;
|
|
1033
|
+
return acc;
|
|
1034
|
+
}, {})
|
|
1035
|
+
};
|
|
1036
|
+
|
|
1037
|
+
// Update SVG node states
|
|
1038
|
+
document.querySelectorAll('.wv-node').forEach((node) => {
|
|
1039
|
+
const nodeId = node.dataset.nodeId;
|
|
1040
|
+
const nodeData = window.__WORKFLOW_DATA__.nodes[nodeId];
|
|
1041
|
+
if (nodeData) {
|
|
1042
|
+
// Update state class
|
|
1043
|
+
node.className = node.className.replace(/wv-node--\\w+/g, '');
|
|
1044
|
+
node.classList.add('wv-node', 'wv-node--' + nodeData.state);
|
|
1045
|
+
|
|
1046
|
+
// Update timing text if present
|
|
1047
|
+
const timing = node.querySelector('.wv-node-timing');
|
|
1048
|
+
if (timing && nodeData.durationMs !== undefined) {
|
|
1049
|
+
timing.textContent = formatDuration(nodeData.durationMs);
|
|
1050
|
+
}
|
|
1051
|
+
}
|
|
1052
|
+
});
|
|
1053
|
+
|
|
1054
|
+
// Update selected node inspector
|
|
1055
|
+
if (selectedNodeId) {
|
|
1056
|
+
updateInspector(selectedNodeId);
|
|
1057
|
+
}
|
|
1058
|
+
}
|
|
1059
|
+
|
|
1060
|
+
function flattenNodes(nodes) {
|
|
1061
|
+
const result = [];
|
|
1062
|
+
for (const node of nodes) {
|
|
1063
|
+
result.push(node);
|
|
1064
|
+
if (node.children) {
|
|
1065
|
+
result.push(...flattenNodes(node.children));
|
|
1066
|
+
}
|
|
1067
|
+
if (node.branches) {
|
|
1068
|
+
for (const branch of node.branches) {
|
|
1069
|
+
result.push(...flattenNodes(branch.children));
|
|
1070
|
+
}
|
|
1071
|
+
}
|
|
1072
|
+
}
|
|
1073
|
+
return result;
|
|
1074
|
+
}
|
|
1075
|
+
|
|
1076
|
+
// Utilities
|
|
1077
|
+
function formatDuration(ms) {
|
|
1078
|
+
if (ms < 1) return '<1ms';
|
|
1079
|
+
if (ms < 1000) return Math.round(ms) + 'ms';
|
|
1080
|
+
if (ms < 60000) return (ms / 1000).toFixed(2) + 's';
|
|
1081
|
+
return (ms / 60000).toFixed(1) + 'm';
|
|
1082
|
+
}
|
|
1083
|
+
})();
|
|
1084
|
+
`}var ee=160,pe=50,$e=40,_t=30,A=20;function Ct(e,n="TB"){let t=n==="TB"||n==="BT",a=[],o=A,r=A,c=0,p=0;for(let d of e){let u=Re(d,o,r,t);a.push(u.node),t?(r+=u.height+_t,c=Math.max(c,u.width),p=r):(o+=u.width+$e,p=Math.max(p,u.height),c=o)}return{nodes:a,width:c+A,height:p+A}}function Re(e,n,t,a){if(V(e))return{node:{id:e.id,name:e.name??e.key??"step",type:"step",state:e.state,x:n,y:t,width:ee,height:pe,durationMs:e.durationMs},width:ee,height:pe};if(K(e)||Y(e)){let o=K(e)?"parallel":"race",r=e.name??o,c=[],p=n+A,d=t+A+20,u=0,s=0;for(let h of e.children){let k=Re(h,p,d,!0);c.push(k.node),p+=k.width+$e,s=Math.max(s,k.height)}u=p-n-A;let l=Math.max(u+A,ee+A*2),f=s+A*2+20;return{node:{id:e.id,name:r,type:o,state:e.state,x:n,y:t,width:l,height:f,durationMs:e.durationMs,children:c,containerType:o,containerLabel:o==="parallel"?"PARALLEL":"RACE"},width:l,height:f}}if(X(e)){let o=e.name??"decision",r=[],c=n+A,p=t+A+20,d=0;for(let l of e.branches)for(let f of l.children){let h=Re(f,c,p,!0);r.push(h.node),c+=h.width+$e,d=Math.max(d,h.height)}let u=Math.max(c-n,ee+A*2),s=d+A*2+20;return{node:{id:e.id,name:o,type:"decision",state:e.state,x:n,y:t,width:u,height:s,durationMs:e.durationMs,children:r,containerType:"decision",containerLabel:"DECISION"},width:u,height:s}}return{node:{id:e.id,name:e.name??"unknown",type:e.type,state:e.state,x:n,y:t,width:ee,height:pe},width:ee,height:pe}}function Pe(e,n){return e.containerType?Wt(e,n):Ot(e,n)}function Ot(e,n){let a=n&&e.durationMs!==void 0?H(e.durationMs):"";return`
|
|
1085
|
+
<g class="wv-node wv-node--${e.state}" data-node-id="${ze(e.id)}" transform="translate(${e.x}, ${e.y})">
|
|
1086
|
+
<rect width="${e.width}" height="${e.height}" rx="8" ry="8" />
|
|
1087
|
+
<text x="${e.width/2}" y="${e.height/2-(a?4:0)}">${Ee(Pt(e.name,20))}</text>
|
|
1088
|
+
${a?`<text class="wv-node-timing" x="${e.width/2}" y="${e.height/2+12}">${a}</text>`:""}
|
|
1089
|
+
</g>
|
|
1090
|
+
`}function Wt(e,n){let a=e.children?.map(o=>Pe(o,n)).join(`
|
|
1091
|
+
`)??"";return`
|
|
1092
|
+
<g class="wv-container wv-container--${e.containerType}" data-node-id="${ze(e.id)}" transform="translate(${e.x}, ${e.y})">
|
|
1093
|
+
<rect width="${e.width}" height="${e.height}" rx="12" ry="12" />
|
|
1094
|
+
<text class="wv-container-label" x="${A}" y="16">${e.containerLabel}</text>
|
|
1095
|
+
<g transform="translate(${-e.x}, ${-e.y})">
|
|
1096
|
+
${a}
|
|
1097
|
+
</g>
|
|
1098
|
+
</g>
|
|
1099
|
+
`}function Lt(e){let n=[];for(let t=0;t<e.length-1;t++){let a=e[t],o=e[t+1],r=a.x+a.width/2,c=a.y+a.height,p=o.x+o.width/2,d=o.y;n.push(`
|
|
1100
|
+
<path class="wv-edge" d="M ${r} ${c} L ${p} ${d-8}" />
|
|
1101
|
+
<polygon class="wv-edge-arrow" points="${p-4},${d-8} ${p+4},${d-8} ${p},${d}" />
|
|
1102
|
+
`)}return n.join(`
|
|
1103
|
+
`)}function Ae(e,n){let t=Ct(e.root.children,n.layout),a=Math.max(t.width,400),o=Math.max(t.height,300),r=t.nodes.map(s=>Pe(s,n.showTimings)).join(`
|
|
1104
|
+
`),c=Lt(t.nodes),p=e.root.name??"Workflow",d=Be(n.theme),u=He({wsUrl:n.wsUrl,interactive:n.interactive,timeTravel:n.timeTravel,heatmap:n.heatmap});return`<!DOCTYPE html>
|
|
1105
|
+
<html lang="en">
|
|
1106
|
+
<head>
|
|
1107
|
+
<meta charset="UTF-8">
|
|
1108
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
1109
|
+
<title>${Ee(p)} - Workflow Visualizer</title>
|
|
1110
|
+
<style>${d}</style>
|
|
1111
|
+
</head>
|
|
1112
|
+
<body>
|
|
1113
|
+
<div class="workflow-visualizer">
|
|
1114
|
+
<header class="wv-header">
|
|
1115
|
+
<h1>${Ee(p)}</h1>
|
|
1116
|
+
<div class="wv-controls">
|
|
1117
|
+
${n.wsUrl?'<div id="live-indicator" class="wv-live" style="display:none"><span class="wv-live-dot"></span>LIVE</div>':""}
|
|
1118
|
+
${n.heatmap?`
|
|
1119
|
+
<button id="heatmap-toggle" class="wv-btn">Heatmap</button>
|
|
1120
|
+
<select id="heatmap-metric" class="wv-btn">
|
|
1121
|
+
<option value="duration">Duration</option>
|
|
1122
|
+
<option value="retryRate">Retry Rate</option>
|
|
1123
|
+
<option value="errorRate">Error Rate</option>
|
|
1124
|
+
</select>
|
|
1125
|
+
`:""}
|
|
1126
|
+
${n.interactive?`
|
|
1127
|
+
<button id="zoom-out" class="wv-btn wv-btn--icon" title="Zoom out (-)">\u2212</button>
|
|
1128
|
+
<button id="zoom-reset" class="wv-btn wv-btn--icon" title="Reset zoom (0)">\u27F2</button>
|
|
1129
|
+
<button id="zoom-in" class="wv-btn wv-btn--icon" title="Zoom in (+)">+</button>
|
|
1130
|
+
`:""}
|
|
1131
|
+
</div>
|
|
1132
|
+
</header>
|
|
1133
|
+
|
|
1134
|
+
<div class="wv-main">
|
|
1135
|
+
<div id="diagram" class="wv-diagram">
|
|
1136
|
+
<svg viewBox="0 0 ${a} ${o}" preserveAspectRatio="xMidYMid meet">
|
|
1137
|
+
<g class="wv-root">
|
|
1138
|
+
${c}
|
|
1139
|
+
${r}
|
|
1140
|
+
</g>
|
|
1141
|
+
</svg>
|
|
1142
|
+
</div>
|
|
1143
|
+
|
|
1144
|
+
${n.interactive?`
|
|
1145
|
+
<aside id="inspector" class="wv-inspector">
|
|
1146
|
+
<div class="wv-inspector-header">
|
|
1147
|
+
<h2>Inspector</h2>
|
|
1148
|
+
</div>
|
|
1149
|
+
<div id="inspector-content" class="wv-inspector-content">
|
|
1150
|
+
<p class="wv-empty">Select a node to inspect</p>
|
|
1151
|
+
</div>
|
|
1152
|
+
</aside>
|
|
1153
|
+
`:""}
|
|
1154
|
+
</div>
|
|
1155
|
+
|
|
1156
|
+
${n.timeTravel?`
|
|
1157
|
+
<div id="timeline" class="wv-timeline">
|
|
1158
|
+
<div class="wv-timeline-track">
|
|
1159
|
+
<input type="range" id="tt-slider" min="0" max="0" value="0" style="width:100%">
|
|
1160
|
+
</div>
|
|
1161
|
+
<div class="wv-timeline-controls">
|
|
1162
|
+
<button id="tt-prev" class="wv-btn wv-btn--icon" title="Step backward (\u2190)">\u23EE</button>
|
|
1163
|
+
<button id="tt-play" class="wv-btn wv-btn--icon" title="Play (Space)">\u25B6</button>
|
|
1164
|
+
<button id="tt-pause" class="wv-btn wv-btn--icon" style="display:none" title="Pause (Space)">\u23F8</button>
|
|
1165
|
+
<button id="tt-next" class="wv-btn wv-btn--icon" title="Step forward (\u2192)">\u23ED</button>
|
|
1166
|
+
<select id="tt-speed" class="wv-btn">
|
|
1167
|
+
<option value="0.5">0.5x</option>
|
|
1168
|
+
<option value="1" selected>1x</option>
|
|
1169
|
+
<option value="2">2x</option>
|
|
1170
|
+
<option value="4">4x</option>
|
|
1171
|
+
<option value="10">10x</option>
|
|
1172
|
+
</select>
|
|
1173
|
+
<span id="tt-time" class="wv-timeline-time">0 / 0</span>
|
|
1174
|
+
</div>
|
|
1175
|
+
</div>
|
|
1176
|
+
`:""}
|
|
1177
|
+
</div>
|
|
1178
|
+
|
|
1179
|
+
<script>
|
|
1180
|
+
window.__WORKFLOW_DATA__ = ${Ht(e)};
|
|
1181
|
+
</script>
|
|
1182
|
+
<script>${u}</script>
|
|
1183
|
+
</body>
|
|
1184
|
+
</html>`}function Bt(e){let n={};function t(a){for(let o of a)if(n[o.id]={id:o.id,name:o.name,type:o.type,state:o.state,key:o.key,durationMs:o.durationMs,startTs:o.startTs,error:o.error?String(o.error):void 0,retryCount:o.retryCount},"children"in o&&Array.isArray(o.children)&&t(o.children),"branches"in o)for(let r of o.branches)t(r.children)}return t(e.root.children),{nodes:n}}function Ht(e){return JSON.stringify(Bt(e)).replace(/</g,"\\u003c").replace(/>/g,"\\u003e").replace(/&/g,"\\u0026").replace(/\u2028/g,"\\u2028").replace(/\u2029/g,"\\u2029")}function Ee(e){return e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}function ze(e){return e.replace(/"/g,""").replace(/'/g,"'")}function Pt(e,n){return e.length<=n?e:e.slice(0,n-1)+"\u2026"}var Fe={interactive:!0,timeTravel:!0,heatmap:!0,animationDuration:200,theme:"auto",layout:"TB"};function Ve(){return{name:"html",supportsLive:!0,render(e,n){let t={...n,...Fe,...n};return Ae(e,t)}}}function fe(e,n={}){let t={showTimings:!0,showKeys:!1,colors:{pending:"#6c757d",running:"#ffc107",success:"#198754",error:"#dc3545",aborted:"#6c757d",cached:"#0dcaf0",skipped:"#adb5bd"},...Fe,...n};return Ae(e,t)}var q={clearToEnd:"\x1B[J",cursorUp:e=>`\x1B[${e}A`,cursorToStart:"\x1B[G",hideCursor:"\x1B[?25l",showCursor:"\x1B[?25h",saveCursor:"\x1B[s",restoreCursor:"\x1B[u"};function Ue(e={}){let{workflowName:n,detectParallel:t=!0,showTimings:a=!0,showKeys:o=!1,colors:r,stream:c=process.stdout,updateInterval:p=100}=e,d=j({detectParallel:t}),u=Z(),s={showTimings:a,showKeys:o,terminalWidth:c.columns??80,colors:{...U,...r}},l=!1,f="",h=0,k=null,v=!1;function R(N){c.writable&&c.write(N)}function T(){if(!l)return;let N=w(),S=u.render(N,s);S!==f&&(h>0&&(R(q.cursorUp(h)),R(q.cursorToStart),R(q.clearToEnd)),R(S),R(`
|
|
1185
|
+
`),f=S,h=S.split(`
|
|
1186
|
+
`).length)}function B(){l&&(v=!0,k===null&&(k=setTimeout(()=>{k=null,v&&(v=!1,T())},p)))}function O(N){if(N.type==="scope_start"||N.type==="scope_end"){g(N);return}d.handleEvent(N),l&&(N.type==="workflow_start"||N.type==="workflow_success"||N.type==="workflow_error"?T():B())}function g(N){d.handleScopeEvent(N),l&&B()}function I(N){d.handleDecisionEvent(N),l&&B()}function w(){let N=d.getIR();return n&&!N.root.name&&(N.root.name=n),N}function $(){return u.render(w(),s)}function W(){l||(l=!0,f="",h=0,R(q.hideCursor),T())}function C(){if(!l)return;l=!1,k!==null&&(clearTimeout(k),k=null);let N=w(),S=u.render(N,s);h>0&&(R(q.cursorUp(h)),R(q.cursorToStart),R(q.clearToEnd)),R(S),R(`
|
|
1187
|
+
`),R(q.showCursor)}function D(){k!==null&&(clearTimeout(k),k=null),v=!1,T()}function M(){d.reset(),f="",h=0}return{handleEvent:O,handleScopeEvent:g,handleDecisionEvent:I,getIR:w,render:$,start:W,stop:C,refresh:D,reset:M}}function me(e,n={}){let{condition:t,value:a,name:o,workflowId:r=crypto.randomUUID(),emit:c}=n,p=Date.now(),d,u=[];function s(f,h,k){u.push({label:f,condition:k,taken:h}),h&&(d=f),c?.({type:"decision_branch",workflowId:r,decisionId:e,branchLabel:f,condition:k,taken:h,ts:Date.now()})}function l(){let f=Date.now()-p;c?.({type:"decision_end",workflowId:r,decisionId:e,branchTaken:d,ts:Date.now(),durationMs:f})}return c?.({type:"decision_start",workflowId:r,decisionId:e,condition:t,decisionValue:a,name:o,ts:p}),{takeBranch:s,end:l,getBranchTaken:()=>d,getBranches:()=>[...u]}}function je(e,n,t={}){let a=me(e,{...t,condition:t.condition??String(n),value:t.value??n});return{...a,condition:n,then:()=>{a.takeBranch("if",!0)},else:()=>{a.takeBranch("else",!0)}}}function Ke(e,n,t={}){let a=me(e,{...t,condition:t.condition??`switch(${String(n)})`,value:n});return{...a,value:n,case:(o,r)=>{a.takeBranch(`case '${o}'`,r,`value === '${o}'`)},default:o=>{a.takeBranch("default",o)}}}function he(e={}){let{maxSnapshots:n=1e3,autoRecord:t=!0,builderOptions:a={}}=e,o=j({...a,enableSnapshots:!0,maxSnapshots:n}),r={snapshots:[],currentIndex:-1,isPlaying:!1,playbackSpeed:1,isRecording:t},c=new Set,p=null;function d(){let D=g();for(let M of c)M(D)}function u(){r.snapshots=o.getSnapshots(),r.isRecording&&r.snapshots.length>0&&(r.currentIndex=r.snapshots.length-1)}function s(D){o.handleEvent(D),r.isRecording&&(u(),d())}function l(D){let M=o.getSnapshots();if(!(D<0||D>=M.length))return r.currentIndex=D,r.snapshots=M,d(),M[D].ir}function f(){return l(r.currentIndex+1)}function h(){return l(r.currentIndex-1)}function k(D=1){r.playbackSpeed=D,r.isPlaying=!0,d();let M=()=>{if(!r.isPlaying)return;let N=o.getSnapshots();if(r.currentIndex<N.length-1){let S=N[r.currentIndex],L=(N[r.currentIndex+1].timestamp-S.timestamp)/r.playbackSpeed;p=setTimeout(()=>{f(),M()},Math.max(16,L))}else v()};M()}function v(){r.isPlaying=!1,p&&(clearTimeout(p),p=null),d()}function R(){let D=o.getSnapshots();return r.currentIndex>=0&&r.currentIndex<D.length?D[r.currentIndex].ir:o.getIR()}function T(D){return o.getIRAt(D)}function B(){return o.getSnapshots()}function O(D){return o.getSnapshotAt(D)}function g(){return{snapshots:o.getSnapshots(),currentIndex:r.currentIndex,isPlaying:r.isPlaying,playbackSpeed:r.playbackSpeed,isRecording:r.isRecording}}function I(D){return c.add(D),()=>c.delete(D)}function w(){r.isRecording=!0,d()}function $(){r.isRecording=!1,d()}function W(){v(),o.reset(),r={snapshots:[],currentIndex:-1,isPlaying:!1,playbackSpeed:1,isRecording:t},d()}function C(){return o}return{handleEvent:s,seek:l,stepForward:f,stepBackward:h,play:k,pause:v,getCurrentIR:R,getIRAt:T,getSnapshots:B,getSnapshotAt:O,getState:g,onStateChange:I,startRecording:w,stopRecording:$,reset:W,getBuilder:C}}var Ge=require("http"),ge=require("child_process");async function qe(e={}){let{port:n=3377,host:t="localhost",autoOpen:a=!0,workflowName:o="Workflow",timeTravel:r=!0,heatmap:c=!0,maxSnapshots:p=1e3}=e,d=he({maxSnapshots:p}),u=le(),s=null,l=null,f=n,h=!1;function k(S){if(!l)return;let x=JSON.stringify(S);for(let E of l.clients)E.readyState===E.OPEN&&E.send(x)}function v(S,x){try{let E=JSON.parse(typeof x=="string"?x:x.toString());switch(E.type){case"time_travel_seek":{let L=E.payload,i=d.seek(L.index);i&&S.send(JSON.stringify({type:"ir_update",payload:i}));break}case"time_travel_play":{let L=E.payload;d.play(L?.speed);break}case"time_travel_pause":d.pause();break;case"time_travel_step_forward":{let L=d.stepForward();L&&S.send(JSON.stringify({type:"ir_update",payload:L}));break}case"time_travel_step_backward":{let L=d.stepBackward();L&&S.send(JSON.stringify({type:"ir_update",payload:L}));break}case"request_snapshots":{let L=d.getSnapshots().map(i=>({id:i.id,eventIndex:i.eventIndex,timestamp:i.timestamp}));S.send(JSON.stringify({type:"snapshots_list",payload:L}));break}case"toggle_heatmap":case"set_heatmap_metric":break}}catch(E){console.error("[DevServer] Failed to handle message:",E)}}function R(){let S=d.getCurrentIR(),x=`ws://${t}:${f}`;return fe(S,{interactive:!0,timeTravel:r,heatmap:c,theme:"auto",layout:"TB",wsUrl:x})}function T(S,x){let E=S.url??"/";if(E==="/"||E==="/index.html"){x.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),x.end(R());return}if(E==="/api/snapshots"){let L=d.getSnapshots().map(i=>({id:i.id,eventIndex:i.eventIndex,timestamp:i.timestamp}));x.writeHead(200,{"Content-Type":"application/json"}),x.end(JSON.stringify(L));return}if(E==="/api/performance"){x.writeHead(200,{"Content-Type":"application/json"}),x.end(u.exportData());return}if(E==="/api/ir"){x.writeHead(200,{"Content-Type":"application/json"}),x.end(JSON.stringify(d.getCurrentIR()));return}x.writeHead(404,{"Content-Type":"text/plain"}),x.end("Not Found")}async function B(){try{let x=await import("ws"),E=x.WebSocketServer??x.default?.WebSocketServer;return E?new E({noServer:!0}):(console.warn("[DevServer] WebSocket server class not found in ws module"),null)}catch{return console.warn(`[DevServer] ws package not installed. Live updates disabled.
|
|
1188
|
+
Install with: npm install ws`),null}}function O(S){let x=process.platform;if(!S.startsWith("http://localhost:")&&!S.startsWith("http://127.0.0.1:")){console.warn("[DevServer] Refusing to open non-localhost URL");return}x==="darwin"?(0,ge.execFile)("open",[S],E=>{E&&console.warn("[DevServer] Failed to open browser:",E.message)}):x==="win32"?(0,ge.execFile)("cmd.exe",["/c","start","",S],E=>{E&&console.warn("[DevServer] Failed to open browser:",E.message)}):(0,ge.execFile)("xdg-open",[S],E=>{E&&console.warn("[DevServer] Failed to open browser:",E.message)})}async function g(){return h?{port:f,url:`http://${t}:${f}`}:(s=(0,Ge.createServer)(T),l=await B(),l&&(s.on("upgrade",(S,x,E)=>{if(!l)return;l.handleUpgrade(S,x,E,i=>{i.send(JSON.stringify({type:"ir_update",payload:d.getCurrentIR()})),i.on("message",m=>v(i,m)),i.on("error",m=>console.error("[DevServer] WS error:",m))})}),d.onStateChange(S=>{k({type:"time_travel_state",payload:S})})),new Promise((S,x)=>{if(!s){x(new Error("HTTP server not initialized"));return}s.on("error",E=>{E.code==="EADDRINUSE"?(f++,s?.listen(f,t)):x(E)}),s.on("listening",()=>{h=!0;let E=`http://${t}:${f}`;console.log(`[DevServer] Visualizer running at ${E}`),a&&O(E),S({port:f,url:E})}),s.listen(f,t)}))}async function I(){if(h)return new Promise(S=>{l&&(l.close(),l=null),s?s.close(()=>{s=null,h=!1,S()}):S()})}function w(S){d.handleEvent(S),u.addEvent(S),k({type:"ir_update",payload:d.getCurrentIR()})}function $(S){k({type:"ir_update",payload:S})}function W(S){let x={};for(let[E,L]of S.heat)x[E]=L;k({type:"performance_data",payload:{...S,heat:x}})}function C(){u.finalizeRun("current"),k({type:"workflow_complete",payload:null})}function D(){return d}function M(){return u}function N(){return d.getCurrentIR()}return{start:g,stop:I,handleEvent:w,pushUpdate:$,pushHeatmap:W,complete:C,getTimeTravel:D,getAnalyzer:M,getCurrentIR:N}}function ve(e={}){let{workflowName:n,detectParallel:t=!0,showTimings:a=!0,showKeys:o=!1,colors:r}=e,c=j({detectParallel:t}),p=new Set,d=Z(),u=ie(),s={showTimings:a,showKeys:o,terminalWidth:process.stdout?.columns??80,colors:{...U,...r}};function l(){if(p.size>0){let g=c.getIR();for(let I of p)I(g)}}function f(g){if(g.type==="scope_start"||g.type==="scope_end"){h(g);return}c.handleEvent(g),g.type,l()}function h(g){c.handleScopeEvent(g),l()}function k(g){c.handleDecisionEvent(g),l()}function v(){let g=c.getIR();return n&&!g.root.name&&(g.root.name=n),g}function R(){let g=v();return d.render(g,s)}function T(g){let I=v();switch(g){case"ascii":return d.render(I,s);case"mermaid":return u.render(I,s);case"json":return JSON.stringify(I,null,2);default:throw new Error(`Unknown format: ${g}`)}}function B(){c.reset(),l()}function O(g){return p.add(g),()=>p.delete(g)}return{handleEvent:f,handleScopeEvent:h,handleDecisionEvent:k,getIR:v,render:R,renderAs:T,reset:B,onUpdate:O}}function At(e,n={}){let t=ve(n);for(let a of e)a.type.startsWith("decision_")?t.handleDecisionEvent(a):t.handleEvent(a);return t.render()}function zt(e={}){let n=[];return{handleEvent:t=>{n.push(t)},handleDecisionEvent:t=>{n.push(t)},getEvents:()=>[...n],getWorkflowEvents:()=>n.filter(t=>!t.type.startsWith("decision_")),getDecisionEvents:()=>n.filter(t=>t.type.startsWith("decision_")),clear:()=>{n.length=0},visualize:()=>{let t=ve(e);for(let a of n)a.type.startsWith("decision_")?t.handleDecisionEvent(a):t.handleEvent(a);return t.render()},visualizeAs:t=>{let a=ve(e);for(let o of n)o.type.startsWith("decision_")?a.handleDecisionEvent(o):a.handleEvent(o);return a.renderAs(t)}}}0&&(module.exports={asciiRenderer,createDevServer,createEventCollector,createIRBuilder,createLiveVisualizer,createParallelDetector,createPerformanceAnalyzer,createTimeTravelController,createVisualizer,defaultColorScheme,detectParallelGroups,getHeatLevel,hasChildren,htmlRenderer,isDecisionNode,isParallelNode,isRaceNode,isSequenceNode,isStepNode,mermaidRenderer,renderToHTML,trackDecision,trackIf,trackSwitch,visualizeEvents});
|
|
7
1189
|
//# sourceMappingURL=visualize.cjs.map
|