@zibby/agent-workflow 0.1.2

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/graph.js ADDED
@@ -0,0 +1,37 @@
1
+ var Yt=Object.defineProperty;var j=(n,t)=>()=>(n&&(t=n(n=0)),t);var mt=(n,t)=>{for(var e in t)Yt(n,e,{get:t[e],enumerable:!0})};var gt,Jt,Y,w,z=j(()=>{gt=()=>{},Jt={debug:gt,info:gt,warn:(...n)=>console.warn("[workflow]",...n),error:(...n)=>console.error("[workflow]",...n)},Y={impl:Jt},w={debug:(...n)=>Y.impl.debug?.(...n),info:(...n)=>Y.impl.info?.(...n),warn:(...n)=>Y.impl.warn?.(...n),error:(...n)=>Y.impl.error?.(...n)}});var J,vt=j(()=>{J=class{constructor(t,e,o=0){this.name=t,this.description=e,this.priority=o}async invoke(t,e={}){throw new Error(`${this.constructor.name}.invoke() must be implemented`)}canHandle(t){throw new Error(`${this.constructor.name}.canHandle() must be implemented`)}getName(){return this.name}getDescription(){return this.description}getPriority(){return this.priority}}});var bt={};mt(bt,{clearSkills:()=>Qt,getAllSkills:()=>qt,getSkill:()=>tt,hasSkill:()=>zt,listSkillIds:()=>Xt,registerSkill:()=>Vt});function Vt(n){if(!n||typeof n.id!="string")throw new Error("Skill definition must include a string id");B.set(n.id,Object.freeze({...n}))}function tt(n){return B.get(n)||null}function zt(n){return B.has(n)}function qt(){return new Map(B)}function Xt(){return Array.from(B.keys())}function Qt(){B.clear()}var B,et=j(()=>{B=new Map});var ot={};mt(ot,{getAgentStrategy:()=>Tt,invokeAgent:()=>oe,listStrategies:()=>ee,registerStrategy:()=>te});function te(n){if(!(n instanceof J))throw new Error("strategy must be an instance of AgentStrategy");let t=x.findIndex(e=>e.getName()===n.getName());t>=0?x[t]=n:x.push(n)}function ee(){return x.map(n=>n.getName())}function Tt(n={}){let{state:t={},preferredAgent:e=null}=n,o=e||t.agentType||process.env.AGENT_TYPE;if(!o){let r=x.map(i=>i.getName()).join(", ")||"none registered";throw new Error(`No agent specified. Set agentType in state or AGENT_TYPE env var. Available: ${r}`)}w.debug(`[workflow] agent selection: requested=${o}`);let s=x.find(r=>r.getName()===o);if(!s){let r=x.map(i=>i.getName()).join(", ")||"none registered";throw new Error(`Unknown agent '${o}'. Available: ${r}`)}if(!s.canHandle(n))throw new Error(`Agent '${o}' is not available in this environment. Check credentials/environment.`);return w.debug(`[workflow] using agent: ${s.getName()}`),s}async function oe(n,t={},e={}){let o=Tt(t),s=t.state?.config||e.config||{},r=s.models||{},i=e.nodeName&&r[e.nodeName]||null,a=r.default||null,c=s.agent?.[o.name]?.model||null,u=i||a||c||e.model||null,h={...e,model:u,workspace:t.state?.workspace||e.workspace,schema:e.schema||t.schema,images:e.images||t.images||[],skills:e.skills||t.skills||[],config:s},l=n,S=h.skills||[];if(S.length>0&&!e.skipPromptFragments){let f=S.map(v=>{let b=tt(v)?.promptFragment;return typeof b=="function"?b():b}).filter(Boolean);f.length>0&&(l+=`
2
+
3
+ ${f.join(`
4
+
5
+ `)}`)}let I=t.state?._currentNodeConfig?.extraPromptInstructions?.trim();return I&&(l+=`
6
+
7
+ \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
8
+ PRIORITY OVERRIDE \u2014 THE FOLLOWING INSTRUCTIONS TAKE PRECEDENCE OVER ALL PREVIOUS CONTENT
9
+ \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
10
+
11
+ ${I}
12
+ `),w.debug(`[workflow] prompt length: ${l.length} chars`),o.invoke(l,h)}var x,st=j(()=>{vt();z();et();x=[]});var Gt=new Set(["__proto__","constructor","prototype"]);function V(n){if(Gt.has(n))throw new Error(`Invalid state key: "${n}"`)}var U=class{constructor(t={}){this._state=Object.create(null),Object.assign(this._state,{messages:[],errors:[],artifacts:{},metadata:{},...t}),this._history=[]}get(t){return this._state[t]}set(t,e){V(t),this._history.push({...this._state}),this._state[t]=e}update(t){let e=Object.getOwnPropertyNames(t);for(let o of e)V(o);this._history.push({...this._state});for(let o of e)this._state[o]=t[o]}append(t,e){V(t),this._history.push({...this._state}),Array.isArray(this._state[t])||(this._state[t]=[]),this._state[t].push(e)}getAll(){return{...this._state}}rollback(){this._history.length>0&&(this._state=this._history.pop())}};var Z=class{constructor(t){this.schema=t}parse(t){let e=t.match(/```json\s*([\s\S]*?)\s*```/);if(e)return this.validate(JSON.parse(e[1]));let o=t.match(/\{[\s\S]*\}/);return o?this.validate(JSON.parse(o[0])):this.validate({result:t.trim()})}validate(t){let e=[];for(let[o,s]of Object.entries(this.schema)){if(s.required&&!(o in t)&&e.push(`Missing required field: ${o}`),o in t&&s.type){let r=typeof t[o];r!==s.type&&e.push(`Field '${o}' expected ${s.type}, got ${r}`)}if(s.validate&&o in t){let r=s.validate(t[o]);r&&e.push(`Field '${o}': ${r}`)}}if(e.length>0)throw new Error(`Output validation failed:
13
+ ${e.join(`
14
+ `)}`);return t}};z();import{writeFileSync as rt,readFileSync as xt,existsSync as At,mkdirSync as se}from"node:fs";import{join as nt,dirname as re}from"node:path";import g from"chalk";var Ht="__WORKFLOW_GRAPH_LOG__",M=g.gray("\u2502"),Kt=g.gray("\u250C"),St=g.gray("\u2514"),q=g.green("\u25C6"),_t=g.hex("#c084fc")("\u25C6"),wt=g.hex("#2dd4bf")("\u25C6"),X=g.red("\u25C6"),yt=`${M} `,Et=2;function It(n){return n<1e3?`${n}ms`:`${(n/1e3).toFixed(1)}s`}function $t(n,t){return(e,o,s)=>{if(typeof e!="string")return n(e,o,s);let r=process.stdout.columns||120,i="";for(let a=0;a<e.length;a++){let c=e[a];t.lineStart&&(i+=yt,t.col=Et,t.lineStart=!1),c===`
15
+ `?(i+=c,t.lineStart=!0,t.col=0,t.inEsc=!1):c==="\x1B"?(t.inEsc=!0,i+=c):t.inEsc?(i+=c,(c>="A"&&c<="Z"||c>="a"&&c<="z")&&(t.inEsc=!1)):(t.col++,i+=c,t.col>=r&&(i+=`
16
+ ${yt}`,t.col=Et))}return n(i,o,s)}}var Q=class{constructor(){this._currentNode=null,this._origStdoutWrite=null,this._origStderrWrite=null;let t=String(process.env.ZIBBY_RUN_SOURCE||"").trim().toLowerCase(),e=String(process.env.ZIBBY_WORKFLOW_GRAPH_LOG_MARKERS||"").trim()==="1";this._emitWorkflowGraphMarkers=e||t==="studio"}get isInsideNode(){return this._currentNode!==null}_startIntercepting(){this._origStdoutWrite=process.stdout.write.bind(process.stdout),this._origStderrWrite=process.stderr.write.bind(process.stderr);let t={lineStart:!0,col:0,inEsc:!1},e={lineStart:!0,col:0,inEsc:!1};this._outState=t,this._errState=e,process.stdout.write=$t(this._origStdoutWrite,t),process.stderr.write=$t(this._origStderrWrite,e)}_stopIntercepting(){this._origStdoutWrite&&(this._outState&&!this._outState.lineStart&&this._origStdoutWrite(`
17
+ `),process.stdout.write=this._origStdoutWrite),this._origStderrWrite&&(this._errState&&!this._errState.lineStart&&this._origStderrWrite(`
18
+ `),process.stderr.write=this._origStderrWrite),this._origStdoutWrite=null,this._origStderrWrite=null}_rawWrite(t){(this._origStdoutWrite||process.stdout.write.bind(process.stdout))(`${t}
19
+ `)}_emitGraphLogMarker(t){if(!this._emitWorkflowGraphMarkers)return;let e=`${Ht}${JSON.stringify(t)}
20
+ `;this._origStdoutWrite?this._origStdoutWrite(e):process.stdout.write(e)}_writeDot(t,e){this._origStdoutWrite?(this._outState&&!this._outState.lineStart&&(this._origStdoutWrite(`
21
+ `),this._outState.lineStart=!0,this._outState.col=0),this._origStdoutWrite(`${t} ${e}
22
+ `)):process.stdout.write.bind(process.stdout)(`${t} ${e}
23
+ `)}step(t){this._origStdoutWrite?this._writeDot(q,t):process.stdout.write.bind(process.stdout)(`${M} ${q} ${t}
24
+ `)}stepInfo(t){this.step(t)}stepTool(t){this._origStdoutWrite?this._writeDot(_t,t):process.stdout.write.bind(process.stdout)(`${M} ${_t} ${t}
25
+ `)}stepMemory(t){let e=g.hex("#2dd4bf")(t);this._origStdoutWrite?this._writeDot(wt,e):process.stdout.write.bind(process.stdout)(`${M} ${wt} ${e}
26
+ `)}stepFail(t){this._origStdoutWrite?this._writeDot(X,g.red(t)):process.stdout.write.bind(process.stdout)(`${M} ${X} ${g.red(t)}
27
+ `)}nodeStart(t){this._currentNode=t,this._emitGraphLogMarker({phase:"node_begin",node:t}),this._rawWrite(`${Kt} ${t}`),this._startIntercepting()}nodeComplete(t,e={}){this._stopIntercepting();let{duration:o,details:s}=e;if(s)for(let i of s)this._rawWrite(`${q} ${i}`);let r=o?g.dim(` ${It(o)}`):"";this._rawWrite(`${St} ${g.green("done")}${r}`),this._emitGraphLogMarker({phase:"node_end",node:t}),this._rawWrite("")}nodeFailed(t,e,o={}){this._stopIntercepting();let{duration:s}=o,r=s?g.dim(` ${It(s)}`):"";this._rawWrite(`${X} ${g.red(e)}`),this._rawWrite(`${St} ${g.red("failed")}${r}`),this._emitGraphLogMarker({phase:"node_end",node:t}),this._rawWrite("")}route(t,e){this._rawWrite(g.dim(` ${t} \u2192 ${e}`)),this._rawWrite("")}graphComplete(){this._rawWrite(g.green.bold("\u2713 Workflow completed"))}},y=new Q;var G=".zibby/output",Ot="sessions",C=".session-info.json",Nt=".zibby-studio-stop";var kt=["CI_JOB_ID","GITHUB_RUN_ID","CIRCLE_WORKFLOW_ID","BUILD_ID"];var W=class{constructor(t){if(this.config=t,this.name=t.name,this.prompt=t.prompt,this.outputSchema=t.outputSchema,!this.outputSchema&&!t._isCustomCode)throw new Error(`Node '${this.name}' must define outputSchema (Zod schema). This defines the contract for what the node returns to state.`);this.isZodSchema=this.outputSchema&&typeof this.outputSchema._def<"u",this.parser=t.outputSchema&&!this.isZodSchema?new Z(t.outputSchema):null,this.retries=t.retries||0,this.onComplete=t.onComplete,this.customExecute=t.execute}async execute(t,e){let o=()=>e&&typeof e.getAll=="function"?e.getAll():t,s=l=>e&&typeof e.get=="function"?e.get(l):t?.[l];if(typeof this.customExecute=="function"){w.debug(`[workflow] node '${this.name}': custom execute (skipping LLM)`);try{let l=await this.customExecute(t);return typeof l=="object"&&l!==null&&l.success===!1?{success:!1,error:l.error||"Node execution failed",raw:l.raw||null}:this.isZodSchema?(w.debug(`[workflow] node '${this.name}': validating output schema`),{success:!0,output:this.outputSchema.parse(l),raw:null}):{success:!0,output:l,raw:null}}catch(l){return w.error(`[workflow] node '${this.name}' failed: ${l.message}`),l.name==="ZodError"&&w.error(`Schema errors: ${JSON.stringify(l.errors,null,2)}`),{success:!1,error:l.message,raw:null}}}let r=typeof this.prompt=="function"?this.prompt(o()):this.prompt,i=s("_skillHints");i&&(r=`${i}
28
+
29
+ ${r}`);let a=o(),c=a.cwd||process.cwd(),u=a.sessionPath;try{if(u){let l=nt(u,C);if(At(l)){let I=JSON.parse(xt(l,"utf-8"));I.currentNode=this.name,rt(l,JSON.stringify(I,null,2),"utf-8")}let S=nt(u,"..",C);if(At(S))try{let I=JSON.parse(xt(S,"utf-8"));I.currentNode=this.name,rt(S,JSON.stringify(I,null,2),"utf-8")}catch{}}}catch(l){w.debug(`[workflow] could not update session info: ${l.message}`)}let h=null;for(let l=0;l<=this.retries;l++)try{w.debug(`[workflow] node '${this.name}' attempt ${l}`);let S=o().config||{},I=S.agents||{},f=this.config.agent??I[this.name]??null,v={state:o()};f&&(v.preferredAgent=f);let b={workspace:c,schema:this.isZodSchema?this.outputSchema:null,skills:this.config.skills||[],sessionPath:u,config:S,nodeName:this.name,timeout:this.config?.timeout||3e5},P=t?._coreInvokeAgent;P||(P=(await Promise.resolve().then(()=>(st(),ot))).invokeAgent);let d=await P(r,v,b),m,$;if(typeof d=="string"?(m=d,$=null):d.structured?(m=d.raw||JSON.stringify(d.structured,null,2),$=d.structured):(m=d.raw||JSON.stringify(d,null,2),$=d.extracted||null),u)try{let p=nt(u,this.name,"raw_stream_output.txt");se(re(p),{recursive:!0}),rt(p,typeof m=="string"?m:JSON.stringify(m),"utf-8")}catch(p){w.debug(`[workflow] could not save raw output: ${p.message}`)}if(this.isZodSchema&&$){w.info(`[workflow] node '${this.name}': output validated: ${JSON.stringify($,null,2)}`);let p=$;if(typeof this.onComplete=="function")try{p=await this.onComplete(o(),$)}catch(_){w.warn(`[workflow] onComplete hook failed: ${_.message}`)}return{success:!0,output:p,raw:m}}if(typeof this.onComplete=="function")try{return{success:!0,output:await this.onComplete(o(),{raw:m}),raw:m}}catch(p){throw new Error(`onComplete failed: ${p.message}`,{cause:p})}if(this.parser){let p=this.parser.parse(m);return w.info(`[workflow] node '${this.name}': parsed output: ${JSON.stringify(p,null,2)}`),y.step("Output parsed"),{success:!0,output:p,raw:m}}return{success:!0,output:m,raw:m}}catch(S){h=S,l<this.retries&&w.info(`[workflow] node '${this.name}' failed, retrying (${l+1}/${this.retries})\u2026`)}return{success:!1,error:h.message,raw:null}}},H=class extends W{constructor(t){super({...t,_isCustomCode:!0}),this.condition=t.condition}async execute(t,e){let o=e&&typeof e.getAll=="function"?e.getAll():t;return{success:!0,output:{nextNode:this.condition(o)},raw:null}}};import{existsSync as Pt,readFileSync as ne}from"node:fs";import{join as it,dirname as Ct}from"node:path";var K=class{static async loadContext(t,e,o={}){let s={},r=o.filenames||["CONTEXT.md","AGENTS.md"];if(t){let a=Ct(it(e,t));for(let c of r){let u=await this.findAndMergeContextFiles(c,a,e);if(u){let h=c.replace(/\.[^.]+$/,"").toLowerCase();s[h]=u}}}let i=o.discovery||{};for(let[a,c]of Object.entries(i))try{let u=it(e,c);Pt(u)&&(s[a]=await this.loadFile(u))}catch(u){console.warn(`[workflow] could not load context '${a}' from '${c}': ${u.message}`)}return s}static async findAndMergeContextFiles(t,e,o){let s=[],r=e;for(;r.startsWith(o);){let i=it(r,t);if(Pt(i))try{s.unshift(await this.loadFile(i))}catch(c){console.warn(`[workflow] could not load ${t} from ${i}: ${c.message}`)}let a=Ct(r);if(a===r)break;r=a}return s.length===0?null:s.every(i=>typeof i=="string")?s.join(`
30
+
31
+ ---
32
+
33
+ `):s.every(i=>typeof i=="object")?Object.assign({},...s):s[s.length-1]}static async loadFile(t){let e=ne(t,"utf-8");if(t.endsWith(".json"))return JSON.parse(e);if(t.endsWith(".js")||t.endsWith(".mjs")){let{pathToFileURL:o}=await import("url"),s=await import(o(t).href);return s.default||s}return e}};import{mkdirSync as Mt,existsSync as at,writeFileSync as Bt,unlinkSync as ie}from"node:fs";import{join as A,resolve as Lt}from"node:path";import{config as ae}from"dotenv";import{zodToJsonSchema as Wt}from"zod-to-json-schema";import ce from"handlebars";function le({traceFrom:n,sessionId:t,sessionPath:e,idSource:o,mkdirFresh:s}){if(process.env.ZIBBY_SESSION_LOG==="0"||process.env.ZIBBY_SESSION_LOG==="false")return;let r=typeof process.ppid=="number"?process.ppid:"n/a",i=`[zibby:session] from=${n} pid=${process.pid} ppid=${r} sessionId=${t} source=${o} mkdir=${s?"yes":"no"} path=${e}`;if(console.log(i),(process.env.ZIBBY_TRACE_SESSION==="1"||process.env.ZIBBY_TRACE_SESSION==="true")&&process.env.ZIBBY_SESSION_LOG!=="0"&&process.env.ZIBBY_SESSION_LOG!=="false"){let u=(new Error("session trace").stack||"").split(`
34
+ `).slice(2,14).join(`
35
+ `);console.log(`[zibby:session] stack (${n}):
36
+ ${u}`)}}function ue(){return process.env.ZIBBY_RUN_SOURCE==="studio"||process.env.ZIBBY_KEEP_SESSION_ENV==="1"||process.env.ZIBBY_KEEP_SESSION_ENV==="true"}function de(){if(process.env.ZIBBY_RUN_SOURCE!=="studio")return;let n=process.env.ZIBBY_SESSION_PATH;if(!(n==null||String(n).trim()===""))try{return Lt(String(n).trim())}catch{return String(n).trim()}}function pe(){ue()||(delete process.env.ZIBBY_SESSION_PATH,delete process.env.ZIBBY_SESSION_ID)}function fe({sessionPath:n,sessionId:t}){n&&typeof n=="string"&&(process.env.ZIBBY_SESSION_PATH=n),t!=null&&String(t).trim()!==""&&(process.env.ZIBBY_SESSION_ID=String(t).trim())}function he(n={}){let t=kt.map(r=>process.env[r]).find(Boolean),e=Math.random().toString(36).slice(2,6),o=t||`${Date.now()}_${e}`,s=n.paths?.sessionPrefix;return s?`${s}_${o}`:o}function me({cwd:n=process.cwd(),config:t={},initialState:e={},traceFrom:o="resolveWorkflowSession"}={}){let s=e.sessionPath,r=e.sessionTimestamp,i="initialState.sessionPath";if(!s&&process.env.ZIBBY_SESSION_PATH)try{let u=Lt(String(process.env.ZIBBY_SESSION_PATH));u&&(s=u,i="ZIBBY_SESSION_PATH")}catch{}let a;if(s)a=String(s).split(/[/\\]/).filter(Boolean).pop(),r==null&&(r=Date.now());else{let u=process.env.ZIBBY_SESSION_ID&&String(process.env.ZIBBY_SESSION_ID).trim();if(u)a=u,i="ZIBBY_SESSION_ID";else{let l=t.sessionId!=null?String(t.sessionId).trim():"";l&&l!=="last"?(a=l,i="config.sessionId"):(a=he(t),i="generated")}r=r??Date.now();let h=t.paths?.output||G;s=A(n,h,Ot,a)}let c=!at(s);return c&&Mt(s,{recursive:!0}),(c||i!=="initialState.sessionPath")&&le({traceFrom:o,sessionId:a,sessionPath:s,idSource:i,mkdirFresh:c}),fe({sessionPath:s,sessionId:a}),{sessionPath:s,sessionId:a,sessionTimestamp:r}}var Rt=class{constructor(t={}){this.nodes=new Map,this.edges=new Map,this.entryPoint=null,this.middleware=Array.isArray(t.middleware)?[...t.middleware]:[],t.nodeMiddleware&&this.middleware.push(t.nodeMiddleware),this.nodeTypeMap=new Map,this.conditionalCodeMap=new Map,this.stateSchema=t.stateSchema||null,this.nodePrompts=new Map,this.nodeOptions=new Map,this._invokeAgent=t.invokeAgent||null}setStateSchema(t){return this.stateSchema=t,this}getStateSchema(){return this.stateSchema}addNode(t,e,o={}){let s=e instanceof W?e:new W(e);return s.name=t,this.nodes.set(t,s),o.prompt&&this.nodePrompts.set(t,o.prompt),Object.keys(o).length>0&&this.nodeOptions.set(t,o),this}addConditionalNode(t,e){return this.nodes.set(t,new H({...e,name:t})),this}addEdge(t,e){return this.edges.set(t,e),this}setNodeType(t,e){return this.nodeTypeMap.set(t,e),this}addConditionalEdges(t,e,{labels:o}={}){return this.edges.set(t,{conditional:!0,routes:e,labels:o}),typeof e=="function"&&this.conditionalCodeMap.set(t,e.toString()),this}setEntryPoint(t){return this.entryPoint=t,this}use(t){return typeof t=="function"&&this.middleware.push(t),this}_composeMiddleware(t,e,o,s,r){let i=o;for(let a=t.length-1;a>=0;a--){let c=t[a],u=i;i=()=>c(e,u,s,r)}return i()}serialize(){let t=[],e={};for(let[r,i]of this.nodes){let a=this.nodeTypeMap.get(r)||r;t.push({id:r,type:a,data:{nodeType:a,label:r}});let c={};i._isCustomCode&&typeof i.execute=="function"&&(c.customCode=i.execute.toString());let u=this.nodePrompts.get(r);if(u&&(c.prompt=u),typeof i.customExecute=="function"&&(c.executeCode=i.customExecute.toString()),i.outputSchema)try{if(typeof i.outputSchema._def<"u"){let l=Wt(i.outputSchema,{target:"openApi3"});c.outputSchema={jsonSchema:l,variables:this._flattenJsonSchemaToVariables(l)}}else c.outputSchema={schema:i.outputSchema}}catch(l){console.warn(`[workflow] failed to convert schema for ${r}:`,l.message)}let h=(this.resolvedToolsMap||{})[r];h?.toolIds&&(c.tools=h.toolIds),Object.keys(c).length>0&&(e[r]=c)}let o=[];for(let[r,i]of this.edges)if(typeof i=="string")o.push({source:r,target:i});else if(i.conditional){let a=this.conditionalCodeMap.get(r)||i.routes.toString(),c=this._inferConditionalTargets(i.routes),u=i.labels||{};for(let h of c){let l={source:r,target:h,data:{conditionalCode:a}};u[h]&&(l.label=u[h]),o.push(l)}}let s=null;if(this.stateSchema)try{s=Wt(this.stateSchema,{target:"openApi3"})}catch{s=this.stateSchema}return{nodes:t,edges:o,nodeConfigs:e,stateSchema:s}}_inferConditionalTargets(t){let e=t.toString(),o=new Set,s=/return\s+['"]([^'"]+)['"]/g,r;for(;(r=s.exec(e))!==null;)o.add(r[1]);return[...o]}_flattenJsonSchemaToVariables(t,e=""){let o=t;if(t.$ref&&t.definitions){let s=t.$ref.replace("#/definitions/","");o=t.definitions[s]||t}return this._flattenSchema(o,e)}_flattenSchema(t,e=""){if(!t||typeof t!="object")return[];let o=[],s=t.properties||{},r=t.required||[];for(let[i,a]of Object.entries(s)){let c=e?`${e}.${i}`:i;o.push({path:c,type:a.type||"unknown",label:a.description||this._formatLabel(i),optional:!r.includes(i)}),a.type==="object"&&a.properties&&o.push(...this._flattenSchema(a,c)),a.type==="array"&&a.items?.type==="object"&&a.items.properties&&o.push(...this._flattenSchema(a.items,`${c}[]`))}return o}_formatLabel(t){return t.replace(/([A-Z])/g," $1").replace(/^./,e=>e.toUpperCase()).trim()}_summarizeNodeOutput(t,e){if(!e||typeof e!="object")return[];let o=[];e.success!==void 0&&o.push(`Result: ${e.success?"passed":"failed"}`);for(let[s,r]of Object.entries(e))if(!(s==="success"||s==="raw"||s==="nextNode")){if(typeof r=="string"&&r.length<=80)o.push(`${s}: ${r}`);else if(Array.isArray(r)){let i=r.length,a=r.filter(u=>u?.passed===!0).length,c=r.some(u=>u?.passed!==void 0);o.push(c?`${s}: ${a}/${i} passed${i-a?`, ${i-a} failed`:""}`:`${s}: ${i} items`)}if(o.length>=4)break}return o}async run(t,e={}){if(!this.entryPoint)throw new Error("No entry point set for graph");let o=e.cwd||process.cwd();ae({path:A(o,".env")});let s=e.config||{};if(!s||Object.keys(s).length===0)try{let p=A(o,".zibby.config.js");at(p)&&(s=(await import(p)).default||{})}catch{}process.env.EXECUTION_ID&&!s.agent?.strictMode&&(s.agent={...s.agent,strictMode:!0});let r=e.agentType;if(!r){let p=s?.agent;p?.provider?r=p.provider:p?.gemini?r="gemini":p?.claude?r="claude":p?.cursor?r="cursor":p?.codex?r="codex":r=process.env.AGENT_TYPE||"cursor"}let i=e.contextConfig||t?.config?.contextConfig||t?.config?.context||s?.context||{};if(this.stateSchema){let p=this.stateSchema.safeParse(e);if(!p.success){let _=p.error.issues.map(O=>`${O.path.join(".")}: ${O.message}`);throw console.error("\u274C Initial state validation failed:"),_.forEach(O=>console.error(` - ${O}`)),new Error(`State validation failed: ${_.join(", ")}`)}y.step("State validated against schema")}let a=de(),c=e.sessionPath||a;c||pe();let{sessionPath:u,sessionTimestamp:h,sessionId:l}=me({cwd:o,config:s,traceFrom:"WorkflowGraph.run",initialState:{sessionPath:c,sessionTimestamp:e.sessionTimestamp}});y.step(`Session ${l}`);let S=await K.loadContext(e.specPath||"",o,i);Object.keys(S).length>0&&y.step(`Context loaded: ${Object.keys(S).join(", ")}`);let I=e.outputPath;!I&&e.specPath&&(t?.calculateOutputPath?I=t.calculateOutputPath(e.specPath):console.warn(`\u26A0\uFE0F outputPath not resolved (specPath=${e.specPath})`));let f=new U({...e,config:s,agentType:r,outputPath:I,sessionPath:u,sessionTimestamp:h,context:S,resolvedTools:this.resolvedToolsMap||{}}),v=new Map;try{await import("@zibby/skills")}catch{}let{getSkill:b}=await Promise.resolve().then(()=>(et(),bt)),P=new Set;for(let[,p]of this.nodes)for(let _ of p.config?.skills||[])P.add(_);for(let p of P){let _=b(p);if(typeof _?.middleware=="function")try{let O=await _.middleware();typeof O=="function"&&v.set(p,O)}catch{}}let d=this.entryPoint,m=[];for(;d&&d!=="END";){let p=A(u,Nt);if(at(p)){console.warn(`
37
+ \u{1F6D1} Studio stop requested \u2014 ending workflow.`);try{ie(p)}catch{}if(t&&typeof t.cleanup=="function")try{await t.cleanup()}catch{}return y.step("Workflow stopped by Studio"),{success:!0,state:f.getAll(),executionLog:m,stoppedByStudio:!0}}let _=this.nodes.get(d);if(!_)throw new Error(`Node '${d}' not found in graph`);let O=JSON.stringify({sessionPath:u,sessionTimestamp:h,currentNode:d,createdAt:new Date().toISOString(),config:f.get("config")}),Dt=A(u,C);Bt(Dt,O,"utf-8");let ct=f.get("config")?.paths?.output||G,Ft=A(o,ct,C);Mt(A(o,ct),{recursive:!0});try{Bt(Ft,O,"utf-8")}catch{}let lt=e.onPipelineProgress;if(typeof lt=="function")try{lt({cwd:o,sessionPath:u,sessionId:l,outputBase:f.get("config")?.paths?.output||G,currentNode:d})}catch{}let jt=(this.resolvedToolsMap||{})[d]||null;f.set("_currentNodeTools",jt);let Ut=f.get("nodeConfigs")||{};f.set("_currentNodeConfig",Ut[d]||{}),y.nodeStart(d);let ut=Date.now(),L=this.nodePrompts.get(d);if(!this._invokeAgent){let N=await Promise.resolve().then(()=>(st(),ot));this._invokeAgent=N.invokeAgent}let dt=this._invokeAgent,pt={state:f,invokeAgent:async(N={},k={})=>{let E=k.prompt||"";if(L)try{E=ce.compile(L,{noEscape:!0})(N)}catch(T){throw console.error(`\u274C Template rendering failed for node '${d}':`,T.message),new Error(`Template rendering failed: ${T.message}`,{cause:T})}else if(!E)throw new Error(`No prompt template configured for node '${d}' and no prompt provided in options`);return dt(E,{state:f.getAll(),images:k.images||[]},{model:k.model||f.get("model"),workspace:f.get("workspace"),schema:k.schema,...k})},_coreInvokeAgent:dt,agent:t,nodeId:d,promptTemplate:L,getPromptTemplate:()=>L,...f.getAll()};try{let N=(_.config?.skills||[]).map(R=>v.get(R)).filter(Boolean),k=[...this.middleware,...N],E;k.length>0?E=await this._composeMiddleware(k,d,async()=>_.execute(pt,f),f.getAll(),f):E=await _.execute(pt,f);let T=Date.now()-ut;if(m.push({node:d,success:E.success,duration:T,timestamp:new Date().toISOString()}),!E.success){if(String(E.error||"").includes("Stopped from Zibby Studio")){if(y.step("Workflow stopped by Studio"),f.set("stoppedByStudio",!0),t&&typeof t.cleanup=="function")try{await t.cleanup()}catch{}return{success:!0,state:f.getAll(),executionLog:m,stoppedByStudio:!0}}f.append("errors",{node:d,error:E.error});let ft=_.config?.retries||0,ht=`${d}_retries`,F=f.getAll()[ht]||0;if(F<ft){y.stepInfo(`Retrying (attempt ${F+1}/${ft})`),f.update({[ht]:F+1,[`${d}_raw`]:E.raw});continue}throw y.nodeFailed(d,E.error,{duration:T}),new Error(`Node '${d}' failed after ${F} attempts: ${E.error}`)}f.update({[d]:E.output});let Zt=this._summarizeNodeOutput(d,E.output);y.nodeComplete(d,{duration:T,details:Zt});let D=this.edges.get(d);if(!D)d="END";else if(D.conditional){let R=D.routes(f.getAll());y.route(d,R),d=R}else d=D}catch(N){throw y.isInsideNode&&y.nodeFailed(d,N.message,{duration:Date.now()-ut}),f.set("failed",!0),f.set("failedAt",d),N}}y.graphComplete();let $={success:!0,state:f.getAll(),executionLog:m};return t&&typeof t.onComplete=="function"&&await t.onComplete($),$}};export{Rt as WorkflowGraph,pe as clearInheritedSessionEnvForFreshRun,he as generateWorkflowSessionId,de as readStudioPinnedSessionPathFromEnv,me as resolveWorkflowSession,ue as shouldTrustInheritedSessionEnv,fe as syncProcessEnvToSession};
@@ -0,0 +1,15 @@
1
+ export { WorkflowState } from "./state.js";
2
+ export { ContextLoader } from "./context-loader.js";
3
+ export { AgentStrategy } from "./agents/base.js";
4
+ export { setLogger } from "./logger.js";
5
+ export { WorkflowGraph, generateWorkflowSessionId, resolveWorkflowSession, shouldTrustInheritedSessionEnv, readStudioPinnedSessionPathFromEnv, clearInheritedSessionEnvForFreshRun, syncProcessEnvToSession } from "./graph.js";
6
+ export { Node, ConditionalNode } from "./node.js";
7
+ export { OutputParser, SchemaTypes } from "./output-parser.js";
8
+ export { compileGraph, validateGraphConfig, extractSteps, CompilationError } from "./graph-compiler.js";
9
+ export { registerNode, getNodeImpl, hasNode, listNodeTypes, getNodeTemplate } from "./node-registry.js";
10
+ export { registerSkill, getSkill, hasSkill, getAllSkills, listSkillIds, clearSkills } from "./skill-registry.js";
11
+ export { resolveNodeTools, getResolvedToolDefinitions, NODE_DEFAULT_TOOLS } from "./tool-resolver.js";
12
+ export { registerStrategy, listStrategies, getAgentStrategy, invokeAgent } from "./strategy-registry.js";
13
+ export { generateWorkflowCode, generateNodeConfigsJson } from "./code-generator.js";
14
+ export { SKILLS, DEFAULT_OUTPUT_BASE, SESSIONS_DIR, SESSION_INFO_FILE, STUDIO_STOP_REQUEST_FILE, RESULT_FILE, RAW_OUTPUT_FILE, EVENTS_FILE, CI_ENV_VARS } from "./constants.js";
15
+ export { timeline, Timeline, WORKFLOW_GRAPH_LOG_MARKER_PREFIX } from "./timeline.js";
package/dist/index.js ADDED
@@ -0,0 +1,54 @@
1
+ var yt=Object.defineProperty;var ae=(o=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(o,{get:(e,t)=>(typeof require<"u"?require:e)[t]}):o)(function(o){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+o+'" is not supported')});var oe=(o,e)=>()=>(o&&(e=o(o=0)),e);var Ce=(o,e)=>{for(var t in e)yt(o,t,{get:e[t],enumerable:!0})};function Et(o){G.impl={...Pe,...o}}var be,Pe,G,_,B=oe(()=>{be=()=>{},Pe={debug:be,info:be,warn:(...o)=>console.warn("[workflow]",...o),error:(...o)=>console.error("[workflow]",...o)},G={impl:Pe};_={debug:(...o)=>G.impl.debug?.(...o),info:(...o)=>G.impl.info?.(...o),warn:(...o)=>G.impl.warn?.(...o),error:(...o)=>G.impl.error?.(...o)}});var J,he=oe(()=>{J=class{constructor(e,t,s=0){this.name=e,this.description=t,this.priority=s}async invoke(e,t={}){throw new Error(`${this.constructor.name}.invoke() must be implemented`)}canHandle(e){throw new Error(`${this.constructor.name}.canHandle() must be implemented`)}getName(){return this.name}getDescription(){return this.description}getPriority(){return this.priority}}});var He={};Ce(He,{clearSkills:()=>Je,getAllSkills:()=>Ze,getSkill:()=>D,hasSkill:()=>Ge,listSkillIds:()=>Ye,registerSkill:()=>Ue});function Ue(o){if(!o||typeof o.id!="string")throw new Error("Skill definition must include a string id");L.set(o.id,Object.freeze({...o}))}function D(o){return L.get(o)||null}function Ge(o){return L.has(o)}function Ze(){return new Map(L)}function Ye(){return Array.from(L.keys())}function Je(){L.clear()}var L,H=oe(()=>{L=new Map});var V={};Ce(V,{getAgentStrategy:()=>me,invokeAgent:()=>ze,listStrategies:()=>Ke,registerStrategy:()=>Ve});function Ve(o){if(!(o instanceof J))throw new Error("strategy must be an instance of AgentStrategy");let e=P.findIndex(t=>t.getName()===o.getName());e>=0?P[e]=o:P.push(o)}function Ke(){return P.map(o=>o.getName())}function me(o={}){let{state:e={},preferredAgent:t=null}=o,s=t||e.agentType||process.env.AGENT_TYPE;if(!s){let n=P.map(r=>r.getName()).join(", ")||"none registered";throw new Error(`No agent specified. Set agentType in state or AGENT_TYPE env var. Available: ${n}`)}_.debug(`[workflow] agent selection: requested=${s}`);let i=P.find(n=>n.getName()===s);if(!i){let n=P.map(r=>r.getName()).join(", ")||"none registered";throw new Error(`Unknown agent '${s}'. Available: ${n}`)}if(!i.canHandle(o))throw new Error(`Agent '${s}' is not available in this environment. Check credentials/environment.`);return _.debug(`[workflow] using agent: ${i.getName()}`),i}async function ze(o,e={},t={}){let s=me(e),i=e.state?.config||t.config||{},n=i.models||{},r=t.nodeName&&n[t.nodeName]||null,a=n.default||null,c=i.agent?.[s.name]?.model||null,d=r||a||c||t.model||null,h={...t,model:d,workspace:e.state?.workspace||t.workspace,schema:t.schema||e.schema,images:t.images||e.images||[],skills:t.skills||e.skills||[],config:i},u=o,l=h.skills||[];if(l.length>0&&!t.skipPromptFragments){let p=l.map(S=>{let y=D(S)?.promptFragment;return typeof y=="function"?y():y}).filter(Boolean);p.length>0&&(u+=`
2
+
3
+ ${p.join(`
4
+
5
+ `)}`)}let g=e.state?._currentNodeConfig?.extraPromptInstructions?.trim();return g&&(u+=`
6
+
7
+ \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
8
+ PRIORITY OVERRIDE \u2014 THE FOLLOWING INSTRUCTIONS TAKE PRECEDENCE OVER ALL PREVIOUS CONTENT
9
+ \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
10
+
11
+ ${g}
12
+ `),_.debug(`[workflow] prompt length: ${u.length} chars`),s.invoke(u,h)}var P,F=oe(()=>{he();B();H();P=[]});var _t=new Set(["__proto__","constructor","prototype"]);function ce(o){if(_t.has(o))throw new Error(`Invalid state key: "${o}"`)}var j=class{constructor(e={}){this._state=Object.create(null),Object.assign(this._state,{messages:[],errors:[],artifacts:{},metadata:{},...e}),this._history=[]}get(e){return this._state[e]}set(e,t){ce(e),this._history.push({...this._state}),this._state[e]=t}update(e){let t=Object.getOwnPropertyNames(e);for(let s of t)ce(s);this._history.push({...this._state});for(let s of t)this._state[s]=e[s]}append(e,t){ce(e),this._history.push({...this._state}),Array.isArray(this._state[e])||(this._state[e]=[]),this._state[e].push(t)}getAll(){return{...this._state}}rollback(){this._history.length>0&&(this._state=this._history.pop())}};var U=class{constructor(e){this.schema=e}parse(e){let t=e.match(/```json\s*([\s\S]*?)\s*```/);if(t)return this.validate(JSON.parse(t[1]));let s=e.match(/\{[\s\S]*\}/);return s?this.validate(JSON.parse(s[0])):this.validate({result:e.trim()})}validate(e){let t=[];for(let[s,i]of Object.entries(this.schema)){if(i.required&&!(s in e)&&t.push(`Missing required field: ${s}`),s in e&&i.type){let n=typeof e[s];n!==i.type&&t.push(`Field '${s}' expected ${i.type}, got ${n}`)}if(i.validate&&s in e){let n=i.validate(e[s]);n&&t.push(`Field '${s}': ${n}`)}}if(t.length>0)throw new Error(`Output validation failed:
13
+ ${t.join(`
14
+ `)}`);return e}},$t={string:(o=!0)=>({type:"string",required:o}),number:(o=!0)=>({type:"number",required:o}),boolean:(o=!0)=>({type:"boolean",required:o}),array:(o=!0)=>({type:"object",required:o,validate:e=>Array.isArray(e)?null:"must be an array"}),enum:(o,e=!0)=>({type:"string",required:e,validate:t=>o.includes(t)?null:`must be one of: ${o.join(", ")}`})};B();import{writeFileSync as ge,readFileSync as qe,existsSync as Xe,mkdirSync as xt}from"node:fs";import{join as Se,dirname as Ot}from"node:path";import E from"chalk";var je="__WORKFLOW_GRAPH_LOG__",Z=E.gray("\u2502"),It=E.gray("\u250C"),Re=E.gray("\u2514"),de=E.green("\u25C6"),We=E.hex("#c084fc")("\u25C6"),Be=E.hex("#2dd4bf")("\u25C6"),le=E.red("\u25C6"),Le=`${Z} `,De=2;function Fe(o){return o<1e3?`${o}ms`:`${(o/1e3).toFixed(1)}s`}function Me(o,e){return(t,s,i)=>{if(typeof t!="string")return o(t,s,i);let n=process.stdout.columns||120,r="";for(let a=0;a<t.length;a++){let c=t[a];e.lineStart&&(r+=Le,e.col=De,e.lineStart=!1),c===`
15
+ `?(r+=c,e.lineStart=!0,e.col=0,e.inEsc=!1):c==="\x1B"?(e.inEsc=!0,r+=c):e.inEsc?(r+=c,(c>="A"&&c<="Z"||c>="a"&&c<="z")&&(e.inEsc=!1)):(e.col++,r+=c,e.col>=n&&(r+=`
16
+ ${Le}`,e.col=De))}return o(r,s,i)}}var se=class{constructor(){this._currentNode=null,this._origStdoutWrite=null,this._origStderrWrite=null;let e=String(process.env.ZIBBY_RUN_SOURCE||"").trim().toLowerCase(),t=String(process.env.ZIBBY_WORKFLOW_GRAPH_LOG_MARKERS||"").trim()==="1";this._emitWorkflowGraphMarkers=t||e==="studio"}get isInsideNode(){return this._currentNode!==null}_startIntercepting(){this._origStdoutWrite=process.stdout.write.bind(process.stdout),this._origStderrWrite=process.stderr.write.bind(process.stderr);let e={lineStart:!0,col:0,inEsc:!1},t={lineStart:!0,col:0,inEsc:!1};this._outState=e,this._errState=t,process.stdout.write=Me(this._origStdoutWrite,e),process.stderr.write=Me(this._origStderrWrite,t)}_stopIntercepting(){this._origStdoutWrite&&(this._outState&&!this._outState.lineStart&&this._origStdoutWrite(`
17
+ `),process.stdout.write=this._origStdoutWrite),this._origStderrWrite&&(this._errState&&!this._errState.lineStart&&this._origStderrWrite(`
18
+ `),process.stderr.write=this._origStderrWrite),this._origStdoutWrite=null,this._origStderrWrite=null}_rawWrite(e){(this._origStdoutWrite||process.stdout.write.bind(process.stdout))(`${e}
19
+ `)}_emitGraphLogMarker(e){if(!this._emitWorkflowGraphMarkers)return;let t=`${je}${JSON.stringify(e)}
20
+ `;this._origStdoutWrite?this._origStdoutWrite(t):process.stdout.write(t)}_writeDot(e,t){this._origStdoutWrite?(this._outState&&!this._outState.lineStart&&(this._origStdoutWrite(`
21
+ `),this._outState.lineStart=!0,this._outState.col=0),this._origStdoutWrite(`${e} ${t}
22
+ `)):process.stdout.write.bind(process.stdout)(`${e} ${t}
23
+ `)}step(e){this._origStdoutWrite?this._writeDot(de,e):process.stdout.write.bind(process.stdout)(`${Z} ${de} ${e}
24
+ `)}stepInfo(e){this.step(e)}stepTool(e){this._origStdoutWrite?this._writeDot(We,e):process.stdout.write.bind(process.stdout)(`${Z} ${We} ${e}
25
+ `)}stepMemory(e){let t=E.hex("#2dd4bf")(e);this._origStdoutWrite?this._writeDot(Be,t):process.stdout.write.bind(process.stdout)(`${Z} ${Be} ${t}
26
+ `)}stepFail(e){this._origStdoutWrite?this._writeDot(le,E.red(e)):process.stdout.write.bind(process.stdout)(`${Z} ${le} ${E.red(e)}
27
+ `)}nodeStart(e){this._currentNode=e,this._emitGraphLogMarker({phase:"node_begin",node:e}),this._rawWrite(`${It} ${e}`),this._startIntercepting()}nodeComplete(e,t={}){this._stopIntercepting();let{duration:s,details:i}=t;if(i)for(let r of i)this._rawWrite(`${de} ${r}`);let n=s?E.dim(` ${Fe(s)}`):"";this._rawWrite(`${Re} ${E.green("done")}${n}`),this._emitGraphLogMarker({phase:"node_end",node:e}),this._rawWrite("")}nodeFailed(e,t,s={}){this._stopIntercepting();let{duration:i}=s,n=i?E.dim(` ${Fe(i)}`):"";this._rawWrite(`${le} ${E.red(t)}`),this._rawWrite(`${Re} ${E.red("failed")}${n}`),this._emitGraphLogMarker({phase:"node_end",node:e}),this._rawWrite("")}route(e,t){this._rawWrite(E.dim(` ${e} \u2192 ${t}`)),this._rawWrite("")}graphComplete(){this._rawWrite(E.green.bold("\u2713 Workflow completed"))}},I=new se;var Y=".zibby/output",ue="sessions",b=".session-info.json",pe=".zibby-studio-stop",Nt="result.json",Tt="raw_stream_output.txt",vt="events.json",kt={BROWSER:"browser",JIRA:"jira",GITHUB:"github",SLACK:"slack",MEMORY:"memory",CHAT_MEMORY:"chat-memory",RUNNER:"runner",SKILL_INSTALLER:"skill-installer",CORE_TOOLS:"core-tools",WORKFLOW_BUILDER:"workflow-builder"},fe=["CI_JOB_ID","GITHUB_RUN_ID","CIRCLE_WORKFLOW_ID","BUILD_ID"];var R=class{constructor(e){if(this.config=e,this.name=e.name,this.prompt=e.prompt,this.outputSchema=e.outputSchema,!this.outputSchema&&!e._isCustomCode)throw new Error(`Node '${this.name}' must define outputSchema (Zod schema). This defines the contract for what the node returns to state.`);this.isZodSchema=this.outputSchema&&typeof this.outputSchema._def<"u",this.parser=e.outputSchema&&!this.isZodSchema?new U(e.outputSchema):null,this.retries=e.retries||0,this.onComplete=e.onComplete,this.customExecute=e.execute}async execute(e,t){let s=()=>t&&typeof t.getAll=="function"?t.getAll():e,i=u=>t&&typeof t.get=="function"?t.get(u):e?.[u];if(typeof this.customExecute=="function"){_.debug(`[workflow] node '${this.name}': custom execute (skipping LLM)`);try{let u=await this.customExecute(e);return typeof u=="object"&&u!==null&&u.success===!1?{success:!1,error:u.error||"Node execution failed",raw:u.raw||null}:this.isZodSchema?(_.debug(`[workflow] node '${this.name}': validating output schema`),{success:!0,output:this.outputSchema.parse(u),raw:null}):{success:!0,output:u,raw:null}}catch(u){return _.error(`[workflow] node '${this.name}' failed: ${u.message}`),u.name==="ZodError"&&_.error(`Schema errors: ${JSON.stringify(u.errors,null,2)}`),{success:!1,error:u.message,raw:null}}}let n=typeof this.prompt=="function"?this.prompt(s()):this.prompt,r=i("_skillHints");r&&(n=`${r}
28
+
29
+ ${n}`);let a=s(),c=a.cwd||process.cwd(),d=a.sessionPath;try{if(d){let u=Se(d,b);if(Xe(u)){let g=JSON.parse(qe(u,"utf-8"));g.currentNode=this.name,ge(u,JSON.stringify(g,null,2),"utf-8")}let l=Se(d,"..",b);if(Xe(l))try{let g=JSON.parse(qe(l,"utf-8"));g.currentNode=this.name,ge(l,JSON.stringify(g,null,2),"utf-8")}catch{}}}catch(u){_.debug(`[workflow] could not update session info: ${u.message}`)}let h=null;for(let u=0;u<=this.retries;u++)try{_.debug(`[workflow] node '${this.name}' attempt ${u}`);let l=s().config||{},g=l.agents||{},p=this.config.agent??g[this.name]??null,S={state:s()};p&&(S.preferredAgent=p);let y={workspace:c,schema:this.isZodSchema?this.outputSchema:null,skills:this.config.skills||[],sessionPath:d,config:l,nodeName:this.name,timeout:this.config?.timeout||3e5},$=e?._coreInvokeAgent;$||($=(await Promise.resolve().then(()=>(F(),V))).invokeAgent);let f=await $(n,S,y),w,k;if(typeof f=="string"?(w=f,k=null):f.structured?(w=f.raw||JSON.stringify(f.structured,null,2),k=f.structured):(w=f.raw||JSON.stringify(f,null,2),k=f.extracted||null),d)try{let m=Se(d,this.name,"raw_stream_output.txt");xt(Ot(m),{recursive:!0}),ge(m,typeof w=="string"?w:JSON.stringify(w),"utf-8")}catch(m){_.debug(`[workflow] could not save raw output: ${m.message}`)}if(this.isZodSchema&&k){_.info(`[workflow] node '${this.name}': output validated: ${JSON.stringify(k,null,2)}`);let m=k;if(typeof this.onComplete=="function")try{m=await this.onComplete(s(),k)}catch(N){_.warn(`[workflow] onComplete hook failed: ${N.message}`)}return{success:!0,output:m,raw:w}}if(typeof this.onComplete=="function")try{return{success:!0,output:await this.onComplete(s(),{raw:w}),raw:w}}catch(m){throw new Error(`onComplete failed: ${m.message}`,{cause:m})}if(this.parser){let m=this.parser.parse(w);return _.info(`[workflow] node '${this.name}': parsed output: ${JSON.stringify(m,null,2)}`),I.step("Output parsed"),{success:!0,output:m,raw:w}}return{success:!0,output:w,raw:w}}catch(l){h=l,u<this.retries&&_.info(`[workflow] node '${this.name}' failed, retrying (${u+1}/${this.retries})\u2026`)}return{success:!1,error:h.message,raw:null}}},K=class extends R{constructor(e){super({...e,_isCustomCode:!0}),this.condition=e.condition}async execute(e,t){let s=t&&typeof t.getAll=="function"?t.getAll():e;return{success:!0,output:{nextNode:this.condition(s)},raw:null}}};import{existsSync as Qe,readFileSync as At}from"node:fs";import{join as we,dirname as et}from"node:path";var z=class{static async loadContext(e,t,s={}){let i={},n=s.filenames||["CONTEXT.md","AGENTS.md"];if(e){let a=et(we(t,e));for(let c of n){let d=await this.findAndMergeContextFiles(c,a,t);if(d){let h=c.replace(/\.[^.]+$/,"").toLowerCase();i[h]=d}}}let r=s.discovery||{};for(let[a,c]of Object.entries(r))try{let d=we(t,c);Qe(d)&&(i[a]=await this.loadFile(d))}catch(d){console.warn(`[workflow] could not load context '${a}' from '${c}': ${d.message}`)}return i}static async findAndMergeContextFiles(e,t,s){let i=[],n=t;for(;n.startsWith(s);){let r=we(n,e);if(Qe(r))try{i.unshift(await this.loadFile(r))}catch(c){console.warn(`[workflow] could not load ${e} from ${r}: ${c.message}`)}let a=et(n);if(a===n)break;n=a}return i.length===0?null:i.every(r=>typeof r=="string")?i.join(`
30
+
31
+ ---
32
+
33
+ `):i.every(r=>typeof r=="object")?Object.assign({},...i):i[i.length-1]}static async loadFile(e){let t=At(e,"utf-8");if(e.endsWith(".json"))return JSON.parse(t);if(e.endsWith(".js")||e.endsWith(".mjs")){let{pathToFileURL:s}=await import("url"),i=await import(s(e).href);return i.default||i}return t}};import{mkdirSync as st,existsSync as ye,writeFileSync as tt,unlinkSync as Ct}from"node:fs";import{join as W,resolve as rt}from"node:path";import{config as bt}from"dotenv";import{zodToJsonSchema as ot}from"zod-to-json-schema";import Pt from"handlebars";function Rt({traceFrom:o,sessionId:e,sessionPath:t,idSource:s,mkdirFresh:i}){if(process.env.ZIBBY_SESSION_LOG==="0"||process.env.ZIBBY_SESSION_LOG==="false")return;let n=typeof process.ppid=="number"?process.ppid:"n/a",r=`[zibby:session] from=${o} pid=${process.pid} ppid=${n} sessionId=${e} source=${s} mkdir=${i?"yes":"no"} path=${t}`;if(console.log(r),(process.env.ZIBBY_TRACE_SESSION==="1"||process.env.ZIBBY_TRACE_SESSION==="true")&&process.env.ZIBBY_SESSION_LOG!=="0"&&process.env.ZIBBY_SESSION_LOG!=="false"){let d=(new Error("session trace").stack||"").split(`
34
+ `).slice(2,14).join(`
35
+ `);console.log(`[zibby:session] stack (${o}):
36
+ ${d}`)}}function nt(){return process.env.ZIBBY_RUN_SOURCE==="studio"||process.env.ZIBBY_KEEP_SESSION_ENV==="1"||process.env.ZIBBY_KEEP_SESSION_ENV==="true"}function it(){if(process.env.ZIBBY_RUN_SOURCE!=="studio")return;let o=process.env.ZIBBY_SESSION_PATH;if(!(o==null||String(o).trim()===""))try{return rt(String(o).trim())}catch{return String(o).trim()}}function at(){nt()||(delete process.env.ZIBBY_SESSION_PATH,delete process.env.ZIBBY_SESSION_ID)}function ct({sessionPath:o,sessionId:e}){o&&typeof o=="string"&&(process.env.ZIBBY_SESSION_PATH=o),e!=null&&String(e).trim()!==""&&(process.env.ZIBBY_SESSION_ID=String(e).trim())}function dt(o={}){let e=fe.map(n=>process.env[n]).find(Boolean),t=Math.random().toString(36).slice(2,6),s=e||`${Date.now()}_${t}`,i=o.paths?.sessionPrefix;return i?`${i}_${s}`:s}function lt({cwd:o=process.cwd(),config:e={},initialState:t={},traceFrom:s="resolveWorkflowSession"}={}){let i=t.sessionPath,n=t.sessionTimestamp,r="initialState.sessionPath";if(!i&&process.env.ZIBBY_SESSION_PATH)try{let d=rt(String(process.env.ZIBBY_SESSION_PATH));d&&(i=d,r="ZIBBY_SESSION_PATH")}catch{}let a;if(i)a=String(i).split(/[/\\]/).filter(Boolean).pop(),n==null&&(n=Date.now());else{let d=process.env.ZIBBY_SESSION_ID&&String(process.env.ZIBBY_SESSION_ID).trim();if(d)a=d,r="ZIBBY_SESSION_ID";else{let u=e.sessionId!=null?String(e.sessionId).trim():"";u&&u!=="last"?(a=u,r="config.sessionId"):(a=dt(e),r="generated")}n=n??Date.now();let h=e.paths?.output||Y;i=W(o,h,ue,a)}let c=!ye(i);return c&&st(i,{recursive:!0}),(c||r!=="initialState.sessionPath")&&Rt({traceFrom:s,sessionId:a,sessionPath:i,idSource:r,mkdirFresh:c}),ct({sessionPath:i,sessionId:a}),{sessionPath:i,sessionId:a,sessionTimestamp:n}}var q=class{constructor(e={}){this.nodes=new Map,this.edges=new Map,this.entryPoint=null,this.middleware=Array.isArray(e.middleware)?[...e.middleware]:[],e.nodeMiddleware&&this.middleware.push(e.nodeMiddleware),this.nodeTypeMap=new Map,this.conditionalCodeMap=new Map,this.stateSchema=e.stateSchema||null,this.nodePrompts=new Map,this.nodeOptions=new Map,this._invokeAgent=e.invokeAgent||null}setStateSchema(e){return this.stateSchema=e,this}getStateSchema(){return this.stateSchema}addNode(e,t,s={}){let i=t instanceof R?t:new R(t);return i.name=e,this.nodes.set(e,i),s.prompt&&this.nodePrompts.set(e,s.prompt),Object.keys(s).length>0&&this.nodeOptions.set(e,s),this}addConditionalNode(e,t){return this.nodes.set(e,new K({...t,name:e})),this}addEdge(e,t){return this.edges.set(e,t),this}setNodeType(e,t){return this.nodeTypeMap.set(e,t),this}addConditionalEdges(e,t,{labels:s}={}){return this.edges.set(e,{conditional:!0,routes:t,labels:s}),typeof t=="function"&&this.conditionalCodeMap.set(e,t.toString()),this}setEntryPoint(e){return this.entryPoint=e,this}use(e){return typeof e=="function"&&this.middleware.push(e),this}_composeMiddleware(e,t,s,i,n){let r=s;for(let a=e.length-1;a>=0;a--){let c=e[a],d=r;r=()=>c(t,d,i,n)}return r()}serialize(){let e=[],t={};for(let[n,r]of this.nodes){let a=this.nodeTypeMap.get(n)||n;e.push({id:n,type:a,data:{nodeType:a,label:n}});let c={};r._isCustomCode&&typeof r.execute=="function"&&(c.customCode=r.execute.toString());let d=this.nodePrompts.get(n);if(d&&(c.prompt=d),typeof r.customExecute=="function"&&(c.executeCode=r.customExecute.toString()),r.outputSchema)try{if(typeof r.outputSchema._def<"u"){let u=ot(r.outputSchema,{target:"openApi3"});c.outputSchema={jsonSchema:u,variables:this._flattenJsonSchemaToVariables(u)}}else c.outputSchema={schema:r.outputSchema}}catch(u){console.warn(`[workflow] failed to convert schema for ${n}:`,u.message)}let h=(this.resolvedToolsMap||{})[n];h?.toolIds&&(c.tools=h.toolIds),Object.keys(c).length>0&&(t[n]=c)}let s=[];for(let[n,r]of this.edges)if(typeof r=="string")s.push({source:n,target:r});else if(r.conditional){let a=this.conditionalCodeMap.get(n)||r.routes.toString(),c=this._inferConditionalTargets(r.routes),d=r.labels||{};for(let h of c){let u={source:n,target:h,data:{conditionalCode:a}};d[h]&&(u.label=d[h]),s.push(u)}}let i=null;if(this.stateSchema)try{i=ot(this.stateSchema,{target:"openApi3"})}catch{i=this.stateSchema}return{nodes:e,edges:s,nodeConfigs:t,stateSchema:i}}_inferConditionalTargets(e){let t=e.toString(),s=new Set,i=/return\s+['"]([^'"]+)['"]/g,n;for(;(n=i.exec(t))!==null;)s.add(n[1]);return[...s]}_flattenJsonSchemaToVariables(e,t=""){let s=e;if(e.$ref&&e.definitions){let i=e.$ref.replace("#/definitions/","");s=e.definitions[i]||e}return this._flattenSchema(s,t)}_flattenSchema(e,t=""){if(!e||typeof e!="object")return[];let s=[],i=e.properties||{},n=e.required||[];for(let[r,a]of Object.entries(i)){let c=t?`${t}.${r}`:r;s.push({path:c,type:a.type||"unknown",label:a.description||this._formatLabel(r),optional:!n.includes(r)}),a.type==="object"&&a.properties&&s.push(...this._flattenSchema(a,c)),a.type==="array"&&a.items?.type==="object"&&a.items.properties&&s.push(...this._flattenSchema(a.items,`${c}[]`))}return s}_formatLabel(e){return e.replace(/([A-Z])/g," $1").replace(/^./,t=>t.toUpperCase()).trim()}_summarizeNodeOutput(e,t){if(!t||typeof t!="object")return[];let s=[];t.success!==void 0&&s.push(`Result: ${t.success?"passed":"failed"}`);for(let[i,n]of Object.entries(t))if(!(i==="success"||i==="raw"||i==="nextNode")){if(typeof n=="string"&&n.length<=80)s.push(`${i}: ${n}`);else if(Array.isArray(n)){let r=n.length,a=n.filter(d=>d?.passed===!0).length,c=n.some(d=>d?.passed!==void 0);s.push(c?`${i}: ${a}/${r} passed${r-a?`, ${r-a} failed`:""}`:`${i}: ${r} items`)}if(s.length>=4)break}return s}async run(e,t={}){if(!this.entryPoint)throw new Error("No entry point set for graph");let s=t.cwd||process.cwd();bt({path:W(s,".env")});let i=t.config||{};if(!i||Object.keys(i).length===0)try{let m=W(s,".zibby.config.js");ye(m)&&(i=(await import(m)).default||{})}catch{}process.env.EXECUTION_ID&&!i.agent?.strictMode&&(i.agent={...i.agent,strictMode:!0});let n=t.agentType;if(!n){let m=i?.agent;m?.provider?n=m.provider:m?.gemini?n="gemini":m?.claude?n="claude":m?.cursor?n="cursor":m?.codex?n="codex":n=process.env.AGENT_TYPE||"cursor"}let r=t.contextConfig||e?.config?.contextConfig||e?.config?.context||i?.context||{};if(this.stateSchema){let m=this.stateSchema.safeParse(t);if(!m.success){let N=m.error.issues.map(x=>`${x.path.join(".")}: ${x.message}`);throw console.error("\u274C Initial state validation failed:"),N.forEach(x=>console.error(` - ${x}`)),new Error(`State validation failed: ${N.join(", ")}`)}I.step("State validated against schema")}let a=it(),c=t.sessionPath||a;c||at();let{sessionPath:d,sessionTimestamp:h,sessionId:u}=lt({cwd:s,config:i,traceFrom:"WorkflowGraph.run",initialState:{sessionPath:c,sessionTimestamp:t.sessionTimestamp}});I.step(`Session ${u}`);let l=await z.loadContext(t.specPath||"",s,r);Object.keys(l).length>0&&I.step(`Context loaded: ${Object.keys(l).join(", ")}`);let g=t.outputPath;!g&&t.specPath&&(e?.calculateOutputPath?g=e.calculateOutputPath(t.specPath):console.warn(`\u26A0\uFE0F outputPath not resolved (specPath=${t.specPath})`));let p=new j({...t,config:i,agentType:n,outputPath:g,sessionPath:d,sessionTimestamp:h,context:l,resolvedTools:this.resolvedToolsMap||{}}),S=new Map;try{await import("@zibby/skills")}catch{}let{getSkill:y}=await Promise.resolve().then(()=>(H(),He)),$=new Set;for(let[,m]of this.nodes)for(let N of m.config?.skills||[])$.add(N);for(let m of $){let N=y(m);if(typeof N?.middleware=="function")try{let x=await N.middleware();typeof x=="function"&&S.set(m,x)}catch{}}let f=this.entryPoint,w=[];for(;f&&f!=="END";){let m=W(d,pe);if(ye(m)){console.warn(`
37
+ \u{1F6D1} Studio stop requested \u2014 ending workflow.`);try{Ct(m)}catch{}if(e&&typeof e.cleanup=="function")try{await e.cleanup()}catch{}return I.step("Workflow stopped by Studio"),{success:!0,state:p.getAll(),executionLog:w,stoppedByStudio:!0}}let N=this.nodes.get(f);if(!N)throw new Error(`Node '${f}' not found in graph`);let x=JSON.stringify({sessionPath:d,sessionTimestamp:h,currentNode:f,createdAt:new Date().toISOString(),config:p.get("config")}),ht=W(d,b);tt(ht,x,"utf-8");let Ne=p.get("config")?.paths?.output||Y,mt=W(s,Ne,b);st(W(s,Ne),{recursive:!0});try{tt(mt,x,"utf-8")}catch{}let Te=t.onPipelineProgress;if(typeof Te=="function")try{Te({cwd:s,sessionPath:d,sessionId:u,outputBase:p.get("config")?.paths?.output||Y,currentNode:f})}catch{}let gt=(this.resolvedToolsMap||{})[f]||null;p.set("_currentNodeTools",gt);let St=p.get("nodeConfigs")||{};p.set("_currentNodeConfig",St[f]||{}),I.nodeStart(f);let ve=Date.now(),Q=this.nodePrompts.get(f);if(!this._invokeAgent){let O=await Promise.resolve().then(()=>(F(),V));this._invokeAgent=O.invokeAgent}let ke=this._invokeAgent,xe={state:p,invokeAgent:async(O={},A={})=>{let T=A.prompt||"";if(Q)try{T=Pt.compile(Q,{noEscape:!0})(O)}catch(C){throw console.error(`\u274C Template rendering failed for node '${f}':`,C.message),new Error(`Template rendering failed: ${C.message}`,{cause:C})}else if(!T)throw new Error(`No prompt template configured for node '${f}' and no prompt provided in options`);return ke(T,{state:p.getAll(),images:A.images||[]},{model:A.model||p.get("model"),workspace:p.get("workspace"),schema:A.schema,...A})},_coreInvokeAgent:ke,agent:e,nodeId:f,promptTemplate:Q,getPromptTemplate:()=>Q,...p.getAll()};try{let O=(N.config?.skills||[]).map(M=>S.get(M)).filter(Boolean),A=[...this.middleware,...O],T;A.length>0?T=await this._composeMiddleware(A,f,async()=>N.execute(xe,p),p.getAll(),p):T=await N.execute(xe,p);let C=Date.now()-ve;if(w.push({node:f,success:T.success,duration:C,timestamp:new Date().toISOString()}),!T.success){if(String(T.error||"").includes("Stopped from Zibby Studio")){if(I.step("Workflow stopped by Studio"),p.set("stoppedByStudio",!0),e&&typeof e.cleanup=="function")try{await e.cleanup()}catch{}return{success:!0,state:p.getAll(),executionLog:w,stoppedByStudio:!0}}p.append("errors",{node:f,error:T.error});let Oe=N.config?.retries||0,Ae=`${f}_retries`,te=p.getAll()[Ae]||0;if(te<Oe){I.stepInfo(`Retrying (attempt ${te+1}/${Oe})`),p.update({[Ae]:te+1,[`${f}_raw`]:T.raw});continue}throw I.nodeFailed(f,T.error,{duration:C}),new Error(`Node '${f}' failed after ${te} attempts: ${T.error}`)}p.update({[f]:T.output});let wt=this._summarizeNodeOutput(f,T.output);I.nodeComplete(f,{duration:C,details:wt});let ee=this.edges.get(f);if(!ee)f="END";else if(ee.conditional){let M=ee.routes(p.getAll());I.route(f,M),f=M}else f=ee}catch(O){throw I.isInsideNode&&I.nodeFailed(f,O.message,{duration:Date.now()-ve}),p.set("failed",!0),p.set("failedAt",f),O}}I.graphComplete();let k={success:!0,state:p.getAll(),executionLog:w};return e&&typeof e.onComplete=="function"&&await e.onComplete(k),k}};var X=new Map;function ut(o,e){X.set(o,e)}function _e(o){return X.get(o)}function re(o){return X.has(o)}function Wt(){return Array.from(X.keys())}function $e(o){let e=X.get(o);return e?e.factory&&typeof e.create=="function"?e.create.toString():typeof e.execute=="function"?e.execute.toString():typeof e=="function"?e.toString():null:null}ut("ai_agent",{name:"ai_agent",factory:!0,create:(o,e={})=>({name:o,_isCustomCode:!0,execute:async t=>{let s=t?._coreInvokeAgent;s||(s=(await Promise.resolve().then(()=>(F(),V))).invokeAgent);let i=e.extraPromptInstructions||"Execute the task based on the current state.",n=Bt(i,t),r=await s(n,{cwd:t.workspace||process.cwd(),model:t.model,tools:e.resolvedTools||null});return{success:!0,output:{raw:r,nodeId:o},raw:typeof r=="string"?r:r.raw}}})});function Bt(o,e){let t=/@([\w.]+)/g,s=new Set,i;for(;(i=t.exec(o))!==null;)s.add(i[1]);if(s.size===0)return o;let n=[],r=new Set;for(let a of s){let c=a.split(".")[0];if(r.has(c))continue;let d=a.split(".").reduce((l,g)=>l?.[g],e);if(d===void 0)continue;let h=typeof d=="string"?d:d?.raw??JSON.stringify(d,null,2),u=a.replace(/_/g," ").replace(/\b\w/g,l=>l.toUpperCase());n.push(`## ${u}
38
+ ${h}`),a.includes(".")||r.add(c)}return n.length===0?o:`${o}
39
+
40
+ ---
41
+ # Referenced Context
42
+
43
+ ${n.join(`
44
+
45
+ `)}`}H();B();var ne={};function Ie(o,e){if(Array.isArray(e))return Ee(e);let t=ne[o];return!t||t.length===0?null:Ee(t)}function Ee(o){if(!Array.isArray(o)||o.length===0)return null;let e=[],t={},s=[];for(let i of o){let n=D(i);if(!n){_.warn(`[workflow] unknown skill "${i}" \u2014 skipping`);continue}s.push(i);for(let r of n.tools||[])e.push({name:r.name,description:r.description,input_schema:r.input_schema||{type:"object",properties:{}}});if(!t[n.serverName])if(typeof n.resolve=="function"){let r=n.resolve();r&&(t[n.serverName]={...r,toolPrefix:i})}else{let r={};for(let a of n.envKeys||[]){let c=process.env[a];c&&(r[a]=c)}t[n.serverName]={command:n.command,args:[...n.args||[]],env:r,toolPrefix:i}}}return s.length===0?null:{toolIds:s,claudeTools:e,mcpServers:t}}B();function Lt(o,e={}){let{nodes:t,edges:s,nodeConfigs:i={}}=o;if(!Array.isArray(t)||t.length===0)throw new v("Graph must have at least one node");if(!Array.isArray(s))throw new v("Graph edges must be an array");let n=new q(e);e.stateSchema&&n.setStateSchema(e.stateSchema);let r=new Set,a=new Map,c={};for(let l of t){let g=ie(l);a.set(l.id,{...l,resolvedType:g}),g==="decision"&&r.add(l.id)}for(let[l,g]of a){if(r.has(l))continue;let p=g.resolvedType,S=i[l]||{},y=Ie(p,S.tools);y&&(c[l]=y);let $={};S.prompt&&($.prompt=S.prompt);let f=re(p);if(_.debug(`[workflow] compiler: node "${l}" type="${p}" registered=${f}`),S.customCode&&!f)n.addNode(l,pt(l,S.customCode,S),$),n.setNodeType(l,p);else if(f){let w=_e(p);w.factory?n.addNode(l,w.create(l,{...S,resolvedTools:y}),$):n.addNode(l,w,$),n.setNodeType(l,p)}else if(S.executeCode)n.addNode(l,pt(l,S.executeCode,S),$),n.setNodeType(l,p);else throw new v(`Unknown node type "${p}" for node "${l}". Did you forget to register it?`)}n.resolvedToolsMap=c;let d=new Set;for(let l of s)r.has(l.target)||d.add(l.target);let h=t.find(l=>!r.has(l.id)&&!d.has(l.id));if(!h)throw new v("Could not determine entry point: no node without incoming edges found");n.setEntryPoint(h.id);let u=Mt(s,"source");for(let l of s)if(!r.has(l.source))if(r.has(l.target)){let g=l.target,p=u.get(g)||[];if(p.length===0)throw new v(`Decision node "${g}" has no outgoing edges`);let S=jt(g,p,r);n.addConditionalEdges(l.source,S)}else n.addEdge(l.source,l.target);return n}function Dt(o){let e=[];if(!o||typeof o!="object")return{valid:!1,errors:["Config must be a non-null object"]};if((!Array.isArray(o.nodes)||o.nodes.length===0)&&e.push("Graph must have at least one node"),Array.isArray(o.edges)||e.push("Graph edges must be an array"),e.length>0)return{valid:!1,errors:e};let t=o.nodeConfigs||{};for(let a of o.nodes){let c=ie(a);if(c==="decision"||re(c))continue;let d=t[a.id]||{};d.customCode||d.executeCode||e.push(`Unknown node type "${c}" for node "${a.id}". Register it or provide customCode/executeCode.`)}let s=new Set(o.nodes.map(a=>a.id));for(let a of o.edges)s.has(a.source)||e.push(`Edge references unknown source node "${a.source}"`),s.has(a.target)||e.push(`Edge references unknown target node "${a.target}"`);let i=new Set(o.nodes.filter(a=>ie(a)==="decision").map(a=>a.id)),n=new Set;for(let a of o.edges)i.has(a.target)||n.add(a.target);let r=o.nodes.filter(a=>!i.has(a.id)&&!n.has(a.id));r.length===0?e.push("No entry point found (every node has incoming edges)"):r.length>1&&e.push(`Multiple entry points found: ${r.map(a=>a.id).join(", ")}`);for(let a of i){let c=o.edges.filter(h=>h.source===a);c.length===0&&e.push(`Decision node "${a}" has no outgoing edges`),c.some(h=>h.data?.conditionalCode||h.conditionalCode)||e.push(`Decision node "${a}" outgoing edges have no conditionalCode`)}return{valid:e.length===0,errors:e}}function Ft(o){return!o||!Array.isArray(o.nodes)?[]:o.nodes.filter(e=>ie(e)!=="decision").map(e=>e.id)}function ie(o){let e=o.data?.nodeType||o.data?.type||o.type;return e==="workflowNode"||e==="custom"||e==="default"?o.id:e}function Mt(o,e){let t=new Map;for(let s of o){let i=s[e];t.has(i)||t.set(i,[]),t.get(i).push(s)}return t}function jt(o,e,t){let s=e.find(a=>a.data?.conditionalCode||a.conditionalCode);if(!s)throw new v(`Decision node "${o}" has no conditionalCode on its outgoing edges`);let i=s.data?.conditionalCode||s.conditionalCode,n=new Set(e.map(a=>a.target).filter(a=>!t.has(a))),r;try{let c=new Function(`return (${i})`)();r=d=>{let h=c(d);return n.has(h)||_.warn(`[workflow] conditional route from "${o}" returned "${h}" which is not in valid targets: ${[...n].join(", ")}`),h}}catch(a){throw new v(`Failed to compile conditionalCode for "${o}": ${a.message}`)}return r}function pt(o,e,t={}){let s;try{s=new Function("invokeAgent","require","console",`return (${e})`)}catch(r){throw new v(`Failed to compile customCode for node "${o}": ${r.message}`)}let i=s(async(...r)=>{let{invokeAgent:a}=await Promise.resolve().then(()=>(F(),V));return a(...r)},typeof ae<"u"?ae:void 0,console),n=null;return t.outputSchema&&(n=t.outputSchema.jsonSchema||t.outputSchema),{name:o,_isCustomCode:!0,outputSchema:n,execute:async r=>{try{let a=await i(r);return typeof a=="object"&&"success"in a?a:{success:!0,output:a,raw:null}}catch(a){return{success:!1,error:a.message,raw:null}}}}}var v=class extends Error{constructor(e){super(e),this.name="CompilationError"}};H();he();F();function Ut(o,e={}){let{nodes:t,edges:s,nodeConfigs:i={}}=o,n=new Set,r=[],a=new Map;for(let y of t){let $=y.data?.nodeType||y.type;a.set(y.id,$),$==="decision"?n.add(y.id):r.push({id:y.id,nodeType:$,label:y.data?.label||y.id})}let c=r.some(y=>{let $=i[y.id]||{};return!$.customCode&&!$.executeCode}),{toolsPerNode:d,toolIdsByVar:h}=zt(r,i),{simpleEdges:u,conditionalEdges:l}=qt(s,n),g=Xt(r,s,n),p=[],S=e.workflowType||"workflow";return p.push(Zt(e)),p.push(Yt(S,{usesRegisteredNodes:c})),p.push(Jt(h)),p.push(Ht(S)),p.push(Vt(r,i)),p.push(Kt(r,g,u,l,d,S)),p.filter(Boolean).join(`
46
+ `)}function Gt(o){let e={};for(let[t,s]of Object.entries(o)){let{tools:i,...n}=s;Object.keys(n).length>0&&(e[t]=n)}return e}function Zt(o){let e=o.workflowType||"workflow";return["// Generated workflow",`// ${o.projectId?`Project: ${o.projectId} | `:""}Type: ${e} | Version: ${o.version??0}`,`// Downloaded: ${new Date().toISOString()}`,""].join(`
47
+ `)}function Yt(o,{usesRegisteredNodes:e=!0}={}){let t=["import { WorkflowGraph, invokeAgent, getResolvedToolDefinitions } from '@zibby/agent-workflow';"];return e&&t.push("// import './register-nodes.js'; // register custom node types here"),t.push("import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'node:fs';","import { join, dirname } from 'node:path';","import { fileURLToPath } from 'node:url';",""),t.join(`
48
+ `)}function Jt(o){if(o.size===0)return"";let e=["// \u2500\u2500 Tool Bindings \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"];for(let[t,s]of o)e.push(`const ${t} = getResolvedToolDefinitions(${JSON.stringify(s)}); // ${s.join(", ")}`);return e.push(""),e.join(`
49
+ `)}function Ht(o){return["// \u2500\u2500 Node Configs \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500","const __filename = fileURLToPath(import.meta.url);","const __dirname = dirname(__filename);",`const configPath = join(__dirname, 'workflow-${o}.config.json');`,"const nodeConfigs = existsSync(configPath) ? JSON.parse(readFileSync(configPath, 'utf-8')) : {};",""].join(`
50
+ `)}function Vt(o,e){let t=["// \u2500\u2500 Node Implementations \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500",""];for(let s of o){let i=ft(s.id),n=e[s.id]?.customCode;if(n)t.push(`// @custom \u2014 modified from default "${s.nodeType}" template`),t.push(`const ${i}_execute = ${n};`);else{let r=$e(s.nodeType);r?(t.push(`// Default "${s.nodeType}" implementation`),t.push(`const ${i}_execute = ${r};`)):(t.push(`// No template for "${s.nodeType}" \u2014 passthrough`),t.push(`const ${i}_execute = async (state) => ({ success: true, output: {}, raw: null });`))}t.push("")}return t.join(`
51
+ `)}function Kt(o,e,t,s,i,n){let r=["// \u2500\u2500 Graph Builder \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"];r.push("export function buildGraph(options = {}) {"),r.push(" const graph = new WorkflowGraph(options);",""),r.push(" // Nodes");for(let c of o){let d=ft(c.id);r.push(` graph.addNode('${c.id}', { name: '${c.id}', execute: ${d}_execute });`),r.push(` graph.setNodeType('${c.id}', '${c.nodeType}');`)}r.push("",` graph.setEntryPoint('${e}');`,""),(t.length>0||s.length>0)&&r.push(" // Edges");for(let c of t)r.push(` graph.addEdge('${c.source}', '${c.target}');`);for(let c of s){let d=c.code.split(`
52
+ `).map((h,u)=>u===0?h:` ${h}`).join(`
53
+ `);r.push(` graph.addConditionalEdges('${c.source}', ${d});`)}let a=[];for(let c of o){let d=i.get(c.id);d&&a.push(` '${c.id}': ${d},`)}return a.length>0&&r.push(""," graph.resolvedToolsMap = {",...a," };"),r.push(""," return graph;","}",""),r.push("export { nodeConfigs };",""),r.join(`
54
+ `)}function zt(o,e){let t=new Map,s=new Map;for(let i of o){let n=e[i.id]?.tools,r;if(Array.isArray(n)&&n.length>0)r=[...n].sort();else{let a=ne[i.nodeType];a?.length>0&&(r=[...a].sort())}if(r){let a=`${r.map(c=>c.replace(/[^a-zA-Z0-9]/g,"")).join("And")}Tools`;t.set(i.id,a),s.has(a)||s.set(a,r)}}return{toolsPerNode:t,toolIdsByVar:s}}function qt(o,e){let t=[],s=[],i=new Map,n=new Set;for(let r of o)i.has(r.source)||i.set(r.source,[]),i.get(r.source).push(r);for(let r of o)if(!e.has(r.source))if(e.has(r.target)){if(n.has(r.target))continue;n.add(r.target);let c=(i.get(r.target)||[]).find(d=>d.data?.conditionalCode||d.conditionalCode);c&&s.push({source:r.source,code:c.data?.conditionalCode||c.conditionalCode})}else t.push({source:r.source,target:r.target});return{simpleEdges:t,conditionalEdges:s}}function Xt(o,e,t){let s=new Set;for(let n of e)t.has(n.target)||s.add(n.target);let i=o.find(n=>!s.has(n.id));return i?i.id:o[0]?.id}function ft(o){return o.replace(/[^a-zA-Z0-9]/g,"_")}B();export{J as AgentStrategy,fe as CI_ENV_VARS,v as CompilationError,K as ConditionalNode,z as ContextLoader,Y as DEFAULT_OUTPUT_BASE,vt as EVENTS_FILE,ne as NODE_DEFAULT_TOOLS,R as Node,U as OutputParser,Tt as RAW_OUTPUT_FILE,Nt as RESULT_FILE,ue as SESSIONS_DIR,b as SESSION_INFO_FILE,kt as SKILLS,pe as STUDIO_STOP_REQUEST_FILE,$t as SchemaTypes,se as Timeline,je as WORKFLOW_GRAPH_LOG_MARKER_PREFIX,q as WorkflowGraph,j as WorkflowState,at as clearInheritedSessionEnvForFreshRun,Je as clearSkills,Lt as compileGraph,Ft as extractSteps,Gt as generateNodeConfigsJson,Ut as generateWorkflowCode,dt as generateWorkflowSessionId,me as getAgentStrategy,Ze as getAllSkills,_e as getNodeImpl,$e as getNodeTemplate,Ee as getResolvedToolDefinitions,D as getSkill,re as hasNode,Ge as hasSkill,ze as invokeAgent,Wt as listNodeTypes,Ye as listSkillIds,Ke as listStrategies,it as readStudioPinnedSessionPathFromEnv,ut as registerNode,Ue as registerSkill,Ve as registerStrategy,Ie as resolveNodeTools,lt as resolveWorkflowSession,Et as setLogger,nt as shouldTrustInheritedSessionEnv,ct as syncProcessEnvToSession,I as timeline,Dt as validateGraphConfig};
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Replace the framework logger.
3
+ * @param {{ debug?, info?, warn?, error? }} impl
4
+ */
5
+ export function setLogger(impl: {
6
+ debug?: any;
7
+ info?: any;
8
+ warn?: any;
9
+ error?: any;
10
+ }): void;
11
+ export namespace logger {
12
+ function debug(...args: any[]): void;
13
+ function info(...args: any[]): void;
14
+ function warn(...args: any[]): void;
15
+ function error(...args: any[]): void;
16
+ }
package/dist/logger.js ADDED
@@ -0,0 +1 @@
1
+ var e=()=>{},n={debug:e,info:e,warn:(...o)=>console.warn("[workflow]",...o),error:(...o)=>console.error("[workflow]",...o)},r={impl:n};function l(o){r.impl={...n,...o}}var t={debug:(...o)=>r.impl.debug?.(...o),info:(...o)=>r.impl.info?.(...o),warn:(...o)=>r.impl.warn?.(...o),error:(...o)=>r.impl.error?.(...o)};export{t as logger,l as setLogger};
@@ -0,0 +1,5 @@
1
+ export function registerNode(type: any, impl: any): void;
2
+ export function getNodeImpl(type: any): any;
3
+ export function hasNode(type: any): boolean;
4
+ export function listNodeTypes(): any[];
5
+ export function getNodeTemplate(type: any): any;
@@ -0,0 +1,20 @@
1
+ var O=Object.defineProperty;var w=(e,t)=>()=>(e&&(t=e(e=0)),t);var C=(e,t)=>{for(var n in t)O(e,n,{get:t[n],enumerable:!0})};var h,E=w(()=>{h=class{constructor(t,n,r=0){this.name=t,this.description=n,this.priority=r}async invoke(t,n={}){throw new Error(`${this.constructor.name}.invoke() must be implemented`)}canHandle(t){throw new Error(`${this.constructor.name}.canHandle() must be implemented`)}getName(){return this.name}getDescription(){return this.description}getPriority(){return this.priority}}});var S,P,k,y,v=w(()=>{S=()=>{},P={debug:S,info:S,warn:(...e)=>console.warn("[workflow]",...e),error:(...e)=>console.error("[workflow]",...e)},k={impl:P},y={debug:(...e)=>k.impl.debug?.(...e),info:(...e)=>k.impl.info?.(...e),warn:(...e)=>k.impl.warn?.(...e),error:(...e)=>k.impl.error?.(...e)}});function A(e){return R.get(e)||null}var R,b=w(()=>{R=new Map});var T={};C(T,{getAgentStrategy:()=>_,invokeAgent:()=>L,listStrategies:()=>j,registerStrategy:()=>M});function M(e){if(!(e instanceof h))throw new Error("strategy must be an instance of AgentStrategy");let t=c.findIndex(n=>n.getName()===e.getName());t>=0?c[t]=e:c.push(e)}function j(){return c.map(e=>e.getName())}function _(e={}){let{state:t={},preferredAgent:n=null}=e,r=n||t.agentType||process.env.AGENT_TYPE;if(!r){let o=c.map(s=>s.getName()).join(", ")||"none registered";throw new Error(`No agent specified. Set agentType in state or AGENT_TYPE env var. Available: ${o}`)}y.debug(`[workflow] agent selection: requested=${r}`);let i=c.find(o=>o.getName()===r);if(!i){let o=c.map(s=>s.getName()).join(", ")||"none registered";throw new Error(`Unknown agent '${r}'. Available: ${o}`)}if(!i.canHandle(e))throw new Error(`Agent '${r}' is not available in this environment. Check credentials/environment.`);return y.debug(`[workflow] using agent: ${i.getName()}`),i}async function L(e,t={},n={}){let r=_(t),i=t.state?.config||n.config||{},o=i.models||{},s=n.nodeName&&o[n.nodeName]||null,a=o.default||null,p=i.agent?.[r.name]?.model||null,l=s||a||p||n.model||null,m={...n,model:l,workspace:t.state?.workspace||n.workspace,schema:n.schema||t.schema,images:n.images||t.images||[],skills:n.skills||t.skills||[],config:i},u=e,g=m.skills||[];if(g.length>0&&!n.skipPromptFragments){let N=g.map(I=>{let x=A(I)?.promptFragment;return typeof x=="function"?x():x}).filter(Boolean);N.length>0&&(u+=`
2
+
3
+ ${N.join(`
4
+
5
+ `)}`)}let d=t.state?._currentNodeConfig?.extraPromptInstructions?.trim();return d&&(u+=`
6
+
7
+ \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
8
+ PRIORITY OVERRIDE \u2014 THE FOLLOWING INSTRUCTIONS TAKE PRECEDENCE OVER ALL PREVIOUS CONTENT
9
+ \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
10
+
11
+ ${d}
12
+ `),y.debug(`[workflow] prompt length: ${u.length} chars`),r.invoke(u,m)}var c,$=w(()=>{E();v();b();c=[]});var f=new Map;function H(e,t){f.set(e,t)}function B(e){return f.get(e)}function J(e){return f.has(e)}function K(){return Array.from(f.keys())}function W(e){let t=f.get(e);return t?t.factory&&typeof t.create=="function"?t.create.toString():typeof t.execute=="function"?t.execute.toString():typeof t=="function"?t.toString():null:null}H("ai_agent",{name:"ai_agent",factory:!0,create:(e,t={})=>({name:e,_isCustomCode:!0,execute:async n=>{let r=n?._coreInvokeAgent;r||(r=(await Promise.resolve().then(()=>($(),T))).invokeAgent);let i=t.extraPromptInstructions||"Execute the task based on the current state.",o=U(i,n),s=await r(o,{cwd:n.workspace||process.cwd(),model:n.model,tools:t.resolvedTools||null});return{success:!0,output:{raw:s,nodeId:e},raw:typeof s=="string"?s:s.raw}}})});function U(e,t){let n=/@([\w.]+)/g,r=new Set,i;for(;(i=n.exec(e))!==null;)r.add(i[1]);if(r.size===0)return e;let o=[],s=new Set;for(let a of r){let p=a.split(".")[0];if(s.has(p))continue;let l=a.split(".").reduce((g,d)=>g?.[d],t);if(l===void 0)continue;let m=typeof l=="string"?l:l?.raw??JSON.stringify(l,null,2),u=a.replace(/_/g," ").replace(/\b\w/g,g=>g.toUpperCase());o.push(`## ${u}
13
+ ${m}`),a.includes(".")||s.add(p)}return o.length===0?e:`${e}
14
+
15
+ ---
16
+ # Referenced Context
17
+
18
+ ${o.join(`
19
+
20
+ `)}`}export{B as getNodeImpl,W as getNodeTemplate,J as hasNode,K as listNodeTypes,H as registerNode};
package/dist/node.d.ts ADDED
@@ -0,0 +1,34 @@
1
+ export class Node {
2
+ constructor(config: any);
3
+ config: any;
4
+ name: any;
5
+ prompt: any;
6
+ outputSchema: any;
7
+ isZodSchema: boolean;
8
+ parser: OutputParser;
9
+ retries: any;
10
+ onComplete: any;
11
+ customExecute: any;
12
+ execute(context: any, state: any): Promise<{
13
+ success: boolean;
14
+ error: any;
15
+ raw: any;
16
+ output?: undefined;
17
+ } | {
18
+ success: boolean;
19
+ output: any;
20
+ raw: any;
21
+ error?: undefined;
22
+ }>;
23
+ }
24
+ export class ConditionalNode extends Node {
25
+ condition: any;
26
+ execute(context: any, state: any): Promise<{
27
+ success: boolean;
28
+ output: {
29
+ nextNode: any;
30
+ };
31
+ raw: any;
32
+ }>;
33
+ }
34
+ import { OutputParser } from './output-parser.js';
package/dist/node.js ADDED
@@ -0,0 +1,29 @@
1
+ var ot=Object.defineProperty;var k=(r,t)=>()=>(r&&(t=r(r=0)),t);var st=(r,t)=>{for(var e in t)ot(r,e,{get:t[e],enumerable:!0})};var M,it,W,c,R=k(()=>{M=()=>{},it={debug:M,info:M,warn:(...r)=>console.warn("[workflow]",...r),error:(...r)=>console.error("[workflow]",...r)},W={impl:it},c={debug:(...r)=>W.impl.debug?.(...r),info:(...r)=>W.impl.info?.(...r),warn:(...r)=>W.impl.warn?.(...r),error:(...r)=>W.impl.error?.(...r)}});var b,Z=k(()=>{b=class{constructor(t,e,o=0){this.name=t,this.description=e,this.priority=o}async invoke(t,e={}){throw new Error(`${this.constructor.name}.invoke() must be implemented`)}canHandle(t){throw new Error(`${this.constructor.name}.canHandle() must be implemented`)}getName(){return this.name}getDescription(){return this.description}getPriority(){return this.priority}}});function V(r){return ut.get(r)||null}var ut,Y=k(()=>{ut=new Map});var q={};st(q,{getAgentStrategy:()=>z,invokeAgent:()=>pt,listStrategies:()=>lt,registerStrategy:()=>ct});function ct(r){if(!(r instanceof b))throw new Error("strategy must be an instance of AgentStrategy");let t=S.findIndex(e=>e.getName()===r.getName());t>=0?S[t]=r:S.push(r)}function lt(){return S.map(r=>r.getName())}function z(r={}){let{state:t={},preferredAgent:e=null}=r,o=e||t.agentType||process.env.AGENT_TYPE;if(!o){let n=S.map(a=>a.getName()).join(", ")||"none registered";throw new Error(`No agent specified. Set agentType in state or AGENT_TYPE env var. Available: ${n}`)}c.debug(`[workflow] agent selection: requested=${o}`);let i=S.find(n=>n.getName()===o);if(!i){let n=S.map(a=>a.getName()).join(", ")||"none registered";throw new Error(`Unknown agent '${o}'. Available: ${n}`)}if(!i.canHandle(r))throw new Error(`Agent '${o}' is not available in this environment. Check credentials/environment.`);return c.debug(`[workflow] using agent: ${i.getName()}`),i}async function pt(r,t={},e={}){let o=z(t),i=t.state?.config||e.config||{},n=i.models||{},a=e.nodeName&&n[e.nodeName]||null,g=n.default||null,p=i.agent?.[o.name]?.model||null,w=a||g||p||e.model||null,$={...e,model:w,workspace:t.state?.workspace||e.workspace,schema:e.schema||t.schema,images:e.images||t.images||[],skills:e.skills||t.skills||[],config:i},s=r,h=$.skills||[];if(h.length>0&&!e.skipPromptFragments){let y=h.map(I=>{let E=V(I)?.promptFragment;return typeof E=="function"?E():E}).filter(Boolean);y.length>0&&(s+=`
2
+
3
+ ${y.join(`
4
+
5
+ `)}`)}let f=t.state?._currentNodeConfig?.extraPromptInstructions?.trim();return f&&(s+=`
6
+
7
+ \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
8
+ PRIORITY OVERRIDE \u2014 THE FOLLOWING INSTRUCTIONS TAKE PRECEDENCE OVER ALL PREVIOUS CONTENT
9
+ \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
10
+
11
+ ${f}
12
+ `),c.debug(`[workflow] prompt length: ${s.length} chars`),o.invoke(s,$)}var S,X=k(()=>{Z();R();Y();S=[]});var N=class{constructor(t){this.schema=t}parse(t){let e=t.match(/```json\s*([\s\S]*?)\s*```/);if(e)return this.validate(JSON.parse(e[1]));let o=t.match(/\{[\s\S]*\}/);return o?this.validate(JSON.parse(o[0])):this.validate({result:t.trim()})}validate(t){let e=[];for(let[o,i]of Object.entries(this.schema)){if(i.required&&!(o in t)&&e.push(`Missing required field: ${o}`),o in t&&i.type){let n=typeof t[o];n!==i.type&&e.push(`Field '${o}' expected ${i.type}, got ${n}`)}if(i.validate&&o in t){let n=i.validate(t[o]);n&&e.push(`Field '${o}': ${n}`)}}if(e.length>0)throw new Error(`Output validation failed:
13
+ ${e.join(`
14
+ `)}`);return t}};R();import{writeFileSync as C,readFileSync as Q,existsSync as tt,mkdirSync as dt}from"node:fs";import{join as P,dirname as ht}from"node:path";import u from"chalk";var nt="__WORKFLOW_GRAPH_LOG__",O=u.gray("\u2502"),at=u.gray("\u250C"),D=u.gray("\u2514"),A=u.green("\u25C6"),U=u.hex("#c084fc")("\u25C6"),j=u.hex("#2dd4bf")("\u25C6"),L=u.red("\u25C6"),G=`${O} `,J=2;function H(r){return r<1e3?`${r}ms`:`${(r/1e3).toFixed(1)}s`}function B(r,t){return(e,o,i)=>{if(typeof e!="string")return r(e,o,i);let n=process.stdout.columns||120,a="";for(let g=0;g<e.length;g++){let p=e[g];t.lineStart&&(a+=G,t.col=J,t.lineStart=!1),p===`
15
+ `?(a+=p,t.lineStart=!0,t.col=0,t.inEsc=!1):p==="\x1B"?(t.inEsc=!0,a+=p):t.inEsc?(a+=p,(p>="A"&&p<="Z"||p>="a"&&p<="z")&&(t.inEsc=!1)):(t.col++,a+=p,t.col>=n&&(a+=`
16
+ ${G}`,t.col=J))}return r(a,o,i)}}var T=class{constructor(){this._currentNode=null,this._origStdoutWrite=null,this._origStderrWrite=null;let t=String(process.env.ZIBBY_RUN_SOURCE||"").trim().toLowerCase(),e=String(process.env.ZIBBY_WORKFLOW_GRAPH_LOG_MARKERS||"").trim()==="1";this._emitWorkflowGraphMarkers=e||t==="studio"}get isInsideNode(){return this._currentNode!==null}_startIntercepting(){this._origStdoutWrite=process.stdout.write.bind(process.stdout),this._origStderrWrite=process.stderr.write.bind(process.stderr);let t={lineStart:!0,col:0,inEsc:!1},e={lineStart:!0,col:0,inEsc:!1};this._outState=t,this._errState=e,process.stdout.write=B(this._origStdoutWrite,t),process.stderr.write=B(this._origStderrWrite,e)}_stopIntercepting(){this._origStdoutWrite&&(this._outState&&!this._outState.lineStart&&this._origStdoutWrite(`
17
+ `),process.stdout.write=this._origStdoutWrite),this._origStderrWrite&&(this._errState&&!this._errState.lineStart&&this._origStderrWrite(`
18
+ `),process.stderr.write=this._origStderrWrite),this._origStdoutWrite=null,this._origStderrWrite=null}_rawWrite(t){(this._origStdoutWrite||process.stdout.write.bind(process.stdout))(`${t}
19
+ `)}_emitGraphLogMarker(t){if(!this._emitWorkflowGraphMarkers)return;let e=`${nt}${JSON.stringify(t)}
20
+ `;this._origStdoutWrite?this._origStdoutWrite(e):process.stdout.write(e)}_writeDot(t,e){this._origStdoutWrite?(this._outState&&!this._outState.lineStart&&(this._origStdoutWrite(`
21
+ `),this._outState.lineStart=!0,this._outState.col=0),this._origStdoutWrite(`${t} ${e}
22
+ `)):process.stdout.write.bind(process.stdout)(`${t} ${e}
23
+ `)}step(t){this._origStdoutWrite?this._writeDot(A,t):process.stdout.write.bind(process.stdout)(`${O} ${A} ${t}
24
+ `)}stepInfo(t){this.step(t)}stepTool(t){this._origStdoutWrite?this._writeDot(U,t):process.stdout.write.bind(process.stdout)(`${O} ${U} ${t}
25
+ `)}stepMemory(t){let e=u.hex("#2dd4bf")(t);this._origStdoutWrite?this._writeDot(j,e):process.stdout.write.bind(process.stdout)(`${O} ${j} ${e}
26
+ `)}stepFail(t){this._origStdoutWrite?this._writeDot(L,u.red(t)):process.stdout.write.bind(process.stdout)(`${O} ${L} ${u.red(t)}
27
+ `)}nodeStart(t){this._currentNode=t,this._emitGraphLogMarker({phase:"node_begin",node:t}),this._rawWrite(`${at} ${t}`),this._startIntercepting()}nodeComplete(t,e={}){this._stopIntercepting();let{duration:o,details:i}=e;if(i)for(let a of i)this._rawWrite(`${A} ${a}`);let n=o?u.dim(` ${H(o)}`):"";this._rawWrite(`${D} ${u.green("done")}${n}`),this._emitGraphLogMarker({phase:"node_end",node:t}),this._rawWrite("")}nodeFailed(t,e,o={}){this._stopIntercepting();let{duration:i}=o,n=i?u.dim(` ${H(i)}`):"";this._rawWrite(`${L} ${u.red(e)}`),this._rawWrite(`${D} ${u.red("failed")}${n}`),this._emitGraphLogMarker({phase:"node_end",node:t}),this._rawWrite("")}route(t,e){this._rawWrite(u.dim(` ${t} \u2192 ${e}`)),this._rawWrite("")}graphComplete(){this._rawWrite(u.green.bold("\u2713 Workflow completed"))}},K=new T;var v=".session-info.json";var F=class{constructor(t){if(this.config=t,this.name=t.name,this.prompt=t.prompt,this.outputSchema=t.outputSchema,!this.outputSchema&&!t._isCustomCode)throw new Error(`Node '${this.name}' must define outputSchema (Zod schema). This defines the contract for what the node returns to state.`);this.isZodSchema=this.outputSchema&&typeof this.outputSchema._def<"u",this.parser=t.outputSchema&&!this.isZodSchema?new N(t.outputSchema):null,this.retries=t.retries||0,this.onComplete=t.onComplete,this.customExecute=t.execute}async execute(t,e){let o=()=>e&&typeof e.getAll=="function"?e.getAll():t,i=s=>e&&typeof e.get=="function"?e.get(s):t?.[s];if(typeof this.customExecute=="function"){c.debug(`[workflow] node '${this.name}': custom execute (skipping LLM)`);try{let s=await this.customExecute(t);return typeof s=="object"&&s!==null&&s.success===!1?{success:!1,error:s.error||"Node execution failed",raw:s.raw||null}:this.isZodSchema?(c.debug(`[workflow] node '${this.name}': validating output schema`),{success:!0,output:this.outputSchema.parse(s),raw:null}):{success:!0,output:s,raw:null}}catch(s){return c.error(`[workflow] node '${this.name}' failed: ${s.message}`),s.name==="ZodError"&&c.error(`Schema errors: ${JSON.stringify(s.errors,null,2)}`),{success:!1,error:s.message,raw:null}}}let n=typeof this.prompt=="function"?this.prompt(o()):this.prompt,a=i("_skillHints");a&&(n=`${a}
28
+
29
+ ${n}`);let g=o(),p=g.cwd||process.cwd(),w=g.sessionPath;try{if(w){let s=P(w,v);if(tt(s)){let f=JSON.parse(Q(s,"utf-8"));f.currentNode=this.name,C(s,JSON.stringify(f,null,2),"utf-8")}let h=P(w,"..",v);if(tt(h))try{let f=JSON.parse(Q(h,"utf-8"));f.currentNode=this.name,C(h,JSON.stringify(f,null,2),"utf-8")}catch{}}}catch(s){c.debug(`[workflow] could not update session info: ${s.message}`)}let $=null;for(let s=0;s<=this.retries;s++)try{c.debug(`[workflow] node '${this.name}' attempt ${s}`);let h=o().config||{},f=h.agents||{},y=this.config.agent??f[this.name]??null,I={state:o()};y&&(I.preferredAgent=y);let E={workspace:p,schema:this.isZodSchema?this.outputSchema:null,skills:this.config.skills||[],sessionPath:w,config:h,nodeName:this.name,timeout:this.config?.timeout||3e5},x=t?._coreInvokeAgent;x||(x=(await Promise.resolve().then(()=>(X(),q))).invokeAgent);let m=await x(n,I,E),d,_;if(typeof m=="string"?(d=m,_=null):m.structured?(d=m.raw||JSON.stringify(m.structured,null,2),_=m.structured):(d=m.raw||JSON.stringify(m,null,2),_=m.extracted||null),w)try{let l=P(w,this.name,"raw_stream_output.txt");dt(ht(l),{recursive:!0}),C(l,typeof d=="string"?d:JSON.stringify(d),"utf-8")}catch(l){c.debug(`[workflow] could not save raw output: ${l.message}`)}if(this.isZodSchema&&_){c.info(`[workflow] node '${this.name}': output validated: ${JSON.stringify(_,null,2)}`);let l=_;if(typeof this.onComplete=="function")try{l=await this.onComplete(o(),_)}catch(rt){c.warn(`[workflow] onComplete hook failed: ${rt.message}`)}return{success:!0,output:l,raw:d}}if(typeof this.onComplete=="function")try{return{success:!0,output:await this.onComplete(o(),{raw:d}),raw:d}}catch(l){throw new Error(`onComplete failed: ${l.message}`,{cause:l})}if(this.parser){let l=this.parser.parse(d);return c.info(`[workflow] node '${this.name}': parsed output: ${JSON.stringify(l,null,2)}`),K.step("Output parsed"),{success:!0,output:l,raw:d}}return{success:!0,output:d,raw:d}}catch(h){$=h,s<this.retries&&c.info(`[workflow] node '${this.name}' failed, retrying (${s+1}/${this.retries})\u2026`)}return{success:!1,error:$.message,raw:null}}},et=class extends F{constructor(t){super({...t,_isCustomCode:!0}),this.condition=t.condition}async execute(t,e){let o=e&&typeof e.getAll=="function"?e.getAll():t;return{success:!0,output:{nextNode:this.condition(o)},raw:null}}};export{et as ConditionalNode,F as Node};
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Structured output parsing with schema validation.
3
+ * Similar to LangChain's StructuredOutputParser.
4
+ */
5
+ export class OutputParser {
6
+ constructor(schema: any);
7
+ schema: any;
8
+ parse(text: any): any;
9
+ validate(data: any): any;
10
+ }
11
+ export namespace SchemaTypes {
12
+ export function string(required?: boolean): {
13
+ type: string;
14
+ required: boolean;
15
+ };
16
+ export function number(required?: boolean): {
17
+ type: string;
18
+ required: boolean;
19
+ };
20
+ export function boolean(required?: boolean): {
21
+ type: string;
22
+ required: boolean;
23
+ };
24
+ export function array(required?: boolean): {
25
+ type: string;
26
+ required: boolean;
27
+ validate: (v: any) => string;
28
+ };
29
+ export function _enum(values: any, required?: boolean): {
30
+ type: string;
31
+ required: boolean;
32
+ validate: (v: any) => string;
33
+ };
34
+ export { _enum as enum };
35
+ }
@@ -0,0 +1,3 @@
1
+ var o=class{constructor(e){this.schema=e}parse(e){let i=e.match(/```json\s*([\s\S]*?)\s*```/);if(i)return this.validate(JSON.parse(i[1]));let r=e.match(/\{[\s\S]*\}/);return r?this.validate(JSON.parse(r[0])):this.validate({result:e.trim()})}validate(e){let i=[];for(let[r,n]of Object.entries(this.schema)){if(n.required&&!(r in e)&&i.push(`Missing required field: ${r}`),r in e&&n.type){let s=typeof e[r];s!==n.type&&i.push(`Field '${r}' expected ${n.type}, got ${s}`)}if(n.validate&&r in e){let s=n.validate(e[r]);s&&i.push(`Field '${r}': ${s}`)}}if(i.length>0)throw new Error(`Output validation failed:
2
+ ${i.join(`
3
+ `)}`);return e}},a={string:(t=!0)=>({type:"string",required:t}),number:(t=!0)=>({type:"number",required:t}),boolean:(t=!0)=>({type:"boolean",required:t}),array:(t=!0)=>({type:"object",required:t,validate:e=>Array.isArray(e)?null:"must be an array"}),enum:(t,e=!0)=>({type:"string",required:e,validate:i=>t.includes(i)?null:`must be one of: ${t.join(", ")}`})};export{o as OutputParser,a as SchemaTypes};
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Register a skill definition.
3
+ * @param {Object} skill
4
+ * @param {string} skill.id - Unique identifier (used in node `skills` arrays)
5
+ * @param {string} skill.serverName - MCP server name (key in mcpServers config)
6
+ * @param {string[]} skill.allowedTools - Tool patterns (e.g. ['mcp__playwright__*'])
7
+ * @param {Function} [skill.resolve] - (options?) => { command, args, env? } | null
8
+ * @param {string[]} [skill.envKeys] - Required environment variable names
9
+ * @param {string} [skill.description] - Human-readable description
10
+ * @param {Object[]} [skill.tools] - Tool schemas for compile-time validation
11
+ * @param {string} [skill.cursorKey] - Override key for ~/.cursor/mcp.json
12
+ * @param {Function} [skill.promptFragment] - () => string | string injected into agent prompt
13
+ * @param {Function} [skill.middleware] - async () => middlewareFn | null
14
+ */
15
+ export function registerSkill(skill: {
16
+ id: string;
17
+ serverName: string;
18
+ allowedTools: string[];
19
+ resolve?: Function;
20
+ envKeys?: string[];
21
+ description?: string;
22
+ tools?: any[];
23
+ cursorKey?: string;
24
+ promptFragment?: Function;
25
+ middleware?: Function;
26
+ }): void;
27
+ /** @returns {object|null} */
28
+ export function getSkill(id: any): object | null;
29
+ /** @returns {boolean} */
30
+ export function hasSkill(id: any): boolean;
31
+ /** @returns {Map<string, object>} shallow copy */
32
+ export function getAllSkills(): Map<string, object>;
33
+ /** @returns {string[]} */
34
+ export function listSkillIds(): string[];
35
+ /** Remove all registered skills. Primarily for test teardown. */
36
+ export function clearSkills(): void;
@@ -0,0 +1 @@
1
+ var e=new Map;function r(t){if(!t||typeof t.id!="string")throw new Error("Skill definition must include a string id");e.set(t.id,Object.freeze({...t}))}function n(t){return e.get(t)||null}function i(t){return e.has(t)}function o(){return new Map(e)}function l(){return Array.from(e.keys())}function u(){e.clear()}export{u as clearSkills,o as getAllSkills,n as getSkill,i as hasSkill,l as listSkillIds,r as registerSkill};
@@ -0,0 +1,11 @@
1
+ export class WorkflowState {
2
+ constructor(initialState?: {});
3
+ _state: any;
4
+ _history: any[];
5
+ get(key: any): any;
6
+ set(key: any, value: any): void;
7
+ update(updates: any): void;
8
+ append(key: any, value: any): void;
9
+ getAll(): any;
10
+ rollback(): void;
11
+ }
package/dist/state.js ADDED
@@ -0,0 +1 @@
1
+ var a=new Set(["__proto__","constructor","prototype"]);function i(r){if(a.has(r))throw new Error(`Invalid state key: "${r}"`)}var h=class{constructor(t={}){this._state=Object.create(null),Object.assign(this._state,{messages:[],errors:[],artifacts:{},metadata:{},...t}),this._history=[]}get(t){return this._state[t]}set(t,s){i(t),this._history.push({...this._state}),this._state[t]=s}update(t){let s=Object.getOwnPropertyNames(t);for(let e of s)i(e);this._history.push({...this._state});for(let e of s)this._state[e]=t[e]}append(t,s){i(t),this._history.push({...this._state}),Array.isArray(this._state[t])||(this._state[t]=[]),this._state[t].push(s)}getAll(){return{...this._state}}rollback(){this._history.length>0&&(this._state=this._history.pop())}};export{h as WorkflowState};
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Register an agent strategy. Re-registering by name replaces the existing entry.
3
+ * @param {AgentStrategy} strategy
4
+ */
5
+ export function registerStrategy(strategy: AgentStrategy): void;
6
+ /** @returns {string[]} names of all registered strategies */
7
+ export function listStrategies(): string[];
8
+ /**
9
+ * Resolve the best strategy for the given context.
10
+ * Agent is selected by: context.preferredAgent > state.agentType > AGENT_TYPE env.
11
+ * @param {object} [context]
12
+ * @returns {AgentStrategy}
13
+ */
14
+ export function getAgentStrategy(context?: object): AgentStrategy;
15
+ /**
16
+ * Invoke an agent with automatic strategy selection.
17
+ * @param {string} prompt
18
+ * @param {object} [context]
19
+ * @param {object} [options]
20
+ * @returns {Promise<string | { raw: string, structured: object }>}
21
+ */
22
+ export function invokeAgent(prompt: string, context?: object, options?: object): Promise<string | {
23
+ raw: string;
24
+ structured: object;
25
+ }>;
26
+ import { AgentStrategy } from './agents/base.js';
@@ -0,0 +1,12 @@
1
+ var c=class{constructor(n,t,r=0){this.name=n,this.description=t,this.priority=r}async invoke(n,t={}){throw new Error(`${this.constructor.name}.invoke() must be implemented`)}canHandle(n){throw new Error(`${this.constructor.name}.canHandle() must be implemented`)}getName(){return this.name}getDescription(){return this.description}getPriority(){return this.priority}};var h=()=>{},y={debug:h,info:h,warn:(...e)=>console.warn("[workflow]",...e),error:(...e)=>console.error("[workflow]",...e)},g={impl:y};var m={debug:(...e)=>g.impl.debug?.(...e),info:(...e)=>g.impl.info?.(...e),warn:(...e)=>g.impl.warn?.(...e),error:(...e)=>g.impl.error?.(...e)};var v=new Map;function k(e){return v.get(e)||null}var s=[];function P(e){if(!(e instanceof c))throw new Error("strategy must be an instance of AgentStrategy");let n=s.findIndex(t=>t.getName()===e.getName());n>=0?s[n]=e:s.push(e)}function R(){return s.map(e=>e.getName())}function A(e={}){let{state:n={},preferredAgent:t=null}=e,r=t||n.agentType||process.env.AGENT_TYPE;if(!r){let i=s.map(a=>a.getName()).join(", ")||"none registered";throw new Error(`No agent specified. Set agentType in state or AGENT_TYPE env var. Available: ${i}`)}m.debug(`[workflow] agent selection: requested=${r}`);let o=s.find(i=>i.getName()===r);if(!o){let i=s.map(a=>a.getName()).join(", ")||"none registered";throw new Error(`Unknown agent '${r}'. Available: ${i}`)}if(!o.canHandle(e))throw new Error(`Agent '${r}' is not available in this environment. Check credentials/environment.`);return m.debug(`[workflow] using agent: ${o.getName()}`),o}async function C(e,n={},t={}){let r=A(n),o=n.state?.config||t.config||{},i=o.models||{},a=t.nodeName&&i[t.nodeName]||null,E=i.default||null,N=o.agent?.[r.name]?.model||null,b=a||E||N||t.model||null,u={...t,model:b,workspace:n.state?.workspace||t.workspace,schema:t.schema||n.schema,images:t.images||n.images||[],skills:t.skills||n.skills||[],config:o},l=e,p=u.skills||[];if(p.length>0&&!t.skipPromptFragments){let w=p.map(S=>{let f=k(S)?.promptFragment;return typeof f=="function"?f():f}).filter(Boolean);w.length>0&&(l+=`
2
+
3
+ ${w.join(`
4
+
5
+ `)}`)}let d=n.state?._currentNodeConfig?.extraPromptInstructions?.trim();return d&&(l+=`
6
+
7
+ \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
8
+ PRIORITY OVERRIDE \u2014 THE FOLLOWING INSTRUCTIONS TAKE PRECEDENCE OVER ALL PREVIOUS CONTENT
9
+ \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
10
+
11
+ ${d}
12
+ `),m.debug(`[workflow] prompt length: ${l.length} chars`),r.invoke(l,u)}export{A as getAgentStrategy,C as invokeAgent,R as listStrategies,P as registerStrategy};
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Prefix for machine-readable stdout lines that bound graph-node execution.
3
+ * Plain text (no styling) so external tools can split logs by node.
4
+ * Line format: `${WORKFLOW_GRAPH_LOG_MARKER_PREFIX}${JSON.stringify(payload)}\n`
5
+ * Payload: `{ phase: 'node_begin'|'node_end', node: string }`
6
+ */
7
+ export const WORKFLOW_GRAPH_LOG_MARKER_PREFIX: "__WORKFLOW_GRAPH_LOG__";
8
+ export const timeline: Timeline;
9
+ export default timeline;
10
+ export class Timeline {
11
+ _currentNode: any;
12
+ _origStdoutWrite: any;
13
+ _origStderrWrite: any;
14
+ _emitWorkflowGraphMarkers: boolean;
15
+ get isInsideNode(): boolean;
16
+ _startIntercepting(): void;
17
+ _outState: {
18
+ lineStart: boolean;
19
+ col: number;
20
+ inEsc: boolean;
21
+ };
22
+ _errState: {
23
+ lineStart: boolean;
24
+ col: number;
25
+ inEsc: boolean;
26
+ };
27
+ _stopIntercepting(): void;
28
+ _rawWrite(msg: any): void;
29
+ /** Emit a single-line graph log marker (never chalk). */
30
+ _emitGraphLogMarker(payload: any): void;
31
+ /**
32
+ * Write a milestone dot ON the line. If interceptor is active and we're
33
+ * mid-line, finish that line first so the dot starts on a fresh line.
34
+ */
35
+ _writeDot(dot: any, message: any): void;
36
+ /**
37
+ * Milestone dot ON the line (inside a node) or with pipe prefix (outside).
38
+ */
39
+ step(message: any): void;
40
+ /** Lighter-weight informational step (no special styling). */
41
+ stepInfo(message: any): void;
42
+ stepTool(message: any): void;
43
+ stepMemory(message: any): void;
44
+ stepFail(message: any): void;
45
+ nodeStart(name: any): void;
46
+ nodeComplete(name: any, opts?: {}): void;
47
+ nodeFailed(name: any, error: any, opts?: {}): void;
48
+ route(from: any, to: any): void;
49
+ graphComplete(): void;
50
+ }