awaitly-visualizer 1.0.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/dist/index.browser.cjs +1677 -0
- package/dist/index.browser.cjs.map +1 -0
- package/dist/index.browser.d.cts +166 -0
- package/dist/index.browser.d.ts +166 -0
- package/dist/index.browser.js +1677 -0
- package/dist/index.browser.js.map +1 -0
- package/dist/index.cjs +1680 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +242 -0
- package/dist/index.d.ts +242 -0
- package/dist/index.js +1680 -0
- package/dist/index.js.map +1 -0
- package/dist/kroki/fetch.cjs +3 -0
- package/dist/kroki/fetch.cjs.map +1 -0
- package/dist/kroki/fetch.d.cts +86 -0
- package/dist/kroki/fetch.d.ts +86 -0
- package/dist/kroki/fetch.js +3 -0
- package/dist/kroki/fetch.js.map +1 -0
- package/dist/notifiers/discord.cjs +3 -0
- package/dist/notifiers/discord.cjs.map +1 -0
- package/dist/notifiers/discord.d.cts +70 -0
- package/dist/notifiers/discord.d.ts +70 -0
- package/dist/notifiers/discord.js +3 -0
- package/dist/notifiers/discord.js.map +1 -0
- package/dist/notifiers/slack.cjs +38 -0
- package/dist/notifiers/slack.cjs.map +1 -0
- package/dist/notifiers/slack.d.cts +95 -0
- package/dist/notifiers/slack.d.ts +95 -0
- package/dist/notifiers/slack.js +38 -0
- package/dist/notifiers/slack.js.map +1 -0
- package/dist/notifiers/webhook.cjs +3 -0
- package/dist/notifiers/webhook.cjs.map +1 -0
- package/dist/notifiers/webhook.d.cts +115 -0
- package/dist/notifiers/webhook.d.ts +115 -0
- package/dist/notifiers/webhook.js +3 -0
- package/dist/notifiers/webhook.js.map +1 -0
- package/dist/performance-analyzer-B5VF5b1F.d.ts +663 -0
- package/dist/performance-analyzer-BNwE4AiO.d.cts +663 -0
- package/dist/types-BIZSmXif.d.ts +350 -0
- package/dist/types-BnWc9Wlr.d.cts +350 -0
- package/dist/url-PkfQz4V5.d.cts +750 -0
- package/dist/url-PkfQz4V5.d.ts +750 -0
- package/package.json +105 -0
|
@@ -0,0 +1,1677 @@
|
|
|
1
|
+
"use strict";var jt=Object.create;var xe=Object.defineProperty;var Vt=Object.getOwnPropertyDescriptor;var Gt=Object.getOwnPropertyNames;var Yt=Object.getPrototypeOf,Jt=Object.prototype.hasOwnProperty;var Xt=(e,t)=>{for(var r in t)xe(e,r,{get:t[r],enumerable:!0})},Qe=(e,t,r,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of Gt(t))!Jt.call(e,i)&&i!==r&&xe(e,i,{get:()=>t[i],enumerable:!(o=Vt(t,i))||o.enumerable});return e};var qt=(e,t,r)=>(r=e!=null?jt(Yt(e)):{},Qe(t||!e||!e.__esModule?xe(r,"default",{value:e,enumerable:!0}):r,e)),Zt=e=>Qe(xe({},"__esModule",{value:!0}),e);var mn={};Xt(mn,{asciiRenderer:()=>ce,buildMermaidInkUrl:()=>Ze,combineEventHandlers:()=>un,createEventCollector:()=>fn,createIRBuilder:()=>ue,createLiveVisualizer:()=>ln,createMermaidInkGenerator:()=>Pt,createParallelDetector:()=>et,createPerformanceAnalyzer:()=>st,createTimeTravelController:()=>Et,createUrlGenerator:()=>Dt,createVisualizer:()=>Ae,defaultColorScheme:()=>V,detectParallelGroups:()=>we,encodeForMermaidInk:()=>qe,flowchartRenderer:()=>le,getHeatLevel:()=>fe,hasChildren:()=>tr,htmlRenderer:()=>St,isDecisionNode:()=>Y,isParallelNode:()=>j,isRaceNode:()=>H,isSequenceNode:()=>Pe,isStepNode:()=>z,isStreamNode:()=>Q,loggerRenderer:()=>ke,mermaidRenderer:()=>te,renderToHTML:()=>Rt,toKrokiPngUrl:()=>Ot,toKrokiSvgUrl:()=>Tt,toKrokiUrl:()=>se,toMermaidInkJpegUrl:()=>Wt,toMermaidInkPdfUrl:()=>At,toMermaidInkPngUrl:()=>_t,toMermaidInkSvgUrl:()=>Lt,toMermaidInkUrl:()=>G,toMermaidInkWebpUrl:()=>Bt,trackDecision:()=>We,trackIf:()=>It,trackSwitch:()=>$t,visualizeEvents:()=>pn});module.exports=Zt(mn);function B(e){if(e<1e3)return`${Math.round(e)}ms`;if(e<6e4)return`${(e/1e3).toFixed(1).replace(/\.0$/,"")}s`;let t=Math.floor(e/6e4),r=Math.round(e%6e4/1e3);return r>=60&&(t+=1,r=0),r===0?`${t}m`:`${t}m ${r}s`}function Se(){return`node_${Date.now()}_${Math.random().toString(36).slice(2,8)}`}function Qt(e){for(let t of e)if((t.type==="parallel"||t.type==="race"||t.type==="sequence")&&!t.id.startsWith("detected_")||t.type==="decision")return!0;return!1}function we(e,t={}){if(Qt(e))return e;let{minOverlapMs:r=0,maxGapMs:o=5}=t,i=[],n=[];for(let c=0;c<e.length;c++){let l=e[c];l.type==="step"&&l.startTs!==void 0?i.push({node:l,startTs:l.startTs,endTs:l.endTs??l.startTs+(l.durationMs??0),originalIndex:c}):n.push({node:l,originalIndex:c})}if(i.length<=1)return e;i.sort((c,l)=>c.startTs-l.startTs);let a=[],s=[i[0]];for(let c=1;c<i.length;c++){let l=i[c],p=Math.min(...s.map($=>$.startTs)),g=Math.max(...s.map($=>$.endTs)),f=l.startTs<=p+o,y=l.startTs<g;if(!f&&!y){a.push(s),s=[l];continue}let k=y?Math.min(l.endTs,g)-l.startTs:0;f||k>=r?s.push(l):(a.push(s),s=[l])}a.push(s);let u=[];for(let c of a){let l=Math.min(...c.map(p=>p.originalIndex));if(c.length===1)u.push({node:c[0].node,position:l});else{let p=c.map(k=>k.node),g=Math.min(...c.map(k=>k.startTs)),f=Math.max(...c.map(k=>k.endTs)),y={type:"parallel",id:`detected_parallel_${g}`,name:`${p.length} parallel steps`,state:er(p),mode:"all",children:p,startTs:g,endTs:f,durationMs:f-g};u.push({node:y,position:l})}}for(let{node:c,originalIndex:l}of n)u.push({node:c,position:l});return u.sort((c,l)=>c.position-l.position),u.map(c=>c.node)}function er(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 et(e={}){return{detect:t=>we(t,e)}}function ue(e={}){let{detectParallel:t=!0,parallelDetection:r,enableSnapshots:o=!1,maxSnapshots:i=1e3}=e,n=o,a=Se(),s,u,c,l="pending",p,g,f=new Map,y=[],k=[],$=new Map,M=[],N=Date.now(),I=N,v={onAfterStep:new Map},x,m=[],w=0;function R(d){return d.stepId??d.stepKey??d.name??Se()}function D(d){if(y.length>0){y[y.length-1].children.push(d),I=Date.now();return}if(k.length>0){let b=k[k.length-1];for(let h of b.branches.values())if(h.taken){h.children.push(d),I=Date.now();return}b.pendingChildren.push(d),I=Date.now();return}M.push(d),I=Date.now()}function E(d){if(!n)return;let b=oe(),h=new Map;for(let[C,J]of f)h.set(C,{id:J.id,name:J.name,key:J.key,startTs:J.startTs,retryCount:J.retryCount,timedOut:J.timedOut,timeoutMs:J.timeoutMs});let A={id:`snapshot_${w}`,eventIndex:w,event:structuredClone(d),ir:structuredClone(b),timestamp:Date.now(),activeSteps:h};m.push(A),m.length>i&&m.shift(),w++}function T(d){switch(d.type){case"workflow_start":{M=[],c=void 0,g=void 0,p=void 0,f.clear(),y.length=0,k.length=0,$.clear(),s=d.workflowId,u=d.ts,l="running",N=Date.now(),I=N,x!==void 0&&x!==d.workflowId&&(v.shouldRun=void 0,v.onBeforeStart=void 0),x=d.workflowId,v.onAfterStep=new Map;break}case"workflow_success":l="success",c=d.ts,g=d.durationMs,I=Date.now();break;case"workflow_error":l="error",c=d.ts,p=d.error,g=d.durationMs,I=Date.now();break;case"workflow_cancelled":l="aborted",c=d.ts,g=d.durationMs,I=Date.now();break;case"step_start":{let b=R(d);f.set(b,{id:b,name:d.name,key:d.stepKey,startTs:d.ts,retryCount:0,timedOut:!1}),I=Date.now();break}case"step_success":{let b=R(d),h=f.get(b);if(h){let A={type:"step",id:h.id,name:h.name,key:h.key,state:"success",startTs:h.startTs,endTs:d.ts,durationMs:d.durationMs,...h.retryCount>0&&{retryCount:h.retryCount},...h.timedOut&&{timedOut:!0,timeoutMs:h.timeoutMs}};D(A),f.delete(b)}break}case"step_error":{let b=R(d),h=f.get(b);if(h){let A={type:"step",id:h.id,name:h.name,key:h.key,state:"error",startTs:h.startTs,endTs:d.ts,durationMs:d.durationMs,error:d.error,...h.retryCount>0&&{retryCount:h.retryCount},...h.timedOut&&{timedOut:!0,timeoutMs:h.timeoutMs}};D(A),f.delete(b)}break}case"step_aborted":{let b=R(d),h=f.get(b);if(h){let A={type:"step",id:h.id,name:h.name,key:h.key,state:"aborted",startTs:h.startTs,endTs:d.ts,durationMs:d.durationMs,...h.retryCount>0&&{retryCount:h.retryCount},...h.timedOut&&{timedOut:!0,timeoutMs:h.timeoutMs}};D(A),f.delete(b)}break}case"step_cache_hit":{let h={type:"step",id:R(d),name:d.name,key:d.stepKey,state:"cached",startTs:d.ts,endTs:d.ts,durationMs:0};D(h);break}case"step_cache_miss":break;case"step_complete":break;case"step_timeout":{let b=R(d),h=f.get(b);h&&(h.timedOut=!0,h.timeoutMs=d.timeoutMs),I=Date.now();break}case"step_retry":{let b=R(d),h=f.get(b);h&&(h.retryCount=(d.attempt??1)-1),I=Date.now();break}case"step_retries_exhausted":I=Date.now();break;case"step_skipped":{let h={type:"step",id:R(d),name:d.name,key:d.stepKey,state:"skipped",startTs:d.ts,endTs:d.ts,durationMs:0};D(h);break}case"hook_should_run":{let b={type:"shouldRun",state:"success",ts:d.ts,durationMs:d.durationMs,context:{result:d.result,skipped:d.skipped}};v.shouldRun=b,x=d.workflowId,I=Date.now();break}case"hook_should_run_error":{let b={type:"shouldRun",state:"error",ts:d.ts,durationMs:d.durationMs,error:d.error};v.shouldRun=b,x=d.workflowId,I=Date.now();break}case"hook_before_start":{let b={type:"onBeforeStart",state:"success",ts:d.ts,durationMs:d.durationMs,context:{result:d.result,skipped:d.skipped}};v.onBeforeStart=b,x=d.workflowId,I=Date.now();break}case"hook_before_start_error":{let b={type:"onBeforeStart",state:"error",ts:d.ts,durationMs:d.durationMs,error:d.error};v.onBeforeStart=b,x=d.workflowId,I=Date.now();break}case"hook_after_step":{let b={type:"onAfterStep",state:"success",ts:d.ts,durationMs:d.durationMs,context:{stepKey:d.stepKey}};v.onAfterStep.set(d.stepKey,b),I=Date.now();break}case"hook_after_step_error":{let b={type:"onAfterStep",state:"error",ts:d.ts,durationMs:d.durationMs,error:d.error,context:{stepKey:d.stepKey}};v.onAfterStep.set(d.stepKey,b),I=Date.now();break}case"stream_created":{let b=`${d.workflowId}:${d.namespace}`;$.set(b,{id:Se(),namespace:d.namespace,startTs:d.ts,writeCount:0,readCount:0,streamState:"active",backpressureOccurred:!1,finalPosition:0}),I=Date.now();break}case"stream_write":{let b=`${d.workflowId}:${d.namespace}`,h=$.get(b);h&&(h.writeCount++,h.finalPosition=Math.max(h.finalPosition,d.position)),I=Date.now();break}case"stream_read":{let b=`${d.workflowId}:${d.namespace}`,h=$.get(b);h&&h.readCount++,I=Date.now();break}case"stream_close":{let b=`${d.workflowId}:${d.namespace}`,h=$.get(b);if(h){h.streamState="closed",h.finalPosition=d.finalPosition;let A={type:"stream",id:h.id,namespace:h.namespace,state:"success",startTs:h.startTs,endTs:d.ts,durationMs:d.ts-h.startTs,writeCount:h.writeCount,readCount:h.readCount,finalPosition:d.finalPosition,streamState:"closed",backpressureOccurred:h.backpressureOccurred};D(A),$.delete(b)}I=Date.now();break}case"stream_error":{let b=`${d.workflowId}:${d.namespace}`,h=$.get(b);if(h){h.streamState="error";let A={type:"stream",id:h.id,namespace:h.namespace,state:"error",error:d.error,startTs:h.startTs,endTs:d.ts,durationMs:d.ts-h.startTs,writeCount:h.writeCount,readCount:h.readCount,finalPosition:d.position,streamState:"error",backpressureOccurred:h.backpressureOccurred};D(A),$.delete(b)}I=Date.now();break}case"stream_backpressure":{let b=`${d.workflowId}:${d.namespace}`,h=$.get(b);h&&(h.backpressureOccurred=!0),I=Date.now();break}}E(d)}function P(d){if(d.type==="scope_start")y.push({id:d.scopeId,name:d.name,type:d.scopeType,startTs:d.ts,children:[]}),I=Date.now();else if(d.type==="scope_end"){let b=y.findIndex(C=>C.id===d.scopeId);if(b===-1)return;for(;y.length>b+1;){let C=y.pop(),J=C.type==="race"?{type:"race",id:C.id,name:C.name,state:_(C.children),startTs:C.startTs,endTs:d.ts,children:C.children}:{type:"parallel",id:C.id,name:C.name,state:_(C.children),startTs:C.startTs,endTs:d.ts,children:C.children,mode:C.type==="allSettled"?"allSettled":"all"};y[y.length-1].children.push(J)}let[h]=y.splice(b,1),A=h.type==="race"?{type:"race",id:h.id,name:h.name,state:_(h.children),startTs:h.startTs,endTs:d.ts,durationMs:d.durationMs,children:h.children,winnerId:d.winnerId}:{type:"parallel",id:h.id,name:h.name,state:_(h.children),startTs:h.startTs,endTs:d.ts,durationMs:d.durationMs,children:h.children,mode:h.type==="allSettled"?"allSettled":"all"};D(A)}}function K(d){if(d.type==="decision_start")k.push({id:d.decisionId,name:d.name,condition:d.condition,decisionValue:d.decisionValue,startTs:d.ts,branches:new Map,pendingChildren:[]}),I=Date.now();else if(d.type==="decision_branch"){let b=k.find(h=>h.id===d.decisionId);if(b){let h=d.branchLabel,A=b.branches.get(h);if(A)A.taken=d.taken,d.taken&&b.pendingChildren.length>0&&(A.children.unshift(...b.pendingChildren),b.pendingChildren=[]);else{let C=d.taken?[...b.pendingChildren]:[];d.taken&&(b.pendingChildren=[]),b.branches.set(h,{label:d.branchLabel,condition:d.condition,taken:d.taken,children:C})}I=Date.now()}}else if(d.type==="decision_end"){let b=k.findIndex(h=>h.id===d.decisionId);if(b!==-1){let[h]=k.splice(b,1),A=k.splice(b),C=Array.from(h.branches.values());C.length===0&&h.pendingChildren.length>0&&(C=[{label:"default",taken:!0,children:[...h.pendingChildren]}]);let J=C.find(ve=>ve.taken)?.label,Kt={type:"decision",id:h.id,name:h.name,state:_(C.flatMap(ve=>ve.taken?ve.children:[])),startTs:h.startTs,endTs:d.ts,durationMs:d.durationMs,condition:h.condition,decisionValue:h.decisionValue,branchTaken:d.branchTaken??J,branches:C};D(Kt),k.push(...A),I=Date.now()}}}function _(d){return d.length===0?"success":d.some(C=>C.state==="error")?"error":d.every(C=>C.state==="success"||C.state==="cached")?"success":d.some(C=>C.state==="running")?"running":"pending"}function ne(){let d=[...M];for(let[,b]of f)d.push({type:"step",id:b.id,name:b.name,key:b.key,state:"running",startTs:b.startTs,...b.retryCount>0&&{retryCount:b.retryCount},...b.timedOut&&{timedOut:!0,timeoutMs:b.timeoutMs}});for(let[,b]of $)d.push({type:"stream",id:b.id,namespace:b.namespace,state:"running",startTs:b.startTs,writeCount:b.writeCount,readCount:b.readCount,finalPosition:b.finalPosition,streamState:b.streamState,backpressureOccurred:b.backpressureOccurred});return d}function oe(){let d=ne();t&&(d=we(d,r));let b={type:"workflow",id:s??a,workflowId:s??a,state:l,startTs:u,endTs:c,durationMs:g,children:d,error:p},h=v.shouldRun!==void 0||v.onBeforeStart!==void 0||v.onAfterStep.size>0;return{root:b,metadata:{createdAt:N,lastUpdatedAt:I},...h&&{hooks:v}}}function ie(){s=void 0,u=void 0,c=void 0,l="pending",p=void 0,g=void 0,f.clear(),y.length=0,k.length=0,$.clear(),M=[],N=Date.now(),I=N,v={onAfterStep:new Map},x=void 0,m.length=0,w=0}function Ht(){return[...m]}function Ft(d){return m[d]}function zt(d){return m[d]?.ir}function Ut(){m.length=0,w=0}return{handleEvent:T,handleScopeEvent:P,handleDecisionEvent:K,getIR:oe,reset:ie,getSnapshots:Ht,getSnapshotAt:Ft,getIRAt:zt,clearSnapshots:Ut,get hasActiveSteps(){return f.size>0},get state(){return l},get snapshotCount(){return m.length},get snapshotsEnabled(){return n},setSnapshotsEnabled(d){n=d}}}var Ie=require("awaitly");function z(e){return e.type==="step"}function Pe(e){return e.type==="sequence"}function j(e){return e.type==="parallel"}function H(e){return e.type==="race"}function Y(e){return e.type==="decision"}function Q(e){return e.type==="stream"}function tr(e){return"children"in e||e.type==="decision"&&"branches"in e}var He="\x1B[0m",rr="\x1B[1m",rt="\x1B[2m",nr="\x1B[31m",or="\x1B[32m",ir="\x1B[33m",ar="\x1B[34m",tt="\x1B[90m",sr="\x1B[37m";function X(e,t){return t?`${t}${e}${He}`:e}function be(e){return`${rr}${e}${He}`}function O(e){return`${rt}${e}${He}`}var V={pending:sr,running:ir,success:or,error:nr,aborted:tt,cached:ar,skipped:rt+tt};function cr(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 ye(e,t){let r=cr(e);return X(r,t[e])}function Re(e,t,r){return X(e,r[t])}function ee(e){return e.replace(/\x1b\[[0-9;]*m/g,"")}var S={topLeft:"\u250C",topRight:"\u2510",bottomLeft:"\u2514",bottomRight:"\u2518",horizontal:"\u2500",vertical:"\u2502",teeRight:"\u251C",teeLeft:"\u2524",teeDown:"\u252C",teeUp:"\u2534",cross:"\u253C"},pe={cold:"\x1B[34m",cool:"\x1B[36m",neutral:"",warm:"\x1B[33m",hot:"\x1B[31m",critical:"\x1B[41m"},dr="\x1B[0m";function lr(e){return e<.2?pe.cold:e<.4?pe.cool:e<.6?pe.neutral:e<.8?pe.warm:e<.95?pe.hot:pe.critical}function nt(e,t){let r=lr(t);return r?`${r}${e}${dr}`:e}function ur(e){try{return(0,Ie.ok)(JSON.stringify(e,(r,o)=>{if(typeof o!="bigint")return o;let i=Number(o);return Number.isSafeInteger(i)?i:o.toString()}))}catch{return(0,Ie.err)("STRINGIFY_ERROR")}}function ot(e){let t=ur(e);return t.ok?t.value:"[unserializable]"}var it="\u2581\u2582\u2583\u2584\u2585\u2586\u2587\u2588";function ze(e,t=10){if(e.length===0)return"";let r=e.slice(-t),o=Math.min(...r),n=Math.max(...r)-o||1;return r.map(a=>{let s=(a-o)/n,u=Math.floor(s*(it.length-1));return it[u]}).join("")}function Fe(e,t){let r=ee(e).length,o=Math.max(0,t-r);return e+" ".repeat(o)}function pr(e,t){if(!t)return S.horizontal.repeat(e);let r=` ${t} `,o=ee(r).length,i=e-o;if(i<4)return S.horizontal.repeat(e);let n=2,a=i-n;return S.horizontal.repeat(n)+r+S.horizontal.repeat(a)}function at(e,t,r){let o=e.state==="success"?X("\u2699",r.success):X("\u26A0",r.error),i=e.durationMs!==void 0?O(` [${B(e.durationMs)}]`):"",n="";e.type==="shouldRun"&&e.context?.skipped?n=O(" \u2192 workflow skipped"):e.type==="shouldRun"&&e.context?.result===!0?n=O(" \u2192 proceed"):e.type==="onBeforeStart"&&e.context?.skipped?n=O(" \u2192 workflow skipped"):e.type==="onAfterStep"&&e.context?.stepKey&&(n=O(` (${e.context.stepKey})`));let a=e.state==="error"&&e.error?O(` error: ${String(e.error)}`):"";return`${o} ${O(t)}${n}${i}${a}`}function fr(e,t){let r=[];return e.shouldRun&&r.push(at(e.shouldRun,"shouldRun",t)),e.onBeforeStart&&r.push(at(e.onBeforeStart,"onBeforeStart",t)),r.length>0&&r.push(O("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")),r}function ce(){return{name:"ascii",supportsLive:!0,render(e,t){let r={...V,...t.colors},o=Math.max(t.terminalWidth??60,5),i=o-4,n=[],a=e.root.name??"workflow",s=be(a);if(n.push(`${S.topLeft}${pr(o-2,s)}${S.topRight}`),n.push(`${S.vertical}${" ".repeat(o-2)}${S.vertical}`),e.hooks){let c=fr(e.hooks,r);for(let l of c)n.push(`${S.vertical} ${Fe(l,i)}${S.vertical}`)}let u=$e(e.root.children,t,r,0,e.hooks);for(let c of u)n.push(`${S.vertical} ${Fe(c,i)}${S.vertical}`);if(n.push(`${S.vertical}${" ".repeat(o-2)}${S.vertical}`),e.root.durationMs!==void 0&&t.showTimings){let c=e.root.state==="success"?"Completed":e.root.state==="aborted"?"Cancelled":"Failed",p=`${Re(c,e.root.state,r)} in ${B(e.root.durationMs)}`;n.push(`${S.vertical} ${Fe(p,i)}${S.vertical}`),n.push(`${S.vertical}${" ".repeat(o-2)}${S.vertical}`)}return n.push(`${S.bottomLeft}${S.horizontal.repeat(o-2)}${S.bottomRight}`),n.join(`
|
|
2
|
+
`)}}}function $e(e,t,r,o,i){let n=[];for(let a of e)z(a)?n.push(Ue(a,t,r,i)):j(a)?n.push(...hr(a,t,r,o,i)):H(a)?n.push(...gr(a,t,r,o,i)):Y(a)?n.push(...wr(a,t,r,o,i)):Q(a)&&n.push(mr(a,t,r));return n}function Ue(e,t,r,o){let i=ye(e.state,r),n=e.name??e.key??"step",a=t,s=a.showHeatmap&&a.heatmapData?a.heatmapData.heat.get(e.key??"")??a.heatmapData.heat.get(e.name??"")??a.heatmapData.heat.get(e.id):void 0,u;s!==void 0?u=nt(n,s):u=Re(n,e.state,r);let c=`${i} ${u}`;if(t.showKeys&&e.key&&e.name&&(c+=O(` [key: ${e.key}]`)),e.input!==void 0){let p=typeof e.input=="string"?e.input:ot(e.input).slice(0,30);c+=O(` [in: ${p}${p.length>=30?"...":""}]`)}if(e.output!==void 0&&e.state==="success"){let p=typeof e.output=="string"?e.output:ot(e.output).slice(0,30);c+=O(` [out: ${p}${p.length>=30?"...":""}]`)}if(t.showTimings&&e.durationMs!==void 0){let p=B(e.durationMs),g=s!==void 0?nt(`[${p}]`,s):O(`[${p}]`);c+=` ${g}`}if(a.showSparklines&&a.timingHistory){let p=a.timingHistory.get(e.key??"")??a.timingHistory.get(e.name??"")??a.timingHistory.get(e.id);p&&p.length>1&&(c+=` ${O(ze(p))}`)}if(e.retryCount!==void 0&&e.retryCount>0&&(c+=O(` [${e.retryCount} ${e.retryCount===1?"retry":"retries"}]`)),e.timedOut){let p=e.timeoutMs!==void 0?` ${e.timeoutMs}ms`:"";c+=O(` [timeout${p}]`)}let l=e.key??e.id;if(o&&l&&o.onAfterStep.has(l)){let p=o.onAfterStep.get(l),g=p.state==="success"?X("\u2699",r.success):X("\u26A0",r.error),f=p.durationMs!==void 0?O(` ${B(p.durationMs)}`):"";c+=` ${g}${f}`}return c}function mr(e,t,r){let o=e.streamState==="active"?X("\u27F3",r.running):e.streamState==="closed"?X("\u2713",r.success):X("\u2717",r.error),i=`stream:${e.namespace}`,n=Re(i,e.state,r),a=O(`[W:${e.writeCount} R:${e.readCount}]`),s=`${o} ${n} ${a}`;return t.showTimings&&e.durationMs!==void 0&&(s+=` ${O(`[${B(e.durationMs)}]`)}`),e.backpressureOccurred&&(s+=O(" [backpressure]")),e.streamState==="closed"&&(s+=O(` pos:${e.finalPosition}`)),s}function hr(e,t,r,o,i){let n=[],a=" ".repeat(o),s=ye(e.state,r),u=e.name??"parallel",c=e.mode==="allSettled"?" (allSettled)":"";if(n.push(`${a}${S.teeRight}${S.teeDown}${S.horizontal} ${s} ${be(u)}${c}`),e.children.length===0)n.push(`${a}${S.vertical} ${O("(operations not individually tracked)")}`),n.push(`${a}${S.vertical} ${O("(wrap each operation with step() to see individual steps)")}`);else for(let l=0;l<e.children.length;l++){let p=e.children[l],f=l===e.children.length-1?`${a}${S.vertical} ${S.bottomLeft}`:`${a}${S.vertical} ${S.teeRight}`;if(z(p))n.push(`${f} ${Ue(p,t,r,i)}`);else{let y=$e([p],t,r,o+1,i);for(let k of y)n.push(`${a}${S.vertical} ${k}`)}}return t.showTimings&&e.durationMs!==void 0&&n.push(`${a}${S.bottomLeft}${S.horizontal}${S.horizontal} ${O(`[${B(e.durationMs)}]`)}`),n}function gr(e,t,r,o,i){let n=[],a=" ".repeat(o),s=ye(e.state,r),u=e.name??"race";if(n.push(`${a}${S.teeRight}\u26A1 ${s} ${be(u)}`),e.children.length===0)n.push(`${a}${S.vertical} ${O("(operations not individually tracked)")}`),n.push(`${a}${S.vertical} ${O("(wrap each operation with step() to see individual steps)")}`);else for(let c=0;c<e.children.length;c++){let l=e.children[c],g=c===e.children.length-1?`${a}${S.vertical} ${S.bottomLeft}`:`${a}${S.vertical} ${S.teeRight}`,y=e.winnerId&&l.id===e.winnerId?O(" (winner)"):"";if(z(l))n.push(`${g} ${Ue(l,t,r,i)}${y}`);else{let k=$e([l],t,r,o+1,i);for(let $ of k)n.push(`${a}${S.vertical} ${$}`)}}return t.showTimings&&e.durationMs!==void 0&&n.push(`${a}${S.bottomLeft}${S.horizontal}${S.horizontal} ${O(`[${B(e.durationMs)}]`)}`),n}function wr(e,t,r,o,i){let n=[],a=" ".repeat(o),s=ye(e.state,r),u=e.name??"decision",c=e.condition?O(` (${e.condition})`):"",l=e.decisionValue!==void 0?O(` = ${String(e.decisionValue)}`):"",p=e.branchTaken!==void 0?O(` \u2192 ${String(e.branchTaken)}`):"";n.push(`${a}${S.teeRight}${S.teeDown}${S.horizontal} ${s} ${be(u)}${c}${l}${p}`);for(let g=0;g<e.branches.length;g++){let f=e.branches[g],k=g===e.branches.length-1?`${a}${S.vertical} ${S.bottomLeft}`:`${a}${S.vertical} ${S.teeRight}`,$=f.taken?"\u2713":"\u2298",M=f.taken?r.success:r.skipped,N=X(`${$} ${f.label}`,M),I=f.condition?O(` (${f.condition})`):"";if(n.push(`${k} ${N}${I}`),f.children.length>0){let v=$e(f.children,t,r,o+1,i);for(let x of v)n.push(`${a}${S.vertical} ${x}`)}else f.taken||n.push(`${a}${S.vertical} ${O("(skipped)")}`)}return t.showTimings&&e.durationMs!==void 0&&n.push(`${a}${S.bottomLeft}${S.horizontal}${S.horizontal} ${O(`[${B(e.durationMs)}]`)}`),n}var Te=require("awaitly");function Ke(e){let t=[];for(let r of e)if(t.push(r),"children"in r&&Array.isArray(r.children)&&t.push(...Ke(r.children)),"branches"in r)for(let o of r.branches)t.push(...Ke(o.children));return t}function Ee(e,t){if(e.length===0)return 0;let r=Math.floor(e.length*t);return e[Math.min(r,e.length-1)]}function fe(e){return e<.2?"cold":e<.4?"cool":e<.6?"neutral":e<.8?"warm":e<.95?"hot":"critical"}function st(){let e=new Map,t=new Map,r=new Map,o=new Map,i=[];function n(v){return v.stepKey??v.stepId??v.name??"unknown"}function a(v){let x=new Map;for(let m of v)switch(m.type){case"step_start":{let w=n(m);x.set(w,{retried:!1,timedOut:!1});break}case"step_retry":{let w=n(m),R=x.get(w);R&&(R.retried=!0);break}case"step_timeout":{let w=n(m),R=x.get(w);R&&(R.timedOut=!0);break}case"step_success":{let w=n(m),R=x.get(w),D=e.get(w)??[];D.push(m.durationMs),e.set(w,D);let E=t.get(w)??{retried:0,total:0};E.total++,R?.retried&&E.retried++,t.set(w,E);let T=o.get(w)??{timedOut:0,total:0};T.total++,R?.timedOut&&T.timedOut++,o.set(w,T);let P=r.get(w)??{errors:0,total:0};P.total++,r.set(w,P),x.delete(w);break}case"step_error":{let w=n(m),R=x.get(w),D=e.get(w)??[];D.push(m.durationMs),e.set(w,D);let E=t.get(w)??{retried:0,total:0};E.total++,R?.retried&&E.retried++,t.set(w,E);let T=o.get(w)??{timedOut:0,total:0};T.total++,R?.timedOut&&T.timedOut++,o.set(w,T);let P=r.get(w)??{errors:0,total:0};P.total++,P.errors++,r.set(w,P),x.delete(w);break}}}function s(v){a(v.events)}function u(v){i.push(v)}function c(v){i.length>0&&(a(i),i=[])}function l(v){let x=e.get(v);if(!x||x.length===0)return;let m=[...x].sort((K,_)=>K-_),R=m.reduce((K,_)=>K+_,0)/m.length,D=m.reduce((K,_)=>K+(_-R)**2,0)/m.length,E=t.get(v)??{retried:0,total:1},T=r.get(v)??{errors:0,total:1},P=o.get(v)??{timedOut:0,total:1};return{nodeId:v,avgDurationMs:R,minDurationMs:m[0],maxDurationMs:m[m.length-1],stdDevMs:Math.sqrt(D),samples:m.length,retryRate:E.total>0?E.retried/E.total:0,timeoutRate:P.total>0?P.timedOut/P.total:0,errorRate:T.total>0?T.errors/T.total:0,percentiles:{p50:Ee(m,.5),p90:Ee(m,.9),p95:Ee(m,.95),p99:Ee(m,.99)}}}function p(v){return l(v)}function g(v,x="duration"){let m=new Map,w=Ke(v.root.children),R=[];for(let _ of w){let ne=("key"in _?_.key:void 0)??_.id??_.name,oe=l(ne);if(oe){let ie;switch(x){case"duration":ie=oe.avgDurationMs;break;case"retryRate":ie=oe.retryRate;break;case"errorRate":ie=oe.errorRate;break}R.push({id:_.id,value:ie})}}if(R.length===0)return{heat:m,metric:x,stats:{min:0,max:0,mean:0,threshold:0}};let D=R.map(_=>_.value),E=Math.min(...D),T=Math.max(...D),P=D.reduce((_,ne)=>_+ne,0)/D.length,K=T-E||1;for(let{id:_,value:ne}of R)m.set(_,(ne-E)/K);return{heat:m,metric:x,stats:{min:E,max:T,mean:P,threshold:P+(T-P)*.5}}}function f(){let v=new Map;for(let x of e.keys()){let m=l(x);m&&v.set(x,m)}return v}function y(v=10){return[...f().values()].sort((m,w)=>w.avgDurationMs-m.avgDurationMs).slice(0,v)}function k(v=10){return[...f().values()].filter(m=>m.errorRate>0).sort((m,w)=>w.errorRate-m.errorRate).slice(0,v)}function $(v=10){return[...f().values()].filter(m=>m.retryRate>0).sort((m,w)=>w.retryRate-m.retryRate).slice(0,v)}function M(){return JSON.stringify({timingData:Object.fromEntries(e),retryData:Object.fromEntries(t),errorData:Object.fromEntries(r),timeoutData:Object.fromEntries(o)})}function N(v){let x=JSON.parse(v);e.clear(),t.clear(),r.clear(),o.clear();for(let[m,w]of Object.entries(x.timingData??{}))e.set(m,w);for(let[m,w]of Object.entries(x.retryData??{}))t.set(m,w);for(let[m,w]of Object.entries(x.errorData??{}))r.set(m,w);for(let[m,w]of Object.entries(x.timeoutData??{}))o.set(m,w)}function I(){e.clear(),t.clear(),r.clear(),o.clear(),i=[]}return{addRun:s,addEvent:u,finalizeRun:c,getNodePerformance:p,getHeatmap:g,getSlowestNodes:y,getErrorProneNodes:k,getRetryProneNodes:$,getAllPerformance:f,exportData:M,importData:N,clear:I}}function br(){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"," classDef stream fill:#ede9fe,stroke:#8b5cf6,stroke-width:3px,color:#5b21b6"," classDef streamActive fill:#ddd6fe,stroke:#7c3aed,stroke-width:3px,color:#4c1d95"," classDef streamError fill:#fce7f3,stroke:#db2777,stroke-width:3px,color:#9d174d"]}function yr(){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 kr(e){return`heat_${e}`}function vr(){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 xr(e){try{return(0,Te.ok)(JSON.stringify(e,(r,o)=>{if(typeof o!="bigint")return o;let i=Number(o);return Number.isSafeInteger(i)?i:o.toString()}))}catch{return(0,Te.err)("STRINGIFY_ERROR")}}function ct(e){let t=xr(e);return t.ok?t.value:"[unserializable]"}function Sr(e,t,r){let o;if(e.shouldRun){let i="hook_shouldRun",n=e.shouldRun.state==="success"?"hook_success":"hook_error",a=e.shouldRun.state==="success"?"\u2699":"\u26A0",s=r.showTimings&&e.shouldRun.durationMs!==void 0?` ${B(e.shouldRun.durationMs)}`:"",u=e.shouldRun.context?.skipped?"\\nskipped workflow":e.shouldRun.context?.result===!0?"\\nproceed":"";t.push(` ${i}[["${a} shouldRun${u}${s}"]]:::${n}`),o=i}if(e.onBeforeStart){let i="hook_beforeStart",n=e.onBeforeStart.state==="success"?"hook_success":"hook_error",a=e.onBeforeStart.state==="success"?"\u2699":"\u26A0",s=r.showTimings&&e.onBeforeStart.durationMs!==void 0?` ${B(e.onBeforeStart.durationMs)}`:"",u=e.onBeforeStart.context?.skipped?"\\nskipped workflow":"";t.push(` ${i}[["${a} onBeforeStart${u}${s}"]]:::${n}`),o&&t.push(` ${o} --> ${i}`),o=i}return{lastHookId:o}}var dt=0,Ne=new Set,Me=new Set;function me(e="node"){return`${e}_${++dt}`}function Rr(){dt=0,Ne.clear(),Me.clear()}function U(e){return e.replace(/"/g,"#quot;").replace(/</g,"<").replace(/>/g,">").trim()}function lt(e){return U(e).replace(/[{}[\]()]/g,"")}function te(){return{name:"mermaid",supportsLive:!1,render(e,t){Rr();let r=[],o=t;r.push("flowchart TD");let i;e.hooks&&(i=Sr(e.hooks,r,t).lastHookId);let n="start";r.push(` ${n}(("\u25B6 Start"))`),i&&r.push(` ${i} --> ${n}`);let a=n;for(let u of e.root.children){let c=Oe(u,t,r,o,e.hooks);r.push(` ${a} --> ${c.entryId}`),a=c.exitId}if(["success","error","aborted"].includes(e.root.state)){let u="finish",c=e.root.state==="success"?"\u2713":e.root.state==="error"?"\u2717":"\u2298",l=e.root.state==="success"?"Done":e.root.state==="error"?"Failed":"Cancelled",p=`(("${c} ${l}"))`,g=e.root.state==="success"?":::success":e.root.state==="error"?":::error":":::aborted";r.push(` ${u}${p}${g}`),r.push(` ${a} --> ${u}`)}return r.push(""),r.push(...br()),o.showHeatmap&&r.push(...yr()),e.hooks&&r.push(...vr()),r.join(`
|
|
3
|
+
`)}}}function Oe(e,t,r,o,i){if(z(e))return Ir(e,t,r,o,i);if(j(e))return $r(e,t,r,o,i);if(H(e))return Er(e,t,r,o,i);if(Y(e))return Nr(e,t,r,o,i);if(Q(e))return Mr(e,t,r);let n=me("unknown");return r.push(` ${n}["Unknown Node"]`),{entryId:n,exitId:n}}function Ir(e,t,r,o,i){let n=t,a=n.showRetryEdges??!0,s=n.showErrorEdges??!0,u=n.showTimeoutEdges??!0,c=e.key?`step_${e.key.replace(/[^a-zA-Z0-9]/g,"_")}`:me("step");if(Me.has(c)){let m=2;for(;Me.has(`${c}_${m}`);)m++;c=`${c}_${m}`}Me.add(c);let l=e.name??e.key??"Step",p=t.showKeys&&e.key&&e.name?`${l} [${e.key}]`:l,g=U(p),f=t.showTimings&&e.durationMs!==void 0?` ${B(e.durationMs)}`:"",y="";switch(e.state){case"success":y="\u2713 ";break;case"error":y="\u2717 ";break;case"cached":y="\u{1F4BE} ";break;case"running":y="\u23F3 ";break;case"skipped":y="\u2298 ";break}let k="";if(e.input!==void 0){let m=typeof e.input=="string"?U(e.input):U(ct(e.input).slice(0,20));k+=`\\nin: ${m}`}if(e.output!==void 0&&e.state==="success"){let m=typeof e.output=="string"?U(e.output):U(ct(e.output).slice(0,20));k+=`\\nout: ${m}`}let $="",M=e.key??e.id;if(i&&M&&i.onAfterStep.has(M)){let m=i.onAfterStep.get(M),w=m.state==="success"?"\u2699":"\u26A0",R=t.showTimings&&m.durationMs!==void 0?` ${B(m.durationMs)}`:"";$=`\\n${w} hook${R}`}let N=(y+g+k+$+f).trim(),I,v=o?.showHeatmap&&o.heatmapData?o.heatmapData.heat.get(e.key??"")??o.heatmapData.heat.get(e.name??"")??o.heatmapData.heat.get(e.id):void 0;if(v!==void 0){let m=fe(v);I=kr(m)}else I=e.state;let x;switch(e.state){case"error":x=`{{"${N}"}}`;break;case"cached":x=`[("${N}")]`;break;case"skipped":x=`["${N}"]`;break;default:x=`["${N}"]`}if(r.push(` ${c}${x}:::${I}`),a&&e.retryCount!==void 0&&e.retryCount>0){let m=`\u21BB ${e.retryCount} retr${e.retryCount===1?"y":"ies"}`;r.push(` ${c} -.->|"${m}"| ${c}`)}if(s&&e.state==="error"&&e.error!==void 0){let m=`ERR_${c}`,w=U(String(e.error)).slice(0,30);r.push(` ${m}{{"${w}"}}`),r.push(` ${c} -->|error| ${m}`),r.push(` style ${m} fill:#fee2e2,stroke:#dc2626`)}if(u&&e.timedOut){let m=`TO_${c}`,w=e.timeoutMs!==void 0?`${e.timeoutMs}ms`:"";r.push(` ${m}{{"\u23F1 Timeout ${w}"}}`),r.push(` ${c} -.->|timeout| ${m}`),r.push(` style ${m} fill:#fef3c7,stroke:#f59e0b`)}return{entryId:c,exitId:c}}function $r(e,t,r,o,i){let n=me("parallel"),a=`${n}_fork`,s=`${n}_join`,u=lt(e.name??"Parallel"),c=e.mode==="allSettled"?" (allSettled)":"";if(e.children.length===0){let g=n,f=U(`${u}${c}`),y="operations not individually tracked",k=t.showTimings&&e.durationMs!==void 0?` ${B(e.durationMs)}`:"";return r.push(` ${g}["${f}${k}\\n${y}"]:::${e.state}`),{entryId:g,exitId:g}}r.push(` subgraph ${n}["${u}${c}"]`),r.push(" direction TB"),r.push(` ${a}{"\u26A1 Fork"}`);let l=[];for(let g of e.children){let f=Oe(g,t,r,o,i);r.push(` ${a} --> ${f.entryId}`),l.push(f.exitId)}r.push(` ${s}{"\u2713 Join"}`);for(let g of l)r.push(` ${g} --> ${s}`);r.push(" end");let p=e.state;return r.push(` class ${n} ${p}`),{entryId:a,exitId:s}}function Er(e,t,r,o,i){let n=me("race"),a=`${n}_start`,s=`${n}_end`,u=lt(e.name??"Race");if(e.children.length===0){let g=n,f=U(u),y="operations not individually tracked",k=t.showTimings&&e.durationMs!==void 0?` ${B(e.durationMs)}`:"";return r.push(` ${g}["\u26A1 ${f}${k}\\n${y}"]:::${e.state}`),{entryId:g,exitId:g}}r.push(` subgraph ${n}["\u26A1 ${u}"]`),r.push(" direction TB"),r.push(` ${a}(("\u{1F3C1} Start"))`);let c=[],l;for(let g of e.children){let f=Oe(g,t,r,o,i),y=e.winnerId===g.id;r.push(` ${a} --> ${f.entryId}`),y&&(l=f.exitId),c.push({exitId:f.exitId,isWinner:y})}r.push(` ${s}(("\u2713 First"))`);for(let{exitId:g,isWinner:f}of c)f&&l?r.push(` ${g} ==>|\u{1F3C6} Winner| ${s}`):e.winnerId?r.push(` ${g} -. cancelled .-> ${s}`):r.push(` ${g} --> ${s}`);r.push(" end");let p=e.state;return r.push(` class ${n} ${p}`),{entryId:a,exitId:s}}function Nr(e,t,r,o,i){let n=e.key?`decision_${e.key.replace(/[^a-zA-Z0-9]/g,"_")}`:me("decision");if(Ne.has(n)){let g=2;for(;Ne.has(`${n}_${g}`);)g++;n=`${n}_${g}`}Ne.add(n);let a=U(e.condition??"condition"),s=e.decisionValue!==void 0?` = ${U(String(e.decisionValue)).slice(0,30)}`:"",u=`${a}${s}`.trim();r.push(` ${n}{"${u}"}`);let c=[],l,p=new Set;for(let g of e.branches){let f=`${n}_${g.label.replace(/[^a-zA-Z0-9]/g,"_")}`;if(p.has(f)){let N=2;for(;p.has(`${f}_${N}`);)N++;f=`${f}_${N}`}p.add(f);let y=U(g.label),k=g.taken?`${y} \u2713`:`${y} skipped`,$=g.taken?":::success":":::skipped";r.push(` ${f}["${k}"]${$}`);let M=g.condition?`|${U(g.condition).replace(/\|/g,"")}|`:"";if(r.push(` ${n} -->${M} ${f}`),g.children.length>0){let N=f;for(let I of g.children){let v=Oe(I,t,r,o,i);r.push(` ${N} --> ${v.entryId}`),N=v.exitId}c.push(N),g.taken&&(l=N)}else c.push(f),g.taken&&(l=f)}return l?{entryId:n,exitId:l}:{entryId:n,exitId:n}}function Mr(e,t,r){let o=`stream_${e.namespace.replace(/[^a-zA-Z0-9]/g,"_")}_${me("")}`,i=`W:${e.writeCount} R:${e.readCount}`,n="";switch(e.streamState){case"active":n="\u27F3 ";break;case"closed":n="\u2713 ";break;case"error":n="\u2717 ";break}let a=t.showTimings&&e.durationMs!==void 0?` ${B(e.durationMs)}`:"",s=e.backpressureOccurred?"\\nbackpressure":"",u=`${n}stream:${U(e.namespace)}\\n${i}${s}${a}`,c;return e.streamState==="error"?c="streamError":e.streamState==="active"?c="streamActive":c="stream",r.push(` ${o}{{"${u}"}}:::${c}`),{entryId:o,exitId:o}}var L={topLeft:"\u250C",topRight:"\u2510",bottomLeft:"\u2514",bottomRight:"\u2518",horizontal:"\u2500",vertical:"\u2502",teeDown:"\u252C",teeUp:"\u2534",teeRight:"\u251C",teeLeft:"\u2524",cross:"\u253C",arrowDown:"\u25BC",arrowUp:"\u25B2"},Tr={cold:"\x1B[34m",cool:"\x1B[36m",neutral:"",warm:"\x1B[33m",hot:"\x1B[31m",critical:"\x1B[41m"},Or="\x1B[0m";function Dr(e,t){let r=[],o=[];for(let i=0;i<t;i++)r.push(Array(e).fill(" ")),o.push(Array(e).fill(void 0));return{cells:r,colors:o,width:e,height:t}}function W(e,t,r,o,i){t>=0&&t<e.width&&r>=0&&r<e.height&&(e.cells[r][t]=o,i&&(e.colors[r][t]=i))}function ft(e,t,r){return t>=0&&t<e.width&&r>=0&&r<e.height?e.cells[r][t]:" "}function Cr(e,t,r,o,i){W(e,t,r,L.topLeft);for(let n=1;n<o-1;n++)W(e,t+n,r,L.horizontal);W(e,t+o-1,r,L.topRight);for(let n=1;n<i-1;n++)W(e,t,r+n,L.vertical),W(e,t+o-1,r+n,L.vertical);W(e,t,r+i-1,L.bottomLeft);for(let n=1;n<o-1;n++)W(e,t+n,r+i-1,L.horizontal);W(e,t+o-1,r+i-1,L.bottomRight)}function ut(e,t,r,o,i){let n=ee(o).split("");for(let a=0;a<n.length;a++)W(e,t+a,r,n[a],i)}function re(e,t,r,o){let i=Math.min(r,o),n=Math.max(r,o);for(let a=i;a<=n;a++){let s=ft(e,t,a);s===L.horizontal?W(e,t,a,L.cross):(s===" "||s===L.vertical)&&W(e,t,a,L.vertical)}}function pt(e,t,r,o){let i=Math.min(r,o),n=Math.max(r,o);for(let a=i;a<=n;a++){let s=ft(e,a,t);s===L.vertical?W(e,a,t,L.cross):(s===" "||s===L.horizontal)&&W(e,a,t,L.horizontal)}}function de(e,t,r){W(e,t,r,L.arrowDown)}function Lr(e){let t=[];for(let r=0;r<e.height;r++){let o="";for(let i=0;i<e.width;i++){let n=e.colors[r][i],a=e.cells[r][i];n?o+=n+a+Or:o+=a}t.push(o.trimEnd())}for(;t.length>0&&t[t.length-1]==="";)t.pop();return t.join(`
|
|
4
|
+
`)}var q=11,Z=2,he=2,De=3;function Ve(e,t){if(e.length<=t)return[e];let r=e.split(" "),o=[],i="";for(let n of r)i?i.length+1+n.length<=t?i+=" "+n:(o.push(i),i=n):i=n;if(i&&o.push(i),o.length===0)for(let n=0;n<e.length;n+=t)o.push(e.slice(n,n+t));return o}function mt(e){switch(e){case"success":return"\u2713";case"error":return"\u2717";case"running":return"\u27F3";case"pending":return"\u25CB";case"aborted":case"skipped":return"\u2298";case"cached":return"\u21BA";default:return"\u25CB"}}function _r(e,t,r){let o=t.showStartEnd??!0,i=t,n=Math.floor(r/2),a=[],s=0;if(o){let c=Ce("start","start",["\u25B6 Start"],"success",n,s);a.push(c),s=c.bottomY+he}for(let c of e.root.children){let l=Le(c,n,s,r-4,t,i);a.push(l.node),s=l.bottomY+he}if(o&&["success","error","aborted"].includes(e.root.state)){let c=e.root.state==="success"?"\u2713 Done":e.root.state==="error"?"\u2717 Failed":"\u2298 Cancelled",l=Ce("end","end",[c],e.root.state,n,s);a.push(l),s=l.bottomY}return{nodes:a,totalHeight:s+2}}function Ce(e,t,r,o,i,n){let a=Math.max(...r.map(l=>ee(l).length)),s=Math.max(q,a+Z*2),u=r.length+2,c=i-Math.floor(s/2);return{id:e,type:t,label:r,state:o,x:c,y:n,width:s,height:u,centerX:i,bottomY:n+u-1}}function Le(e,t,r,o,i,n){if(z(e))return Wr(e,t,r,o,i,n);if(j(e)||H(e))return Ar(e,t,r,o,i,n);if(Y(e))return Pr(e,t,r,o,i,n);if(Q(e))return Br(e,t,r,o,i,n);let a=Ce(e.id,"step",["?"],e.state,t,r);return{node:a,bottomY:a.bottomY}}function Wr(e,t,r,o,i,n){let a=e.name??e.key??"step",s=mt(e.state),u=[],c=`${s} ${a}`;i.showKeys&&e.key&&e.name&&(c+=` [${e.key}]`);let l=Math.min(o-Z*2,40);if(u.push(...Ve(c,l)),i.showTimings&&e.durationMs!==void 0&&u.push(`[${B(e.durationMs)}]`),e.retryCount&&e.retryCount>0&&u.push(`${e.retryCount}x retry`),e.timedOut&&u.push("timeout"),n?.showSparklines&&n.timingHistory){let M=n.timingHistory.get(e.key??"")??n.timingHistory.get(e.name??"")??n.timingHistory.get(e.id);M&&M.length>1&&u.push(ze(M,8))}let p=Math.max(...u.map(M=>ee(M).length)),g=Math.max(q,p+Z*2),f=u.length+2,y=t-Math.floor(g/2),k;if(n?.showHeatmap&&n.heatmapData){let M=e.key??e.name??e.id;k=n.heatmapData.heat.get(e.id)??n.heatmapData.heat.get(M)}let $={id:e.id,type:"step",label:u,state:e.state,x:y,y:r,width:g,height:f,centerX:t,bottomY:r+f-1,metadata:k!==void 0?{heat:k}:void 0};return{node:$,bottomY:$.bottomY}}function Br(e,t,r,o,i,n){let a=`stream:${e.namespace}`,s=e.streamState==="active"?"\u27F3":e.streamState==="closed"?"\u2713":"\u2717",u=[],c=`${s} ${a}`,l=Math.min(o-Z*2,40);u.push(...Ve(c,l)),u.push(`W:${e.writeCount} R:${e.readCount}`),i.showTimings&&e.durationMs!==void 0&&u.push(`[${B(e.durationMs)}]`),e.backpressureOccurred&&u.push("backpressure");let p=Math.max(...u.map($=>ee($).length)),g=Math.max(q,p+Z*2),f=u.length+2,y=t-Math.floor(g/2),k={id:e.id,type:"stream",label:u,state:e.state,x:y,y:r,width:g,height:f,centerX:t,bottomY:r+f-1,metadata:{streamState:e.streamState,backpressureOccurred:e.backpressureOccurred}};return{node:k,bottomY:k.bottomY}}function Ar(e,t,r,o,i,n){let a=H(e),s=e.name??(a?"race":"parallel"),c=`${a?"\u26A1":"\u2AD8"} ${s}`;if(e.children.length===0){let w=[c,"(not tracked)"],R=Ce(e.id,a?"race":"parallel",w,e.state,t,r);return{node:R,bottomY:R.bottomY}}let l=Math.floor((o-De*(e.children.length-1))/e.children.length),p=[];for(let w of e.children){let R=je(w,Math.max(l,q),i,n);p.push(R.width)}let g=p.reduce((w,R)=>w+R,0)+De*(e.children.length-1),f=g>o&&e.children.length>1,y=Math.max(q,c.length+Z*2),k=3,$=t-Math.floor(y/2),M=r;M+=k,M+=1,M+=1;let N=[];if(f)for(let w=0;w<e.children.length;w++){let R=e.children[w],D=Le(R,t,M,o,i,n);a&&H(e)&&e.winnerId===R.id&&(D.node.metadata={...D.node.metadata,isWinner:!0}),N.push(D.node),M=D.bottomY+he}else{let w=t-Math.floor(g/2);for(let R=0;R<e.children.length;R++){let D=e.children[R],E=w+Math.floor(p[R]/2),T=Le(D,E,M,p[R],i,n);a&&H(e)&&e.winnerId===D.id&&(T.node.metadata={...T.node.metadata,isWinner:!0}),N.push(T.node),w+=p[R]+De}}let I=Math.max(...N.map(w=>w.bottomY)),x=!f&&N.length>1?I+2:I;return{node:{id:e.id,type:a?"race":"parallel",label:[c],state:e.state,x:$,y:r,width:y,height:k,centerX:t,bottomY:x,children:N,metadata:{verticalLayout:f}},bottomY:x}}function Pr(e,t,r,o,i,n){let a=e.name??"decision",s=e.condition?` (${e.condition.slice(0,20)})`:"",u=`\u25C7 ${a}${s}`,c=Math.min(o-Z*2,40),l=Ve(u,c),p=Math.max(...l.map(x=>ee(x).length)),g=Math.max(q,p+Z*2),f=l.length+2,y=t-Math.floor(g/2),k=e.branches.find(x=>x.taken),$=k&&k.children.length>0?k:e.branches.find(x=>x.children.length>0);if(!$||$.children.length===0){let x={id:e.id,type:"decision",label:l,state:e.state,x:y,y:r,width:g,height:f,centerX:t,bottomY:r+f-1};return{node:x,bottomY:x.bottomY}}let M=r+f+he,N=[];for(let x of $.children){let m=Le(x,t,M,o,i,n);N.push(m.node),M=m.bottomY+he}let I=N.length>0?N[N.length-1].bottomY:r+f-1;return{node:{id:e.id,type:"decision",label:l,state:e.state,x:y,y:r,width:g,height:f,centerX:t,bottomY:I,children:N},bottomY:I}}function je(e,t,r,o){if(z(e)){let i=e.name??e.key??"step",n=mt(e.state),a=1;r.showTimings&&e.durationMs!==void 0&&a++,e.retryCount&&e.retryCount>0&&a++,e.timedOut&&a++,o?.showSparklines&&(o.timingHistory?.has(e.key??"")||o.timingHistory?.has(e.name??"")||o.timingHistory?.has(e.id))&&a++;let s=`${n} ${i}`;r.showKeys&&e.key&&e.name&&(s+=` [${e.key}]`);let u=Math.min(t,Math.max(q,s.length+Z*2)),c=a+2;return{width:u,height:c}}if(j(e)||H(e)){if(e.children.length===0)return{width:q+4,height:4};let i=Math.floor(t/e.children.length),n=0,a=0;for(let s of e.children){let u=je(s,i,r,o);n+=u.width,a=Math.max(a,u.height)}return n+=De*(e.children.length-1),{width:Math.max(n,q),height:5+a+2}}if(Y(e)){let i=e.branches.find(a=>a.taken),n=0;if(i)for(let a of i.children){let s=je(a,t,r,o);n+=s.height+he}return{width:Math.min(t,30),height:3+n}}if(Q(e)){let i=`stream:${e.namespace}`,n=2;r.showTimings&&e.durationMs!==void 0&&n++,e.backpressureOccurred&&n++;let a=Math.min(t,Math.max(q,i.length+Z*2+4)),s=n+2;return{width:a,height:s}}return{width:q,height:3}}function Hr(e,t,r){let o={...V,...r.colors};for(let i=0;i<t.length;i++){let n=t[i],a=i===t.length-1;if(_e(e,n,o),!a){let s=t[i+1],u=n.centerX,c=n.bottomY+1,l=s.centerX,p=s.y-1;re(e,u,c,p-1),de(e,l,p)}}}function _e(e,t,r){let o=t.type!=="start",i=t.type!=="end"&&(!t.children||t.children.length===0);Cr(e,t.x,t.y,t.width,t.height),o&&W(e,t.centerX,t.y,L.teeUp),(i||t.children&&t.children.length>0)&&W(e,t.centerX,t.y+t.height-1,L.teeDown);let n=t.width-Z*2,a=Kr(t,r);for(let s=0;s<t.label.length;s++){let u=t.label[s],c=t.x+1+Math.floor((n-ee(u).length)/2),l=t.y+1+s;ut(e,c,l,u,a)}t.metadata?.isWinner&&ut(e,t.x+t.width-2,t.y,"\u{1F3C6}"),t.children&&t.children.length>0&&(t.type==="parallel"||t.type==="race"?Fr(e,t,r):zr(e,t,r))}function Fr(e,t,r){let o=t.children;if(o.length===0)return;let i=t.y+t.height,n=t.centerX;if(t.metadata?.verticalLayout===!0){let s=o[0];re(e,n,i,s.y-2),de(e,s.centerX,s.y-1);for(let u=0;u<o.length;u++){let c=o[u];if(_e(e,c,r),u<o.length-1){let l=o[u+1];re(e,c.centerX,c.bottomY+1,l.y-2),de(e,l.centerX,l.y-1)}}return}if(o.length===1)re(e,n,i,o[0].y-2),de(e,o[0].centerX,o[0].y-1);else{let s=o.map(l=>l.centerX),u=Math.min(...s),c=Math.max(...s);re(e,n,i,i+1),pt(e,i+1,u,c),W(e,n,i+1,L.teeUp);for(let l of o){let p=l.centerX;p===u?W(e,p,i+1,L.topLeft):p===c?W(e,p,i+1,L.topRight):p!==n&&W(e,p,i+1,L.teeDown),re(e,p,i+2,l.y-2),de(e,p,l.y-1)}}for(let s of o)_e(e,s,r);if(o.length>1){let s=o.map(f=>f.bottomY),u=Math.max(...s),c=u+1,l=o.map(f=>f.centerX),p=Math.min(...l),g=Math.max(...l);for(let f of o)f.bottomY<u&&re(e,f.centerX,f.bottomY+1,c-1);pt(e,c,p,g);for(let f of o){let y=f.centerX;y===p?W(e,y,c,L.bottomLeft):y===g?W(e,y,c,L.bottomRight):W(e,y,c,L.teeUp)}W(e,t.centerX,c,L.teeDown),W(e,t.centerX,c+1,L.vertical)}}function zr(e,t,r){let o=t.children;if(o.length===0)return;let i=t.y+t.height,n=o[0];re(e,t.centerX,i,n.y-2),de(e,n.centerX,n.y-1);for(let a=0;a<o.length;a++){let s=o[a];if(_e(e,s,r),a<o.length-1){let u=o[a+1];re(e,s.centerX,s.bottomY+1,u.y-2),de(e,u.centerX,u.y-1)}}}var Ur={active:"\x1B[36m",closed:"\x1B[32m",error:"\x1B[31m"};function Kr(e,t){if(e.metadata?.heat!==void 0){let r=fe(e.metadata.heat);return Tr[r]||void 0}return e.type==="stream"&&e.metadata?.streamState?Ur[e.metadata.streamState]||void 0:t[e.state]||void 0}function le(){return{name:"flowchart",supportsLive:!1,render(e,t){let r=t.terminalWidth??80,{nodes:o,totalHeight:i}=_r(e,t,r),n=Dr(r,i);return Hr(n,o,t),Lr(n)}}}function jr(e){return e.replace(/\x1b\[[0-9;]*m/g,"")}function Vr(e){let t=[];function r(o){for(let i of o)if(z(i))t.push(i);else if(Pe(i))r(i.children);else if(j(i)||H(i))r(i.children);else if(Y(i))for(let n of i.branches)n.taken&&r(n.children)}return r(e),t}function Gr(e){let t={id:e.id,name:e.name??e.key??e.id,state:e.state};return e.key&&(t.key=e.key),e.durationMs!==void 0&&(t.durationMs=e.durationMs),e.startTs!==void 0&&(t.startTs=e.startTs),e.endTs!==void 0&&(t.endTs=e.endTs),e.retryCount!==void 0&&e.retryCount>0&&(t.retryCount=e.retryCount),e.timedOut&&(t.timedOut=!0,e.timeoutMs!==void 0&&(t.timeoutMs=e.timeoutMs)),e.error!==void 0&&(t.error=typeof e.error=="string"?e.error:String(e.error)),t}function Yr(e){let t=0,r=0,o=0,i=0,n=0,a;for(let s of e)s.state==="success"&&t++,s.state==="error"&&r++,s.state==="cached"&&o++,s.state==="skipped"&&i++,s.retryCount!==void 0&&(n+=s.retryCount),s.durationMs!==void 0&&(!a||s.durationMs>a.durationMs)&&(a={name:s.name??s.key??s.id,durationMs:s.durationMs});return{totalSteps:e.length,successCount:t,errorCount:r,cacheHits:o,skippedCount:i,totalRetries:n,slowestStep:a}}function Jr(e){let t={};if(e.shouldRun&&(t.shouldRun={result:e.shouldRun.context?.result,durationMs:e.shouldRun.durationMs},e.shouldRun.error!==void 0&&e.shouldRun.error!==null&&(t.shouldRun.error=String(e.shouldRun.error))),e.onBeforeStart&&(t.onBeforeStart={durationMs:e.onBeforeStart.durationMs},e.onBeforeStart.error!==void 0&&e.onBeforeStart.error!==null&&(t.onBeforeStart.error=String(e.onBeforeStart.error))),e.onAfterStep.size>0){t.onAfterStep=[];for(let[r,o]of e.onAfterStep){let i={stepKey:r};o.durationMs!==void 0&&(i.durationMs=o.durationMs),o.error!==void 0&&o.error!==null&&(i.error=String(o.error)),t.onAfterStep.push(i)}}return t}function Xr(e,t){let r=e.root,o=Vr(r.children),i=t.includeDiagram??!0,n=t.stripAnsiColors??!0,a={workflow:{id:r.workflowId,name:r.name,state:r.state,durationMs:r.durationMs,startedAt:r.startTs,completedAt:r.endTs},steps:o.map(Gr),summary:Yr(o)};if(e.hooks){let s=Jr(e.hooks);Object.keys(s).length>0&&(a.hooks=s)}if(i){let c=((t.diagramFormat??"ascii")==="flowchart"?le():ce()).render(e,t);n&&(c=jr(c)),a.diagram=c}return a}function ke(){return{name:"logger",supportsLive:!1,render(e,t){let o=Xr(e,t);return JSON.stringify(o)}}}function ht(e){let t={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"},r={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"},o=n=>`
|
|
5
|
+
--bg: ${n.bg};
|
|
6
|
+
--bg-secondary: ${n.bgSecondary};
|
|
7
|
+
--text: ${n.text};
|
|
8
|
+
--text-muted: ${n.textMuted};
|
|
9
|
+
--border: ${n.border};
|
|
10
|
+
--primary: ${n.primary};
|
|
11
|
+
--success: ${n.success};
|
|
12
|
+
--error: ${n.error};
|
|
13
|
+
--warning: ${n.warning};
|
|
14
|
+
--info: ${n.info};
|
|
15
|
+
--muted: ${n.muted};
|
|
16
|
+
--node-pending: ${n.nodePending};
|
|
17
|
+
--node-running: ${n.nodeRunning};
|
|
18
|
+
--node-success: ${n.nodeSuccess};
|
|
19
|
+
--node-error: ${n.nodeError};
|
|
20
|
+
--node-aborted: ${n.nodeAborted};
|
|
21
|
+
--node-cached: ${n.nodeCached};
|
|
22
|
+
--node-skipped: ${n.nodeSkipped};
|
|
23
|
+
--heat-cold: ${n.heatCold};
|
|
24
|
+
--heat-cool: ${n.heatCool};
|
|
25
|
+
--heat-neutral: ${n.heatNeutral};
|
|
26
|
+
--heat-warm: ${n.heatWarm};
|
|
27
|
+
--heat-hot: ${n.heatHot};
|
|
28
|
+
--heat-critical: ${n.heatCritical};
|
|
29
|
+
`,i;return e==="auto"?i=`
|
|
30
|
+
:root {
|
|
31
|
+
${o(t)}
|
|
32
|
+
}
|
|
33
|
+
@media (prefers-color-scheme: dark) {
|
|
34
|
+
:root {
|
|
35
|
+
${o(r)}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
`:e==="dark"?i=`
|
|
39
|
+
:root {
|
|
40
|
+
${o(r)}
|
|
41
|
+
}
|
|
42
|
+
`:i=`
|
|
43
|
+
:root {
|
|
44
|
+
${o(t)}
|
|
45
|
+
}
|
|
46
|
+
`,`
|
|
47
|
+
${i}
|
|
48
|
+
|
|
49
|
+
* {
|
|
50
|
+
box-sizing: border-box;
|
|
51
|
+
margin: 0;
|
|
52
|
+
padding: 0;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
body {
|
|
56
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
|
57
|
+
background-color: var(--bg);
|
|
58
|
+
color: var(--text);
|
|
59
|
+
line-height: 1.5;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.workflow-visualizer {
|
|
63
|
+
display: flex;
|
|
64
|
+
flex-direction: column;
|
|
65
|
+
height: 100vh;
|
|
66
|
+
overflow: hidden;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/* Header */
|
|
70
|
+
.wv-header {
|
|
71
|
+
display: flex;
|
|
72
|
+
align-items: center;
|
|
73
|
+
justify-content: space-between;
|
|
74
|
+
padding: 12px 20px;
|
|
75
|
+
background-color: var(--bg-secondary);
|
|
76
|
+
border-bottom: 1px solid var(--border);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
.wv-header h1 {
|
|
80
|
+
font-size: 1.25rem;
|
|
81
|
+
font-weight: 600;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.wv-controls {
|
|
85
|
+
display: flex;
|
|
86
|
+
gap: 8px;
|
|
87
|
+
align-items: center;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
.wv-btn {
|
|
91
|
+
display: inline-flex;
|
|
92
|
+
align-items: center;
|
|
93
|
+
justify-content: center;
|
|
94
|
+
padding: 6px 12px;
|
|
95
|
+
font-size: 0.875rem;
|
|
96
|
+
font-weight: 500;
|
|
97
|
+
border: 1px solid var(--border);
|
|
98
|
+
border-radius: 6px;
|
|
99
|
+
background-color: var(--bg);
|
|
100
|
+
color: var(--text);
|
|
101
|
+
cursor: pointer;
|
|
102
|
+
transition: all 0.15s ease;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.wv-btn:hover {
|
|
106
|
+
background-color: var(--bg-secondary);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
.wv-btn:disabled {
|
|
110
|
+
opacity: 0.5;
|
|
111
|
+
cursor: not-allowed;
|
|
112
|
+
background-color: var(--bg-secondary);
|
|
113
|
+
color: var(--text-muted);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
.wv-btn--primary {
|
|
117
|
+
background-color: var(--primary);
|
|
118
|
+
border-color: var(--primary);
|
|
119
|
+
color: white;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
.wv-btn--primary:hover {
|
|
123
|
+
opacity: 0.9;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
.wv-btn--icon {
|
|
127
|
+
padding: 6px;
|
|
128
|
+
min-width: 32px;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/* Main content area */
|
|
132
|
+
.wv-main {
|
|
133
|
+
display: flex;
|
|
134
|
+
flex: 1;
|
|
135
|
+
overflow: hidden;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/* Diagram container */
|
|
139
|
+
.wv-diagram {
|
|
140
|
+
flex: 1;
|
|
141
|
+
position: relative;
|
|
142
|
+
overflow: hidden;
|
|
143
|
+
background-color: var(--bg);
|
|
144
|
+
background-image:
|
|
145
|
+
radial-gradient(circle, var(--border) 1px, transparent 1px);
|
|
146
|
+
background-size: 20px 20px;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
.wv-diagram svg {
|
|
150
|
+
width: 100%;
|
|
151
|
+
height: 100%;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/* SVG Node styles */
|
|
155
|
+
.wv-node {
|
|
156
|
+
cursor: pointer;
|
|
157
|
+
transition: filter 0.15s ease;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
.wv-node:hover {
|
|
161
|
+
filter: brightness(1.1) drop-shadow(0 2px 4px rgba(0, 0, 0, 0.2));
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
.wv-node rect,
|
|
165
|
+
.wv-node circle {
|
|
166
|
+
stroke: var(--border);
|
|
167
|
+
stroke-width: 2;
|
|
168
|
+
transition: all 0.2s ease;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
.wv-node:hover rect,
|
|
172
|
+
.wv-node:hover circle {
|
|
173
|
+
stroke-width: 3;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
.wv-node--pending rect { fill: var(--node-pending); }
|
|
177
|
+
.wv-node--running rect { fill: var(--node-running); stroke: var(--warning); }
|
|
178
|
+
.wv-node--success rect { fill: var(--node-success); stroke: var(--success); }
|
|
179
|
+
.wv-node--error rect { fill: var(--node-error); stroke: var(--error); }
|
|
180
|
+
.wv-node--aborted rect { fill: var(--node-aborted); }
|
|
181
|
+
.wv-node--cached rect { fill: var(--node-cached); stroke: var(--info); }
|
|
182
|
+
.wv-node--skipped rect { fill: var(--node-skipped); opacity: 0.6; }
|
|
183
|
+
|
|
184
|
+
.wv-node--selected rect {
|
|
185
|
+
stroke: var(--primary);
|
|
186
|
+
stroke-width: 3;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
.wv-node text {
|
|
190
|
+
fill: var(--text);
|
|
191
|
+
font-size: 12px;
|
|
192
|
+
font-weight: 500;
|
|
193
|
+
dominant-baseline: middle;
|
|
194
|
+
text-anchor: middle;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
.wv-node .wv-node-timing {
|
|
198
|
+
fill: var(--text-muted);
|
|
199
|
+
font-size: 10px;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/* Edge styles */
|
|
203
|
+
.wv-edge {
|
|
204
|
+
fill: none;
|
|
205
|
+
stroke: var(--border);
|
|
206
|
+
stroke-width: 2;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
.wv-edge--active {
|
|
210
|
+
stroke: var(--success);
|
|
211
|
+
stroke-width: 2.5;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
.wv-edge-arrow {
|
|
215
|
+
fill: var(--border);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/* Parallel/Race container */
|
|
219
|
+
.wv-container {
|
|
220
|
+
fill: transparent;
|
|
221
|
+
stroke: var(--border);
|
|
222
|
+
stroke-dasharray: 5 3;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
.wv-container--parallel { stroke: var(--info); }
|
|
226
|
+
.wv-container--race { stroke: var(--warning); }
|
|
227
|
+
|
|
228
|
+
.wv-container-label {
|
|
229
|
+
fill: var(--text-muted);
|
|
230
|
+
font-size: 10px;
|
|
231
|
+
font-weight: 600;
|
|
232
|
+
text-transform: uppercase;
|
|
233
|
+
letter-spacing: 0.5px;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/* Heatmap overlay */
|
|
237
|
+
.wv-node--heat-cold rect { fill: var(--heat-cold) !important; opacity: 0.7; }
|
|
238
|
+
.wv-node--heat-cool rect { fill: var(--heat-cool) !important; opacity: 0.7; }
|
|
239
|
+
.wv-node--heat-neutral rect { fill: var(--heat-neutral) !important; opacity: 0.7; }
|
|
240
|
+
.wv-node--heat-warm rect { fill: var(--heat-warm) !important; opacity: 0.7; }
|
|
241
|
+
.wv-node--heat-hot rect { fill: var(--heat-hot) !important; opacity: 0.7; }
|
|
242
|
+
.wv-node--heat-critical rect { fill: var(--heat-critical) !important; opacity: 0.85; }
|
|
243
|
+
|
|
244
|
+
/* Timeline scrubber */
|
|
245
|
+
.wv-timeline {
|
|
246
|
+
height: 80px;
|
|
247
|
+
padding: 12px 20px;
|
|
248
|
+
background-color: var(--bg-secondary);
|
|
249
|
+
border-top: 1px solid var(--border);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
.wv-timeline-track {
|
|
253
|
+
position: relative;
|
|
254
|
+
height: 24px;
|
|
255
|
+
background-color: var(--bg);
|
|
256
|
+
border-radius: 4px;
|
|
257
|
+
overflow: hidden;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
.wv-timeline-progress {
|
|
261
|
+
position: absolute;
|
|
262
|
+
top: 0;
|
|
263
|
+
left: 0;
|
|
264
|
+
height: 100%;
|
|
265
|
+
background-color: var(--primary);
|
|
266
|
+
opacity: 0.3;
|
|
267
|
+
transition: width 0.1s ease;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
.wv-timeline-marker {
|
|
271
|
+
position: absolute;
|
|
272
|
+
top: 0;
|
|
273
|
+
width: 3px;
|
|
274
|
+
height: 100%;
|
|
275
|
+
background-color: var(--primary);
|
|
276
|
+
cursor: ew-resize;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
.wv-timeline-events {
|
|
280
|
+
display: flex;
|
|
281
|
+
gap: 2px;
|
|
282
|
+
height: 100%;
|
|
283
|
+
align-items: center;
|
|
284
|
+
padding: 4px;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
.wv-timeline-event {
|
|
288
|
+
width: 4px;
|
|
289
|
+
height: 16px;
|
|
290
|
+
border-radius: 2px;
|
|
291
|
+
background-color: var(--muted);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
.wv-timeline-event--success { background-color: var(--success); }
|
|
295
|
+
.wv-timeline-event--error { background-color: var(--error); }
|
|
296
|
+
.wv-timeline-event--running { background-color: var(--warning); }
|
|
297
|
+
|
|
298
|
+
.wv-timeline-controls {
|
|
299
|
+
display: flex;
|
|
300
|
+
gap: 8px;
|
|
301
|
+
margin-top: 8px;
|
|
302
|
+
align-items: center;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
.wv-timeline-time {
|
|
306
|
+
font-size: 0.75rem;
|
|
307
|
+
color: var(--text-muted);
|
|
308
|
+
font-family: monospace;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/* Inspector panel */
|
|
312
|
+
.wv-inspector {
|
|
313
|
+
width: 320px;
|
|
314
|
+
background-color: var(--bg-secondary);
|
|
315
|
+
border-left: 1px solid var(--border);
|
|
316
|
+
overflow-y: auto;
|
|
317
|
+
transition: width 0.2s ease;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
.wv-inspector--collapsed {
|
|
321
|
+
width: 0;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
.wv-inspector-header {
|
|
325
|
+
display: flex;
|
|
326
|
+
align-items: center;
|
|
327
|
+
justify-content: space-between;
|
|
328
|
+
padding: 12px 16px;
|
|
329
|
+
border-bottom: 1px solid var(--border);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
.wv-inspector-header h2 {
|
|
333
|
+
font-size: 0.875rem;
|
|
334
|
+
font-weight: 600;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
.wv-inspector-content {
|
|
338
|
+
padding: 16px;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
.wv-inspector-section {
|
|
342
|
+
margin-bottom: 20px;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
.wv-inspector-section h3 {
|
|
346
|
+
font-size: 0.75rem;
|
|
347
|
+
font-weight: 600;
|
|
348
|
+
text-transform: uppercase;
|
|
349
|
+
letter-spacing: 0.5px;
|
|
350
|
+
color: var(--text-muted);
|
|
351
|
+
margin-bottom: 8px;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
.wv-inspector-row {
|
|
355
|
+
display: flex;
|
|
356
|
+
justify-content: space-between;
|
|
357
|
+
padding: 4px 0;
|
|
358
|
+
font-size: 0.875rem;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
.wv-inspector-label {
|
|
362
|
+
color: var(--text-muted);
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
.wv-inspector-value {
|
|
366
|
+
font-weight: 500;
|
|
367
|
+
font-family: monospace;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
.wv-inspector-value--success { color: var(--success); }
|
|
371
|
+
.wv-inspector-value--error { color: var(--error); }
|
|
372
|
+
.wv-inspector-value--running { color: var(--warning); }
|
|
373
|
+
|
|
374
|
+
/* Status badge */
|
|
375
|
+
.wv-badge {
|
|
376
|
+
display: inline-flex;
|
|
377
|
+
align-items: center;
|
|
378
|
+
padding: 2px 8px;
|
|
379
|
+
font-size: 0.75rem;
|
|
380
|
+
font-weight: 500;
|
|
381
|
+
border-radius: 4px;
|
|
382
|
+
text-transform: capitalize;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
.wv-badge--pending { background-color: var(--node-pending); }
|
|
386
|
+
.wv-badge--running { background-color: var(--node-running); color: #664d03; }
|
|
387
|
+
.wv-badge--success { background-color: var(--node-success); color: #0f5132; }
|
|
388
|
+
.wv-badge--error { background-color: var(--node-error); color: #842029; }
|
|
389
|
+
.wv-badge--cached { background-color: var(--node-cached); color: #084298; }
|
|
390
|
+
|
|
391
|
+
/* Live indicator */
|
|
392
|
+
.wv-live {
|
|
393
|
+
display: flex;
|
|
394
|
+
align-items: center;
|
|
395
|
+
gap: 6px;
|
|
396
|
+
padding: 4px 10px;
|
|
397
|
+
background-color: var(--error);
|
|
398
|
+
color: white;
|
|
399
|
+
font-size: 0.75rem;
|
|
400
|
+
font-weight: 600;
|
|
401
|
+
border-radius: 4px;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
.wv-live-dot {
|
|
405
|
+
width: 8px;
|
|
406
|
+
height: 8px;
|
|
407
|
+
background-color: white;
|
|
408
|
+
border-radius: 50%;
|
|
409
|
+
animation: wv-pulse 1.5s infinite;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
@keyframes wv-pulse {
|
|
413
|
+
0%, 100% { opacity: 1; }
|
|
414
|
+
50% { opacity: 0.5; }
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
/* Performance stats */
|
|
418
|
+
.wv-perf-bar {
|
|
419
|
+
height: 8px;
|
|
420
|
+
background-color: var(--bg);
|
|
421
|
+
border-radius: 4px;
|
|
422
|
+
overflow: hidden;
|
|
423
|
+
margin-top: 4px;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
.wv-perf-bar-fill {
|
|
427
|
+
height: 100%;
|
|
428
|
+
border-radius: 4px;
|
|
429
|
+
transition: width 0.3s ease;
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
.wv-perf-bar-fill--cold { background-color: var(--heat-cold); }
|
|
433
|
+
.wv-perf-bar-fill--cool { background-color: var(--heat-cool); }
|
|
434
|
+
.wv-perf-bar-fill--neutral { background-color: var(--heat-neutral); }
|
|
435
|
+
.wv-perf-bar-fill--warm { background-color: var(--heat-warm); }
|
|
436
|
+
.wv-perf-bar-fill--hot { background-color: var(--heat-hot); }
|
|
437
|
+
.wv-perf-bar-fill--critical { background-color: var(--heat-critical); }
|
|
438
|
+
|
|
439
|
+
/* Tooltip */
|
|
440
|
+
.wv-tooltip {
|
|
441
|
+
position: fixed;
|
|
442
|
+
padding: 8px 12px;
|
|
443
|
+
background-color: var(--text);
|
|
444
|
+
color: var(--bg);
|
|
445
|
+
font-size: 0.75rem;
|
|
446
|
+
border-radius: 4px;
|
|
447
|
+
pointer-events: none;
|
|
448
|
+
z-index: 1000;
|
|
449
|
+
max-width: 300px;
|
|
450
|
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
/* Loading state */
|
|
454
|
+
.wv-loading {
|
|
455
|
+
display: flex;
|
|
456
|
+
align-items: center;
|
|
457
|
+
justify-content: center;
|
|
458
|
+
height: 100%;
|
|
459
|
+
color: var(--text-muted);
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
.wv-spinner {
|
|
463
|
+
width: 24px;
|
|
464
|
+
height: 24px;
|
|
465
|
+
border: 3px solid var(--border);
|
|
466
|
+
border-top-color: var(--primary);
|
|
467
|
+
border-radius: 50%;
|
|
468
|
+
animation: wv-spin 1s linear infinite;
|
|
469
|
+
margin-right: 8px;
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
@keyframes wv-spin {
|
|
473
|
+
to { transform: rotate(360deg); }
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
/* Empty state */
|
|
477
|
+
.wv-empty {
|
|
478
|
+
display: flex;
|
|
479
|
+
flex-direction: column;
|
|
480
|
+
align-items: center;
|
|
481
|
+
justify-content: center;
|
|
482
|
+
height: 100%;
|
|
483
|
+
color: var(--text-muted);
|
|
484
|
+
text-align: center;
|
|
485
|
+
padding: 40px;
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
.wv-empty svg {
|
|
489
|
+
width: 64px;
|
|
490
|
+
height: 64px;
|
|
491
|
+
margin-bottom: 16px;
|
|
492
|
+
opacity: 0.5;
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
/* Modal */
|
|
496
|
+
.wv-modal {
|
|
497
|
+
position: fixed;
|
|
498
|
+
top: 0;
|
|
499
|
+
left: 0;
|
|
500
|
+
right: 0;
|
|
501
|
+
bottom: 0;
|
|
502
|
+
background-color: rgba(0, 0, 0, 0.5);
|
|
503
|
+
display: flex;
|
|
504
|
+
align-items: center;
|
|
505
|
+
justify-content: center;
|
|
506
|
+
z-index: 1000;
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
.wv-modal-content {
|
|
510
|
+
background-color: var(--bg);
|
|
511
|
+
border-radius: 8px;
|
|
512
|
+
width: 90%;
|
|
513
|
+
max-width: 600px;
|
|
514
|
+
max-height: 90vh;
|
|
515
|
+
display: flex;
|
|
516
|
+
flex-direction: column;
|
|
517
|
+
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.2);
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
.wv-modal-header {
|
|
521
|
+
display: flex;
|
|
522
|
+
align-items: center;
|
|
523
|
+
justify-content: space-between;
|
|
524
|
+
padding: 16px 20px;
|
|
525
|
+
border-bottom: 1px solid var(--border);
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
.wv-modal-header h2 {
|
|
529
|
+
font-size: 1.125rem;
|
|
530
|
+
font-weight: 600;
|
|
531
|
+
margin: 0;
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
.wv-modal-body {
|
|
535
|
+
padding: 20px;
|
|
536
|
+
overflow-y: auto;
|
|
537
|
+
flex: 1;
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
.wv-modal-body p {
|
|
541
|
+
margin: 0 0 12px 0;
|
|
542
|
+
font-size: 0.875rem;
|
|
543
|
+
color: var(--text-muted);
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
.wv-modal-body code {
|
|
547
|
+
background-color: var(--bg-secondary);
|
|
548
|
+
padding: 2px 6px;
|
|
549
|
+
border-radius: 4px;
|
|
550
|
+
font-size: 0.875rem;
|
|
551
|
+
font-family: monospace;
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
.wv-textarea {
|
|
555
|
+
width: 100%;
|
|
556
|
+
padding: 12px;
|
|
557
|
+
font-family: monospace;
|
|
558
|
+
font-size: 0.875rem;
|
|
559
|
+
border: 1px solid var(--border);
|
|
560
|
+
border-radius: 6px;
|
|
561
|
+
background-color: var(--bg);
|
|
562
|
+
color: var(--text);
|
|
563
|
+
resize: vertical;
|
|
564
|
+
box-sizing: border-box;
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
.wv-textarea:focus {
|
|
568
|
+
outline: none;
|
|
569
|
+
border-color: var(--primary);
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
.wv-error {
|
|
573
|
+
margin-top: 12px;
|
|
574
|
+
padding: 12px;
|
|
575
|
+
background-color: var(--node-error);
|
|
576
|
+
color: #842029;
|
|
577
|
+
border-radius: 6px;
|
|
578
|
+
font-size: 0.875rem;
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
.wv-modal-footer {
|
|
582
|
+
display: flex;
|
|
583
|
+
gap: 8px;
|
|
584
|
+
justify-content: flex-end;
|
|
585
|
+
padding: 16px 20px;
|
|
586
|
+
border-top: 1px solid var(--border);
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
/* Responsive */
|
|
590
|
+
@media (max-width: 768px) {
|
|
591
|
+
.wv-inspector {
|
|
592
|
+
position: fixed;
|
|
593
|
+
right: 0;
|
|
594
|
+
top: 0;
|
|
595
|
+
bottom: 0;
|
|
596
|
+
z-index: 100;
|
|
597
|
+
box-shadow: -4px 0 12px rgba(0, 0, 0, 0.1);
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
.wv-timeline {
|
|
601
|
+
height: auto;
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
.wv-modal-content {
|
|
605
|
+
width: 95%;
|
|
606
|
+
max-height: 95vh;
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
`}function gt(e){return`
|
|
610
|
+
(function() {
|
|
611
|
+
'use strict';
|
|
612
|
+
|
|
613
|
+
// State
|
|
614
|
+
let selectedNodeId = null;
|
|
615
|
+
let transform = { x: 0, y: 0, scale: 1 };
|
|
616
|
+
let isDragging = false;
|
|
617
|
+
let dragStart = { x: 0, y: 0 };
|
|
618
|
+
let ws = null;
|
|
619
|
+
let snapshots = [];
|
|
620
|
+
let currentSnapshotIndex = -1;
|
|
621
|
+
let isPlaying = false;
|
|
622
|
+
let playbackSpeed = 1;
|
|
623
|
+
let heatmapEnabled = false;
|
|
624
|
+
let heatmapMetric = 'duration';
|
|
625
|
+
|
|
626
|
+
// DOM elements
|
|
627
|
+
const diagram = document.getElementById('diagram');
|
|
628
|
+
const svg = diagram?.querySelector('svg');
|
|
629
|
+
const inspector = document.getElementById('inspector');
|
|
630
|
+
const timeline = document.getElementById('timeline');
|
|
631
|
+
|
|
632
|
+
// Initialize
|
|
633
|
+
document.addEventListener('DOMContentLoaded', init);
|
|
634
|
+
|
|
635
|
+
function init() {
|
|
636
|
+
${e.interactive?"setupInteractivity(); setupLoadJSON();":""}
|
|
637
|
+
// WebSocket must be initialized before time-travel and heatmap checks
|
|
638
|
+
${e.wsUrl?`setupWebSocket('${e.wsUrl}');`:""}
|
|
639
|
+
${e.timeTravel?"setupTimeTravel(); initializeTimeTravelFromData();":""}
|
|
640
|
+
${e.heatmap?"setupHeatmap();":""}
|
|
641
|
+
setupKeyboardShortcuts();
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
// Load JSON functionality
|
|
645
|
+
function setupLoadJSON() {
|
|
646
|
+
const loadBtn = document.getElementById('load-json-btn');
|
|
647
|
+
const modal = document.getElementById('load-json-modal');
|
|
648
|
+
const closeBtn = document.getElementById('load-json-close');
|
|
649
|
+
const cancelBtn = document.getElementById('load-json-cancel');
|
|
650
|
+
const submitBtn = document.getElementById('load-json-submit');
|
|
651
|
+
const input = document.getElementById('load-json-input');
|
|
652
|
+
const errorDiv = document.getElementById('load-json-error');
|
|
653
|
+
|
|
654
|
+
if (!loadBtn || !modal) return;
|
|
655
|
+
|
|
656
|
+
loadBtn.addEventListener('click', () => {
|
|
657
|
+
modal.style.display = 'flex';
|
|
658
|
+
if (input) {
|
|
659
|
+
input.value = '';
|
|
660
|
+
input.focus();
|
|
661
|
+
}
|
|
662
|
+
if (errorDiv) errorDiv.style.display = 'none';
|
|
663
|
+
});
|
|
664
|
+
|
|
665
|
+
const closeModal = () => {
|
|
666
|
+
modal.style.display = 'none';
|
|
667
|
+
if (errorDiv) errorDiv.style.display = 'none';
|
|
668
|
+
};
|
|
669
|
+
|
|
670
|
+
closeBtn?.addEventListener('click', closeModal);
|
|
671
|
+
cancelBtn?.addEventListener('click', closeModal);
|
|
672
|
+
modal.addEventListener('click', (e) => {
|
|
673
|
+
if (e.target === modal) closeModal();
|
|
674
|
+
});
|
|
675
|
+
|
|
676
|
+
submitBtn?.addEventListener('click', () => {
|
|
677
|
+
if (!input) return;
|
|
678
|
+
|
|
679
|
+
try {
|
|
680
|
+
const jsonText = input.value.trim();
|
|
681
|
+
if (!jsonText) {
|
|
682
|
+
showError('Please paste JSON data');
|
|
683
|
+
return;
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
const ir = JSON.parse(jsonText);
|
|
687
|
+
|
|
688
|
+
// Validate IR structure
|
|
689
|
+
if (!ir || !ir.root || !ir.root.type || ir.root.type !== 'workflow') {
|
|
690
|
+
showError('Invalid workflow IR. Expected object with root.type === "workflow"');
|
|
691
|
+
return;
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
// Update global data
|
|
695
|
+
window.__WORKFLOW_IR__ = ir;
|
|
696
|
+
const newData = buildWorkflowDataFromIR(ir);
|
|
697
|
+
window.__WORKFLOW_DATA__ = newData;
|
|
698
|
+
|
|
699
|
+
// Save to sessionStorage for full rebuild on reload
|
|
700
|
+
try {
|
|
701
|
+
sessionStorage.setItem('workflow_ir', JSON.stringify(ir));
|
|
702
|
+
} catch (storageErr) {
|
|
703
|
+
console.warn('Failed to save IR to sessionStorage:', storageErr);
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
// Rebuild the diagram (updates node states in-place)
|
|
707
|
+
rebuildDiagram(ir);
|
|
708
|
+
|
|
709
|
+
// Update inspector if node is selected
|
|
710
|
+
if (selectedNodeId) {
|
|
711
|
+
updateInspector(selectedNodeId);
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
closeModal();
|
|
715
|
+
|
|
716
|
+
// Offer full rebuild via reload if structure changed significantly
|
|
717
|
+
console.log('IR loaded. Node states updated. Reload page for full layout rebuild with new structure.');
|
|
718
|
+
} catch (e) {
|
|
719
|
+
showError('Invalid JSON: ' + e.message);
|
|
720
|
+
}
|
|
721
|
+
});
|
|
722
|
+
|
|
723
|
+
function showError(message) {
|
|
724
|
+
if (errorDiv) {
|
|
725
|
+
errorDiv.textContent = message;
|
|
726
|
+
errorDiv.style.display = 'block';
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
function buildWorkflowDataFromIR(ir) {
|
|
732
|
+
const nodes = {};
|
|
733
|
+
|
|
734
|
+
function collectNodes(flowNodes) {
|
|
735
|
+
for (const node of flowNodes || []) {
|
|
736
|
+
nodes[node.id] = {
|
|
737
|
+
id: node.id,
|
|
738
|
+
name: node.name,
|
|
739
|
+
type: node.type,
|
|
740
|
+
state: node.state,
|
|
741
|
+
key: node.key,
|
|
742
|
+
durationMs: node.durationMs,
|
|
743
|
+
startTs: node.startTs,
|
|
744
|
+
error: node.error !== undefined && node.error !== null ? String(node.error) : undefined,
|
|
745
|
+
retryCount: node.retryCount,
|
|
746
|
+
input: node.input,
|
|
747
|
+
output: node.output,
|
|
748
|
+
...(node.type === 'stream' && {
|
|
749
|
+
namespace: node.namespace,
|
|
750
|
+
writeCount: node.writeCount,
|
|
751
|
+
readCount: node.readCount,
|
|
752
|
+
finalPosition: node.finalPosition,
|
|
753
|
+
streamState: node.streamState,
|
|
754
|
+
backpressureOccurred: node.backpressureOccurred,
|
|
755
|
+
}),
|
|
756
|
+
...(node.type === 'decision' && {
|
|
757
|
+
condition: node.condition,
|
|
758
|
+
decisionValue: node.decisionValue,
|
|
759
|
+
branchTaken: node.branchTaken,
|
|
760
|
+
branches: node.branches,
|
|
761
|
+
}),
|
|
762
|
+
};
|
|
763
|
+
|
|
764
|
+
if (node.children) {
|
|
765
|
+
collectNodes(node.children);
|
|
766
|
+
}
|
|
767
|
+
if (node.branches) {
|
|
768
|
+
for (const branch of node.branches) {
|
|
769
|
+
collectNodes(branch.children);
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
collectNodes(ir.root.children);
|
|
776
|
+
const hooks = ir.hooks
|
|
777
|
+
? {
|
|
778
|
+
...ir.hooks,
|
|
779
|
+
onAfterStep:
|
|
780
|
+
ir.hooks.onAfterStep instanceof Map
|
|
781
|
+
? Object.fromEntries(ir.hooks.onAfterStep)
|
|
782
|
+
: ir.hooks.onAfterStep,
|
|
783
|
+
}
|
|
784
|
+
: undefined;
|
|
785
|
+
return { nodes, hooks };
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
function rebuildDiagram(ir) {
|
|
789
|
+
// Update workflow data and node states
|
|
790
|
+
const newData = buildWorkflowDataFromIR(ir);
|
|
791
|
+
window.__WORKFLOW_DATA__ = newData;
|
|
792
|
+
window.__WORKFLOW_IR__ = ir;
|
|
793
|
+
|
|
794
|
+
// Update existing node states in SVG
|
|
795
|
+
renderIR(ir);
|
|
796
|
+
|
|
797
|
+
// Note: Full diagram rebuild (new nodes, layout changes) requires regenerating the HTML
|
|
798
|
+
// For now, we update node states. Users can save the IR and regenerate HTML for full rebuild.
|
|
799
|
+
console.log('Workflow IR loaded. Node states updated. For full diagram rebuild, regenerate HTML with the new IR.');
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
function initializeTimeTravelFromData() {
|
|
803
|
+
// For static HTML (no WebSocket), time travel doesn't work since we only have one state
|
|
804
|
+
// Initialize with empty snapshots and disable controls
|
|
805
|
+
if (!ws) {
|
|
806
|
+
snapshots = [];
|
|
807
|
+
currentSnapshotIndex = -1;
|
|
808
|
+
updateTimelineUI();
|
|
809
|
+
|
|
810
|
+
// Disable time travel controls for static HTML
|
|
811
|
+
const playBtn = document.getElementById('tt-play');
|
|
812
|
+
const pauseBtn = document.getElementById('tt-pause');
|
|
813
|
+
const prevBtn = document.getElementById('tt-prev');
|
|
814
|
+
const nextBtn = document.getElementById('tt-next');
|
|
815
|
+
const slider = document.getElementById('tt-slider');
|
|
816
|
+
|
|
817
|
+
[playBtn, pauseBtn, prevBtn, nextBtn, slider].forEach(btn => {
|
|
818
|
+
if (btn) {
|
|
819
|
+
btn.disabled = true;
|
|
820
|
+
btn.title = 'Time travel requires a live WebSocket connection';
|
|
821
|
+
}
|
|
822
|
+
});
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
// Interactivity
|
|
827
|
+
function setupInteractivity() {
|
|
828
|
+
if (!diagram || !svg) return;
|
|
829
|
+
|
|
830
|
+
// Zoom with mouse wheel
|
|
831
|
+
diagram.addEventListener('wheel', (e) => {
|
|
832
|
+
e.preventDefault();
|
|
833
|
+
const delta = e.deltaY > 0 ? 0.9 : 1.1;
|
|
834
|
+
const rect = diagram.getBoundingClientRect();
|
|
835
|
+
const x = e.clientX - rect.left;
|
|
836
|
+
const y = e.clientY - rect.top;
|
|
837
|
+
|
|
838
|
+
// Zoom towards cursor position
|
|
839
|
+
transform.scale *= delta;
|
|
840
|
+
transform.scale = Math.max(0.1, Math.min(5, transform.scale));
|
|
841
|
+
transform.x = x - (x - transform.x) * delta;
|
|
842
|
+
transform.y = y - (y - transform.y) * delta;
|
|
843
|
+
|
|
844
|
+
applyTransform();
|
|
845
|
+
});
|
|
846
|
+
|
|
847
|
+
// Pan with drag
|
|
848
|
+
diagram.addEventListener('mousedown', (e) => {
|
|
849
|
+
if (e.target === diagram || e.target === svg) {
|
|
850
|
+
isDragging = true;
|
|
851
|
+
dragStart = { x: e.clientX - transform.x, y: e.clientY - transform.y };
|
|
852
|
+
diagram.style.cursor = 'grabbing';
|
|
853
|
+
}
|
|
854
|
+
});
|
|
855
|
+
|
|
856
|
+
document.addEventListener('mousemove', (e) => {
|
|
857
|
+
if (!isDragging) return;
|
|
858
|
+
transform.x = e.clientX - dragStart.x;
|
|
859
|
+
transform.y = e.clientY - dragStart.y;
|
|
860
|
+
applyTransform();
|
|
861
|
+
});
|
|
862
|
+
|
|
863
|
+
document.addEventListener('mouseup', () => {
|
|
864
|
+
isDragging = false;
|
|
865
|
+
if (diagram) diagram.style.cursor = 'grab';
|
|
866
|
+
});
|
|
867
|
+
|
|
868
|
+
// Node selection - handle clicks on nodes and their children (rect, text, etc.)
|
|
869
|
+
document.querySelectorAll('.wv-node').forEach((node) => {
|
|
870
|
+
node.addEventListener('click', (e) => {
|
|
871
|
+
e.stopPropagation();
|
|
872
|
+
const nodeId = node.dataset.nodeId;
|
|
873
|
+
if (nodeId) {
|
|
874
|
+
selectNode(nodeId);
|
|
875
|
+
}
|
|
876
|
+
});
|
|
877
|
+
});
|
|
878
|
+
|
|
879
|
+
// Also handle clicks directly on child elements (rect, text) that bubble up
|
|
880
|
+
if (svg) {
|
|
881
|
+
svg.addEventListener('click', (e) => {
|
|
882
|
+
// Find the closest .wv-node parent
|
|
883
|
+
let target = e.target;
|
|
884
|
+
while (target && target !== svg) {
|
|
885
|
+
if (target.classList && target.classList.contains('wv-node')) {
|
|
886
|
+
const nodeId = target.dataset?.nodeId;
|
|
887
|
+
if (nodeId) {
|
|
888
|
+
e.stopPropagation();
|
|
889
|
+
selectNode(nodeId);
|
|
890
|
+
return;
|
|
891
|
+
}
|
|
892
|
+
}
|
|
893
|
+
target = target.parentElement;
|
|
894
|
+
}
|
|
895
|
+
});
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
// Deselect on background click
|
|
899
|
+
diagram.addEventListener('click', (e) => {
|
|
900
|
+
if (e.target === diagram || e.target === svg) {
|
|
901
|
+
selectNode(null);
|
|
902
|
+
}
|
|
903
|
+
});
|
|
904
|
+
|
|
905
|
+
// Zoom buttons
|
|
906
|
+
document.getElementById('zoom-in')?.addEventListener('click', () => zoom(1.2));
|
|
907
|
+
document.getElementById('zoom-out')?.addEventListener('click', () => zoom(0.8));
|
|
908
|
+
document.getElementById('zoom-reset')?.addEventListener('click', resetZoom);
|
|
909
|
+
|
|
910
|
+
// Set initial cursor
|
|
911
|
+
diagram.style.cursor = 'grab';
|
|
912
|
+
}
|
|
913
|
+
|
|
914
|
+
function applyTransform() {
|
|
915
|
+
if (!svg) return;
|
|
916
|
+
const g = svg.querySelector('g.wv-root');
|
|
917
|
+
if (g) {
|
|
918
|
+
g.setAttribute('transform', 'translate(' + transform.x + ',' + transform.y + ') scale(' + transform.scale + ')');
|
|
919
|
+
}
|
|
920
|
+
}
|
|
921
|
+
|
|
922
|
+
function zoom(factor) {
|
|
923
|
+
if (!diagram) return;
|
|
924
|
+
const rect = diagram.getBoundingClientRect();
|
|
925
|
+
const centerX = rect.width / 2;
|
|
926
|
+
const centerY = rect.height / 2;
|
|
927
|
+
|
|
928
|
+
transform.scale *= factor;
|
|
929
|
+
transform.scale = Math.max(0.1, Math.min(5, transform.scale));
|
|
930
|
+
transform.x = centerX - (centerX - transform.x) * factor;
|
|
931
|
+
transform.y = centerY - (centerY - transform.y) * factor;
|
|
932
|
+
|
|
933
|
+
applyTransform();
|
|
934
|
+
}
|
|
935
|
+
|
|
936
|
+
function resetZoom() {
|
|
937
|
+
transform = { x: 0, y: 0, scale: 1 };
|
|
938
|
+
applyTransform();
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
function selectNode(nodeId) {
|
|
942
|
+
// Remove previous selection
|
|
943
|
+
document.querySelectorAll('.wv-node--selected').forEach((n) => {
|
|
944
|
+
n.classList.remove('wv-node--selected');
|
|
945
|
+
});
|
|
946
|
+
|
|
947
|
+
selectedNodeId = nodeId;
|
|
948
|
+
|
|
949
|
+
if (nodeId) {
|
|
950
|
+
const node = document.querySelector('[data-node-id="' + nodeId + '"]');
|
|
951
|
+
if (node) {
|
|
952
|
+
node.classList.add('wv-node--selected');
|
|
953
|
+
updateInspector(nodeId);
|
|
954
|
+
}
|
|
955
|
+
} else {
|
|
956
|
+
clearInspector();
|
|
957
|
+
}
|
|
958
|
+
}
|
|
959
|
+
|
|
960
|
+
function updateInspector(nodeId) {
|
|
961
|
+
const content = document.getElementById('inspector-content');
|
|
962
|
+
if (!content) return;
|
|
963
|
+
|
|
964
|
+
const nodeData = window.__WORKFLOW_DATA__?.nodes?.[nodeId];
|
|
965
|
+
if (!nodeData) {
|
|
966
|
+
// Clear and add empty message using safe DOM methods
|
|
967
|
+
while (content.firstChild) content.removeChild(content.firstChild);
|
|
968
|
+
const p = document.createElement('p');
|
|
969
|
+
p.className = 'wv-empty';
|
|
970
|
+
p.textContent = 'No data available';
|
|
971
|
+
content.appendChild(p);
|
|
972
|
+
return;
|
|
973
|
+
}
|
|
974
|
+
|
|
975
|
+
renderInspectorContent(content, nodeData);
|
|
976
|
+
}
|
|
977
|
+
|
|
978
|
+
function renderInspectorContent(container, node) {
|
|
979
|
+
// Clear container using safe DOM method
|
|
980
|
+
while (container.firstChild) container.removeChild(container.firstChild);
|
|
981
|
+
|
|
982
|
+
// Node Info section
|
|
983
|
+
const infoSection = createSection('Node Info');
|
|
984
|
+
infoSection.appendChild(createRow('Name', node.name || node.id));
|
|
985
|
+
infoSection.appendChild(createRow('Type', node.type));
|
|
986
|
+
|
|
987
|
+
// State badge
|
|
988
|
+
const stateRow = document.createElement('div');
|
|
989
|
+
stateRow.className = 'wv-inspector-row';
|
|
990
|
+
const stateLabel = document.createElement('span');
|
|
991
|
+
stateLabel.className = 'wv-inspector-label';
|
|
992
|
+
stateLabel.textContent = 'State';
|
|
993
|
+
const stateBadge = document.createElement('span');
|
|
994
|
+
stateBadge.className = 'wv-badge wv-badge--' + node.state;
|
|
995
|
+
stateBadge.textContent = node.state;
|
|
996
|
+
stateRow.appendChild(stateLabel);
|
|
997
|
+
stateRow.appendChild(stateBadge);
|
|
998
|
+
infoSection.appendChild(stateRow);
|
|
999
|
+
|
|
1000
|
+
if (node.key) {
|
|
1001
|
+
infoSection.appendChild(createRow('Key', node.key));
|
|
1002
|
+
}
|
|
1003
|
+
container.appendChild(infoSection);
|
|
1004
|
+
|
|
1005
|
+
// Timing section
|
|
1006
|
+
if (node.durationMs !== undefined) {
|
|
1007
|
+
const timingSection = createSection('Timing');
|
|
1008
|
+
timingSection.appendChild(createRow('Duration', formatDuration(node.durationMs)));
|
|
1009
|
+
if (node.startTs !== undefined) {
|
|
1010
|
+
timingSection.appendChild(createRow('Started', new Date(node.startTs).toLocaleTimeString()));
|
|
1011
|
+
}
|
|
1012
|
+
container.appendChild(timingSection);
|
|
1013
|
+
}
|
|
1014
|
+
|
|
1015
|
+
// Retries section
|
|
1016
|
+
if (node.retryCount !== undefined && node.retryCount > 0) {
|
|
1017
|
+
const retrySection = createSection('Retries');
|
|
1018
|
+
retrySection.appendChild(createRow('Retry Count', String(node.retryCount)));
|
|
1019
|
+
container.appendChild(retrySection);
|
|
1020
|
+
}
|
|
1021
|
+
|
|
1022
|
+
// Input/Output section
|
|
1023
|
+
if (node.input !== undefined || node.output !== undefined) {
|
|
1024
|
+
const ioSection = createSection('Input / Output');
|
|
1025
|
+
if (node.input !== undefined) {
|
|
1026
|
+
const inputPre = document.createElement('pre');
|
|
1027
|
+
inputPre.style.cssText = 'font-size:11px;overflow:auto;max-height:120px;background:var(--bg);padding:8px;border-radius:4px;';
|
|
1028
|
+
inputPre.textContent = typeof node.input === 'string' ? node.input : safeStringify(node.input);
|
|
1029
|
+
ioSection.appendChild(createRow('Input', ''));
|
|
1030
|
+
ioSection.appendChild(inputPre);
|
|
1031
|
+
}
|
|
1032
|
+
if (node.output !== undefined) {
|
|
1033
|
+
const outputPre = document.createElement('pre');
|
|
1034
|
+
outputPre.style.cssText = 'font-size:11px;overflow:auto;max-height:120px;background:var(--bg);padding:8px;border-radius:4px;';
|
|
1035
|
+
outputPre.textContent = typeof node.output === 'string' ? node.output : safeStringify(node.output);
|
|
1036
|
+
ioSection.appendChild(createRow('Output', ''));
|
|
1037
|
+
ioSection.appendChild(outputPre);
|
|
1038
|
+
}
|
|
1039
|
+
container.appendChild(ioSection);
|
|
1040
|
+
}
|
|
1041
|
+
|
|
1042
|
+
// Hook timing (onAfterStep)
|
|
1043
|
+
const hookKey = node.key || node.id;
|
|
1044
|
+
const hookExec = window.__WORKFLOW_DATA__?.hooks?.onAfterStep?.[hookKey];
|
|
1045
|
+
if (hookExec && (hookExec.durationMs !== undefined || hookExec.ts !== undefined)) {
|
|
1046
|
+
const hookSection = createSection('Hook (onAfterStep)');
|
|
1047
|
+
if (hookExec.durationMs !== undefined) {
|
|
1048
|
+
hookSection.appendChild(createRow('Duration', formatDuration(hookExec.durationMs)));
|
|
1049
|
+
}
|
|
1050
|
+
if (hookExec.ts !== undefined) {
|
|
1051
|
+
hookSection.appendChild(createRow('At', new Date(hookExec.ts).toLocaleTimeString()));
|
|
1052
|
+
}
|
|
1053
|
+
container.appendChild(hookSection);
|
|
1054
|
+
}
|
|
1055
|
+
|
|
1056
|
+
// Error section (preserve falsy errors: 0, "", false)
|
|
1057
|
+
if (node.error !== undefined && node.error !== null) {
|
|
1058
|
+
const errorSection = createSection('Error');
|
|
1059
|
+
const pre = document.createElement('pre');
|
|
1060
|
+
pre.style.cssText = 'font-size:11px;overflow:auto;max-height:150px;background:var(--bg);padding:8px;border-radius:4px;';
|
|
1061
|
+
pre.textContent = String(node.error);
|
|
1062
|
+
errorSection.appendChild(pre);
|
|
1063
|
+
container.appendChild(errorSection);
|
|
1064
|
+
}
|
|
1065
|
+
}
|
|
1066
|
+
|
|
1067
|
+
function createSection(title) {
|
|
1068
|
+
const section = document.createElement('div');
|
|
1069
|
+
section.className = 'wv-inspector-section';
|
|
1070
|
+
const h3 = document.createElement('h3');
|
|
1071
|
+
h3.textContent = title;
|
|
1072
|
+
section.appendChild(h3);
|
|
1073
|
+
return section;
|
|
1074
|
+
}
|
|
1075
|
+
|
|
1076
|
+
function createRow(label, value) {
|
|
1077
|
+
const row = document.createElement('div');
|
|
1078
|
+
row.className = 'wv-inspector-row';
|
|
1079
|
+
const labelSpan = document.createElement('span');
|
|
1080
|
+
labelSpan.className = 'wv-inspector-label';
|
|
1081
|
+
labelSpan.textContent = label;
|
|
1082
|
+
const valueSpan = document.createElement('span');
|
|
1083
|
+
valueSpan.className = 'wv-inspector-value';
|
|
1084
|
+
valueSpan.textContent = value;
|
|
1085
|
+
row.appendChild(labelSpan);
|
|
1086
|
+
row.appendChild(valueSpan);
|
|
1087
|
+
return row;
|
|
1088
|
+
}
|
|
1089
|
+
|
|
1090
|
+
function clearInspector() {
|
|
1091
|
+
const content = document.getElementById('inspector-content');
|
|
1092
|
+
if (content) {
|
|
1093
|
+
while (content.firstChild) content.removeChild(content.firstChild);
|
|
1094
|
+
const p = document.createElement('p');
|
|
1095
|
+
p.className = 'wv-empty';
|
|
1096
|
+
p.textContent = 'Select a node to inspect';
|
|
1097
|
+
content.appendChild(p);
|
|
1098
|
+
}
|
|
1099
|
+
}
|
|
1100
|
+
|
|
1101
|
+
// Time Travel
|
|
1102
|
+
function setupTimeTravel() {
|
|
1103
|
+
const playBtn = document.getElementById('tt-play');
|
|
1104
|
+
const pauseBtn = document.getElementById('tt-pause');
|
|
1105
|
+
const prevBtn = document.getElementById('tt-prev');
|
|
1106
|
+
const nextBtn = document.getElementById('tt-next');
|
|
1107
|
+
const speedSelect = document.getElementById('tt-speed');
|
|
1108
|
+
const slider = document.getElementById('tt-slider');
|
|
1109
|
+
|
|
1110
|
+
playBtn?.addEventListener('click', play);
|
|
1111
|
+
pauseBtn?.addEventListener('click', pause);
|
|
1112
|
+
prevBtn?.addEventListener('click', stepBackward);
|
|
1113
|
+
nextBtn?.addEventListener('click', stepForward);
|
|
1114
|
+
speedSelect?.addEventListener('change', (e) => {
|
|
1115
|
+
playbackSpeed = parseFloat(e.target.value);
|
|
1116
|
+
});
|
|
1117
|
+
slider?.addEventListener('input', (e) => {
|
|
1118
|
+
seek(parseInt(e.target.value, 10));
|
|
1119
|
+
});
|
|
1120
|
+
}
|
|
1121
|
+
|
|
1122
|
+
function play() {
|
|
1123
|
+
if (snapshots.length === 0) {
|
|
1124
|
+
console.warn('[Visualizer] No snapshots available for time travel. Time travel requires a live WebSocket connection.');
|
|
1125
|
+
return;
|
|
1126
|
+
}
|
|
1127
|
+
isPlaying = true;
|
|
1128
|
+
updatePlaybackUI();
|
|
1129
|
+
playNext();
|
|
1130
|
+
}
|
|
1131
|
+
|
|
1132
|
+
function pause() {
|
|
1133
|
+
isPlaying = false;
|
|
1134
|
+
updatePlaybackUI();
|
|
1135
|
+
}
|
|
1136
|
+
|
|
1137
|
+
function playNext() {
|
|
1138
|
+
if (!isPlaying) return;
|
|
1139
|
+
if (currentSnapshotIndex < snapshots.length - 1) {
|
|
1140
|
+
const current = snapshots[currentSnapshotIndex];
|
|
1141
|
+
const next = snapshots[currentSnapshotIndex + 1];
|
|
1142
|
+
const delay = (next.timestamp - current.timestamp) / playbackSpeed;
|
|
1143
|
+
|
|
1144
|
+
setTimeout(() => {
|
|
1145
|
+
stepForward();
|
|
1146
|
+
playNext();
|
|
1147
|
+
}, Math.max(16, delay));
|
|
1148
|
+
} else {
|
|
1149
|
+
pause();
|
|
1150
|
+
}
|
|
1151
|
+
}
|
|
1152
|
+
|
|
1153
|
+
function stepForward() {
|
|
1154
|
+
if (snapshots.length === 0) {
|
|
1155
|
+
console.warn('[Visualizer] No snapshots available for time travel.');
|
|
1156
|
+
return;
|
|
1157
|
+
}
|
|
1158
|
+
if (currentSnapshotIndex < snapshots.length - 1) {
|
|
1159
|
+
seek(currentSnapshotIndex + 1);
|
|
1160
|
+
}
|
|
1161
|
+
}
|
|
1162
|
+
|
|
1163
|
+
function stepBackward() {
|
|
1164
|
+
if (snapshots.length === 0) {
|
|
1165
|
+
console.warn('[Visualizer] No snapshots available for time travel.');
|
|
1166
|
+
return;
|
|
1167
|
+
}
|
|
1168
|
+
if (currentSnapshotIndex > 0) {
|
|
1169
|
+
seek(currentSnapshotIndex - 1);
|
|
1170
|
+
}
|
|
1171
|
+
}
|
|
1172
|
+
|
|
1173
|
+
function seek(index) {
|
|
1174
|
+
if (index < 0 || index >= snapshots.length) return;
|
|
1175
|
+
currentSnapshotIndex = index;
|
|
1176
|
+
updateTimelineUI();
|
|
1177
|
+
|
|
1178
|
+
// Request IR update from server or use cached
|
|
1179
|
+
if (ws && ws.readyState === WebSocket.OPEN) {
|
|
1180
|
+
ws.send(JSON.stringify({ type: 'time_travel_seek', payload: { index } }));
|
|
1181
|
+
} else if (snapshots[index]?.ir) {
|
|
1182
|
+
renderIR(snapshots[index].ir);
|
|
1183
|
+
}
|
|
1184
|
+
}
|
|
1185
|
+
|
|
1186
|
+
function updatePlaybackUI() {
|
|
1187
|
+
const playBtn = document.getElementById('tt-play');
|
|
1188
|
+
const pauseBtn = document.getElementById('tt-pause');
|
|
1189
|
+
|
|
1190
|
+
if (playBtn) playBtn.style.display = isPlaying ? 'none' : 'inline-flex';
|
|
1191
|
+
if (pauseBtn) pauseBtn.style.display = isPlaying ? 'inline-flex' : 'none';
|
|
1192
|
+
}
|
|
1193
|
+
|
|
1194
|
+
function updateTimelineUI() {
|
|
1195
|
+
const slider = document.getElementById('tt-slider');
|
|
1196
|
+
const timeDisplay = document.getElementById('tt-time');
|
|
1197
|
+
|
|
1198
|
+
if (slider) {
|
|
1199
|
+
slider.max = String(Math.max(0, snapshots.length - 1));
|
|
1200
|
+
slider.value = String(Math.max(0, currentSnapshotIndex));
|
|
1201
|
+
}
|
|
1202
|
+
|
|
1203
|
+
if (timeDisplay) {
|
|
1204
|
+
timeDisplay.textContent = (currentSnapshotIndex + 1) + ' / ' + snapshots.length;
|
|
1205
|
+
}
|
|
1206
|
+
}
|
|
1207
|
+
|
|
1208
|
+
// WebSocket
|
|
1209
|
+
function setupWebSocket(url) {
|
|
1210
|
+
ws = new WebSocket(url);
|
|
1211
|
+
|
|
1212
|
+
ws.onopen = () => {
|
|
1213
|
+
console.log('[Visualizer] Connected to server');
|
|
1214
|
+
showLiveIndicator(true);
|
|
1215
|
+
${e.timeTravel?"if (ws && ws.readyState === 1) ws.send(JSON.stringify({ type: 'request_snapshots' }));":""}
|
|
1216
|
+
};
|
|
1217
|
+
|
|
1218
|
+
ws.onclose = () => {
|
|
1219
|
+
console.log('[Visualizer] Disconnected from server');
|
|
1220
|
+
showLiveIndicator(false);
|
|
1221
|
+
// Attempt reconnect after 2 seconds
|
|
1222
|
+
setTimeout(() => setupWebSocket(url), 2000);
|
|
1223
|
+
};
|
|
1224
|
+
|
|
1225
|
+
ws.onmessage = (event) => {
|
|
1226
|
+
try {
|
|
1227
|
+
const msg = JSON.parse(event.data);
|
|
1228
|
+
handleServerMessage(msg);
|
|
1229
|
+
} catch (e) {
|
|
1230
|
+
console.error('[Visualizer] Failed to parse message:', e);
|
|
1231
|
+
}
|
|
1232
|
+
};
|
|
1233
|
+
|
|
1234
|
+
ws.onerror = (error) => {
|
|
1235
|
+
console.error('[Visualizer] WebSocket error:', error);
|
|
1236
|
+
};
|
|
1237
|
+
}
|
|
1238
|
+
|
|
1239
|
+
function handleServerMessage(msg) {
|
|
1240
|
+
switch (msg.type) {
|
|
1241
|
+
case 'ir_update':
|
|
1242
|
+
renderIR(msg.payload);
|
|
1243
|
+
break;
|
|
1244
|
+
case 'snapshot':
|
|
1245
|
+
snapshots.push(msg.payload);
|
|
1246
|
+
currentSnapshotIndex = snapshots.length - 1;
|
|
1247
|
+
updateTimelineUI();
|
|
1248
|
+
break;
|
|
1249
|
+
case 'snapshots_list':
|
|
1250
|
+
snapshots = msg.payload;
|
|
1251
|
+
currentSnapshotIndex = snapshots.length - 1;
|
|
1252
|
+
updateTimelineUI();
|
|
1253
|
+
break;
|
|
1254
|
+
case 'performance_data':
|
|
1255
|
+
window.__PERFORMANCE_DATA__ = msg.payload;
|
|
1256
|
+
if (heatmapEnabled) applyHeatmap();
|
|
1257
|
+
break;
|
|
1258
|
+
case 'workflow_complete':
|
|
1259
|
+
showLiveIndicator(false);
|
|
1260
|
+
break;
|
|
1261
|
+
case 'time_travel_state':
|
|
1262
|
+
currentSnapshotIndex = msg.payload.currentIndex;
|
|
1263
|
+
isPlaying = msg.payload.isPlaying;
|
|
1264
|
+
playbackSpeed = msg.payload.playbackSpeed;
|
|
1265
|
+
updateTimelineUI();
|
|
1266
|
+
updatePlaybackUI();
|
|
1267
|
+
break;
|
|
1268
|
+
}
|
|
1269
|
+
}
|
|
1270
|
+
|
|
1271
|
+
function showLiveIndicator(show) {
|
|
1272
|
+
const indicator = document.getElementById('live-indicator');
|
|
1273
|
+
if (indicator) {
|
|
1274
|
+
indicator.style.display = show ? 'flex' : 'none';
|
|
1275
|
+
}
|
|
1276
|
+
}
|
|
1277
|
+
|
|
1278
|
+
// Heatmap
|
|
1279
|
+
function setupHeatmap() {
|
|
1280
|
+
const toggle = document.getElementById('heatmap-toggle');
|
|
1281
|
+
const metricSelect = document.getElementById('heatmap-metric');
|
|
1282
|
+
|
|
1283
|
+
// For static HTML (no WebSocket), disable heatmap controls
|
|
1284
|
+
if (!ws) {
|
|
1285
|
+
if (toggle) {
|
|
1286
|
+
toggle.disabled = true;
|
|
1287
|
+
toggle.title = 'Heatmap requires a live WebSocket connection with performance data';
|
|
1288
|
+
}
|
|
1289
|
+
if (metricSelect) {
|
|
1290
|
+
metricSelect.disabled = true;
|
|
1291
|
+
metricSelect.title = 'Heatmap requires a live WebSocket connection with performance data';
|
|
1292
|
+
}
|
|
1293
|
+
return;
|
|
1294
|
+
}
|
|
1295
|
+
|
|
1296
|
+
toggle?.addEventListener('click', () => {
|
|
1297
|
+
heatmapEnabled = !heatmapEnabled;
|
|
1298
|
+
toggle.classList.toggle('wv-btn--primary', heatmapEnabled);
|
|
1299
|
+
if (ws && ws.readyState === 1) {
|
|
1300
|
+
ws.send(JSON.stringify({ type: 'toggle_heatmap', payload: { enabled: heatmapEnabled } }));
|
|
1301
|
+
}
|
|
1302
|
+
if (heatmapEnabled) {
|
|
1303
|
+
applyHeatmap();
|
|
1304
|
+
} else {
|
|
1305
|
+
removeHeatmap();
|
|
1306
|
+
}
|
|
1307
|
+
});
|
|
1308
|
+
|
|
1309
|
+
metricSelect?.addEventListener('change', (e) => {
|
|
1310
|
+
heatmapMetric = e.target.value;
|
|
1311
|
+
if (ws && ws.readyState === 1) {
|
|
1312
|
+
ws.send(JSON.stringify({ type: 'set_heatmap_metric', payload: { metric: heatmapMetric } }));
|
|
1313
|
+
}
|
|
1314
|
+
if (heatmapEnabled) applyHeatmap();
|
|
1315
|
+
});
|
|
1316
|
+
}
|
|
1317
|
+
|
|
1318
|
+
function applyHeatmap() {
|
|
1319
|
+
const perfData = window.__PERFORMANCE_DATA__;
|
|
1320
|
+
if (!perfData) return;
|
|
1321
|
+
|
|
1322
|
+
const heat = perfData.heat;
|
|
1323
|
+
document.querySelectorAll('.wv-node').forEach((node) => {
|
|
1324
|
+
const nodeId = node.dataset.nodeId;
|
|
1325
|
+
const value = heat && (typeof heat.get === 'function' ? heat.get(nodeId) : heat[nodeId]);
|
|
1326
|
+
|
|
1327
|
+
// Remove existing heat classes
|
|
1328
|
+
node.classList.remove(
|
|
1329
|
+
'wv-node--heat-cold',
|
|
1330
|
+
'wv-node--heat-cool',
|
|
1331
|
+
'wv-node--heat-neutral',
|
|
1332
|
+
'wv-node--heat-warm',
|
|
1333
|
+
'wv-node--heat-hot',
|
|
1334
|
+
'wv-node--heat-critical'
|
|
1335
|
+
);
|
|
1336
|
+
|
|
1337
|
+
if (value !== undefined) {
|
|
1338
|
+
const level = getHeatLevel(value);
|
|
1339
|
+
node.classList.add('wv-node--heat-' + level);
|
|
1340
|
+
}
|
|
1341
|
+
});
|
|
1342
|
+
}
|
|
1343
|
+
|
|
1344
|
+
function removeHeatmap() {
|
|
1345
|
+
document.querySelectorAll('.wv-node').forEach((node) => {
|
|
1346
|
+
node.classList.remove(
|
|
1347
|
+
'wv-node--heat-cold',
|
|
1348
|
+
'wv-node--heat-cool',
|
|
1349
|
+
'wv-node--heat-neutral',
|
|
1350
|
+
'wv-node--heat-warm',
|
|
1351
|
+
'wv-node--heat-hot',
|
|
1352
|
+
'wv-node--heat-critical'
|
|
1353
|
+
);
|
|
1354
|
+
});
|
|
1355
|
+
}
|
|
1356
|
+
|
|
1357
|
+
function getHeatLevel(heat) {
|
|
1358
|
+
if (heat < 0.2) return 'cold';
|
|
1359
|
+
if (heat < 0.4) return 'cool';
|
|
1360
|
+
if (heat < 0.6) return 'neutral';
|
|
1361
|
+
if (heat < 0.8) return 'warm';
|
|
1362
|
+
if (heat < 0.95) return 'hot';
|
|
1363
|
+
return 'critical';
|
|
1364
|
+
}
|
|
1365
|
+
|
|
1366
|
+
// Keyboard shortcuts
|
|
1367
|
+
function setupKeyboardShortcuts() {
|
|
1368
|
+
document.addEventListener('keydown', (e) => {
|
|
1369
|
+
// Don't trigger shortcuts when typing in inputs
|
|
1370
|
+
if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA') return;
|
|
1371
|
+
|
|
1372
|
+
switch (e.key) {
|
|
1373
|
+
case ' ':
|
|
1374
|
+
e.preventDefault();
|
|
1375
|
+
isPlaying ? pause() : play();
|
|
1376
|
+
break;
|
|
1377
|
+
case 'ArrowLeft':
|
|
1378
|
+
e.preventDefault();
|
|
1379
|
+
stepBackward();
|
|
1380
|
+
break;
|
|
1381
|
+
case 'ArrowRight':
|
|
1382
|
+
e.preventDefault();
|
|
1383
|
+
stepForward();
|
|
1384
|
+
break;
|
|
1385
|
+
case '0':
|
|
1386
|
+
resetZoom();
|
|
1387
|
+
break;
|
|
1388
|
+
case '+':
|
|
1389
|
+
case '=':
|
|
1390
|
+
zoom(1.2);
|
|
1391
|
+
break;
|
|
1392
|
+
case '-':
|
|
1393
|
+
zoom(0.8);
|
|
1394
|
+
break;
|
|
1395
|
+
case 'h':
|
|
1396
|
+
${e.heatmap?"document.getElementById('heatmap-toggle')?.click();":""}
|
|
1397
|
+
break;
|
|
1398
|
+
case 'Escape':
|
|
1399
|
+
selectNode(null);
|
|
1400
|
+
break;
|
|
1401
|
+
}
|
|
1402
|
+
});
|
|
1403
|
+
}
|
|
1404
|
+
|
|
1405
|
+
// Render functions
|
|
1406
|
+
function renderIR(ir) {
|
|
1407
|
+
window.__WORKFLOW_DATA__ = buildWorkflowDataFromIR(ir);
|
|
1408
|
+
|
|
1409
|
+
// Update SVG node states
|
|
1410
|
+
document.querySelectorAll('.wv-node').forEach((node) => {
|
|
1411
|
+
const nodeId = node.dataset.nodeId;
|
|
1412
|
+
const nodeData = window.__WORKFLOW_DATA__.nodes[nodeId];
|
|
1413
|
+
if (nodeData) {
|
|
1414
|
+
// Update only state class so heatmap (wv-node--heat-*) and other classes are preserved
|
|
1415
|
+
node.className = node.className.replace(/wv-node--(success|error|running|cached|skipped|pending|aborted)/g, '').replace(/\\s+/g, ' ').trim();
|
|
1416
|
+
node.classList.add('wv-node', 'wv-node--' + nodeData.state);
|
|
1417
|
+
|
|
1418
|
+
// Update timing text if present
|
|
1419
|
+
const timing = node.querySelector('.wv-node-timing');
|
|
1420
|
+
if (timing && nodeData.durationMs !== undefined) {
|
|
1421
|
+
timing.textContent = formatDuration(nodeData.durationMs);
|
|
1422
|
+
}
|
|
1423
|
+
}
|
|
1424
|
+
});
|
|
1425
|
+
|
|
1426
|
+
// Re-apply selection so wv-node--selected is not lost after class updates
|
|
1427
|
+
if (selectedNodeId) {
|
|
1428
|
+
selectNode(selectedNodeId);
|
|
1429
|
+
}
|
|
1430
|
+
}
|
|
1431
|
+
|
|
1432
|
+
function flattenNodes(nodes) {
|
|
1433
|
+
const result = [];
|
|
1434
|
+
for (const node of nodes) {
|
|
1435
|
+
result.push(node);
|
|
1436
|
+
if (node.children) {
|
|
1437
|
+
result.push(...flattenNodes(node.children));
|
|
1438
|
+
}
|
|
1439
|
+
if (node.branches) {
|
|
1440
|
+
for (const branch of node.branches) {
|
|
1441
|
+
result.push(...flattenNodes(branch.children));
|
|
1442
|
+
}
|
|
1443
|
+
}
|
|
1444
|
+
}
|
|
1445
|
+
return result;
|
|
1446
|
+
}
|
|
1447
|
+
|
|
1448
|
+
// Utilities
|
|
1449
|
+
function safeStringify(val) {
|
|
1450
|
+
const seen = new WeakSet();
|
|
1451
|
+
try {
|
|
1452
|
+
return JSON.stringify(val, function(key, value) {
|
|
1453
|
+
if (typeof value === 'bigint') return value.toString();
|
|
1454
|
+
if (typeof value === 'object' && value !== null) {
|
|
1455
|
+
if (seen.has(value)) return '[Circular]';
|
|
1456
|
+
seen.add(value);
|
|
1457
|
+
}
|
|
1458
|
+
return value;
|
|
1459
|
+
}, 2);
|
|
1460
|
+
} catch (e) {
|
|
1461
|
+
return String(val);
|
|
1462
|
+
}
|
|
1463
|
+
}
|
|
1464
|
+
|
|
1465
|
+
function formatDuration(ms) {
|
|
1466
|
+
if (ms < 1000) return Math.round(ms) + 'ms';
|
|
1467
|
+
if (ms < 60000) {
|
|
1468
|
+
const s = (ms / 1000).toFixed(1).replace(/\\.0$/, '');
|
|
1469
|
+
return s + 's';
|
|
1470
|
+
}
|
|
1471
|
+
let min = Math.floor(ms / 60000);
|
|
1472
|
+
let sec = Math.round((ms % 60000) / 1000);
|
|
1473
|
+
if (sec >= 60) { min += 1; sec = 0; }
|
|
1474
|
+
if (sec === 0) return min + 'm';
|
|
1475
|
+
return min + 'm ' + sec + 's';
|
|
1476
|
+
}
|
|
1477
|
+
})();
|
|
1478
|
+
`}var ae=160,ge=50,Ge=40,qr=30,F=20;function Zr(e,t="TB",r){let o=t==="TB"||t==="BT",i=t==="RL"||t==="BT",n=[],a=F,s=F,u=0,c=0;for(let g of e){let f=Ye(g,a,s,o,r);n.push(f.node),o?(s+=f.height+qr,u=Math.max(u,f.width),c=s):(a+=f.width+Ge,c=Math.max(c,f.height),u=a)}let l=u+F,p=c+F;if(i)for(let g of n)bt(g,l,p,o);return{nodes:n,width:l,height:p}}function bt(e,t,r,o){if(o?e.y=r-e.y-e.height:e.x=t-e.x-e.width,e.children)for(let i of e.children)bt(i,t,r,o)}function Ye(e,t,r,o,i){if(z(e)){let n=e.name??e.key??"step",a=i?.showKeys&&e.key&&e.name?`${n} [key: ${e.key}]`:n;return{node:{id:e.id,name:a,type:"step",state:e.state,x:t,y:r,width:ae,height:ge,durationMs:e.durationMs},width:ae,height:ge}}if(Q(e)){let n=e.streamState==="active"?`stream:${e.namespace} \u27F3`:e.streamState==="error"?`stream:${e.namespace} \u2717`:`stream:${e.namespace} \u2713`;return{node:{id:e.id,name:n,type:"stream",state:e.state,x:t,y:r,width:ae,height:ge,durationMs:e.durationMs},width:ae,height:ge}}if(j(e)||H(e)){let n=j(e)?"parallel":"race",a=e.name??n,s=[],u=t+F,c=r+F+20,l=0,p=0;for(let y of e.children){let k=Ye(y,u,c,!0,i);s.push(k.node),u+=k.width+Ge,p=Math.max(p,k.height)}l=u-t-F;let g=Math.max(l+F,ae+F*2),f=p+F*2+20;return{node:{id:e.id,name:a,type:n,state:e.state,x:t,y:r,width:g,height:f,durationMs:e.durationMs,children:s,containerType:n,containerLabel:n==="parallel"?"PARALLEL":"RACE"},width:g,height:f}}if(Y(e)){let n=e.name??"decision",a=[],s=t+F,u=r+F+20,c=0;for(let g of e.branches)for(let f of g.children){let y=Ye(f,s,u,!0,i);a.push(y.node),s+=y.width+Ge,c=Math.max(c,y.height)}let l=Math.max(s-t,ae+F*2),p=c+F*2+20;return{node:{id:e.id,name:n,type:"decision",state:e.state,x:t,y:r,width:l,height:p,durationMs:e.durationMs,children:a,containerType:"decision",containerLabel:"DECISION"},width:l,height:p}}return{node:{id:e.id,name:e.name??"unknown",type:e.type,state:e.state,x:t,y:r,width:ae,height:ge},width:ae,height:ge}}function yt(e,t){return e.containerType?en(e,t):Qr(e,t)}function Qr(e,t){let o=t&&e.durationMs!==void 0?B(e.durationMs):"";return`
|
|
1479
|
+
<g class="wv-node wv-node--${e.state}" data-node-id="${vt(e.id)}" transform="translate(${e.x}, ${e.y})">
|
|
1480
|
+
<rect width="${e.width}" height="${e.height}" rx="8" ry="8" />
|
|
1481
|
+
<text x="${e.width/2}" y="${e.height/2-(o?4:0)}">${Xe(rn(e.name,e.name.includes("[key:")?40:20))}</text>
|
|
1482
|
+
${o?`<text class="wv-node-timing" x="${e.width/2}" y="${e.height/2+12}">${o}</text>`:""}
|
|
1483
|
+
</g>
|
|
1484
|
+
`}function en(e,t){let o=e.children?.map(i=>yt(i,t)).join(`
|
|
1485
|
+
`)??"";return`
|
|
1486
|
+
<g class="wv-container wv-container--${e.containerType}" data-node-id="${vt(e.id)}" transform="translate(${e.x}, ${e.y})">
|
|
1487
|
+
<rect width="${e.width}" height="${e.height}" rx="12" ry="12" />
|
|
1488
|
+
<text class="wv-container-label" x="${F}" y="16">${e.containerLabel}</text>
|
|
1489
|
+
<g transform="translate(${-e.x}, ${-e.y})">
|
|
1490
|
+
${o}
|
|
1491
|
+
</g>
|
|
1492
|
+
</g>
|
|
1493
|
+
`}function Je(e,t){for(let r of e){if(r.id===t)return r;if("children"in r&&r.children){let o=Je(r.children,t);if(o)return o}if("branches"in r&&r.branches)for(let o of r.branches){let i=Je(o.children,t);if(i)return i}}}function tn(e,t){let r=[];function o(n,a){if(Math.abs(n.y-a.y)<n.height){let u=n.x+n.width,c=n.y+n.height/2,l=a.x,p=a.y+a.height/2;r.push(`
|
|
1494
|
+
<path class="wv-edge" d="M ${u} ${c} L ${l-8} ${p}" />
|
|
1495
|
+
<polygon class="wv-edge-arrow" points="${l-8},${p-4} ${l-8},${p+4} ${l},${p}" />
|
|
1496
|
+
`)}else{let u=n.x+n.width/2,c=n.y+n.height,l=a.x+a.width/2,p=a.y;r.push(`
|
|
1497
|
+
<path class="wv-edge" d="M ${u} ${c} L ${l} ${p-8}" />
|
|
1498
|
+
<polygon class="wv-edge-arrow" points="${l-4},${p-8} ${l+4},${p-8} ${l},${p}" />
|
|
1499
|
+
`)}}function i(n){for(let a=0;a<n.length-1;a++)o(n[a],n[a+1]);for(let a of n)if(a.children&&a.children.length>0)if(a.containerType==="decision"){let s=Je(t.root.children,a.id);if(s&&s.type==="decision"&&s.branches){let u=0;for(let c of s.branches){let l=c.children.length;l>0&&o(a,a.children[u]);for(let p=0;p<l-1;p++)o(a.children[u+p],a.children[u+p+1]);u+=l}}}else if(a.containerType==="parallel"||a.containerType==="race")for(let s of a.children)s.children&&s.children.length>0&&i([s]);else i(a.children)}return i(e),r.join(`
|
|
1500
|
+
`)}function kt(e,t){let r=Zr(e.root.children,t.layout,t),o=Math.max(r.width,400),i=Math.max(r.height,300),n=r.nodes.map(l=>yt(l,t.showTimings)).join(`
|
|
1501
|
+
`),a=tn(r.nodes,e),s=e.root.name??"Workflow",u=ht(t.theme),c=gt({wsUrl:t.wsUrl,interactive:t.interactive,timeTravel:t.timeTravel,heatmap:t.heatmap});return`<!DOCTYPE html>
|
|
1502
|
+
<html lang="en">
|
|
1503
|
+
<head>
|
|
1504
|
+
<meta charset="UTF-8">
|
|
1505
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
1506
|
+
<title>${Xe(s)} - Workflow Visualizer</title>
|
|
1507
|
+
<style>${u}</style>
|
|
1508
|
+
</head>
|
|
1509
|
+
<body>
|
|
1510
|
+
<div class="workflow-visualizer">
|
|
1511
|
+
<header class="wv-header">
|
|
1512
|
+
<h1>${Xe(s)}</h1>
|
|
1513
|
+
<div class="wv-controls">
|
|
1514
|
+
${t.interactive?`
|
|
1515
|
+
<button id="load-json-btn" class="wv-btn" title="Load workflow state from JSON">Load JSON</button>
|
|
1516
|
+
`:""}
|
|
1517
|
+
${t.wsUrl?'<div id="live-indicator" class="wv-live" style="display:none"><span class="wv-live-dot"></span>LIVE</div>':""}
|
|
1518
|
+
${t.heatmap&&t.wsUrl?`
|
|
1519
|
+
<button id="heatmap-toggle" class="wv-btn">Heatmap</button>
|
|
1520
|
+
<select id="heatmap-metric" class="wv-btn">
|
|
1521
|
+
<option value="duration">Duration</option>
|
|
1522
|
+
<option value="retryRate">Retry Rate</option>
|
|
1523
|
+
<option value="errorRate">Error Rate</option>
|
|
1524
|
+
</select>
|
|
1525
|
+
`:""}
|
|
1526
|
+
${t.interactive?`
|
|
1527
|
+
<button id="zoom-out" class="wv-btn wv-btn--icon" title="Zoom out (-)">\u2212</button>
|
|
1528
|
+
<button id="zoom-reset" class="wv-btn wv-btn--icon" title="Reset zoom (0)">\u27F2</button>
|
|
1529
|
+
<button id="zoom-in" class="wv-btn wv-btn--icon" title="Zoom in (+)">+</button>
|
|
1530
|
+
`:""}
|
|
1531
|
+
</div>
|
|
1532
|
+
</header>
|
|
1533
|
+
|
|
1534
|
+
<div class="wv-main">
|
|
1535
|
+
<div id="diagram" class="wv-diagram">
|
|
1536
|
+
<svg viewBox="0 0 ${o} ${i}" preserveAspectRatio="xMidYMid meet">
|
|
1537
|
+
<g class="wv-root">
|
|
1538
|
+
${a}
|
|
1539
|
+
${n}
|
|
1540
|
+
</g>
|
|
1541
|
+
</svg>
|
|
1542
|
+
</div>
|
|
1543
|
+
|
|
1544
|
+
${t.interactive?`
|
|
1545
|
+
<aside id="inspector" class="wv-inspector">
|
|
1546
|
+
<div class="wv-inspector-header">
|
|
1547
|
+
<h2>Inspector</h2>
|
|
1548
|
+
</div>
|
|
1549
|
+
<div id="inspector-content" class="wv-inspector-content">
|
|
1550
|
+
<p class="wv-empty">Select a node to inspect</p>
|
|
1551
|
+
</div>
|
|
1552
|
+
</aside>
|
|
1553
|
+
`:""}
|
|
1554
|
+
</div>
|
|
1555
|
+
|
|
1556
|
+
${t.timeTravel?`
|
|
1557
|
+
<div id="timeline" class="wv-timeline">
|
|
1558
|
+
<div class="wv-timeline-track">
|
|
1559
|
+
<input type="range" id="tt-slider" min="0" max="0" value="0" style="width:100%">
|
|
1560
|
+
</div>
|
|
1561
|
+
<div class="wv-timeline-controls">
|
|
1562
|
+
<button id="tt-prev" class="wv-btn wv-btn--icon" title="Step backward (\u2190)">\u23EE</button>
|
|
1563
|
+
<button id="tt-play" class="wv-btn wv-btn--icon" title="Play (Space)">\u25B6</button>
|
|
1564
|
+
<button id="tt-pause" class="wv-btn wv-btn--icon" style="display:none" title="Pause (Space)">\u23F8</button>
|
|
1565
|
+
<button id="tt-next" class="wv-btn wv-btn--icon" title="Step forward (\u2192)">\u23ED</button>
|
|
1566
|
+
<select id="tt-speed" class="wv-btn">
|
|
1567
|
+
<option value="0.5">0.5x</option>
|
|
1568
|
+
<option value="1" selected>1x</option>
|
|
1569
|
+
<option value="2">2x</option>
|
|
1570
|
+
<option value="4">4x</option>
|
|
1571
|
+
<option value="10">10x</option>
|
|
1572
|
+
</select>
|
|
1573
|
+
<span id="tt-time" class="wv-timeline-time">0 / 0</span>
|
|
1574
|
+
</div>
|
|
1575
|
+
</div>
|
|
1576
|
+
`:""}
|
|
1577
|
+
</div>
|
|
1578
|
+
|
|
1579
|
+
${t.interactive?`
|
|
1580
|
+
<div id="load-json-modal" class="wv-modal" style="display:none">
|
|
1581
|
+
<div class="wv-modal-content">
|
|
1582
|
+
<div class="wv-modal-header">
|
|
1583
|
+
<h2>Load Workflow State</h2>
|
|
1584
|
+
<button id="load-json-close" class="wv-btn wv-btn--icon" title="Close">\xD7</button>
|
|
1585
|
+
</div>
|
|
1586
|
+
<div class="wv-modal-body">
|
|
1587
|
+
<p>Paste the workflow IR JSON (from <code>viz.getIR()</code> or <code>viz.renderAs('json')</code>):</p>
|
|
1588
|
+
<textarea id="load-json-input" class="wv-textarea" rows="15" placeholder='{"root":{"type":"workflow","id":"...","children":[...]}}'></textarea>
|
|
1589
|
+
<div id="load-json-error" class="wv-error" style="display:none"></div>
|
|
1590
|
+
</div>
|
|
1591
|
+
<div class="wv-modal-footer">
|
|
1592
|
+
<button id="load-json-submit" class="wv-btn wv-btn--primary">Load</button>
|
|
1593
|
+
<button id="load-json-cancel" class="wv-btn">Cancel</button>
|
|
1594
|
+
</div>
|
|
1595
|
+
</div>
|
|
1596
|
+
</div>
|
|
1597
|
+
`:""}
|
|
1598
|
+
|
|
1599
|
+
<script>
|
|
1600
|
+
// Check if we have a saved IR in sessionStorage (from Load JSON)
|
|
1601
|
+
(function() {
|
|
1602
|
+
let initialIR = ${wt(nn(e))};
|
|
1603
|
+
try {
|
|
1604
|
+
const savedIR = sessionStorage.getItem('workflow_ir');
|
|
1605
|
+
if (savedIR) {
|
|
1606
|
+
initialIR = JSON.parse(savedIR);
|
|
1607
|
+
sessionStorage.removeItem('workflow_ir'); // Clear after use
|
|
1608
|
+
}
|
|
1609
|
+
} catch (e) {
|
|
1610
|
+
console.warn('Failed to load saved IR:', e);
|
|
1611
|
+
}
|
|
1612
|
+
|
|
1613
|
+
const irObj = typeof initialIR === 'string' ? JSON.parse(initialIR) : initialIR;
|
|
1614
|
+
window.__WORKFLOW_IR__ = irObj;
|
|
1615
|
+
|
|
1616
|
+
// Build workflow data from IR (nodes include input/output; hooks serialized for inspector)
|
|
1617
|
+
function buildWorkflowDataFromIR(ir) {
|
|
1618
|
+
const nodes = {};
|
|
1619
|
+
function collectNodes(flowNodes) {
|
|
1620
|
+
for (const node of flowNodes || []) {
|
|
1621
|
+
nodes[node.id] = {
|
|
1622
|
+
id: node.id,
|
|
1623
|
+
name: node.name,
|
|
1624
|
+
type: node.type,
|
|
1625
|
+
state: node.state,
|
|
1626
|
+
key: node.key,
|
|
1627
|
+
durationMs: node.durationMs,
|
|
1628
|
+
startTs: node.startTs,
|
|
1629
|
+
error: node.error !== undefined && node.error !== null ? String(node.error) : undefined,
|
|
1630
|
+
retryCount: node.retryCount,
|
|
1631
|
+
input: node.input,
|
|
1632
|
+
output: node.output,
|
|
1633
|
+
...(node.type === "stream" && {
|
|
1634
|
+
namespace: node.namespace,
|
|
1635
|
+
writeCount: node.writeCount,
|
|
1636
|
+
readCount: node.readCount,
|
|
1637
|
+
finalPosition: node.finalPosition,
|
|
1638
|
+
streamState: node.streamState,
|
|
1639
|
+
backpressureOccurred: node.backpressureOccurred,
|
|
1640
|
+
}),
|
|
1641
|
+
...(node.type === "decision" && {
|
|
1642
|
+
condition: node.condition,
|
|
1643
|
+
decisionValue: node.decisionValue,
|
|
1644
|
+
branchTaken: node.branchTaken,
|
|
1645
|
+
branches: node.branches,
|
|
1646
|
+
}),
|
|
1647
|
+
};
|
|
1648
|
+
if (node.children) collectNodes(node.children);
|
|
1649
|
+
if (node.branches) {
|
|
1650
|
+
for (const branch of node.branches) {
|
|
1651
|
+
collectNodes(branch.children);
|
|
1652
|
+
}
|
|
1653
|
+
}
|
|
1654
|
+
}
|
|
1655
|
+
}
|
|
1656
|
+
collectNodes(ir.root.children);
|
|
1657
|
+
const hooks = ir.hooks
|
|
1658
|
+
? {
|
|
1659
|
+
...ir.hooks,
|
|
1660
|
+
onAfterStep:
|
|
1661
|
+
ir.hooks.onAfterStep instanceof Map
|
|
1662
|
+
? Object.fromEntries(ir.hooks.onAfterStep)
|
|
1663
|
+
: ir.hooks.onAfterStep,
|
|
1664
|
+
}
|
|
1665
|
+
: undefined;
|
|
1666
|
+
return { nodes, hooks };
|
|
1667
|
+
}
|
|
1668
|
+
|
|
1669
|
+
window.__WORKFLOW_DATA__ = buildWorkflowDataFromIR(irObj);
|
|
1670
|
+
|
|
1671
|
+
${t.heatmapData?`window.__PERFORMANCE_DATA__ = ${wt({heat:Object.fromEntries(t.heatmapData.heat),metric:t.heatmapData.metric,stats:t.heatmapData.stats})};`:""}
|
|
1672
|
+
})();
|
|
1673
|
+
</script>
|
|
1674
|
+
<script>${c}</script>
|
|
1675
|
+
</body>
|
|
1676
|
+
</html>`}function Xe(e){return e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}function vt(e){return e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}function rn(e,t){return e.length<=t?e:e.slice(0,t-1)+"\u2026"}function nn(e){if(!e.hooks)return e;let t=e.hooks.onAfterStep instanceof Map?Object.fromEntries(e.hooks.onAfterStep):e.hooks.onAfterStep;return{...e,hooks:{...e.hooks,onAfterStep:t}}}function wt(e){let t=new WeakSet;return JSON.stringify(e,(o,i)=>{if(typeof i=="bigint")return i.toString();if(o==="error"&&i!==void 0&&i!==null)return String(i);if(typeof i=="object"&&i!==null){if(t.has(i))return"[Circular]";t.add(i)}return i}).replace(/</g,"\\u003c").replace(/>/g,"\\u003e").replace(/&/g,"\\u0026").replace(/\u2028/g,"\\u2028").replace(/\u2029/g,"\\u2029")}var xt={interactive:!0,timeTravel:!0,heatmap:!0,animationDuration:200,theme:"auto",layout:"TB"};function St(){return{name:"html",supportsLive:!0,render(e,t){let r={...t,...xt,...t};return kt(e,r)}}}function Rt(e,t={}){let r={showTimings:!0,showKeys:!1,colors:{pending:"#6c757d",running:"#ffc107",success:"#198754",error:"#dc3545",aborted:"#6c757d",cached:"#0dcaf0",skipped:"#adb5bd"},...xt,...t};return kt(e,r)}function We(e,t={}){let{condition:r,value:o,name:i,workflowId:n=crypto.randomUUID(),emit:a}=t,s=Date.now(),u,c=[];function l(g,f,y){c.push({label:g,condition:y,taken:f}),f&&(u=g),a?.({type:"decision_branch",workflowId:n,decisionId:e,branchLabel:g,condition:y,taken:f,ts:Date.now()})}function p(){let g=Date.now()-s;a?.({type:"decision_end",workflowId:n,decisionId:e,branchTaken:u,ts:Date.now(),durationMs:g})}return a?.({type:"decision_start",workflowId:n,decisionId:e,condition:r,decisionValue:o,name:i,ts:s}),{takeBranch:l,end:p,getBranchTaken:()=>u,getBranches:()=>[...c]}}function It(e,t,r={}){let o=We(e,{...r,condition:r.condition??String(t),value:r.value??t}),i=!1;return{...o,condition:t,then:()=>{i||(i=!0,o.takeBranch("if",!0),o.takeBranch("else",!1))},else:()=>{i||(i=!0,o.takeBranch("if",!1),o.takeBranch("else",!0))}}}function $t(e,t,r={}){let o=We(e,{...r,condition:r.condition??`switch(${String(t)})`,value:t});return{...o,value:t,case:(i,n)=>{o.takeBranch(`case '${i}'`,n,`value === '${i}'`)},default:i=>{o.takeBranch("default",i)}}}function Et(e={}){let{maxSnapshots:t=1e3,autoRecord:r=!0,builderOptions:o={}}=e,i=ue({...o,enableSnapshots:!0,maxSnapshots:t}),n={snapshots:[],currentIndex:-1,isPlaying:!1,playbackSpeed:1,isRecording:r},a=new Set,s=null;function u(){let E=v();for(let T of a)T(E)}function c(){n.snapshots=i.getSnapshots(),n.isRecording&&n.snapshots.length>0&&(n.currentIndex=n.snapshots.length-1)}function l(E){i.handleEvent(E),n.isRecording&&(c(),u())}function p(E){let T=i.getSnapshots();if(!(E<0||E>=T.length))return n.currentIndex=E,n.snapshots=T,u(),T[E].ir}function g(){return p(n.currentIndex+1)}function f(){return p(n.currentIndex-1)}function y(E=1){let T=i.getSnapshots();if(T.length===0)return;n.currentIndex===-1&&(n.currentIndex=0,n.snapshots=T),n.playbackSpeed=E,n.isPlaying=!0,u();let P=()=>{if(!n.isPlaying)return;let K=i.getSnapshots();if(n.currentIndex<K.length-1){let _=K[n.currentIndex],ie=(K[n.currentIndex+1].timestamp-_.timestamp)/n.playbackSpeed;s=setTimeout(()=>{g(),P()},Math.max(16,ie))}else k()};P()}function k(){n.isPlaying=!1,s&&(clearTimeout(s),s=null),u()}function $(){let E=i.getSnapshots();return n.currentIndex>=0&&n.currentIndex<E.length?E[n.currentIndex].ir:i.getIR()}function M(E){return i.getIRAt(E)}function N(){return i.getSnapshots()}function I(E){return i.getSnapshotAt(E)}function v(){return{snapshots:i.getSnapshots(),currentIndex:n.currentIndex,isPlaying:n.isPlaying,playbackSpeed:n.playbackSpeed,isRecording:n.isRecording}}function x(E){return a.add(E),()=>a.delete(E)}function m(){n.isRecording=!0,i.setSnapshotsEnabled(!0),c(),u()}function w(){n.isRecording=!1,i.setSnapshotsEnabled(!1),u()}function R(){k(),i.reset(),i.setSnapshotsEnabled(r),n={snapshots:[],currentIndex:-1,isPlaying:!1,playbackSpeed:1,isRecording:r},u()}function D(){return i}return{handleEvent:l,seek:p,stepForward:g,stepBackward:f,play:y,pause:k,getCurrentIR:$,getIRAt:M,getSnapshots:N,getSnapshotAt:I,getState:v,onStateChange:x,startRecording:m,stopRecording:w,reset:R,getBuilder:D}}var Nt=qt(require("pako"),1),on=typeof globalThis<"u"&&"Buffer"in globalThis&&typeof globalThis.Buffer=="function";function an(e){let t;if(on)t=globalThis.Buffer.from(e).toString("base64");else{let r="";for(let o=0;o<e.length;o++)r+=String.fromCharCode(e[o]);t=btoa(r)}return t.replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}function Be(e){let r=new TextEncoder().encode(e),o=Nt.default.deflate(r);return an(o)}var Mt="https://kroki.io";function sn(e,t,r,o={}){let i=o.baseUrl??Mt,n=Be(r);return`${i}/${e}/${t}/${n}`}function se(e,t="svg",r={}){let o=te(),i={showTimings:!0,showKeys:!1,terminalWidth:80,colors:V},n=o.render(e,i);return sn("mermaid",t,n,r)}function Tt(e,t={}){return se(e,"svg",t)}function Ot(e,t={}){return se(e,"png",t)}function Dt(e={}){let t=e.baseUrl??Mt;return{toUrl(r,o){return se(r,o,{baseUrl:t})},toSvgUrl(r){return se(r,"svg",{baseUrl:t})},toPngUrl(r){return se(r,"png",{baseUrl:t})},toPdfUrl(r){return se(r,"pdf",{baseUrl:t})},getBaseUrl(){return t}}}var Ct="https://mermaid.ink";function qe(e){return`pako:${Be(e)}`}function cn(e){if("provider"in e){let t=e;return{theme:t.mermaidTheme,bgColor:t.background,scale:t.scale,fit:t.fit,width:t.width,height:t.height,paper:t.paper,imageType:"png"}}return e}function dn(e,t){let r=[];return t.bgColor&&r.push(`bgColor=${encodeURIComponent(t.bgColor)}`),t.theme&&r.push(`theme=${t.theme}`),t.width!==void 0&&r.push(`width=${t.width}`),t.height!==void 0&&r.push(`height=${t.height}`),t.scale!==void 0&&(t.width!==void 0||t.height!==void 0)&&r.push(`scale=${t.scale}`),e==="img"&&t.imageType&&t.imageType!=="jpeg"&&r.push(`type=${t.imageType}`),e==="pdf"&&(t.fit&&r.push("fit"),t.paper&&!t.fit&&r.push(`paper=${t.paper}`),t.landscape&&!t.fit&&r.push("landscape")),r.length>0?`?${r.join("&")}`:""}function Ze(e,t,r={}){let o=cn(r),i=o.baseUrl??Ct,n=qe(t),a=dn(e,o);return`${i}/${e}/${n}${a}`}function G(e,t="svg",r={}){let o=te(),i={showTimings:!0,showKeys:!1,terminalWidth:80,colors:V},n=o.render(e,i);return Ze(t,n,r)}function Lt(e,t={}){return G(e,"svg",t)}function _t(e,t={}){return G(e,"img",{...t,imageType:"png"})}function Wt(e,t={}){return G(e,"img",{...t,imageType:"jpeg"})}function Bt(e,t={}){return G(e,"img",{...t,imageType:"webp"})}function At(e,t={}){return G(e,"pdf",t)}function Pt(e={}){let t=e.baseUrl??Ct;return{toUrl(r,o){return G(r,o,e)},toSvgUrl(r){return G(r,"svg",e)},toPngUrl(r){return G(r,"img",{...e,imageType:"png"})},toJpegUrl(r){return G(r,"img",{...e,imageType:"jpeg"})},toWebpUrl(r){return G(r,"img",{...e,imageType:"webp"})},toPdfUrl(r){return G(r,"pdf",e)},getBaseUrl(){return t},getOptions(){return{...e}}}}var ln=()=>{throw new Error("createLiveVisualizer is not available in browser. It requires Node.js process.stdout.")};function Ae(e={}){let{workflowName:t,detectParallel:r=!0,showTimings:o=!0,showKeys:i=!1,colors:n}=e,a=ue({detectParallel:r}),s=new Set,u=ce(),c=te(),l=ke(),p=le(),g={showTimings:o,showKeys:i,terminalWidth:80,colors:{...V,...n}};function f(){if(s.size>0){let m=a.getIR();for(let w of s)w(m)}}function y(m){if(m.type==="scope_start"||m.type==="scope_end"){k(m);return}a.handleEvent(m),m.type,f()}function k(m){a.handleScopeEvent(m),f()}function $(m){a.handleDecisionEvent(m),f()}function M(){let m=a.getIR();return t&&!m.root.name&&(m.root.name=t),m}function N(){let m=M();return u.render(m,g)}function I(m){let w=M();switch(m){case"ascii":return u.render(w,g);case"mermaid":return c.render(w,g);case"json":{let R=w.hooks?{...w,hooks:{...w.hooks,onAfterStep:w.hooks.onAfterStep instanceof Map?Object.fromEntries(w.hooks.onAfterStep):w.hooks.onAfterStep??{}}}:w;return JSON.stringify(R,(E,T)=>typeof T=="bigint"?T.toString():T,2)}case"logger":return l.render(w,g);case"flowchart":return p.render(w,g);default:throw new Error(`Unknown format: ${m}`)}}function v(){a.reset(),f()}function x(m){return s.add(m),()=>s.delete(m)}return{handleEvent:y,handleScopeEvent:k,handleDecisionEvent:$,getIR:M,render:N,renderAs:I,reset:v,onUpdate:x}}function un(...e){return(t,r)=>{for(let o of e)o(t,r)}}function pn(e,t={}){let r=Ae(t);for(let o of e)o.type.startsWith("decision_")?r.handleDecisionEvent(o):r.handleEvent(o);return r.render()}function fn(e={}){let t=[];return{handleEvent:r=>{t.push(r)},handleDecisionEvent:r=>{t.push(r)},getEvents:()=>[...t],getWorkflowEvents:()=>t.filter(r=>!r.type.startsWith("decision_")),getDecisionEvents:()=>t.filter(r=>r.type.startsWith("decision_")),clear:()=>{t.length=0},visualize:()=>{let r=Ae(e);for(let o of t)o.type.startsWith("decision_")?r.handleDecisionEvent(o):r.handleEvent(o);return r.render()},visualizeAs:r=>{let o=Ae(e);for(let i of t)i.type.startsWith("decision_")?o.handleDecisionEvent(i):o.handleEvent(i);return o.renderAs(r)}}}0&&(module.exports={asciiRenderer,buildMermaidInkUrl,combineEventHandlers,createEventCollector,createIRBuilder,createLiveVisualizer,createMermaidInkGenerator,createParallelDetector,createPerformanceAnalyzer,createTimeTravelController,createUrlGenerator,createVisualizer,defaultColorScheme,detectParallelGroups,encodeForMermaidInk,flowchartRenderer,getHeatLevel,hasChildren,htmlRenderer,isDecisionNode,isParallelNode,isRaceNode,isSequenceNode,isStepNode,isStreamNode,loggerRenderer,mermaidRenderer,renderToHTML,toKrokiPngUrl,toKrokiSvgUrl,toKrokiUrl,toMermaidInkJpegUrl,toMermaidInkPdfUrl,toMermaidInkPngUrl,toMermaidInkSvgUrl,toMermaidInkUrl,toMermaidInkWebpUrl,trackDecision,trackIf,trackSwitch,visualizeEvents});
|
|
1677
|
+
//# sourceMappingURL=index.browser.cjs.map
|