@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.js
CHANGED
|
@@ -1,7 +1,1189 @@
|
|
|
1
|
-
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 Y(){return`node_${Date.now()}_${Math.random().toString(36).slice(2,8)}`}function ce(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 A(e,n={}){if(ce(e))return e;let{minOverlapMs:t=0,maxGapMs:o=5}=n,a=[],r=[];for(let c=0;c<e.length;c++){let s=e[c];s.type==="step"&&s.startTs!==void 0?a.push({node:s,startTs:s.startTs,endTs:s.endTs??s.startTs+(s.durationMs??0),originalIndex:c}):r.push({node:s,originalIndex:c})}if(a.length<=1)return e;a.sort((c,s)=>c.startTs-s.startTs);let u=[],h=[a[0]];for(let c=1;c<a.length;c++){let s=a[c],l=Math.min(...h.map(y=>y.startTs)),g=Math.max(...h.map(y=>y.endTs)),$=s.startTs<=l+o,k=s.startTs<g;if(!$&&!k){u.push(h),h=[s];continue}let w=k?Math.min(s.endTs,g)-s.startTs:0;$||w>=t?h.push(s):(u.push(h),h=[s])}u.push(h);let p=[];for(let c of u){let s=Math.min(...c.map(l=>l.originalIndex));if(c.length===1)p.push({node:c[0].node,position:s});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:de(l),mode:"all",children:l,startTs:g,endTs:$,durationMs:$-g};p.push({node:k,position:s})}}for(let{node:c,originalIndex:s}of r)p.push({node:c,position:s});return p.sort((c,s)=>c.position-s.position),p.map(c=>c.node)}function de(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 le(e={}){return{detect:n=>A(n,e)}}function F(e={}){let{detectParallel:n=!0,parallelDetection:t}=e,o,a,r="pending",u,h,p=new Map,c=[],s=[],l=[],g=Date.now(),$=g;function k(i){return i.stepId??i.stepKey??i.name??Y()}function w(i){if(s.length>0){let d=s[s.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":o=i.workflowId,a=i.ts,r="running",g=Date.now(),$=g;break;case"workflow_success":r="success",h=i.durationMs,$=Date.now();break;case"workflow_error":r="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")s.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=s[s.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=s.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=A(i,t)),{root:{type:"workflow",id:o??Y(),workflowId:o??"unknown",state:r,startTs:a,durationMs:h,children:i,error:u},metadata:{createdAt:g,lastUpdatedAt:$}}}function W(){o=void 0,a=void 0,r="pending",u=void 0,h=void 0,p.clear(),c.length=0,s.length=0,l=[],g=Date.now(),$=g}return{handleEvent:y,handleScopeEvent:x,handleDecisionEvent:T,getIR:O,reset:W,get hasActiveSteps(){return p.size>0},get state(){return r}}}function _(e){return e.type==="step"}function Be(e){return e.type==="sequence"}function G(e){return e.type==="parallel"}function U(e){return e.type==="race"}function K(e){return e.type==="decision"}function Le(e){return"children"in e||e.type==="decision"&&"branches"in e}var H="\x1B[0m",ue="\x1B[1m",re="\x1B[2m",pe="\x1B[31m",fe="\x1B[32m",he="\x1B[33m",me="\x1B[34m",ne="\x1B[90m",ge="\x1B[37m";function j(e,n){return n?`${n}${e}${H}`:e}function z(e){return`${ue}${e}${H}`}function v(e){return`${re}${e}${H}`}var M={pending:ge,running:he,success:fe,error:pe,aborted:ne,cached:me,skipped:re+ne};function $e(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 P(e,n){let t=$e(e);return j(t,n[e])}function X(e,n,t){return j(e,t[n])}function oe(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 ie(e,n){let t=oe(e).length,o=Math.max(0,n-t);return e+" ".repeat(o)}function ke(e,n){if(!n)return f.horizontal.repeat(e);let t=` ${n} `,o=e-t.length;if(o<4)return f.horizontal.repeat(e);let a=2,r=o-a;return f.horizontal.repeat(a)+t+f.horizontal.repeat(r)}function L(){return{name:"ascii",supportsLive:!0,render(e,n){let t={...M,...n.colors},o=n.terminalWidth??60,a=o-4,r=[],u=e.root.name??"workflow",h=z(u);r.push(`${f.topLeft}${ke(o-2,h)}${f.topRight}`),r.push(`${f.vertical}${" ".repeat(o-2)}${f.vertical}`);let p=q(e.root.children,n,t,0);for(let c of p)r.push(`${f.vertical} ${ie(c,a)}${f.vertical}`);if(r.push(`${f.vertical}${" ".repeat(o-2)}${f.vertical}`),e.root.durationMs!==void 0&&n.showTimings){let c=e.root.state==="success"?"Completed":"Failed",l=`${X(c,e.root.state,t)} in ${N(e.root.durationMs)}`;r.push(`${f.vertical} ${ie(l,a)}${f.vertical}`),r.push(`${f.vertical}${" ".repeat(o-2)}${f.vertical}`)}return r.push(`${f.bottomLeft}${f.horizontal.repeat(o-2)}${f.bottomRight}`),r.join(`
|
|
2
|
-
`)}}}function q(e,n,t,o){let a=[];for(let r of e)_(r)?a.push(Q(r,n,t)):G(r)?a.push(...we(r,n,t,o)):U(r)?a.push(...be(r,n,t,o)):K(r)&&a.push(...ye(r,n,t,o));return a}function Q(e,n,t){let o=P(e.state,t),a=e.name??e.key??"step",r=X(a,e.state,t),u=`${o} ${r}`;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 we(e,n,t,o){let a=[],r=" ".repeat(o),u=P(e.state,t),h=e.name??"parallel",p=e.mode==="allSettled"?" (allSettled)":"";if(a.push(`${r}${f.teeRight}${f.teeDown}${f.horizontal} ${u} ${z(h)}${p}`),e.children.length===0)a.push(`${r}${f.vertical} ${v("(operations not individually tracked)")}`),a.push(`${r}${f.vertical} ${v("(wrap each operation with step() to see individual steps)")}`);else for(let c=0;c<e.children.length;c++){let s=e.children[c],g=c===e.children.length-1?`${r}${f.vertical} ${f.bottomLeft}`:`${r}${f.vertical} ${f.teeRight}`;if(_(s))a.push(`${g} ${Q(s,n,t)}`);else{let $=q([s],n,t,o+1);for(let k of $)a.push(`${r}${f.vertical} ${k}`)}}return n.showTimings&&e.durationMs!==void 0&&a.push(`${r}${f.bottomLeft}${f.horizontal}${f.horizontal} ${v(`[${N(e.durationMs)}]`)}`),a}function be(e,n,t,o){let a=[],r=" ".repeat(o),u=P(e.state,t),h=e.name??"race";if(a.push(`${r}${f.teeRight}\u26A1 ${u} ${z(h)}`),e.children.length===0)a.push(`${r}${f.vertical} ${v("(operations not individually tracked)")}`),a.push(`${r}${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?`${r}${f.vertical} ${f.bottomLeft}`:`${r}${f.vertical} ${f.teeRight}`,$=e.winnerId&&c.id===e.winnerId?v(" (winner)"):"";if(_(c))a.push(`${l} ${Q(c,n,t)}${$}`);else{let k=q([c],n,t,o+1);for(let w of k)a.push(`${r}${f.vertical} ${w}`)}}return n.showTimings&&e.durationMs!==void 0&&a.push(`${r}${f.bottomLeft}${f.horizontal}${f.horizontal} ${v(`[${N(e.durationMs)}]`)}`),a}function ye(e,n,t,o){let a=[],r=" ".repeat(o),u=P(e.state,t),h=e.name??"decision",p=e.condition?v(` (${e.condition})`):"",c=e.decisionValue!==void 0?v(` = ${String(e.decisionValue)}`):"",s=e.branchTaken!==void 0?v(` \u2192 ${String(e.branchTaken)}`):"";a.push(`${r}${f.teeRight}${f.teeDown}${f.horizontal} ${u} ${z(h)}${p}${c}${s}`);for(let l=0;l<e.branches.length;l++){let g=e.branches[l],k=l===e.branches.length-1?`${r}${f.vertical} ${f.bottomLeft}`:`${r}${f.vertical} ${f.teeRight}`,w=g.taken?"\u2713":"\u2298",y=g.taken?t.success:t.skipped,x=j(`${w} ${g.label}`,y),T=g.condition?v(` (${g.condition})`):"";if(a.push(`${k} ${x}${T}`),g.children.length>0){let R=q(g.children,n,t,o+1);for(let b of R)a.push(`${r}${f.vertical} ${b}`)}else g.taken||a.push(`${r}${f.vertical} ${v("(skipped)")}`)}return n.showTimings&&e.durationMs!==void 0&&a.push(`${r}${f.bottomLeft}${f.horizontal}${f.horizontal} ${v(`[${N(e.durationMs)}]`)}`),a}function Se(){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 se=0;function V(e="node"){return`${e}_${++se}`}function ve(){se=0}function D(e){return e.replace(/[{}[\]()]/g,"").replace(/[<>]/g,"").replace(/"/g,"'").trim()}function ae(e){return D(e).replace(/[[\]]/g,"")}function J(){return{name:"mermaid",supportsLive:!1,render(e,n){ve();let t=[];t.push("flowchart TD");let o="start";t.push(` ${o}(("\u25B6 Start"))`);let a=o;for(let r of e.root.children){let u=Z(r,n,t);t.push(` ${a} --> ${u.entryId}`),a=u.exitId}if(e.root.state==="success"||e.root.state==="error"){let r="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(` ${r}${p}${c}`),t.push(` ${a} --> ${r}`)}return t.push(""),t.push(...Se()),t.join(`
|
|
3
|
-
`)}}}function
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
function H(e){if(e<1e3)return`${Math.round(e)}ms`;if(e<6e4)return`${(e/1e3).toFixed(1).replace(/\.0$/,"")}s`;let r=Math.floor(e/6e4),t=Math.round(e%6e4/1e3);return t===0?`${r}m`:`${r}m ${t}s`}function le(){return`node_${Date.now()}_${Math.random().toString(36).slice(2,8)}`}function Ae(e){for(let r of e)if((r.type==="parallel"||r.type==="race"||r.type==="sequence")&&!r.id.startsWith("detected_")||"decisionId"in r)return!0;return!1}function oe(e,r={}){if(Ae(e))return e;let{minOverlapMs:t=0,maxGapMs:a=5}=r,o=[],n=[];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}):n.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:ze(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 n)d.push({node:u,position:s});return d.sort((u,s)=>u.position-s.position),d.map(u=>u.node)}function ze(e){return e.some(n=>n.state==="error")?"error":e.some(n=>n.state==="running")?"running":e.some(n=>n.state==="pending")?"pending":(e.every(n=>n.state==="success"||n.state==="cached"),"success")}function Fe(e={}){return{detect:r=>oe(r,e)}}function q(e={}){let{detectParallel:r=!0,parallelDetection:t,enableSnapshots:a=!1,maxSnapshots:o=1e3}=e,n,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??le()}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,G]of s)b.set(F,{id:G.id,name:G.name,key:G.key,startTs:G.startTs,retryCount:G.retryCount,timedOut:G.timedOut,timeoutMs:G.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":n=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();r&&(i=oe(i,t));let m={type:"workflow",id:n??le(),workflowId:n??"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(){n=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 Ct(e){return e.type==="sequence"}function J(e){return e.type==="parallel"}function Y(e){return e.type==="race"}function X(e){return e.type==="decision"}function Ot(e){return"children"in e||e.type==="decision"&&"branches"in e}var ue="\x1B[0m",Ve="\x1B[1m",Ie="\x1B[2m",Ue="\x1B[31m",je="\x1B[32m",Ke="\x1B[33m",Ge="\x1B[34m",Ee="\x1B[90m",qe="\x1B[37m";function U(e,r){return r?`${r}${e}${ue}`:e}function te(e){return`${Ve}${e}${ue}`}function _(e){return`${Ie}${e}${ue}`}var j={pending:qe,running:Ke,success:je,error:Ue,aborted:Ee,cached:Ge,skipped:Ie+Ee};function Je(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 ne(e,r){let t=Je(e);return U(t,r[e])}function pe(e,r,t){return U(e,t[r])}function De(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"},Z={cold:"\x1B[34m",cool:"\x1B[36m",neutral:"",warm:"\x1B[33m",hot:"\x1B[31m",critical:"\x1B[41m"},Ye="\x1B[0m";function Xe(e){return e<.2?Z.cold:e<.4?Z.cool:e<.6?Z.neutral:e<.8?Z.warm:e<.95?Z.hot:Z.critical}function Te(e,r){let t=Xe(r);return t?`${t}${e}${Ye}`:e}var Ne="\u2581\u2582\u2583\u2584\u2585\u2586\u2587\u2588";function Ze(e,r=10){if(e.length===0)return"";let t=e.slice(-r),a=Math.min(...t),n=Math.max(...t)-a||1;return t.map(c=>{let p=(c-a)/n,d=Math.floor(p*(Ne.length-1));return Ne[d]}).join("")}function fe(e,r){let t=De(e).length,a=Math.max(0,r-t);return e+" ".repeat(a)}function Qe(e,r){if(!r)return y.horizontal.repeat(e);let t=` ${r} `,a=e-t.length;if(a<4)return y.horizontal.repeat(e);let o=2,n=a-o;return y.horizontal.repeat(o)+t+y.horizontal.repeat(n)}function Me(e,r,t){let a=e.state==="success"?U("\u2699",t.success):U("\u26A0",t.error),o=e.durationMs!==void 0?_(` [${H(e.durationMs)}]`):"",n="";e.type==="shouldRun"&&e.context?.skipped?n=_(" \u2192 workflow skipped"):e.type==="shouldRun"&&e.context?.result===!0?n=_(" \u2192 proceed"):e.type==="onBeforeStart"&&e.context?.skipped?n=_(" \u2192 workflow skipped"):e.type==="onAfterStep"&&e.context?.stepKey&&(n=_(` (${e.context.stepKey})`));let c=e.state==="error"&&e.error?_(` error: ${String(e.error)}`):"";return`${a} ${_(r)}${n}${o}${c}`}function et(e,r){let t=[];return e.shouldRun&&t.push(Me(e.shouldRun,"shouldRun",r)),e.onBeforeStart&&t.push(Me(e.onBeforeStart,"onBeforeStart",r)),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 Q(){return{name:"ascii",supportsLive:!0,render(e,r){let t={...j,...r.colors},a=r.terminalWidth??60,o=a-4,n=[],c=e.root.name??"workflow",p=te(c);if(n.push(`${y.topLeft}${Qe(a-2,p)}${y.topRight}`),n.push(`${y.vertical}${" ".repeat(a-2)}${y.vertical}`),e.hooks){let u=et(e.hooks,t);for(let s of u)n.push(`${y.vertical} ${fe(s,o)}${y.vertical}`)}let d=ie(e.root.children,r,t,0,e.hooks);for(let u of d)n.push(`${y.vertical} ${fe(u,o)}${y.vertical}`);if(n.push(`${y.vertical}${" ".repeat(a-2)}${y.vertical}`),e.root.durationMs!==void 0&&r.showTimings){let u=e.root.state==="success"?"Completed":"Failed",l=`${pe(u,e.root.state,t)} in ${H(e.root.durationMs)}`;n.push(`${y.vertical} ${fe(l,o)}${y.vertical}`),n.push(`${y.vertical}${" ".repeat(a-2)}${y.vertical}`)}return n.push(`${y.bottomLeft}${y.horizontal.repeat(a-2)}${y.bottomRight}`),n.join(`
|
|
2
|
+
`)}}}function ie(e,r,t,a,o){let n=[];for(let c of e)V(c)?n.push(me(c,r,t,o)):J(c)?n.push(...tt(c,r,t,a,o)):Y(c)?n.push(...nt(c,r,t,a,o)):X(c)&&n.push(...rt(c,r,t,a,o));return n}function me(e,r,t,a){let o=ne(e.state,t),n=e.name??e.key??"step",c=r,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=Te(n,d):u=pe(n,e.state,t);let s=`${o} ${u}`;if(r.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(r.showTimings&&e.durationMs!==void 0){let l=H(e.durationMs),f=d!==void 0?Te(`[${l}]`,d):_(`[${l}]`);s+=` ${f}`}if(c.showSparklines&&c.timingHistory){let l=c.timingHistory.get(p);l&&l.length>1&&(s+=` ${_(Ze(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"?U("\u2699",t.success):U("\u26A0",t.error),h=l.durationMs!==void 0?_(` ${H(l.durationMs)}`):"";s+=` ${f}${h}`}return s}function tt(e,r,t,a,o){let n=[],c=" ".repeat(a),p=ne(e.state,t),d=e.name??"parallel",u=e.mode==="allSettled"?" (allSettled)":"";if(n.push(`${c}${y.teeRight}${y.teeDown}${y.horizontal} ${p} ${te(d)}${u}`),e.children.length===0)n.push(`${c}${y.vertical} ${_("(operations not individually tracked)")}`),n.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))n.push(`${h} ${me(l,r,t,o)}`);else{let k=ie([l],r,t,a+1,o);for(let v of k)n.push(`${c}${y.vertical} ${v}`)}}return r.showTimings&&e.durationMs!==void 0&&n.push(`${c}${y.bottomLeft}${y.horizontal}${y.horizontal} ${_(`[${H(e.durationMs)}]`)}`),n}function nt(e,r,t,a,o){let n=[],c=" ".repeat(a),p=ne(e.state,t),d=e.name??"race";if(n.push(`${c}${y.teeRight}\u26A1 ${p} ${te(d)}`),e.children.length===0)n.push(`${c}${y.vertical} ${_("(operations not individually tracked)")}`),n.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))n.push(`${f} ${me(s,r,t,o)}${k}`);else{let v=ie([s],r,t,a+1,o);for(let R of v)n.push(`${c}${y.vertical} ${R}`)}}return r.showTimings&&e.durationMs!==void 0&&n.push(`${c}${y.bottomLeft}${y.horizontal}${y.horizontal} ${_(`[${H(e.durationMs)}]`)}`),n}function rt(e,r,t,a,o){let n=[],c=" ".repeat(a),p=ne(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)}`):"";n.push(`${c}${y.teeRight}${y.teeDown}${y.horizontal} ${p} ${te(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=U(`${R} ${h.label}`,T),O=h.condition?_(` (${h.condition})`):"";if(n.push(`${v} ${B}${O}`),h.children.length>0){let g=ie(h.children,r,t,a+1,o);for(let I of g)n.push(`${c}${y.vertical} ${I}`)}else h.taken||n.push(`${c}${y.vertical} ${_("(skipped)")}`)}return r.showTimings&&e.durationMs!==void 0&&n.push(`${c}${y.bottomLeft}${y.horizontal}${y.horizontal} ${_(`[${H(e.durationMs)}]`)}`),n}function he(e){let r=[];for(let t of e)if(r.push(t),"children"in t&&Array.isArray(t.children)&&r.push(...he(t.children)),"branches"in t)for(let a of t.branches)r.push(...he(a.children));return r}function ae(e,r){if(e.length===0)return 0;let t=Math.floor(e.length*r);return e[Math.min(t,e.length-1)]}function ge(e){return e<.2?"cold":e<.4?"cool":e<.6?"neutral":e<.8?"warm":e<.95?"hot":"critical"}function ve(){let e=new Map,r=new Map,t=new Map,a=new Map,o=[];function n(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 $=n(w);I.set($,{retried:!1,timedOut:!1});break}case"step_retry":{let $=n(w),W=I.get($);W&&(W.retried=!0);break}case"step_timeout":{let $=n(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 $=n(w),W=I.get($),C=e.get($)??[];C.push(w.durationMs),e.set($,C);let D=r.get($)??{retried:0,total:0};D.total++,W?.retried&&D.retried++,r.set($,D);let M=t.get($)??{errors:0,total:0};M.total++,t.set($,M),I.delete($);break}case"step_error":{let $=n(w),W=I.get($),C=e.get($)??[];C.push(w.durationMs),e.set($,C);let D=r.get($)??{retried:0,total:0};D.total++,W?.retried&&D.retried++,r.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=r.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:ae(w,.5),p90:ae(w,.9),p95:ae(w,.95),p99:ae(w,.99)}}}function l(g){return s(g)}function f(g,I="duration"){let w=new Map,$=he(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(r),errorData:Object.fromEntries(t),timeoutData:Object.fromEntries(a)})}function B(g){let I=JSON.parse(g);e.clear(),r.clear(),t.clear(),a.clear();for(let[w,$]of Object.entries(I.timingData??{}))e.set(w,$);for(let[w,$]of Object.entries(I.retryData??{}))r.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(),r.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 ot(){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 it(){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 at(e){return`heat_${e}`}function st(){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 ct(e,r,t){let a;if(e.shouldRun){let o="hook_shouldRun",n=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":"";r.push(` ${o}[["${c} shouldRun${d}${p}"]]:::${n}`),a=o}if(e.onBeforeStart){let o="hook_beforeStart",n=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":"";r.push(` ${o}[["${c} onBeforeStart${d}${p}"]]:::${n}`),a&&r.push(` ${a} --> ${o}`),a=o}return{lastHookId:a}}var _e=0;function re(e="node"){return`${e}_${++_e}`}function dt(){_e=0}function z(e){return e.replace(/[{}[\]()]/g,"").replace(/[<>]/g,"").replace(/"/g,"'").trim()}function Ce(e){return z(e).replace(/[[\]]/g,"")}function se(){return{name:"mermaid",supportsLive:!1,render(e,r){dt();let t=[],a=r;t.push("flowchart TD");let o;e.hooks&&(o=ct(e.hooks,t,r).lastHookId);let n="start";t.push(` ${n}(("\u25B6 Start"))`),o&&t.push(` ${o} --> ${n}`);let c=n;for(let p of e.root.children){let d=ce(p,r,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(...ot()),a.showHeatmap&&t.push(...it()),e.hooks&&t.push(...st()),t.join(`
|
|
3
|
+
`)}}}function ce(e,r,t,a,o){if(V(e))return lt(e,r,t,a,o);if(J(e))return ut(e,r,t,a,o);if(Y(e))return pt(e,r,t,a,o);if(X(e))return ft(e,r,t,a,o);let n=re("unknown");return t.push(` ${n}[Unknown Node]`),{entryId:n,exitId:n}}function lt(e,r,t,a,o){let n=e.key?`step_${e.key.replace(/[^a-zA-Z0-9]/g,"_")}`:re("step"),c=z(e.name??e.key??"Step"),p=r.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=r.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=ge(v);h=at(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(` ${n}${R}:::${h}`),{entryId:n,exitId:n}}function ut(e,r,t,a,o){let n=re("parallel"),c=`${n}_fork`,p=`${n}_join`,d=Ce(e.name??"Parallel"),u=e.mode==="allSettled"?" (allSettled)":"";if(e.children.length===0){let f=n,h=z(`${d}${u}`),k="operations not individually tracked",v=r.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 ${n}["${d}${u}"]`),t.push(" direction TB"),t.push(` ${c}{"\u26A1 Fork"}`);let s=[];for(let f of e.children){let h=ce(f,r,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 ${n} ${l}`),{entryId:c,exitId:p}}function pt(e,r,t,a,o){let n=re("race"),c=`${n}_start`,p=`${n}_end`,d=Ce(e.name??"Race");if(e.children.length===0){let f=n,h=z(d),k="operations not individually tracked",v=r.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 ${n}["\u26A1 ${d}"]`),t.push(" direction TB"),t.push(` ${c}(("\u{1F3C1} Start"))`);let u=[],s;for(let f of e.children){let h=ce(f,r,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 ${n} ${l}`),{entryId:c,exitId:p}}function ft(e,r,t,a,o){let n=e.key?`decision_${e.key.replace(/[^a-zA-Z0-9]/g,"_")}`:re("decision"),c=z(e.condition??"condition"),p=e.decisionValue!==void 0?` = ${z(String(e.decisionValue)).slice(0,30)}`:"",d=`${c}${p}`.trim();t.push(` ${n}{${d}}`);let u=[],s;for(let l of e.branches){let f=`${n}_${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(` ${n} -->${R} ${f}`),l.children.length>0){let T=f;for(let B of l.children){let O=ce(B,r,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:n,exitId:s}:{entryId:n,exitId:n}}function Oe(e){let r={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=n=>`
|
|
4
|
+
--bg: ${n.bg};
|
|
5
|
+
--bg-secondary: ${n.bgSecondary};
|
|
6
|
+
--text: ${n.text};
|
|
7
|
+
--text-muted: ${n.textMuted};
|
|
8
|
+
--border: ${n.border};
|
|
9
|
+
--primary: ${n.primary};
|
|
10
|
+
--success: ${n.success};
|
|
11
|
+
--error: ${n.error};
|
|
12
|
+
--warning: ${n.warning};
|
|
13
|
+
--info: ${n.info};
|
|
14
|
+
--muted: ${n.muted};
|
|
15
|
+
--node-pending: ${n.nodePending};
|
|
16
|
+
--node-running: ${n.nodeRunning};
|
|
17
|
+
--node-success: ${n.nodeSuccess};
|
|
18
|
+
--node-error: ${n.nodeError};
|
|
19
|
+
--node-aborted: ${n.nodeAborted};
|
|
20
|
+
--node-cached: ${n.nodeCached};
|
|
21
|
+
--node-skipped: ${n.nodeSkipped};
|
|
22
|
+
--heat-cold: ${n.heatCold};
|
|
23
|
+
--heat-cool: ${n.heatCool};
|
|
24
|
+
--heat-neutral: ${n.heatNeutral};
|
|
25
|
+
--heat-warm: ${n.heatWarm};
|
|
26
|
+
--heat-hot: ${n.heatHot};
|
|
27
|
+
--heat-critical: ${n.heatCritical};
|
|
28
|
+
`,o;return e==="auto"?o=`
|
|
29
|
+
:root {
|
|
30
|
+
${a(r)}
|
|
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(r)}
|
|
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 We(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,de=50,we=40,mt=30,A=20;function ht(e,r="TB"){let t=r==="TB"||r==="BT",a=[],o=A,n=A,c=0,p=0;for(let d of e){let u=be(d,o,n,t);a.push(u.node),t?(n+=u.height+mt,c=Math.max(c,u.width),p=n):(o+=u.width+we,p=Math.max(p,u.height),c=o)}return{nodes:a,width:c+A,height:p+A}}function be(e,r,t,a){if(V(e))return{node:{id:e.id,name:e.name??e.key??"step",type:"step",state:e.state,x:r,y:t,width:ee,height:de,durationMs:e.durationMs},width:ee,height:de};if(J(e)||Y(e)){let o=J(e)?"parallel":"race",n=e.name??o,c=[],p=r+A,d=t+A+20,u=0,s=0;for(let h of e.children){let k=be(h,p,d,!0);c.push(k.node),p+=k.width+we,s=Math.max(s,k.height)}u=p-r-A;let l=Math.max(u+A,ee+A*2),f=s+A*2+20;return{node:{id:e.id,name:n,type:o,state:e.state,x:r,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",n=[],c=r+A,p=t+A+20,d=0;for(let l of e.branches)for(let f of l.children){let h=be(f,c,p,!0);n.push(h.node),c+=h.width+we,d=Math.max(d,h.height)}let u=Math.max(c-r,ee+A*2),s=d+A*2+20;return{node:{id:e.id,name:o,type:"decision",state:e.state,x:r,y:t,width:u,height:s,durationMs:e.durationMs,children:n,containerType:"decision",containerLabel:"DECISION"},width:u,height:s}}return{node:{id:e.id,name:e.name??"unknown",type:e.type,state:e.state,x:r,y:t,width:ee,height:de},width:ee,height:de}}function Le(e,r){return e.containerType?vt(e,r):gt(e,r)}function gt(e,r){let a=r&&e.durationMs!==void 0?H(e.durationMs):"";return`
|
|
1085
|
+
<g class="wv-node wv-node--${e.state}" data-node-id="${He(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)}">${ye(kt(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 vt(e,r){let a=e.children?.map(o=>Le(o,r)).join(`
|
|
1091
|
+
`)??"";return`
|
|
1092
|
+
<g class="wv-container wv-container--${e.containerType}" data-node-id="${He(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 wt(e){let r=[];for(let t=0;t<e.length-1;t++){let a=e[t],o=e[t+1],n=a.x+a.width/2,c=a.y+a.height,p=o.x+o.width/2,d=o.y;r.push(`
|
|
1100
|
+
<path class="wv-edge" d="M ${n} ${c} L ${p} ${d-8}" />
|
|
1101
|
+
<polygon class="wv-edge-arrow" points="${p-4},${d-8} ${p+4},${d-8} ${p},${d}" />
|
|
1102
|
+
`)}return r.join(`
|
|
1103
|
+
`)}function Be(e,r){let t=ht(e.root.children,r.layout),a=Math.max(t.width,400),o=Math.max(t.height,300),n=t.nodes.map(s=>Le(s,r.showTimings)).join(`
|
|
1104
|
+
`),c=wt(t.nodes),p=e.root.name??"Workflow",d=Oe(r.theme),u=We({wsUrl:r.wsUrl,interactive:r.interactive,timeTravel:r.timeTravel,heatmap:r.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>${ye(p)} - Workflow Visualizer</title>
|
|
1110
|
+
<style>${d}</style>
|
|
1111
|
+
</head>
|
|
1112
|
+
<body>
|
|
1113
|
+
<div class="workflow-visualizer">
|
|
1114
|
+
<header class="wv-header">
|
|
1115
|
+
<h1>${ye(p)}</h1>
|
|
1116
|
+
<div class="wv-controls">
|
|
1117
|
+
${r.wsUrl?'<div id="live-indicator" class="wv-live" style="display:none"><span class="wv-live-dot"></span>LIVE</div>':""}
|
|
1118
|
+
${r.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
|
+
${r.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
|
+
${n}
|
|
1140
|
+
</g>
|
|
1141
|
+
</svg>
|
|
1142
|
+
</div>
|
|
1143
|
+
|
|
1144
|
+
${r.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
|
+
${r.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__ = ${yt(e)};
|
|
1181
|
+
</script>
|
|
1182
|
+
<script>${u}</script>
|
|
1183
|
+
</body>
|
|
1184
|
+
</html>`}function bt(e){let r={};function t(a){for(let o of a)if(r[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 n of o.branches)t(n.children)}return t(e.root.children),{nodes:r}}function yt(e){return JSON.stringify(bt(e)).replace(/</g,"\\u003c").replace(/>/g,"\\u003e").replace(/&/g,"\\u0026").replace(/\u2028/g,"\\u2028").replace(/\u2029/g,"\\u2029")}function ye(e){return e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}function He(e){return e.replace(/"/g,""").replace(/'/g,"'")}function kt(e,r){return e.length<=r?e:e.slice(0,r-1)+"\u2026"}var Pe={interactive:!0,timeTravel:!0,heatmap:!0,animationDuration:200,theme:"auto",layout:"TB"};function St(){return{name:"html",supportsLive:!0,render(e,r){let t={...r,...Pe,...r};return Be(e,t)}}}function ke(e,r={}){let t={showTimings:!0,showKeys:!1,colors:{pending:"#6c757d",running:"#ffc107",success:"#198754",error:"#dc3545",aborted:"#6c757d",cached:"#0dcaf0",skipped:"#adb5bd"},...Pe,...r};return Be(e,t)}var K={clearToEnd:"\x1B[J",cursorUp:e=>`\x1B[${e}A`,cursorToStart:"\x1B[G",hideCursor:"\x1B[?25l",showCursor:"\x1B[?25h",saveCursor:"\x1B[s",restoreCursor:"\x1B[u"};function xt(e={}){let{workflowName:r,detectParallel:t=!0,showTimings:a=!0,showKeys:o=!1,colors:n,stream:c=process.stdout,updateInterval:p=100}=e,d=q({detectParallel:t}),u=Q(),s={showTimings:a,showKeys:o,terminalWidth:c.columns??80,colors:{...j,...n}},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(K.cursorUp(h)),R(K.cursorToStart),R(K.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 r&&!N.root.name&&(N.root.name=r),N}function $(){return u.render(w(),s)}function W(){l||(l=!0,f="",h=0,R(K.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(K.cursorUp(h)),R(K.cursorToStart),R(K.clearToEnd)),R(S),R(`
|
|
1187
|
+
`),R(K.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 Se(e,r={}){let{condition:t,value:a,name:o,workflowId:n=crypto.randomUUID(),emit:c}=r,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:n,decisionId:e,branchLabel:f,condition:k,taken:h,ts:Date.now()})}function l(){let f=Date.now()-p;c?.({type:"decision_end",workflowId:n,decisionId:e,branchTaken:d,ts:Date.now(),durationMs:f})}return c?.({type:"decision_start",workflowId:n,decisionId:e,condition:t,decisionValue:a,name:o,ts:p}),{takeBranch:s,end:l,getBranchTaken:()=>d,getBranches:()=>[...u]}}function $t(e,r,t={}){let a=Se(e,{...t,condition:t.condition??String(r),value:t.value??r});return{...a,condition:r,then:()=>{a.takeBranch("if",!0)},else:()=>{a.takeBranch("else",!0)}}}function Rt(e,r,t={}){let a=Se(e,{...t,condition:t.condition??`switch(${String(r)})`,value:r});return{...a,value:r,case:(o,n)=>{a.takeBranch(`case '${o}'`,n,`value === '${o}'`)},default:o=>{a.takeBranch("default",o)}}}function xe(e={}){let{maxSnapshots:r=1e3,autoRecord:t=!0,builderOptions:a={}}=e,o=q({...a,enableSnapshots:!0,maxSnapshots:r}),n={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(){n.snapshots=o.getSnapshots(),n.isRecording&&n.snapshots.length>0&&(n.currentIndex=n.snapshots.length-1)}function s(D){o.handleEvent(D),n.isRecording&&(u(),d())}function l(D){let M=o.getSnapshots();if(!(D<0||D>=M.length))return n.currentIndex=D,n.snapshots=M,d(),M[D].ir}function f(){return l(n.currentIndex+1)}function h(){return l(n.currentIndex-1)}function k(D=1){n.playbackSpeed=D,n.isPlaying=!0,d();let M=()=>{if(!n.isPlaying)return;let N=o.getSnapshots();if(n.currentIndex<N.length-1){let S=N[n.currentIndex],L=(N[n.currentIndex+1].timestamp-S.timestamp)/n.playbackSpeed;p=setTimeout(()=>{f(),M()},Math.max(16,L))}else v()};M()}function v(){n.isPlaying=!1,p&&(clearTimeout(p),p=null),d()}function R(){let D=o.getSnapshots();return n.currentIndex>=0&&n.currentIndex<D.length?D[n.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:n.currentIndex,isPlaying:n.isPlaying,playbackSpeed:n.playbackSpeed,isRecording:n.isRecording}}function I(D){return c.add(D),()=>c.delete(D)}function w(){n.isRecording=!0,d()}function $(){n.isRecording=!1,d()}function W(){v(),o.reset(),n={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}}import{createServer as Et}from"http";import{execFile as $e}from"child_process";async function It(e={}){let{port:r=3377,host:t="localhost",autoOpen:a=!0,workflowName:o="Workflow",timeTravel:n=!0,heatmap:c=!0,maxSnapshots:p=1e3}=e,d=xe({maxSnapshots:p}),u=ve(),s=null,l=null,f=r,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 ke(S,{interactive:!0,timeTravel:n,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"?$e("open",[S],E=>{E&&console.warn("[DevServer] Failed to open browser:",E.message)}):x==="win32"?$e("cmd.exe",["/c","start","",S],E=>{E&&console.warn("[DevServer] Failed to open browser:",E.message)}):$e("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=Et(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 Re(e={}){let{workflowName:r,detectParallel:t=!0,showTimings:a=!0,showKeys:o=!1,colors:n}=e,c=q({detectParallel:t}),p=new Set,d=Q(),u=se(),s={showTimings:a,showKeys:o,terminalWidth:process.stdout?.columns??80,colors:{...j,...n}};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 r&&!g.root.name&&(g.root.name=r),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 wn(e,r={}){let t=Re(r);for(let a of e)a.type.startsWith("decision_")?t.handleDecisionEvent(a):t.handleEvent(a);return t.render()}function bn(e={}){let r=[];return{handleEvent:t=>{r.push(t)},handleDecisionEvent:t=>{r.push(t)},getEvents:()=>[...r],getWorkflowEvents:()=>r.filter(t=>!t.type.startsWith("decision_")),getDecisionEvents:()=>r.filter(t=>t.type.startsWith("decision_")),clear:()=>{r.length=0},visualize:()=>{let t=Re(e);for(let a of r)a.type.startsWith("decision_")?t.handleDecisionEvent(a):t.handleEvent(a);return t.render()},visualizeAs:t=>{let a=Re(e);for(let o of r)o.type.startsWith("decision_")?a.handleDecisionEvent(o):a.handleEvent(o);return a.renderAs(t)}}}export{Q as asciiRenderer,It as createDevServer,bn as createEventCollector,q as createIRBuilder,xt as createLiveVisualizer,Fe as createParallelDetector,ve as createPerformanceAnalyzer,xe as createTimeTravelController,Re as createVisualizer,j as defaultColorScheme,oe as detectParallelGroups,ge as getHeatLevel,Ot as hasChildren,St as htmlRenderer,X as isDecisionNode,J as isParallelNode,Y as isRaceNode,Ct as isSequenceNode,V as isStepNode,se as mermaidRenderer,ke as renderToHTML,Se as trackDecision,$t as trackIf,Rt as trackSwitch,wn as visualizeEvents};
|
|
7
1189
|
//# sourceMappingURL=visualize.js.map
|