@zibby/agent-workflow 0.1.3 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -1
- package/dist/code-generator.js +10 -10
- package/dist/constants.d.ts +14 -1
- package/dist/constants.js +1 -1
- package/dist/graph-compiler.js +21 -21
- package/dist/graph.d.ts +49 -8
- package/dist/graph.js +24 -24
- package/dist/index.d.ts +2 -2
- package/dist/index.js +29 -29
- package/dist/node-registry.js +5 -5
- package/dist/node.js +11 -11
- package/dist/output-parser.js +3 -3
- package/dist/skill-registry.js +1 -1
- package/dist/strategy-registry.js +5 -5
- package/dist/timeline.js +5 -5
- package/dist/tool-resolver.js +1 -1
- package/package.json +1 -1
package/dist/graph.js
CHANGED
|
@@ -1,37 +1,37 @@
|
|
|
1
|
-
var
|
|
1
|
+
var ot=Object.defineProperty;var H=(i,e)=>()=>(i&&(e=i(i=0)),e);var Ne=(i,e)=>{for(var t in e)ot(i,t,{get:e[t],enumerable:!0})};var be,st,J,w,oe=H(()=>{be=()=>{},st={debug:be,info:be,warn:(...i)=>console.warn("[workflow]",...i),error:(...i)=>console.error("[workflow]",...i)},J={impl:st},w={debug:(...i)=>J.impl.debug?.(...i),info:(...i)=>J.impl.info?.(...i),warn:(...i)=>J.impl.warn?.(...i),error:(...i)=>J.impl.error?.(...i)}});var We=H(()=>{});var Me={};Ne(Me,{clearSkills:()=>dt,getAllSkills:()=>lt,getSkill:()=>ae,hasSkill:()=>ct,listSkillIds:()=>ut,registerSkill:()=>at});function at(i){if(!i||typeof i.id!="string")throw new Error("Skill definition must include a string id");L.set(i.id,Object.freeze({...i}))}function ae(i){return L.get(i)||null}function ct(i){return L.has(i)}function lt(){return new Map(L)}function ut(){return Array.from(L.keys())}function dt(){L.clear()}var ie,L,ce=H(()=>{ie=Symbol.for("@zibby/agent-workflow.skills");globalThis[ie]||(globalThis[ie]=new Map);L=globalThis[ie]});var ue={};Ne(ue,{getAgentStrategy:()=>De,invokeAgent:()=>ht,listStrategies:()=>ft,registerStrategy:()=>pt});function pt(i){if(!i||typeof i.getName!="function"||typeof i.invoke!="function")throw new Error("strategy must implement getName() and invoke() (AgentStrategy shape)");let e=C.findIndex(t=>t.getName()===i.getName());e>=0?C[e]=i:C.push(i)}function ft(){return C.map(i=>i.getName())}function De(i={}){let{state:e={},preferredAgent:t=null}=i,r=t||e.agentType||process.env.AGENT_TYPE;if(!r){let s=C.map(n=>n.getName()).join(", ")||"none registered";throw new Error(`No agent specified. Set agentType in state or AGENT_TYPE env var. Available: ${s}`)}w.debug(`[workflow] agent selection: requested=${r}`);let o=C.find(s=>s.getName()===r);if(!o){let s=C.map(n=>n.getName()).join(", ")||"none registered";throw new Error(`Unknown agent '${r}'. Available: ${s}`)}if(!o.canHandle(i))throw new Error(`Agent '${r}' is not available in this environment. Check credentials/environment.`);return w.debug(`[workflow] using agent: ${o.getName()}`),o}async function ht(i,e={},t={}){let r=De(e),o=e.state?.config||t.config||{},s=o.models||{},n=t.nodeName&&s[t.nodeName]||null,a=s.default||null,c=o.agent?.[r.name]?.model||null,d=n||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:o},l=i,m=h.skills||[];if(m.length>0&&!t.skipPromptFragments){let k=m.map(P=>{let A=ae(P)?.promptFragment;return typeof A=="function"?A():A}).filter(Boolean);k.length>0&&(l+=`
|
|
2
2
|
|
|
3
|
-
${
|
|
3
|
+
${k.join(`
|
|
4
4
|
|
|
5
|
-
`)}`)}let
|
|
5
|
+
`)}`)}let E=e.state?._currentNodeConfig?.extraPromptInstructions?.trim();return E&&(l+=`
|
|
6
6
|
|
|
7
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
8
|
PRIORITY OVERRIDE \u2014 THE FOLLOWING INSTRUCTIONS TAKE PRECEDENCE OVER ALL PREVIOUS CONTENT
|
|
9
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
10
|
|
|
11
|
-
${
|
|
12
|
-
`),w.debug(`[workflow] prompt length: ${l.length} chars`),
|
|
13
|
-
${
|
|
14
|
-
`)}`);return
|
|
15
|
-
`?(
|
|
16
|
-
${
|
|
11
|
+
${E}
|
|
12
|
+
`),w.debug(`[workflow] prompt length: ${l.length} chars`),r.invoke(l,h)}var le,C,de=H(()=>{We();oe();ce();le=Symbol.for("@zibby/agent-workflow.strategies");globalThis[le]||(globalThis[le]=[]);C=globalThis[le]});var rt=new Set(["__proto__","constructor","prototype"]);function te(i){if(rt.has(i))throw new Error(`Invalid state key: "${i}"`)}var K=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){te(e),this._history.push({...this._state}),this._state[e]=t}update(e){let t=Object.getOwnPropertyNames(e);for(let r of t)te(r);this._history.push({...this._state});for(let r of t)this._state[r]=e[r]}append(e,t){te(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 z=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 r=[e.match(/\{[\s\S]*?\}/),e.match(/\{[\s\S]*\}/)].filter(Boolean).map(o=>o[0]);for(let o of r)try{return this.validate(JSON.parse(o))}catch(s){if(!(s instanceof SyntaxError))throw s}return this.validate({result:e.trim()})}validate(e){let t=[];for(let[r,o]of Object.entries(this.schema)){if(o.required&&!(r in e)&&t.push(`Missing required field: ${r}`),r in e&&o.type){let s=typeof e[r];s!==o.type&&t.push(`Field '${r}' expected ${o.type}, got ${s}`)}if(o.validate&&r in e){let s=o.validate(e[r]);s&&t.push(`Field '${r}': ${s}`)}}if(t.length>0)throw new Error(`Output validation failed:
|
|
13
|
+
${t.join(`
|
|
14
|
+
`)}`);return e}};oe();import{writeFileSync as pe,readFileSync as Le,existsSync as Ye,mkdirSync as mt}from"node:fs";import{join as fe,dirname as gt}from"node:path";import S from"chalk";var nt="__WORKFLOW_GRAPH_LOG__",U=S.gray("\u2502"),it=S.gray("\u250C"),Oe=S.gray("\u2514"),re=S.green("\u25C6"),$e=S.hex("#c084fc")("\u25C6"),Te=S.hex("#2dd4bf")("\u25C6"),se=S.red("\u25C6"),ve=`${U} `,Ae=2;function ke(i){return i<1e3?`${i}ms`:`${(i/1e3).toFixed(1)}s`}function Pe(i,e){return(t,r,o)=>{if(typeof t!="string")return i(t,r,o);let s=process.stdout.columns||120,n="";for(let a=0;a<t.length;a++){let c=t[a];e.lineStart&&(n+=ve,e.col=Ae,e.lineStart=!1),c===`
|
|
15
|
+
`?(n+=c,e.lineStart=!0,e.col=0,e.inEsc=!1):c==="\x1B"?(e.inEsc=!0,n+=c):e.inEsc?(n+=c,(c>="A"&&c<="Z"||c>="a"&&c<="z")&&(e.inEsc=!1)):(e.col++,n+=c,e.col>=s&&(n+=`
|
|
16
|
+
${ve}`,e.col=Ae))}return i(n,r,o)}}var ne=class{constructor(){this._currentNode=null,this._origStdoutWrite=null,this._origStderrWrite=null;let e=String(process.env.ZIBBY_EMIT_GRAPH_MARKERS||"").trim()==="1"||String(process.env.ZIBBY_WORKFLOW_GRAPH_LOG_MARKERS||"").trim()==="1",t=!e&&String(process.env.ZIBBY_RUN_SOURCE||"").trim().toLowerCase()==="studio";t&&process.env.ZIBBY_NO_DEPRECATION_WARNINGS!=="1"&&console.warn("[zibby/agent-workflow] `ZIBBY_RUN_SOURCE=studio` env var is deprecated for graph-marker emission. Set `ZIBBY_EMIT_GRAPH_MARKERS=1` instead. The Studio-specific value will be ignored in v2. Suppress with ZIBBY_NO_DEPRECATION_WARNINGS=1."),this._emitWorkflowGraphMarkers=e||t}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=Pe(this._origStdoutWrite,e),process.stderr.write=Pe(this._origStderrWrite,t)}_stopIntercepting(){this._origStdoutWrite&&(this._outState&&!this._outState.lineStart&&this._origStdoutWrite(`
|
|
17
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(
|
|
19
|
-
`)}_emitGraphLogMarker(
|
|
20
|
-
`;this._origStdoutWrite?this._origStdoutWrite(
|
|
21
|
-
`),this._outState.lineStart=!0,this._outState.col=0),this._origStdoutWrite(`${
|
|
22
|
-
`)):process.stdout.write.bind(process.stdout)(`${
|
|
23
|
-
`)}step(
|
|
24
|
-
`)}stepInfo(
|
|
25
|
-
`)}stepMemory(
|
|
26
|
-
`)}stepFail(
|
|
27
|
-
`)}nodeStart(
|
|
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=`${nt}${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(re,e):process.stdout.write.bind(process.stdout)(`${U} ${re} ${e}
|
|
24
|
+
`)}stepInfo(e){this.step(e)}stepTool(e){this._origStdoutWrite?this._writeDot($e,e):process.stdout.write.bind(process.stdout)(`${U} ${$e} ${e}
|
|
25
|
+
`)}stepMemory(e){let t=S.hex("#2dd4bf")(e);this._origStdoutWrite?this._writeDot(Te,t):process.stdout.write.bind(process.stdout)(`${U} ${Te} ${t}
|
|
26
|
+
`)}stepFail(e){this._origStdoutWrite?this._writeDot(se,S.red(e)):process.stdout.write.bind(process.stdout)(`${U} ${se} ${S.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:r,details:o}=t;if(o)for(let n of o)this._rawWrite(`${re} ${n}`);let s=r?S.dim(` ${ke(r)}`):"";this._rawWrite(`${Oe} ${S.green("done")}${s}`),this._emitGraphLogMarker({phase:"node_end",node:e}),this._rawWrite("")}nodeFailed(e,t,r={}){this._stopIntercepting();let{duration:o}=r,s=o?S.dim(` ${ke(o)}`):"";this._rawWrite(`${se} ${S.red(t)}`),this._rawWrite(`${Oe} ${S.red("failed")}${s}`),this._emitGraphLogMarker({phase:"node_end",node:e}),this._rawWrite("")}route(e,t){this._rawWrite(S.dim(` ${e} \u2192 ${t}`)),this._rawWrite("")}graphComplete(){this._rawWrite(S.green.bold("\u2713 Workflow completed"))}},_=new ne;var V=".zibby/output",Be="sessions",D=".session-info.json",Re=".zibby-stop",xe=".zibby-studio-stop";var Ce=["CI_JOB_ID","GITHUB_RUN_ID","CIRCLE_WORKFLOW_ID","BUILD_ID"];var Y=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 z(e.outputSchema):null,this.retries=e.retries||0,this.onComplete=e.onComplete,this.customExecute=e.execute}async execute(e,t){let r=()=>t&&typeof t.getAll=="function"?t.getAll():e,o=l=>t&&typeof t.get=="function"?t.get(l):e?.[l];if(typeof this.customExecute=="function"){w.debug(`[workflow] node '${this.name}': custom execute (skipping LLM)`);try{let l=await this.customExecute(e);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.issues||l.errors,null,2)}`),{success:!1,error:l.message,raw:null}}}let s=typeof this.prompt=="function"?this.prompt(r()):this.prompt,n=o("_skillHints");n&&(s=`${n}
|
|
28
28
|
|
|
29
|
-
${
|
|
29
|
+
${s}`);let a=r(),c=a.cwd||process.cwd(),d=a.sessionPath;try{if(d){let l=fe(d,D);if(Ye(l)){let E=JSON.parse(Le(l,"utf-8"));E.currentNode=this.name,pe(l,JSON.stringify(E,null,2),"utf-8")}let m=fe(d,"..",D);if(Ye(m))try{let E=JSON.parse(Le(m,"utf-8"));E.currentNode=this.name,pe(m,JSON.stringify(E,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 m=r().config||{},E=m.agents||{},k=this.config.agent??E[this.name]??null,P={state:r()};k&&(P.preferredAgent=k);let A={workspace:c,schema:this.isZodSchema?this.outputSchema:null,skills:this.config.skills||[],sessionPath:d,config:m,nodeName:this.name,timeout:this.config?.timeout||3e5},p=e?._coreInvokeAgent;p||(p=(await Promise.resolve().then(()=>(de(),ue))).invokeAgent);let I=await p(s,P,A),y,O;if(typeof I=="string"?(y=I,O=null):I.structured?(y=I.raw||JSON.stringify(I.structured,null,2),O=I.structured):(y=I.raw||JSON.stringify(I,null,2),O=I.extracted||null),d)try{let u=fe(d,this.name,"raw_stream_output.txt");mt(gt(u),{recursive:!0}),pe(u,typeof y=="string"?y:JSON.stringify(y),"utf-8")}catch(u){w.debug(`[workflow] could not save raw output: ${u.message}`)}if(this.isZodSchema&&O){w.info(`[workflow] node '${this.name}': output validated: ${JSON.stringify(O,null,2)}`);let u=O;if(typeof this.onComplete=="function")try{u=await this.onComplete(r(),O)}catch(R){w.warn(`[workflow] onComplete hook failed: ${R.message}`)}return{success:!0,output:u,raw:y}}if(typeof this.onComplete=="function")try{return{success:!0,output:await this.onComplete(r(),{raw:y}),raw:y}}catch(u){throw new Error(`onComplete failed: ${u.message}`,{cause:u})}if(this.parser){let u=this.parser.parse(y);return w.info(`[workflow] node '${this.name}': parsed output: ${JSON.stringify(u,null,2)}`),_.step("Output parsed"),{success:!0,output:u,raw:y}}return{success:!0,output:y,raw:y}}catch(m){h=m,l<this.retries&&w.info(`[workflow] node '${this.name}' failed, retrying (${l+1}/${this.retries})\u2026`)}return{success:!1,error:h.message,raw:null}}},q=class extends Y{constructor(e){super({...e,_isCustomCode:!0}),this.condition=e.condition}async execute(e,t){let r=t&&typeof t.getAll=="function"?t.getAll():e;return{success:!0,output:{nextNode:this.condition(r)},raw:null}}};import{existsSync as Ze,readFileSync as St}from"node:fs";import{join as he,dirname as Fe}from"node:path";var Q=class{static async loadContext(e,t,r={}){let o={},s=r.filenames||["CONTEXT.md","AGENTS.md"];if(e){let a=Fe(he(t,e));for(let c of s){let d=await this.findAndMergeContextFiles(c,a,t);if(d){let h=c.replace(/\.[^.]+$/,"").toLowerCase();o[h]=d}}}let n=r.discovery||{};for(let[a,c]of Object.entries(n))try{let d=he(t,c);Ze(d)&&(o[a]=await this.loadFile(d))}catch(d){console.warn(`[workflow] could not load context '${a}' from '${c}': ${d.message}`)}return o}static async findAndMergeContextFiles(e,t,r){let o=[],s=t;for(;s.startsWith(r);){let n=he(s,e);if(Ze(n))try{o.unshift(await this.loadFile(n))}catch(c){console.warn(`[workflow] could not load ${e} from ${n}: ${c.message}`)}let a=Fe(s);if(a===s)break;s=a}return o.length===0?null:o.every(n=>typeof n=="string")?o.join(`
|
|
30
30
|
|
|
31
31
|
---
|
|
32
32
|
|
|
33
|
-
`):
|
|
33
|
+
`):o.every(n=>typeof n=="object")?Object.assign({},...o):o[o.length-1]}static async loadFile(e){let t=St(e,"utf-8");if(e.endsWith(".json"))return JSON.parse(t);if(e.endsWith(".js")||e.endsWith(".mjs")){let{pathToFileURL:r}=await import("url"),o=await import(r(e).href);return o.default||o}return t}};import{mkdirSync as ze,existsSync as X,writeFileSync as Ue,unlinkSync as je}from"node:fs";import{join as B,resolve as Je}from"node:path";import{config as _t}from"dotenv";import{zodToJsonSchema as Ge}from"zod-to-json-schema";import wt from"handlebars";var He=new Set;function ee(i,e){He.has(i)||(He.add(i),process.env.ZIBBY_NO_DEPRECATION_WARNINGS!=="1"&&console.warn(`[zibby/agent-workflow] ${e}`))}function yt({traceFrom:i,sessionId:e,sessionPath:t,idSource:r,mkdirFresh:o}){if(!(process.env.ZIBBY_SESSION_LOG==="1"||process.env.ZIBBY_SESSION_LOG==="true"))return;let n=typeof process.ppid=="number"?process.ppid:"n/a",a=`[zibby:session] from=${i} pid=${process.pid} ppid=${n} sessionId=${e} source=${r} mkdir=${o?"yes":"no"} path=${t}`;if(console.log(a),process.env.ZIBBY_TRACE_SESSION==="1"||process.env.ZIBBY_TRACE_SESSION==="true"){let h=(new Error("session trace").stack||"").split(`
|
|
34
34
|
`).slice(2,14).join(`
|
|
35
|
-
`);console.log(`[zibby:session] stack (${
|
|
36
|
-
${
|
|
37
|
-
\u{1F6D1}
|
|
35
|
+
`);console.log(`[zibby:session] stack (${i}):
|
|
36
|
+
${h}`)}}function Et(){return process.env.ZIBBY_TRUST_SESSION_ENV==="1"||process.env.ZIBBY_TRUST_SESSION_ENV==="true"||process.env.ZIBBY_KEEP_SESSION_ENV==="1"||process.env.ZIBBY_KEEP_SESSION_ENV==="true"?!0:process.env.ZIBBY_RUN_SOURCE==="studio"?(ee("legacy-zibby-run-source","`ZIBBY_RUN_SOURCE=studio` env var is deprecated. Set `ZIBBY_TRUST_SESSION_ENV=1` (and `ZIBBY_PIN_SESSION_PATH=1` / `ZIBBY_EMIT_GRAPH_MARKERS=1` if you need those gates) instead. The Studio-specific value will be ignored in v2. Suppress with ZIBBY_NO_DEPRECATION_WARNINGS=1."),!0):!1}function It(){let i=process.env.ZIBBY_PIN_SESSION_PATH==="1"||process.env.ZIBBY_PIN_SESSION_PATH==="true",e=!i&&process.env.ZIBBY_RUN_SOURCE==="studio";if(e&&ee("legacy-zibby-run-source","`ZIBBY_RUN_SOURCE=studio` env var is deprecated. Set `ZIBBY_PIN_SESSION_PATH=1` (and `ZIBBY_TRUST_SESSION_ENV=1` / `ZIBBY_EMIT_GRAPH_MARKERS=1` if you need those gates) instead. The Studio-specific value will be ignored in v2. Suppress with ZIBBY_NO_DEPRECATION_WARNINGS=1."),!i&&!e)return;let t=process.env.ZIBBY_SESSION_PATH;if(!(t==null||String(t).trim()===""))try{return Je(String(t).trim())}catch{return String(t).trim()}}var Nt=It;function bt(){Et()||(delete process.env.ZIBBY_SESSION_PATH,delete process.env.ZIBBY_SESSION_ID)}function Ot({sessionPath:i,sessionId:e}){i&&typeof i=="string"&&(process.env.ZIBBY_SESSION_PATH=i),e!=null&&String(e).trim()!==""&&(process.env.ZIBBY_SESSION_ID=String(e).trim())}function $t(i={}){let e=Ce.map(s=>process.env[s]).find(Boolean),t=Math.random().toString(36).slice(2,6),r=e||`${Date.now()}_${t}`,o=i.paths?.sessionPrefix;return o?`${o}_${r}`:r}function Tt({cwd:i=process.cwd(),config:e={},initialState:t={},traceFrom:r="resolveWorkflowSession"}={}){let o=t.sessionPath,s=t.sessionTimestamp,n="initialState.sessionPath";if(!o&&process.env.ZIBBY_SESSION_PATH)try{let d=Je(String(process.env.ZIBBY_SESSION_PATH));d&&(o=d,n="ZIBBY_SESSION_PATH")}catch{}let a;if(o)a=String(o).split(/[/\\]/).filter(Boolean).pop(),s==null&&(s=Date.now());else{let d=process.env.ZIBBY_SESSION_ID&&String(process.env.ZIBBY_SESSION_ID).trim();if(d)a=d,n="ZIBBY_SESSION_ID";else{let l=e.sessionId!=null?String(e.sessionId).trim():"";l&&l!=="last"?(a=l,n="config.sessionId"):(a=$t(e),n="generated")}s=s??Date.now();let h=e.paths?.output||V;o=B(i,h,Be,a)}let c=!X(o);return c&&ze(o,{recursive:!0}),(c||n!=="initialState.sessionPath")&&yt({traceFrom:r,sessionId:a,sessionPath:o,idSource:n,mkdirFresh:c}),Ot({sessionPath:o,sessionId:a}),{sessionPath:o,sessionId:a,sessionTimestamp:s}}var Ke=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,this._compiledPrompts=new Map}setStateSchema(e){return this.stateSchema=e,this}getStateSchema(){return this.stateSchema}addNode(e,t,r={}){let o=t instanceof Y?t:new Y(t);return o.name=e,this.nodes.set(e,o),r.prompt&&this.nodePrompts.set(e,r.prompt),Object.keys(r).length>0&&this.nodeOptions.set(e,r),this}addConditionalNode(e,t){return this.nodes.set(e,new q({...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:r}={}){return this.edges.set(e,{conditional:!0,routes:t,labels:r}),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,r,o,s){let n=r;for(let a=e.length-1;a>=0;a--){let c=e[a],d=n;n=()=>c(t,d,o,s)}return n()}serialize(){let e=[],t={};for(let[s,n]of this.nodes){let a=this.nodeTypeMap.get(s)||s;e.push({id:s,type:a,data:{nodeType:a,label:s}});let c={};n._isCustomCode&&typeof n.execute=="function"&&(c.customCode=n.execute.toString());let d=this.nodePrompts.get(s);if(d&&(c.prompt=d),typeof n.customExecute=="function"&&(c.executeCode=n.customExecute.toString()),n.outputSchema)try{if(typeof n.outputSchema._def<"u"){let l=Ge(n.outputSchema,{target:"openApi3"});c.outputSchema={jsonSchema:l,variables:this._flattenJsonSchemaToVariables(l)}}else c.outputSchema={schema:n.outputSchema}}catch(l){console.warn(`[workflow] failed to convert schema for ${s}:`,l.message)}let h=(this.resolvedToolsMap||{})[s];h?.toolIds&&(c.tools=h.toolIds),Object.keys(c).length>0&&(t[s]=c)}let r=[];for(let[s,n]of this.edges)if(typeof n=="string")r.push({source:s,target:n});else if(n.conditional){let a=this.conditionalCodeMap.get(s)||n.routes.toString(),c=this._inferConditionalTargets(n.routes),d=n.labels||{};for(let h of c){let l={source:s,target:h,data:{conditionalCode:a}};d[h]&&(l.label=d[h]),r.push(l)}}let o=null;if(this.stateSchema)try{o=Ge(this.stateSchema,{target:"openApi3"})}catch{o=this.stateSchema}return{nodes:e,edges:r,nodeConfigs:t,stateSchema:o}}_inferConditionalTargets(e){let t=e.toString(),r=new Set,o=/return\s+['"]([^'"]+)['"]/g,s;for(;(s=o.exec(t))!==null;)r.add(s[1]);return[...r]}_flattenJsonSchemaToVariables(e,t=""){let r=e;if(e.$ref&&e.definitions){let o=e.$ref.replace("#/definitions/","");r=e.definitions[o]||e}return this._flattenSchema(r,t)}_flattenSchema(e,t=""){if(!e||typeof e!="object")return[];let r=[],o=e.properties||{},s=e.required||[];for(let[n,a]of Object.entries(o)){let c=t?`${t}.${n}`:n;r.push({path:c,type:a.type||"unknown",label:a.description||this._formatLabel(n),optional:!s.includes(n)}),a.type==="object"&&a.properties&&r.push(...this._flattenSchema(a,c)),a.type==="array"&&a.items?.type==="object"&&a.items.properties&&r.push(...this._flattenSchema(a.items,`${c}[]`))}return r}_formatLabel(e){return e.replace(/([A-Z])/g," $1").replace(/^./,t=>t.toUpperCase()).trim()}_summarizeNodeOutput(e,t){if(!t||typeof t!="object")return[];let r=[];t.success!==void 0&&r.push(`Result: ${t.success?"passed":"failed"}`);for(let[o,s]of Object.entries(t))if(!(o==="success"||o==="raw"||o==="nextNode")){if(typeof s=="string"&&s.length<=80)r.push(`${o}: ${s}`);else if(Array.isArray(s)){let n=s.length,a=s.filter(d=>d?.passed===!0).length,c=s.some(d=>d?.passed!==void 0);r.push(c?`${o}: ${a}/${n} passed${n-a?`, ${n-a} failed`:""}`:`${o}: ${n} items`)}if(r.length>=4)break}return r}async run(e,t={},r={}){if(!this.entryPoint)throw new Error("No entry point set for graph");let o=new AbortController;r.signal&&(r.signal.aborted?o.abort():r.signal.addEventListener("abort",()=>o.abort(),{once:!0}));let s=r.strategyAbortTimeoutMs??t.config?.strategyAbortTimeoutMs??5e3,n=t.cwd||process.cwd();_t({path:B(n,".env")});let a=t.config||{};if(!a||Object.keys(a).length===0)try{let f=B(n,".zibby.config.js");X(f)&&(a=(await import(f)).default||{})}catch{}process.env.EXECUTION_ID&&!a.agent?.strictMode&&(a.agent={...a.agent,strictMode:!0});let c=t.agentType;if(!c){let f=a?.agent;f?.provider?c=f.provider:f?.gemini?c="gemini":f?.claude?c="claude":f?.cursor?c="cursor":f?.codex?c="codex":c=process.env.AGENT_TYPE||"cursor"}let d=t.contextConfig||e?.config?.contextConfig||e?.config?.context||a?.context||{};if(this.stateSchema){let f=this.stateSchema.safeParse(t);if(!f.success){let b=f.error.issues.map($=>`${$.path.join(".")}: ${$.message}`);throw console.error("\u274C Initial state validation failed:"),b.forEach($=>console.error(` - ${$}`)),new Error(`State validation failed: ${b.join(", ")}`)}_.step("State validated against schema")}let h=Nt(),l=t.sessionPath||h;l||bt();let{sessionPath:m,sessionTimestamp:E,sessionId:k}=Tt({cwd:n,config:a,traceFrom:"WorkflowGraph.run",initialState:{sessionPath:l,sessionTimestamp:t.sessionTimestamp}});_.step(`Session ${k}`);let P=await Q.loadContext(t.specPath||"",n,d);Object.keys(P).length>0&&_.step(`Context loaded: ${Object.keys(P).join(", ")}`);let A=t.outputPath;!A&&t.specPath&&(e?.calculateOutputPath?A=e.calculateOutputPath(t.specPath):console.warn(`\u26A0\uFE0F outputPath not resolved (specPath=${t.specPath})`));let p=new K({...t,config:a,agentType:c,outputPath:A,sessionPath:m,sessionTimestamp:E,context:P,resolvedTools:this.resolvedToolsMap||{},_signal:o.signal}),I=new Map;try{await import("@zibby/skills")}catch{}let{getSkill:y}=await Promise.resolve().then(()=>(ce(),Me)),O=new Set;for(let[,f]of this.nodes)for(let b of f.config?.skills||[])O.add(b);for(let f of O){let b=y(f);if(typeof b?.middleware=="function")try{let $=await b.middleware();typeof $=="function"&&I.set(f,$)}catch{}}let u=this.entryPoint,R=[],me=a?.recursionLimit??100,Ve=0;try{for(;u&&u!=="END";){if(++Ve>me)throw new Error(`Workflow exceeded recursion limit (${me}) \u2014 likely a cyclic conditional route. Set config.recursionLimit if you need a higher cap.`);let b=B(m,Re),$=B(m,xe);if(X(b)){try{je(b)}catch{}o.abort()}if(X($)){try{je($)}catch{}o.abort(),ee("legacy-stop-file","Detected legacy `.zibby-studio-stop` file. Consumers should migrate to either `.zibby-stop` (renamed) or pass an AbortSignal to graph.run. The legacy filename will be removed in v2. Suppress with ZIBBY_NO_DEPRECATION_WARNINGS=1.")}if(o.signal.aborted)return console.warn(`
|
|
37
|
+
\u{1F6D1} External stop requested \u2014 ending workflow.`),_.step("Workflow stopped externally"),{success:!0,state:p.getAll(),executionLog:R,stoppedExternally:!0,stoppedByStudio:!0};let Z=this.nodes.get(u);if(!Z)throw new Error(`Node '${u}' not found in graph`);let ge=JSON.stringify({sessionPath:m,sessionTimestamp:E,currentNode:u,createdAt:new Date().toISOString(),config:p.get("config")}),qe=B(m,D);Ue(qe,ge,"utf-8");let Se=p.get("config")?.paths?.output||V,Qe=B(n,Se,D);ze(B(n,Se),{recursive:!0});try{Ue(Qe,ge,"utf-8")}catch{}let _e=t.onPipelineProgress;if(typeof _e=="function")try{_e({cwd:n,sessionPath:m,sessionId:k,outputBase:p.get("config")?.paths?.output||V,currentNode:u})}catch{}let Xe=(this.resolvedToolsMap||{})[u]||null;p.set("_currentNodeTools",Xe);let et=p.get("nodeConfigs")||{};p.set("_currentNodeConfig",et[u]||{}),_.nodeStart(u);let we=Date.now(),j=this.nodePrompts.get(u);if(!this._invokeAgent){let T=await Promise.resolve().then(()=>(de(),ue));this._invokeAgent=T.invokeAgent}let tt=this._invokeAgent,ye=async(T,v,g={})=>{let N=tt(T,v,{...g,signal:o.signal});return N.catch(()=>{}),o.signal.aborted?N:Promise.race([N,new Promise((W,M)=>{let x=()=>{setTimeout(()=>{let F=new Error(`Strategy ignored AbortSignal \u2014 engine deadman fired after ${s}ms`);F.name="AbortError",M(F)},s)};o.signal.addEventListener("abort",x,{once:!0})})])},Ee={state:p,invokeAgent:async(T={},v={})=>{let g=v.prompt||"";if(j){let N=this._compiledPrompts.get(u);N||(N=wt.compile(j,{noEscape:!0}),this._compiledPrompts.set(u,N));try{g=N(T)}catch(W){throw console.error(`\u274C Template rendering failed for node '${u}':`,W.message),new Error(`Template rendering failed: ${W.message}`,{cause:W})}}else if(!g)throw new Error(`No prompt template configured for node '${u}' and no prompt provided in options`);return ye(g,{state:p.getAll(),images:v.images||[]},{model:v.model||p.get("model"),workspace:p.get("workspace"),schema:v.schema,...v,signal:o.signal})},_coreInvokeAgent:ye,agent:e,nodeId:u,promptTemplate:j,getPromptTemplate:()=>j,...p.getAll()};try{let T=(Z.config?.skills||[]).map(x=>I.get(x)).filter(Boolean),v=[...this.middleware,...T],g;v.length>0?g=await this._composeMiddleware(v,u,async()=>Z.execute(Ee,p),p.getAll(),p):g=await Z.execute(Ee,p);let N=Date.now()-we;if(R.push({node:u,success:g.success,duration:N,timestamp:new Date().toISOString()}),!g.success){if(String(g.error||"").includes("Stopped from Zibby Studio"))return ee("legacy-error-string",'Strategy returned the legacy `Stopped from Zibby Studio` error string. Strategies should reject with `Error.name === "AbortError"` instead. The string-match fallback will be removed in v2. Suppress with ZIBBY_NO_DEPRECATION_WARNINGS=1.'),_.step("Workflow stopped externally"),p.set("stoppedExternally",!0),p.set("stoppedByStudio",!0),{success:!0,state:p.getAll(),executionLog:R,stoppedExternally:!0,stoppedByStudio:!0};if(o.signal.aborted)return _.step("Workflow stopped externally"),{success:!0,state:p.getAll(),executionLog:R,stoppedExternally:!0,stoppedByStudio:!0};p.append("errors",{node:u,error:g.error});let F=Z.config?.retries||0,Ie=`${u}_retries`,G=p.getAll()[Ie]||0;if(G<F){_.stepInfo(`Retrying (attempt ${G+1}/${F})`),p.update({[Ie]:G+1,[`${u}_raw`]:g.raw});continue}throw _.nodeFailed(u,g.error,{duration:N}),new Error(`Node '${u}' failed after ${G} attempts: ${g.error}`)}p.update({[u]:g.output});let W=this._summarizeNodeOutput(u,g.output);_.nodeComplete(u,{duration:N,details:W});let M=this.edges.get(u);if(!M)u="END";else if(M.conditional){let x=M.routes(p.getAll());_.route(u,x),u=x}else u=M}catch(T){throw _.isInsideNode&&_.nodeFailed(u,T.message,{duration:Date.now()-we}),p.set("failed",!0),p.set("failedAt",u),T}}_.graphComplete();let f={success:!0,state:p.getAll(),executionLog:R};return e&&typeof e.onComplete=="function"&&await e.onComplete(f),f}finally{if(e&&typeof e.cleanup=="function")try{await e.cleanup()}catch(f){console.warn(`[workflow] agent.cleanup() failed: ${f.message}`)}}}};export{Ke as WorkflowGraph,bt as clearInheritedSessionEnvForFreshRun,$t as generateWorkflowSessionId,It as readPinnedSessionPathFromEnv,Nt as readStudioPinnedSessionPathFromEnv,Tt as resolveWorkflowSession,Et as shouldTrustInheritedSessionEnv,Ot as syncProcessEnvToSession};
|
package/dist/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ export { WorkflowState } from "./state.js";
|
|
|
2
2
|
export { ContextLoader } from "./context-loader.js";
|
|
3
3
|
export { AgentStrategy } from "./agents/base.js";
|
|
4
4
|
export { setLogger } from "./logger.js";
|
|
5
|
-
export { WorkflowGraph, generateWorkflowSessionId, resolveWorkflowSession, shouldTrustInheritedSessionEnv, readStudioPinnedSessionPathFromEnv, clearInheritedSessionEnvForFreshRun, syncProcessEnvToSession } from "./graph.js";
|
|
5
|
+
export { WorkflowGraph, generateWorkflowSessionId, resolveWorkflowSession, shouldTrustInheritedSessionEnv, readPinnedSessionPathFromEnv, readStudioPinnedSessionPathFromEnv, clearInheritedSessionEnvForFreshRun, syncProcessEnvToSession } from "./graph.js";
|
|
6
6
|
export { Node, ConditionalNode } from "./node.js";
|
|
7
7
|
export { OutputParser, SchemaTypes } from "./output-parser.js";
|
|
8
8
|
export { compileGraph, validateGraphConfig, extractSteps, CompilationError } from "./graph-compiler.js";
|
|
@@ -11,5 +11,5 @@ export { registerSkill, getSkill, hasSkill, getAllSkills, listSkillIds, clearSki
|
|
|
11
11
|
export { resolveNodeTools, getResolvedToolDefinitions, NODE_DEFAULT_TOOLS } from "./tool-resolver.js";
|
|
12
12
|
export { registerStrategy, listStrategies, getAgentStrategy, invokeAgent } from "./strategy-registry.js";
|
|
13
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";
|
|
14
|
+
export { SKILLS, DEFAULT_OUTPUT_BASE, SESSIONS_DIR, SESSION_INFO_FILE, STOP_REQUEST_FILE, STUDIO_STOP_REQUEST_FILE, RESULT_FILE, RAW_OUTPUT_FILE, EVENTS_FILE, CI_ENV_VARS } from "./constants.js";
|
|
15
15
|
export { timeline, Timeline, WORKFLOW_GRAPH_LOG_MARKER_PREFIX } from "./timeline.js";
|