@zibby/agent-workflow 0.4.33 β†’ 0.4.34

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 CHANGED
@@ -9,12 +9,12 @@
9
9
 
10
10
  πŸ“– **Full docs:** [docs.zibby.app](https://docs.zibby.app) Β· [Get Started](https://docs.zibby.app/get-started/install) Β· [Concepts](https://docs.zibby.app/concepts/graph) Β· [CLI Reference](https://docs.zibby.app/cli-reference) Β· [Cloud](https://docs.zibby.app/cloud/triggering)
11
11
 
12
- > **The cloud pipeline for Claude Code, Cursor, Codex, and Gemini.** Compose them into structured workflows with Zod-validated handoff between nodes. Vendor-neutral, JavaScript-first, runs locally or in our cloud.
12
+ > **The cloud pipeline for Claude Code, Codex, and Gemini.** Compose them into structured workflows with Zod-validated handoff between nodes. Vendor-neutral, JavaScript-first, runs locally or in our cloud.
13
13
 
14
14
  ```
15
15
  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
16
16
  trigger β†’ β”‚ plan β”‚ β†’ β”‚ implementβ”‚ β†’ β”‚ verify β”‚ β†’ result
17
- β”‚ (claude) β”‚ β”‚ (cursor) β”‚ β”‚ (codex) β”‚
17
+ β”‚ (claude) β”‚ β”‚ (codex) β”‚ β”‚ (gemini) β”‚
18
18
  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
19
19
  β”‚ β”‚ β”‚
20
20
  Zod out Zod out Zod out
@@ -22,16 +22,16 @@
22
22
 
23
23
  Each node hands off to a complete agent. The agent does its own tool calls, file edits, and multi-turn reasoning. Your graph defines *what* agent runs *when*, *what schema* it has to return, and *what state* flows between them.
24
24
 
25
- Mix and match agents per node β€” Claude for planning, Cursor for implementation, Codex for verification. Or stick with one. Your call:
25
+ Mix and match agents per node β€” Claude for planning, Codex for implementation, Gemini for verification. Or stick with one. Your call:
26
26
 
27
27
  ```js
28
28
  graph
29
29
  .addNode('plan', { prompt, outputSchema: Plan, agent: 'claude' })
30
- .addNode('implement', { prompt, outputSchema: Diff, agent: 'cursor' })
31
- .addNode('verify', { prompt, outputSchema: Result, agent: 'codex' });
30
+ .addNode('implement', { prompt, outputSchema: Diff, agent: 'codex' })
31
+ .addNode('verify', { prompt, outputSchema: Result, agent: 'gemini' });
32
32
  ```
33
33
 
34
- Each agent reads its own credential env var (`ANTHROPIC_API_KEY`, `CURSOR_API_KEY`, `OPENAI_API_KEY`). In **Zibby Cloud** you can set those per-workflow β€” different keys per pipeline, no global state β€” see [Per-workflow env vars](https://docs.zibby.app/cloud/env-vars). Per-node `model` overrides come from `.zibby.config.mjs` (`models: { node_id: 'claude-opus-4.6' }`), which the CLI ships to cloud as part of the deploy bundle.
34
+ Each agent reads its own credential env var (`ANTHROPIC_API_KEY`, `OPENAI_API_KEY`). In **Zibby Cloud** you can set those per-workflow β€” different keys per pipeline, no global state β€” see [Per-workflow env vars](https://docs.zibby.app/cloud/env-vars). Per-node `model` overrides come from `.zibby.config.mjs` (`models: { node_id: 'claude-opus-4.6' }`), which the CLI ships to cloud as part of the deploy bundle.
35
35
 
36
36
  ---
37
37
 
@@ -140,11 +140,11 @@ See [`examples/`](./examples/) for runnable demos of each pattern.
140
140
 
141
141
  | | What it does | Why this is different |
142
142
  |---|---|---|
143
- | **LangGraph** | Python-first graph runtime over LangChain β€” nodes are LangChain agents or LLM calls, state is shared via the graph. | Our nodes hand off to **external coding-agent CLIs** (Claude Code, cursor-agent, OpenAI Codex SDK) β€” independent processes that own their own tool use, multi-turn loops, and file edits. JS-first, no Python interop, no LangChain assembly. |
143
+ | **LangGraph** | Python-first graph runtime over LangChain β€” nodes are LangChain agents or LLM calls, state is shared via the graph. | Our nodes hand off to **external coding-agent CLIs** (Claude Code, OpenAI Codex, Gemini CLI) β€” independent processes that own their own tool use, multi-turn loops, and file edits. JS-first, no Python interop, no LangChain assembly. |
144
144
  | **n8n / Zapier** | Visual workflow editor β€” wire SaaS APIs together. | Code-first, no UI. Built around composing coding-agent CLIs against your repo, not connecting SaaS APIs. |
145
145
  | **CrewAI / AutoGen** | Multi-agent role-play β€” agents converse to solve a task. | No agent debate. Each node is a discrete, schema-validated invocation. Deterministic edges, retry-friendly. |
146
146
 
147
- If you want to compose Claude Code + Cursor + Codex into one pipeline with structured handoff between them β€” JS, no Python, no LangChain β€” this is that.
147
+ If you want to compose Claude Code + Codex + Gemini into one pipeline with structured handoff between them β€” JS, no Python, no LangChain β€” this is that.
148
148
 
149
149
  ---
150
150
 
@@ -238,7 +238,7 @@ Examples 01–03 and 05 use a fake agent β€” no API key required.
238
238
 
239
239
  ## Why graph-of-agents
240
240
 
241
- Real coding agents (Claude Code, cursor-agent, OpenAI Codex CLI) are themselves capable runtimes β€” they edit files, run shells, call MCP tools, handle multi-turn. But on their own they have no memory across runs and no way to verify their own output.
241
+ Real coding agents (Claude Code, OpenAI Codex, Gemini CLI) are themselves capable runtimes β€” they edit files, run shells, call MCP tools, handle multi-turn. But on their own they have no memory across runs and no way to verify their own output.
242
242
 
243
243
  A graph gives you:
244
244
 
@@ -258,13 +258,25 @@ You're not replacing the agent. You're giving it a job description, a contract,
258
258
  | Package | What it adds |
259
259
  |---|---|
260
260
  | [`@zibby/cli`](https://www.npmjs.com/package/@zibby/cli) | `zibby` command β€” scaffold, dev server, deploy, trigger, logs. |
261
- | [`@zibby/core`](https://www.npmjs.com/package/@zibby/core) | Built-in agent strategies (Claude / Cursor / Codex / Gemini / OpenAI Assistant), MCP client, runtime. |
261
+ | [`@zibby/core`](https://www.npmjs.com/package/@zibby/core) | Built-in agent strategies (Claude / Codex / Gemini / OpenAI Assistant), MCP client, runtime. |
262
262
  | [`@zibby/skills`](https://www.npmjs.com/package/@zibby/skills) | Pre-built skills (browser via Playwright MCP, GitHub, Jira, Slack, memory). |
263
263
 
264
264
  Workflow itself ships **zero agent strategies and zero skills** β€” bring your own, or `npm install @zibby/core @zibby/skills` for the batteries-included experience.
265
265
 
266
266
  ---
267
267
 
268
+ ## Self-hosted Zibby (single VM)
269
+
270
+ Run the **full Zibby platform** β€” control plane + agents + marketplace β€” on your own box:
271
+
272
+ ```bash
273
+ curl -fsSL https://dl.zibby.app/selfhosted/latest/install.sh | bash
274
+ ```
275
+
276
+ Requirements: Docker + ~8 GB RAM. The installer downloads the release bundle, `docker load`s the images locally (**no registry login needed**), generates secrets, brings the stack up, and prints your dashboard URL + access token. Free tier: up to 10 deployed agents.
277
+
278
+ ---
279
+
268
280
  ## Status
269
281
 
270
282
  `0.1.x`. The public protocol surface is stable and consumed by Zibby Studio + tooling:
@@ -38,7 +38,7 @@ ${s}`);let i=r(),u=i.cwd||process.cwd(),d=i.sessionPath;try{if(d){let l=Te(d,K);
38
38
  `):a.every(n=>typeof n=="object")?Object.assign({},...a):a[a.length-1]}static async loadFile(e){let t=Eo(e,"utf-8");if(e.endsWith(".json"))return JSON.parse(t);if(e.endsWith(".js")||e.endsWith(".mjs")){let{pathToFileURL:r}=await import("url"),a=await import(r(e).href);return a.default||a}return t}};import{mkdirSync as bt,existsSync as Ne,writeFileSync as It,unlinkSync as bo}from"node:fs";import{join as Y,resolve as $t}from"node:path";import{config as $o}from"dotenv";import{zodToJsonSchema as Et}from"zod-to-json-schema";import{z as he}from"zod";import vo from"handlebars";function To({traceFrom:o,sessionId:e,sessionPath:t,idSource:r,mkdirFresh:a}){if(!(process.env.ZIBBY_SESSION_LOG==="1"||process.env.ZIBBY_SESSION_LOG==="true"))return;let n=typeof process.ppid=="number"?process.ppid:"n/a",i=`[zibby:session] from=${o} pid=${process.pid} ppid=${n} sessionId=${e} source=${r} mkdir=${a?"yes":"no"} path=${t}`;if(console.log(i),process.env.ZIBBY_TRACE_SESSION==="1"||process.env.ZIBBY_TRACE_SESSION==="true"){let h=(new Error("session trace").stack||"").split(`
39
39
  `).slice(2,14).join(`
40
40
  `);console.log(`[zibby:session] stack (${o}):
41
- ${h}`)}}function Ao(){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"}function ko(){if(!(process.env.ZIBBY_PIN_SESSION_PATH==="1"||process.env.ZIBBY_PIN_SESSION_PATH==="true"))return;let e=process.env.ZIBBY_SESSION_PATH;if(!(e==null||String(e).trim()===""))try{return $t(String(e).trim())}catch{return String(e).trim()}}function xo(){Ao()||(delete process.env.ZIBBY_SESSION_PATH,delete process.env.ZIBBY_SESSION_ID)}function Oo({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 No(o={}){let e=et.map(s=>process.env[s]).find(Boolean),t=Math.random().toString(36).slice(2,6),r=e||`${Date.now()}_${t}`,a=o.paths?.sessionPrefix;return a?`${a}_${r}`:r}function Po({cwd:o=process.cwd(),config:e={},initialState:t={},traceFrom:r="resolveWorkflowSession"}={}){let a=t.sessionPath,s=t.sessionTimestamp,n="initialState.sessionPath";if(!a&&process.env.ZIBBY_SESSION_PATH)try{let d=$t(String(process.env.ZIBBY_SESSION_PATH));d&&(a=d,n="ZIBBY_SESSION_PATH")}catch{}let i;if(a)i=String(a).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)i=d,n="ZIBBY_SESSION_ID";else{let l=e.sessionId!=null?String(e.sessionId).trim():"";l&&l!=="last"?(i=l,n="config.sessionId"):(i=No(e),n="generated")}s=s??Date.now();let h=e.paths?.output||ue;a=Y(o,h,Xe,i)}let u=!Ne(a);return u&&bt(a,{recursive:!0}),(u||n!=="initialState.sessionPath")&&To({traceFrom:r,sessionId:i,sessionPath:a,idSource:n,mkdirFresh:u}),Oo({sessionPath:a,sessionId:i}),{sessionPath:a,sessionId:i,sessionTimestamp:s}}var ge=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.inputSchema=e.inputSchema||null,this.contextSchema=e.contextSchema||null,this.nodePrompts=new Map,this.nodeOptions=new Map,this._invokeAgent=e.invokeAgent||null,this._compiledPrompts=new Map}setInputSchema(e){return this.inputSchema=e,this}setContextSchema(e){return this.contextSchema=e,this}setStateSchema(e){return this.stateSchema=e,this}getInputSchema(){return this.inputSchema}getContextSchema(){return this.contextSchema}getStateSchema(){return this.stateSchema}_runtimeSchema(){if(this.inputSchema&&this.contextSchema)try{if(typeof this.inputSchema.merge=="function")return this.inputSchema.merge(this.contextSchema);if(typeof this.inputSchema.and=="function")return this.inputSchema.and(this.contextSchema)}catch{}return this.inputSchema&&!this.contextSchema?this.inputSchema:this.stateSchema}addNode(e,t,r={}){if(!(t instanceof L)&&t&&typeof t=="object"&&typeof t.workflow=="string"){let n=t,i={name:e,_isCustomCode:!0,dispatchesWorkflow:n.workflow,retries:n.retries,onComplete:n.onComplete,execute:async d=>{let h=d?.state&&typeof d.state.getAll=="function"?d.state.getAll():d,l;return typeof n.input=="function"?l=n.input(h):n.input&&typeof n.input=="object"?l=n.input:l={},yt(n.workflow,{input:l,async:n.async===!0,conversationId:typeof n.conversationId=="function"?n.conversationId(h):n.conversationId,output:n.output,timeoutMs:n.timeoutMs,pollIntervalMs:n.pollIntervalMs,signal:h?._signal,parentAgent:d?.agent})}},u=new L(i);return u.name=e,this.nodes.set(e,u),r.prompt&&this.nodePrompts.set(e,r.prompt),Object.keys(r).length>0&&this.nodeOptions.set(e,r),this}let a=!(t instanceof L)&&t&&typeof t=="object"&&typeof t.execute!="function"&&t.prompt==null&&t.outputSchema==null&&t._isCustomCode!==!0,s=t instanceof L?t:new L(a?{...t,_isRouter:!0}:t);return s.name=e,this.nodes.set(e,s),r.prompt?this.nodePrompts.set(e,r.prompt):typeof t?.prompt=="string"&&t.prompt.trim()&&this.nodePrompts.set(e,t.prompt),Object.keys(r).length>0&&this.nodeOptions.set(e,r),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,a,s){let n=r;for(let i=e.length-1;i>=0;i--){let u=e[i],d=n;n=()=>u(t,d,a,s)}return n()}serialize(){let e=[],t={};for(let[l,c]of this.nodes){let m=this.nodeTypeMap.get(l)||(c?.config?._isRouter===!0?"decision":l);e.push({id:l,type:m,data:{nodeType:m,label:l}});let S={};c._isCustomCode&&typeof c.execute=="function"&&(S.customCode=c.execute.toString());let _=typeof c?.config?.description=="string"&&c.config.description.trim()?c.config.description:typeof c?.description=="string"&&c.description.trim()?c.description:null;_&&(S.description=_);let v=this.nodePrompts.get(l);if(v)S.prompt=v;else if(typeof c.prompt=="function")try{let p=c.prompt({});typeof p=="string"&&p.trim()&&(S.prompt=p,S.promptIsCode=!0)}catch{}if(typeof c.customExecute=="function"&&(S.executeCode=c.customExecute.toString()),typeof c?.config?.dispatchesWorkflow=="string"&&c.config.dispatchesWorkflow.trim()&&(S.dispatchesWorkflow=c.config.dispatchesWorkflow.trim()),c.outputSchema)if(typeof c.outputSchema._def<"u"){let p=null;if(typeof he?.toJSONSchema=="function")try{p=he.toJSONSchema(c.outputSchema)}catch{}if(!p)try{p=Et(c.outputSchema,{target:"openApi3"})}catch{}S.outputSchema=p?{jsonSchema:p,variables:this._flattenJsonSchemaToVariables(p)}:{schema:c.outputSchema}}else S.outputSchema={schema:c.outputSchema};let E=(this.resolvedToolsMap||{})[l];E?.toolIds&&(S.tools=E.toolIds);let g=Array.isArray(c?.config?.skills)?c.config.skills:Array.isArray(c?.skills)?c.skills:null;g&&g.length>0&&(S.skills=[...g]);let f=Array.isArray(c?.config?.plugins)?c.config.plugins:Array.isArray(c?.plugins)?c.plugins:null;f&&f.length>0&&(S.plugins=f.map(p=>p&&typeof p=="object"?{...p}:p));let y=Array.isArray(c?.config?.stores)?c.config.stores:Array.isArray(c?.stores)?c.stores:null;y&&y.length>0&&(S.stores=y.map(p=>p&&typeof p=="object"?{...p}:p)),Object.keys(S).length>0&&(t[l]=S)}let r=[];for(let[l,c]of this.edges)if(typeof c=="string")r.push({source:l,target:c});else if(c.conditional){let m=this.conditionalCodeMap.get(l)||c.routes.toString(),S=this._inferConditionalTargets(c.routes,c.labels),_=c.labels||{},v=this.nodes.get(l),E=v?.config?._isRouter===!0||this.nodeTypeMap.get(l)==="decision"||!v,g=l;if(!E){let f=`${l}__branch`;e.push({id:f,type:"decision",data:{nodeType:"decision",label:f}}),r.push({source:l,target:f}),g=f}for(let f of S){let y={source:g,target:f,data:{conditionalCode:m}};_[f]&&(y.label=_[f]),r.push(y)}}let a=l=>{if(!l)return null;if(typeof he?.toJSONSchema=="function")try{return he.toJSONSchema(l)}catch{}try{return Et(l,{target:"openApi3"})}catch{return null}};this.entryPoint&&this.nodes.has(this.entryPoint)&&(e.unshift({id:"START",type:"start",data:{nodeType:"start",label:"Start"}}),r.unshift({source:"START",target:this.entryPoint}));let s=0;for(let l of r)if(l.target==="END"){s+=1;let c=`END__${s}`;l.target=c,e.push({id:c,type:"end",data:{nodeType:"end",label:"End"}})}for(let l of this.nodes.keys())if(!this.edges.has(l)){s+=1;let c=`END__${s}`;e.push({id:c,type:"end",data:{nodeType:"end",label:"End"}}),r.push({source:l,target:c})}let n=this._topoOrderNodes(e,r),i=this._runtimeSchema(),u=a(i||this.stateSchema),d=a(this.inputSchema),h=a(this.contextSchema);return{nodes:n,edges:r,nodeConfigs:t,stateSchema:u,inputSchema:d,contextSchema:h}}_topoOrderNodes(e,t){let r=new Map(e.map((l,c)=>[l.id,c])),a=new Map(e.map(l=>[l.id,l])),s=new Map(e.map(l=>[l.id,0])),n=new Map(e.map(l=>[l.id,[]]));for(let l of t)n.has(l.source)&&s.has(l.target)&&(n.get(l.source).push(l.target),s.set(l.target,s.get(l.target)+1));let i=new Set,u=new Set(r.keys()),d=[...u].filter(l=>s.get(l)===0),h=[];for(;h.length<e.length;){let l;if(d.length>0){if(d.sort((c,m)=>r.get(c)-r.get(m)),l=d.shift(),i.has(l))continue}else l=[...u].sort((c,m)=>r.get(c)-r.get(m))[0];i.add(l),u.delete(l),h.push(a.get(l));for(let c of n.get(l)||[])s.set(c,s.get(c)-1),s.get(c)<=0&&!i.has(c)&&d.push(c)}return h}_inferConditionalTargets(e,t){let r=e.toString(),a=new Set,s=/(['"])((?:\\.|(?!\1).)*?)\1|`((?:\\.|[^`$]|\$(?!\{))*?)`/g,n;for(;(n=s.exec(r))!==null;){let d=n[2]!==void 0?n[2]:n[3];d!==void 0&&d!==""&&a.add(d)}let i=new Set(["END","START","__end__","__start__"]);for(let d of this.nodes.keys())i.add(d);if(t&&typeof t=="object")for(let d of Object.keys(t))i.add(d);let u=new Set;for(let d of a)i.has(d)&&u.add(d);if(u.size===0){let d=/return\s+['"]([^'"]+)['"]/g,h;for(;(h=d.exec(r))!==null;)u.add(h[1])}return[...u]}_flattenJsonSchemaToVariables(e,t=""){let r=e;if(e.$ref&&e.definitions){let a=e.$ref.replace("#/definitions/","");r=e.definitions[a]||e}return this._flattenSchema(r,t)}_flattenSchema(e,t=""){if(!e||typeof e!="object")return[];let r=[],a=e.properties||{},s=e.required||[];for(let[n,i]of Object.entries(a)){let u=t?`${t}.${n}`:n;r.push({path:u,type:i.type||"unknown",label:i.description||this._formatLabel(n),optional:!s.includes(n)}),i.type==="object"&&i.properties&&r.push(...this._flattenSchema(i,u)),i.type==="array"&&i.items?.type==="object"&&i.items.properties&&r.push(...this._flattenSchema(i.items,`${u}[]`))}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[a,s]of Object.entries(t))if(!(a==="success"||a==="raw"||a==="nextNode")){if(typeof s=="string"&&s.length<=80)r.push(`${a}: ${s}`);else if(Array.isArray(s)){let n=s.length,i=s.filter(d=>d?.passed===!0).length,u=s.some(d=>d?.passed!==void 0);r.push(u?`${a}: ${i}/${n} passed${n-i?`, ${n-i} failed`:""}`:`${a}: ${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 a=new AbortController;r.signal&&(r.signal.aborted?a.abort():r.signal.addEventListener("abort",()=>a.abort(),{once:!0}));let s=r.strategyAbortTimeoutMs??t.config?.strategyAbortTimeoutMs??5e3,n=t.cwd||process.cwd();$o({path:Y(n,".env")});let i=t.config||{};if(!i||Object.keys(i).length===0)try{let $=Y(n,".zibby.config.js");Ne($)&&(i=(await import($)).default||{})}catch{}process.env.EXECUTION_ID&&!i.agent?.strictMode&&(i.agent={...i.agent,strictMode:!0});let u=t.agentType;if(!u){let $=i?.agent;$?.provider?u=$.provider:$?.gemini?u="gemini":$?.claude?u="claude":$?.cursor?u="cursor":$?.codex?u="codex":u=process.env.AGENT_TYPE||"cursor"}let d=t.contextConfig||e?.config?.contextConfig||e?.config?.context||i?.context||{},h=this._runtimeSchema();if(h){let $=h.safeParse(t);if(!$.success){let P=$.error.issues.map(C=>`${C.path.join(".")}: ${C.message}`);throw console.error("\u274C Initial state validation failed:"),P.forEach(C=>console.error(` - ${C}`)),new Error(`State validation failed: ${P.join(", ")}`)}O.step("State validated against schema")}let l=ko(),c=t.sessionPath||l;c||xo();let{sessionPath:m,sessionTimestamp:S,sessionId:_}=Po({cwd:n,config:i,traceFrom:"WorkflowGraph.run",initialState:{sessionPath:c,sessionTimestamp:t.sessionTimestamp}});O.step(`Session ${_}`);let v=await fe.loadContext(t.specPath||"",n,d);Object.keys(v).length>0&&O.step(`Context loaded: ${Object.keys(v).join(", ")}`);let E=t.outputPath;!E&&t.specPath&&(e?.calculateOutputPath?E=e.calculateOutputPath(t.specPath):console.warn(`\u26A0\uFE0F outputPath not resolved (specPath=${t.specPath})`));let g=new ae({...t,config:i,agentType:u,outputPath:E,sessionPath:m,sessionTimestamp:S,context:v,resolvedTools:this.resolvedToolsMap||{},_signal:a.signal}),f=new Map;try{await import("@zibby/skills")}catch{}let{getSkill:y}=await Promise.resolve().then(()=>(de(),ot)),p=i.skills&&typeof i.skills=="object"?i.skills:{},b=Object.values(p).filter($=>$&&typeof $=="object"&&typeof $.id=="string"),A=$=>{for(let P of b)if(P.id===$)return P;return y($)},R=new Set;for(let[,$]of this.nodes)for(let P of $.config?.skills||[])R.add(P);for(let $ of R){let P=A($);if(typeof P?.middleware=="function")try{let C=await P.middleware();typeof C=="function"&&f.set($,C)}catch{}}let w=this.entryPoint,re=[],Be=i?.recursionLimit??100,xt=0;try{for(;w&&w!=="END";){if(++xt>Be)throw new Error(`Workflow exceeded recursion limit (${Be}) \u2014 likely a cyclic conditional route. Set config.recursionLimit if you need a higher cap.`);let P=Y(m,Qe);if(Ne(P)){try{bo(P)}catch{}a.abort()}if(a.signal.aborted)return console.warn(`
41
+ ${h}`)}}function Ao(){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"}function ko(){if(!(process.env.ZIBBY_PIN_SESSION_PATH==="1"||process.env.ZIBBY_PIN_SESSION_PATH==="true"))return;let e=process.env.ZIBBY_SESSION_PATH;if(!(e==null||String(e).trim()===""))try{return $t(String(e).trim())}catch{return String(e).trim()}}function xo(){Ao()||(delete process.env.ZIBBY_SESSION_PATH,delete process.env.ZIBBY_SESSION_ID)}function Oo({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 No(o={}){let e=et.map(s=>process.env[s]).find(Boolean),t=Math.random().toString(36).slice(2,6),r=e||`${Date.now()}_${t}`,a=o.paths?.sessionPrefix;return a?`${a}_${r}`:r}function Po({cwd:o=process.cwd(),config:e={},initialState:t={},traceFrom:r="resolveWorkflowSession"}={}){let a=t.sessionPath,s=t.sessionTimestamp,n="initialState.sessionPath";if(!a&&process.env.ZIBBY_SESSION_PATH)try{let d=$t(String(process.env.ZIBBY_SESSION_PATH));d&&(a=d,n="ZIBBY_SESSION_PATH")}catch{}let i;if(a)i=String(a).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)i=d,n="ZIBBY_SESSION_ID";else{let l=e.sessionId!=null?String(e.sessionId).trim():"";l&&l!=="last"?(i=l,n="config.sessionId"):(i=No(e),n="generated")}s=s??Date.now();let h=e.paths?.output||ue;a=Y(o,h,Xe,i)}let u=!Ne(a);return u&&bt(a,{recursive:!0}),(u||n!=="initialState.sessionPath")&&To({traceFrom:r,sessionId:i,sessionPath:a,idSource:n,mkdirFresh:u}),Oo({sessionPath:a,sessionId:i}),{sessionPath:a,sessionId:i,sessionTimestamp:s}}var ge=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.inputSchema=e.inputSchema||null,this.contextSchema=e.contextSchema||null,this.nodePrompts=new Map,this.nodeOptions=new Map,this._invokeAgent=e.invokeAgent||null,this._compiledPrompts=new Map}setInputSchema(e){return this.inputSchema=e,this}setContextSchema(e){return this.contextSchema=e,this}setStateSchema(e){return this.stateSchema=e,this}getInputSchema(){return this.inputSchema}getContextSchema(){return this.contextSchema}getStateSchema(){return this.stateSchema}_runtimeSchema(){if(this.inputSchema&&this.contextSchema)try{if(typeof this.inputSchema.merge=="function")return this.inputSchema.merge(this.contextSchema);if(typeof this.inputSchema.and=="function")return this.inputSchema.and(this.contextSchema)}catch{}return this.inputSchema&&!this.contextSchema?this.inputSchema:this.stateSchema}addNode(e,t,r={}){if(!(t instanceof L)&&t&&typeof t=="object"&&typeof t.workflow=="string"){let n=t,i={name:e,_isCustomCode:!0,dispatchesWorkflow:n.workflow,retries:n.retries,onComplete:n.onComplete,execute:async d=>{let h=d?.state&&typeof d.state.getAll=="function"?d.state.getAll():d,l;return typeof n.input=="function"?l=n.input(h):n.input&&typeof n.input=="object"?l=n.input:l={},yt(n.workflow,{input:l,async:n.async===!0,conversationId:typeof n.conversationId=="function"?n.conversationId(h):n.conversationId,output:n.output,timeoutMs:n.timeoutMs,pollIntervalMs:n.pollIntervalMs,signal:h?._signal,parentAgent:d?.agent})}},u=new L(i);return u.name=e,this.nodes.set(e,u),r.prompt&&this.nodePrompts.set(e,r.prompt),Object.keys(r).length>0&&this.nodeOptions.set(e,r),this}let a=!(t instanceof L)&&t&&typeof t=="object"&&typeof t.execute!="function"&&t.prompt==null&&t.outputSchema==null&&t._isCustomCode!==!0,s=t instanceof L?t:new L(a?{...t,_isRouter:!0}:t);return s.name=e,this.nodes.set(e,s),r.prompt?this.nodePrompts.set(e,r.prompt):typeof t?.prompt=="string"&&t.prompt.trim()&&this.nodePrompts.set(e,t.prompt),Object.keys(r).length>0&&this.nodeOptions.set(e,r),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,a,s){let n=r;for(let i=e.length-1;i>=0;i--){let u=e[i],d=n;n=()=>u(t,d,a,s)}return n()}serialize(){let e=[],t={};for(let[l,c]of this.nodes){let m=this.nodeTypeMap.get(l)||(c?.config?._isRouter===!0?"decision":l);e.push({id:l,type:m,data:{nodeType:m,label:l}});let S={};c._isCustomCode&&typeof c.execute=="function"&&(S.customCode=c.execute.toString());let _=typeof c?.config?.description=="string"&&c.config.description.trim()?c.config.description:typeof c?.description=="string"&&c.description.trim()?c.description:null;_&&(S.description=_);let v=this.nodePrompts.get(l);if(v)S.prompt=v;else if(typeof c.prompt=="function")try{let p=c.prompt({});typeof p=="string"&&p.trim()&&(S.prompt=p,S.promptIsCode=!0)}catch{}if(typeof c.customExecute=="function"&&(S.executeCode=c.customExecute.toString()),typeof c?.config?.dispatchesWorkflow=="string"&&c.config.dispatchesWorkflow.trim()&&(S.dispatchesWorkflow=c.config.dispatchesWorkflow.trim()),c.outputSchema)if(typeof c.outputSchema._def<"u"){let p=null;if(typeof he?.toJSONSchema=="function")try{p=he.toJSONSchema(c.outputSchema)}catch{}if(!p)try{p=Et(c.outputSchema,{target:"openApi3"})}catch{}S.outputSchema=p?{jsonSchema:p,variables:this._flattenJsonSchemaToVariables(p)}:{schema:c.outputSchema}}else S.outputSchema={schema:c.outputSchema};let E=(this.resolvedToolsMap||{})[l];E?.toolIds&&(S.tools=E.toolIds);let g=Array.isArray(c?.config?.skills)?c.config.skills:Array.isArray(c?.skills)?c.skills:null;g&&g.length>0&&(S.skills=[...g]);let f=Array.isArray(c?.config?.plugins)?c.config.plugins:Array.isArray(c?.plugins)?c.plugins:null;f&&f.length>0&&(S.plugins=f.map(p=>p&&typeof p=="object"?{...p}:p));let y=Array.isArray(c?.config?.stores)?c.config.stores:Array.isArray(c?.stores)?c.stores:null;y&&y.length>0&&(S.stores=y.map(p=>p&&typeof p=="object"?{...p}:p)),Object.keys(S).length>0&&(t[l]=S)}let r=[];for(let[l,c]of this.edges)if(typeof c=="string")r.push({source:l,target:c});else if(c.conditional){let m=this.conditionalCodeMap.get(l)||c.routes.toString(),S=this._inferConditionalTargets(c.routes,c.labels),_=c.labels||{},v=this.nodes.get(l),E=v?.config?._isRouter===!0||this.nodeTypeMap.get(l)==="decision"||!v,g=l;if(!E){let f=`${l}__branch`;e.push({id:f,type:"decision",data:{nodeType:"decision",label:f}}),r.push({source:l,target:f}),g=f}for(let f of S){let y={source:g,target:f,data:{conditionalCode:m}};_[f]&&(y.label=_[f]),r.push(y)}}let a=l=>{if(!l)return null;if(typeof he?.toJSONSchema=="function")try{return he.toJSONSchema(l)}catch{}try{return Et(l,{target:"openApi3"})}catch{return null}};this.entryPoint&&this.nodes.has(this.entryPoint)&&(e.unshift({id:"START",type:"start",data:{nodeType:"start",label:"Start"}}),r.unshift({source:"START",target:this.entryPoint}));let s=0;for(let l of r)if(l.target==="END"){s+=1;let c=`END__${s}`;l.target=c,e.push({id:c,type:"end",data:{nodeType:"end",label:"End"}})}for(let l of this.nodes.keys())if(!this.edges.has(l)){s+=1;let c=`END__${s}`;e.push({id:c,type:"end",data:{nodeType:"end",label:"End"}}),r.push({source:l,target:c})}let n=this._topoOrderNodes(e,r),i=this._runtimeSchema(),u=a(i||this.stateSchema),d=a(this.inputSchema),h=a(this.contextSchema);return{nodes:n,edges:r,nodeConfigs:t,stateSchema:u,inputSchema:d,contextSchema:h}}_topoOrderNodes(e,t){let r=new Map(e.map((l,c)=>[l.id,c])),a=new Map(e.map(l=>[l.id,l])),s=new Map(e.map(l=>[l.id,0])),n=new Map(e.map(l=>[l.id,[]]));for(let l of t)n.has(l.source)&&s.has(l.target)&&(n.get(l.source).push(l.target),s.set(l.target,s.get(l.target)+1));let i=new Set,u=new Set(r.keys()),d=[...u].filter(l=>s.get(l)===0),h=[];for(;h.length<e.length;){let l;if(d.length>0){if(d.sort((c,m)=>r.get(c)-r.get(m)),l=d.shift(),i.has(l))continue}else l=[...u].sort((c,m)=>r.get(c)-r.get(m))[0];i.add(l),u.delete(l),h.push(a.get(l));for(let c of n.get(l)||[])s.set(c,s.get(c)-1),s.get(c)<=0&&!i.has(c)&&d.push(c)}return h}_inferConditionalTargets(e,t){let r=e.toString(),a=new Set,s=/(['"])((?:\\.|(?!\1).)*?)\1|`((?:\\.|[^`$]|\$(?!\{))*?)`/g,n;for(;(n=s.exec(r))!==null;){let d=n[2]!==void 0?n[2]:n[3];d!==void 0&&d!==""&&a.add(d)}let i=new Set(["END","START","__end__","__start__"]);for(let d of this.nodes.keys())i.add(d);if(t&&typeof t=="object")for(let d of Object.keys(t))i.add(d);let u=new Set;for(let d of a)i.has(d)&&u.add(d);if(u.size===0){let d=/return\s+['"]([^'"]+)['"]/g,h;for(;(h=d.exec(r))!==null;)u.add(h[1])}return[...u]}_flattenJsonSchemaToVariables(e,t=""){let r=e;if(e.$ref&&e.definitions){let a=e.$ref.replace("#/definitions/","");r=e.definitions[a]||e}return this._flattenSchema(r,t)}_flattenSchema(e,t=""){if(!e||typeof e!="object")return[];let r=[],a=e.properties||{},s=e.required||[];for(let[n,i]of Object.entries(a)){let u=t?`${t}.${n}`:n;r.push({path:u,type:i.type||"unknown",label:i.description||this._formatLabel(n),optional:!s.includes(n)}),i.type==="object"&&i.properties&&r.push(...this._flattenSchema(i,u)),i.type==="array"&&i.items?.type==="object"&&i.items.properties&&r.push(...this._flattenSchema(i.items,`${u}[]`))}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[a,s]of Object.entries(t))if(!(a==="success"||a==="raw"||a==="nextNode")){if(typeof s=="string"&&s.length<=80)r.push(`${a}: ${s}`);else if(Array.isArray(s)){let n=s.length,i=s.filter(d=>d?.passed===!0).length,u=s.some(d=>d?.passed!==void 0);r.push(u?`${a}: ${i}/${n} passed${n-i?`, ${n-i} failed`:""}`:`${a}: ${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 a=new AbortController;r.signal&&(r.signal.aborted?a.abort():r.signal.addEventListener("abort",()=>a.abort(),{once:!0}));let s=r.strategyAbortTimeoutMs??t.config?.strategyAbortTimeoutMs??5e3,n=t.cwd||process.cwd();$o({path:Y(n,".env")});let i=t.config||{};if(!i||Object.keys(i).length===0)try{let $=Y(n,".zibby.config.js");Ne($)&&(i=(await import($)).default||{})}catch{}process.env.EXECUTION_ID&&!i.agent?.strictMode&&(i.agent={...i.agent,strictMode:!0});let u=t.agentType;if(!u){let $=i?.agent;$?.provider?u=$.provider:$?.gemini?u="gemini":$?.claude?u="claude":$?.cursor?u="cursor":$?.codex?u="codex":u=process.env.AGENT_TYPE||"claude"}let d=t.contextConfig||e?.config?.contextConfig||e?.config?.context||i?.context||{},h=this._runtimeSchema();if(h){let $=h.safeParse(t);if(!$.success){let P=$.error.issues.map(C=>`${C.path.join(".")}: ${C.message}`);throw console.error("\u274C Initial state validation failed:"),P.forEach(C=>console.error(` - ${C}`)),new Error(`State validation failed: ${P.join(", ")}`)}O.step("State validated against schema")}let l=ko(),c=t.sessionPath||l;c||xo();let{sessionPath:m,sessionTimestamp:S,sessionId:_}=Po({cwd:n,config:i,traceFrom:"WorkflowGraph.run",initialState:{sessionPath:c,sessionTimestamp:t.sessionTimestamp}});O.step(`Session ${_}`);let v=await fe.loadContext(t.specPath||"",n,d);Object.keys(v).length>0&&O.step(`Context loaded: ${Object.keys(v).join(", ")}`);let E=t.outputPath;!E&&t.specPath&&(e?.calculateOutputPath?E=e.calculateOutputPath(t.specPath):console.warn(`\u26A0\uFE0F outputPath not resolved (specPath=${t.specPath})`));let g=new ae({...t,config:i,agentType:u,outputPath:E,sessionPath:m,sessionTimestamp:S,context:v,resolvedTools:this.resolvedToolsMap||{},_signal:a.signal}),f=new Map;try{await import("@zibby/skills")}catch{}let{getSkill:y}=await Promise.resolve().then(()=>(de(),ot)),p=i.skills&&typeof i.skills=="object"?i.skills:{},b=Object.values(p).filter($=>$&&typeof $=="object"&&typeof $.id=="string"),A=$=>{for(let P of b)if(P.id===$)return P;return y($)},R=new Set;for(let[,$]of this.nodes)for(let P of $.config?.skills||[])R.add(P);for(let $ of R){let P=A($);if(typeof P?.middleware=="function")try{let C=await P.middleware();typeof C=="function"&&f.set($,C)}catch{}}let w=this.entryPoint,re=[],Be=i?.recursionLimit??100,xt=0;try{for(;w&&w!=="END";){if(++xt>Be)throw new Error(`Workflow exceeded recursion limit (${Be}) \u2014 likely a cyclic conditional route. Set config.recursionLimit if you need a higher cap.`);let P=Y(m,Qe);if(Ne(P)){try{bo(P)}catch{}a.abort()}if(a.signal.aborted)return console.warn(`
42
42
  \u{1F6D1} External stop requested \u2014 ending workflow.`),O.step("Workflow stopped externally"),{success:!0,state:g.getAll(),executionLog:re,stoppedExternally:!0};let C=this.nodes.get(w);if(!C)throw new Error(`Node '${w}' not found in graph`);let Me=JSON.stringify({sessionPath:m,sessionTimestamp:S,currentNode:w,createdAt:new Date().toISOString(),config:g.get("config")}),Ot=Y(m,K);It(Ot,Me,"utf-8");let De=g.get("config")?.paths?.output||ue,Nt=Y(n,De,K);bt(Y(n,De),{recursive:!0});try{It(Nt,Me,"utf-8")}catch{}let je=t.onPipelineProgress;if(typeof je=="function")try{je({cwd:n,sessionPath:m,sessionId:_,outputBase:g.get("config")?.paths?.output||ue,currentNode:w})}catch{}let Pt=(this.resolvedToolsMap||{})[w]||null;g.set("_currentNodeTools",Pt);let Ct=g.get("nodeConfigs")||{};g.set("_currentNodeConfig",Ct[w]||{}),O.nodeStart(w);let Le=Date.now(),ne=this.nodePrompts.get(w);if(!this._invokeAgent){let k=await Promise.resolve().then(()=>(te(),ee));this._invokeAgent=k.invokeAgent}let Rt=this._invokeAgent,Se={},Bt=C.config?.skills||[];for(let k of Bt){let B=A(k);if(typeof B?.invokeAgentOptions=="function")try{let T=B.invokeAgentOptions(g.getAll(),{agentType:g.get("agentType"),nodeName:w});T&&typeof T=="object"&&(Se={...Se,...T})}catch(T){console.warn(`[graph] skill '${k}' invokeAgentOptions threw: ${T.message}`)}}let Ue=async(k,B,T={})=>{let M=Rt(k,B,{...Se,...T,signal:a.signal});return M.catch(()=>{}),a.signal.aborted?M:Promise.race([M,new Promise((Z,z)=>{let j=()=>{setTimeout(()=>{let V=new Error(`Strategy ignored AbortSignal \u2014 engine deadman fired after ${s}ms`);V.name="AbortError",z(V)},s)};a.signal.addEventListener("abort",j,{once:!0})})])},Mt=async(k={},B={})=>{let T=B.prompt||"";if(ne){let M=this._compiledPrompts.get(w);M||(M=vo.compile(ne,{noEscape:!0}),this._compiledPrompts.set(w,M));try{T=M(k)}catch(Z){throw console.error(`\u274C Template rendering failed for node '${w}':`,Z.message),new Error(`Template rendering failed: ${Z.message}`,{cause:Z})}}else if(!T)throw new Error(`No prompt template configured for node '${w}' and no prompt provided in options`);return Ue(T,{state:g.getAll(),images:B.images||[]},{model:B.model||g.get("model"),workspace:g.get("workspace"),schema:B.schema,...B,signal:a.signal})},We=g.getAll(),Dt=["state","invokeAgent","_coreInvokeAgent","agent","nodeId","promptTemplate","getPromptTemplate"];for(let k of Dt)Object.prototype.hasOwnProperty.call(We,k)&&console.warn(`[workflow] node "${w}": state key "${k}" is shadowed by the engine context prop; read it via context.state.get('${k}')`);let Ge={...We,state:g,invokeAgent:Mt,_coreInvokeAgent:Ue,agent:e,nodeId:w,promptTemplate:ne,getPromptTemplate:()=>ne};try{let k=(C.config?.skills||[]).map(j=>f.get(j)).filter(Boolean),B=[...this.middleware,...k],T;B.length>0?T=await this._composeMiddleware(B,w,async()=>C.execute(Ge,g),g.getAll(),g):T=await C.execute(Ge,g);let M=Date.now()-Le;if(re.push({node:w,success:T.success,duration:M,timestamp:new Date().toISOString()}),!T.success){if(a.signal.aborted)return O.step("Workflow stopped externally"),{success:!0,state:g.getAll(),executionLog:re,stoppedExternally:!0};g.append("errors",{node:w,error:T.error});let j=C.config?.retries||0,V=`${w}_retries`,se=g.getAll()[V]||0;if(se<j){O.stepInfo(`Retrying (attempt ${se+1}/${j})`),g.update({[V]:se+1,[`${w}_raw`]:T.raw});continue}throw O.nodeFailed(w,T.error,{duration:M}),new Error(`Node '${w}' failed after ${se} attempts: ${T.error}`)}g.update({[w]:T.output});let Z=this._summarizeNodeOutput(w,T.output);O.nodeComplete(w,{duration:M,details:Z});let z=this.edges.get(w);if(!z)w="END";else if(z.conditional){let j=z.routes(g.getAll());O.route(w,j),w=j}else w=z}catch(k){throw O.isInsideNode&&O.nodeFailed(w,k.message,{duration:Date.now()-Le}),g.set("failed",!0),g.set("failedAt",w),k}}O.graphComplete();let $={success:!0,state:g.getAll(),executionLog:re};return e&&typeof e.onComplete=="function"&&await e.onComplete($),$}finally{if(e&&typeof e.cleanup=="function")try{await e.cleanup()}catch($){console.warn(`[workflow] agent.cleanup() failed: ${$.message}`)}}}};var Pe=Symbol.for("@zibby/agent-workflow.nodes");globalThis[Pe]||(globalThis[Pe]=new Map);var Ce=globalThis[Pe];function Co(o,e){Ce.set(o,e)}function vt(o){return Ce.get(o)}function Re(o){return Ce.has(o)}Co("ai_agent",{name:"ai_agent",factory:!0,create:(o,e={})=>({name:o,_isCustomCode:!0,execute:async t=>{let r=t?._coreInvokeAgent;r||(r=(await Promise.resolve().then(()=>(te(),ee))).invokeAgent);let a=e.extraPromptInstructions||"Execute the task based on the current state.",s=Ro(a,t),n=await r(s,{cwd:t.workspace||process.cwd(),model:t.model,tools:e.resolvedTools||null});return{success:!0,output:{raw:n,nodeId:o},raw:typeof n=="string"?n:n.raw}}})});function Ro(o,e){let t=/@([\w.]+)/g,r=new Set,a;for(;(a=t.exec(o))!==null;)r.add(a[1]);if(r.size===0)return o;let s=[],n=new Set;for(let i of r){let u=i.split(".")[0];if(n.has(u))continue;let d=i.split(".").reduce((c,m)=>c?.[m],e);if(d===void 0)continue;let h=typeof d=="string"?d:d?.raw??JSON.stringify(d,null,2),l=i.replace(/_/g," ").replace(/\b\w/g,c=>c.toUpperCase());s.push(`## ${l}
43
43
  ${h}`),i.includes(".")||n.add(u)}return s.length===0?o:`${o}
44
44
 
package/dist/graph.js CHANGED
@@ -38,5 +38,5 @@ ${i}`);let a=r(),u=a.cwd||process.cwd(),p=a.sessionPath;try{if(p){let c=Et(p,Z);
38
38
  `):s.every(n=>typeof n=="object")?Object.assign({},...s):s[s.length-1]}static async loadFile(t){let e=pr(t,"utf-8");if(t.endsWith(".json"))return JSON.parse(e);if(t.endsWith(".js")||t.endsWith(".mjs")){let{pathToFileURL:r}=await import("url"),s=await import(r(t).href);return s.default||s}return e}};import{mkdirSync as Se,existsSync as vt,writeFileSync as he,unlinkSync as dr}from"node:fs";import{join as H,resolve as ye}from"node:path";import{config as fr}from"dotenv";import{zodToJsonSchema as ge}from"zod-to-json-schema";import{z as lt}from"zod";import hr from"handlebars";function gr({traceFrom:o,sessionId:t,sessionPath:e,idSource:r,mkdirFresh:s}){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=${o} pid=${process.pid} ppid=${n} sessionId=${t} source=${r} mkdir=${s?"yes":"no"} path=${e}`;if(console.log(a),process.env.ZIBBY_TRACE_SESSION==="1"||process.env.ZIBBY_TRACE_SESSION==="true"){let g=(new Error("session trace").stack||"").split(`
39
39
  `).slice(2,14).join(`
40
40
  `);console.log(`[zibby:session] stack (${o}):
41
- ${g}`)}}function mr(){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"}function Sr(){if(!(process.env.ZIBBY_PIN_SESSION_PATH==="1"||process.env.ZIBBY_PIN_SESSION_PATH==="true"))return;let t=process.env.ZIBBY_SESSION_PATH;if(!(t==null||String(t).trim()===""))try{return ye(String(t).trim())}catch{return String(t).trim()}}function yr(){mr()||(delete process.env.ZIBBY_SESSION_PATH,delete process.env.ZIBBY_SESSION_ID)}function wr({sessionPath:o,sessionId:t}){o&&typeof o=="string"&&(process.env.ZIBBY_SESSION_PATH=o),t!=null&&String(t).trim()!==""&&(process.env.ZIBBY_SESSION_ID=String(t).trim())}function _r(o={}){let t=Zt.map(i=>process.env[i]).find(Boolean),e=Math.random().toString(36).slice(2,6),r=t||`${Date.now()}_${e}`,s=o.paths?.sessionPrefix;return s?`${s}_${r}`:r}function Ir({cwd:o=process.cwd(),config:t={},initialState:e={},traceFrom:r="resolveWorkflowSession"}={}){let s=e.sessionPath,i=e.sessionTimestamp,n="initialState.sessionPath";if(!s&&process.env.ZIBBY_SESSION_PATH)try{let p=ye(String(process.env.ZIBBY_SESSION_PATH));p&&(s=p,n="ZIBBY_SESSION_PATH")}catch{}let a;if(s)a=String(s).split(/[/\\]/).filter(Boolean).pop(),i==null&&(i=Date.now());else{let p=process.env.ZIBBY_SESSION_ID&&String(process.env.ZIBBY_SESSION_ID).trim();if(p)a=p,n="ZIBBY_SESSION_ID";else{let c=t.sessionId!=null?String(t.sessionId).trim():"";c&&c!=="last"?(a=c,n="config.sessionId"):(a=_r(t),n="generated")}i=i??Date.now();let g=t.paths?.output||it;s=H(o,g,Jt,a)}let u=!vt(s);return u&&Se(s,{recursive:!0}),(u||n!=="initialState.sessionPath")&&gr({traceFrom:r,sessionId:a,sessionPath:s,idSource:n,mkdirFresh:u}),wr({sessionPath:s,sessionId:a}),{sessionPath:s,sessionId:a,sessionTimestamp:i}}var me=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.inputSchema=t.inputSchema||null,this.contextSchema=t.contextSchema||null,this.nodePrompts=new Map,this.nodeOptions=new Map,this._invokeAgent=t.invokeAgent||null,this._compiledPrompts=new Map}setInputSchema(t){return this.inputSchema=t,this}setContextSchema(t){return this.contextSchema=t,this}setStateSchema(t){return this.stateSchema=t,this}getInputSchema(){return this.inputSchema}getContextSchema(){return this.contextSchema}getStateSchema(){return this.stateSchema}_runtimeSchema(){if(this.inputSchema&&this.contextSchema)try{if(typeof this.inputSchema.merge=="function")return this.inputSchema.merge(this.contextSchema);if(typeof this.inputSchema.and=="function")return this.inputSchema.and(this.contextSchema)}catch{}return this.inputSchema&&!this.contextSchema?this.inputSchema:this.stateSchema}addNode(t,e,r={}){if(!(e instanceof L)&&e&&typeof e=="object"&&typeof e.workflow=="string"){let n=e,a={name:t,_isCustomCode:!0,dispatchesWorkflow:n.workflow,retries:n.retries,onComplete:n.onComplete,execute:async p=>{let g=p?.state&&typeof p.state.getAll=="function"?p.state.getAll():p,c;return typeof n.input=="function"?c=n.input(g):n.input&&typeof n.input=="object"?c=n.input:c={},pe(n.workflow,{input:c,async:n.async===!0,conversationId:typeof n.conversationId=="function"?n.conversationId(g):n.conversationId,output:n.output,timeoutMs:n.timeoutMs,pollIntervalMs:n.pollIntervalMs,signal:g?._signal,parentAgent:p?.agent})}},u=new L(a);return u.name=t,this.nodes.set(t,u),r.prompt&&this.nodePrompts.set(t,r.prompt),Object.keys(r).length>0&&this.nodeOptions.set(t,r),this}let s=!(e instanceof L)&&e&&typeof e=="object"&&typeof e.execute!="function"&&e.prompt==null&&e.outputSchema==null&&e._isCustomCode!==!0,i=e instanceof L?e:new L(s?{...e,_isRouter:!0}:e);return i.name=t,this.nodes.set(t,i),r.prompt?this.nodePrompts.set(t,r.prompt):typeof e?.prompt=="string"&&e.prompt.trim()&&this.nodePrompts.set(t,e.prompt),Object.keys(r).length>0&&this.nodeOptions.set(t,r),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:r}={}){return this.edges.set(t,{conditional:!0,routes:e,labels:r}),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,r,s,i){let n=r;for(let a=t.length-1;a>=0;a--){let u=t[a],p=n;n=()=>u(e,p,s,i)}return n()}serialize(){let t=[],e={};for(let[c,l]of this.nodes){let y=this.nodeTypeMap.get(c)||(l?.config?._isRouter===!0?"decision":c);t.push({id:c,type:y,data:{nodeType:y,label:c}});let w={};l._isCustomCode&&typeof l.execute=="function"&&(w.customCode=l.execute.toString());let $=typeof l?.config?.description=="string"&&l.config.description.trim()?l.config.description:typeof l?.description=="string"&&l.description.trim()?l.description:null;$&&(w.description=$);let v=this.nodePrompts.get(c);if(v)w.prompt=v;else if(typeof l.prompt=="function")try{let d=l.prompt({});typeof d=="string"&&d.trim()&&(w.prompt=d,w.promptIsCode=!0)}catch{}if(typeof l.customExecute=="function"&&(w.executeCode=l.customExecute.toString()),typeof l?.config?.dispatchesWorkflow=="string"&&l.config.dispatchesWorkflow.trim()&&(w.dispatchesWorkflow=l.config.dispatchesWorkflow.trim()),l.outputSchema)if(typeof l.outputSchema._def<"u"){let d=null;if(typeof lt?.toJSONSchema=="function")try{d=lt.toJSONSchema(l.outputSchema)}catch{}if(!d)try{d=ge(l.outputSchema,{target:"openApi3"})}catch{}w.outputSchema=d?{jsonSchema:d,variables:this._flattenJsonSchemaToVariables(d)}:{schema:l.outputSchema}}else w.outputSchema={schema:l.outputSchema};let b=(this.resolvedToolsMap||{})[c];b?.toolIds&&(w.tools=b.toolIds);let h=Array.isArray(l?.config?.skills)?l.config.skills:Array.isArray(l?.skills)?l.skills:null;h&&h.length>0&&(w.skills=[...h]);let f=Array.isArray(l?.config?.plugins)?l.config.plugins:Array.isArray(l?.plugins)?l.plugins:null;f&&f.length>0&&(w.plugins=f.map(d=>d&&typeof d=="object"?{...d}:d));let m=Array.isArray(l?.config?.stores)?l.config.stores:Array.isArray(l?.stores)?l.stores:null;m&&m.length>0&&(w.stores=m.map(d=>d&&typeof d=="object"?{...d}:d)),Object.keys(w).length>0&&(e[c]=w)}let r=[];for(let[c,l]of this.edges)if(typeof l=="string")r.push({source:c,target:l});else if(l.conditional){let y=this.conditionalCodeMap.get(c)||l.routes.toString(),w=this._inferConditionalTargets(l.routes,l.labels),$=l.labels||{},v=this.nodes.get(c),b=v?.config?._isRouter===!0||this.nodeTypeMap.get(c)==="decision"||!v,h=c;if(!b){let f=`${c}__branch`;t.push({id:f,type:"decision",data:{nodeType:"decision",label:f}}),r.push({source:c,target:f}),h=f}for(let f of w){let m={source:h,target:f,data:{conditionalCode:y}};$[f]&&(m.label=$[f]),r.push(m)}}let s=c=>{if(!c)return null;if(typeof lt?.toJSONSchema=="function")try{return lt.toJSONSchema(c)}catch{}try{return ge(c,{target:"openApi3"})}catch{return null}};this.entryPoint&&this.nodes.has(this.entryPoint)&&(t.unshift({id:"START",type:"start",data:{nodeType:"start",label:"Start"}}),r.unshift({source:"START",target:this.entryPoint}));let i=0;for(let c of r)if(c.target==="END"){i+=1;let l=`END__${i}`;c.target=l,t.push({id:l,type:"end",data:{nodeType:"end",label:"End"}})}for(let c of this.nodes.keys())if(!this.edges.has(c)){i+=1;let l=`END__${i}`;t.push({id:l,type:"end",data:{nodeType:"end",label:"End"}}),r.push({source:c,target:l})}let n=this._topoOrderNodes(t,r),a=this._runtimeSchema(),u=s(a||this.stateSchema),p=s(this.inputSchema),g=s(this.contextSchema);return{nodes:n,edges:r,nodeConfigs:e,stateSchema:u,inputSchema:p,contextSchema:g}}_topoOrderNodes(t,e){let r=new Map(t.map((c,l)=>[c.id,l])),s=new Map(t.map(c=>[c.id,c])),i=new Map(t.map(c=>[c.id,0])),n=new Map(t.map(c=>[c.id,[]]));for(let c of e)n.has(c.source)&&i.has(c.target)&&(n.get(c.source).push(c.target),i.set(c.target,i.get(c.target)+1));let a=new Set,u=new Set(r.keys()),p=[...u].filter(c=>i.get(c)===0),g=[];for(;g.length<t.length;){let c;if(p.length>0){if(p.sort((l,y)=>r.get(l)-r.get(y)),c=p.shift(),a.has(c))continue}else c=[...u].sort((l,y)=>r.get(l)-r.get(y))[0];a.add(c),u.delete(c),g.push(s.get(c));for(let l of n.get(c)||[])i.set(l,i.get(l)-1),i.get(l)<=0&&!a.has(l)&&p.push(l)}return g}_inferConditionalTargets(t,e){let r=t.toString(),s=new Set,i=/(['"])((?:\\.|(?!\1).)*?)\1|`((?:\\.|[^`$]|\$(?!\{))*?)`/g,n;for(;(n=i.exec(r))!==null;){let p=n[2]!==void 0?n[2]:n[3];p!==void 0&&p!==""&&s.add(p)}let a=new Set(["END","START","__end__","__start__"]);for(let p of this.nodes.keys())a.add(p);if(e&&typeof e=="object")for(let p of Object.keys(e))a.add(p);let u=new Set;for(let p of s)a.has(p)&&u.add(p);if(u.size===0){let p=/return\s+['"]([^'"]+)['"]/g,g;for(;(g=p.exec(r))!==null;)u.add(g[1])}return[...u]}_flattenJsonSchemaToVariables(t,e=""){let r=t;if(t.$ref&&t.definitions){let s=t.$ref.replace("#/definitions/","");r=t.definitions[s]||t}return this._flattenSchema(r,e)}_flattenSchema(t,e=""){if(!t||typeof t!="object")return[];let r=[],s=t.properties||{},i=t.required||[];for(let[n,a]of Object.entries(s)){let u=e?`${e}.${n}`:n;r.push({path:u,type:a.type||"unknown",label:a.description||this._formatLabel(n),optional:!i.includes(n)}),a.type==="object"&&a.properties&&r.push(...this._flattenSchema(a,u)),a.type==="array"&&a.items?.type==="object"&&a.items.properties&&r.push(...this._flattenSchema(a.items,`${u}[]`))}return r}_formatLabel(t){return t.replace(/([A-Z])/g," $1").replace(/^./,e=>e.toUpperCase()).trim()}_summarizeNodeOutput(t,e){if(!e||typeof e!="object")return[];let r=[];e.success!==void 0&&r.push(`Result: ${e.success?"passed":"failed"}`);for(let[s,i]of Object.entries(e))if(!(s==="success"||s==="raw"||s==="nextNode")){if(typeof i=="string"&&i.length<=80)r.push(`${s}: ${i}`);else if(Array.isArray(i)){let n=i.length,a=i.filter(p=>p?.passed===!0).length,u=i.some(p=>p?.passed!==void 0);r.push(u?`${s}: ${a}/${n} passed${n-a?`, ${n-a} failed`:""}`:`${s}: ${n} items`)}if(r.length>=4)break}return r}async run(t,e={},r={}){if(!this.entryPoint)throw new Error("No entry point set for graph");let s=new AbortController;r.signal&&(r.signal.aborted?s.abort():r.signal.addEventListener("abort",()=>s.abort(),{once:!0}));let i=r.strategyAbortTimeoutMs??e.config?.strategyAbortTimeoutMs??5e3,n=e.cwd||process.cwd();fr({path:H(n,".env")});let a=e.config||{};if(!a||Object.keys(a).length===0)try{let E=H(n,".zibby.config.js");vt(E)&&(a=(await import(E)).default||{})}catch{}process.env.EXECUTION_ID&&!a.agent?.strictMode&&(a.agent={...a.agent,strictMode:!0});let u=e.agentType;if(!u){let E=a?.agent;E?.provider?u=E.provider:E?.gemini?u="gemini":E?.claude?u="claude":E?.cursor?u="cursor":E?.codex?u="codex":u=process.env.AGENT_TYPE||"cursor"}let p=e.contextConfig||t?.config?.contextConfig||t?.config?.context||a?.context||{},g=this._runtimeSchema();if(g){let E=g.safeParse(e);if(!E.success){let N=E.error.issues.map(R=>`${R.path.join(".")}: ${R.message}`);throw console.error("\u274C Initial state validation failed:"),N.forEach(R=>console.error(` - ${R}`)),new Error(`State validation failed: ${N.join(", ")}`)}x.step("State validated against schema")}let c=Sr(),l=e.sessionPath||c;l||yr();let{sessionPath:y,sessionTimestamp:w,sessionId:$}=Ir({cwd:n,config:a,traceFrom:"WorkflowGraph.run",initialState:{sessionPath:l,sessionTimestamp:e.sessionTimestamp}});x.step(`Session ${$}`);let v=await ct.loadContext(e.specPath||"",n,p);Object.keys(v).length>0&&x.step(`Context loaded: ${Object.keys(v).join(", ")}`);let b=e.outputPath;!b&&e.specPath&&(t?.calculateOutputPath?b=t.calculateOutputPath(e.specPath):console.warn(`\u26A0\uFE0F outputPath not resolved (specPath=${e.specPath})`));let h=new ot({...e,config:a,agentType:u,outputPath:b,sessionPath:y,sessionTimestamp:w,context:v,resolvedTools:this.resolvedToolsMap||{},_signal:s.signal}),f=new Map;try{await import("@zibby/skills")}catch{}let{getSkill:m}=await Promise.resolve().then(()=>(St(),Kt)),d=a.skills&&typeof a.skills=="object"?a.skills:{},I=Object.values(d).filter(E=>E&&typeof E=="object"&&typeof E.id=="string"),A=E=>{for(let N of I)if(N.id===E)return N;return m(E)},B=new Set;for(let[,E]of this.nodes)for(let N of E.config?.skills||[])B.add(N);for(let E of B){let N=A(E);if(typeof N?.middleware=="function")try{let R=await N.middleware();typeof R=="function"&&f.set(E,R)}catch{}}let S=this.entryPoint,Q=[],kt=a?.recursionLimit??100,we=0;try{for(;S&&S!=="END";){if(++we>kt)throw new Error(`Workflow exceeded recursion limit (${kt}) \u2014 likely a cyclic conditional route. Set config.recursionLimit if you need a higher cap.`);let N=H(y,Yt);if(vt(N)){try{dr(N)}catch{}s.abort()}if(s.signal.aborted)return console.warn(`
41
+ ${g}`)}}function mr(){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"}function Sr(){if(!(process.env.ZIBBY_PIN_SESSION_PATH==="1"||process.env.ZIBBY_PIN_SESSION_PATH==="true"))return;let t=process.env.ZIBBY_SESSION_PATH;if(!(t==null||String(t).trim()===""))try{return ye(String(t).trim())}catch{return String(t).trim()}}function yr(){mr()||(delete process.env.ZIBBY_SESSION_PATH,delete process.env.ZIBBY_SESSION_ID)}function wr({sessionPath:o,sessionId:t}){o&&typeof o=="string"&&(process.env.ZIBBY_SESSION_PATH=o),t!=null&&String(t).trim()!==""&&(process.env.ZIBBY_SESSION_ID=String(t).trim())}function _r(o={}){let t=Zt.map(i=>process.env[i]).find(Boolean),e=Math.random().toString(36).slice(2,6),r=t||`${Date.now()}_${e}`,s=o.paths?.sessionPrefix;return s?`${s}_${r}`:r}function Ir({cwd:o=process.cwd(),config:t={},initialState:e={},traceFrom:r="resolveWorkflowSession"}={}){let s=e.sessionPath,i=e.sessionTimestamp,n="initialState.sessionPath";if(!s&&process.env.ZIBBY_SESSION_PATH)try{let p=ye(String(process.env.ZIBBY_SESSION_PATH));p&&(s=p,n="ZIBBY_SESSION_PATH")}catch{}let a;if(s)a=String(s).split(/[/\\]/).filter(Boolean).pop(),i==null&&(i=Date.now());else{let p=process.env.ZIBBY_SESSION_ID&&String(process.env.ZIBBY_SESSION_ID).trim();if(p)a=p,n="ZIBBY_SESSION_ID";else{let c=t.sessionId!=null?String(t.sessionId).trim():"";c&&c!=="last"?(a=c,n="config.sessionId"):(a=_r(t),n="generated")}i=i??Date.now();let g=t.paths?.output||it;s=H(o,g,Jt,a)}let u=!vt(s);return u&&Se(s,{recursive:!0}),(u||n!=="initialState.sessionPath")&&gr({traceFrom:r,sessionId:a,sessionPath:s,idSource:n,mkdirFresh:u}),wr({sessionPath:s,sessionId:a}),{sessionPath:s,sessionId:a,sessionTimestamp:i}}var me=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.inputSchema=t.inputSchema||null,this.contextSchema=t.contextSchema||null,this.nodePrompts=new Map,this.nodeOptions=new Map,this._invokeAgent=t.invokeAgent||null,this._compiledPrompts=new Map}setInputSchema(t){return this.inputSchema=t,this}setContextSchema(t){return this.contextSchema=t,this}setStateSchema(t){return this.stateSchema=t,this}getInputSchema(){return this.inputSchema}getContextSchema(){return this.contextSchema}getStateSchema(){return this.stateSchema}_runtimeSchema(){if(this.inputSchema&&this.contextSchema)try{if(typeof this.inputSchema.merge=="function")return this.inputSchema.merge(this.contextSchema);if(typeof this.inputSchema.and=="function")return this.inputSchema.and(this.contextSchema)}catch{}return this.inputSchema&&!this.contextSchema?this.inputSchema:this.stateSchema}addNode(t,e,r={}){if(!(e instanceof L)&&e&&typeof e=="object"&&typeof e.workflow=="string"){let n=e,a={name:t,_isCustomCode:!0,dispatchesWorkflow:n.workflow,retries:n.retries,onComplete:n.onComplete,execute:async p=>{let g=p?.state&&typeof p.state.getAll=="function"?p.state.getAll():p,c;return typeof n.input=="function"?c=n.input(g):n.input&&typeof n.input=="object"?c=n.input:c={},pe(n.workflow,{input:c,async:n.async===!0,conversationId:typeof n.conversationId=="function"?n.conversationId(g):n.conversationId,output:n.output,timeoutMs:n.timeoutMs,pollIntervalMs:n.pollIntervalMs,signal:g?._signal,parentAgent:p?.agent})}},u=new L(a);return u.name=t,this.nodes.set(t,u),r.prompt&&this.nodePrompts.set(t,r.prompt),Object.keys(r).length>0&&this.nodeOptions.set(t,r),this}let s=!(e instanceof L)&&e&&typeof e=="object"&&typeof e.execute!="function"&&e.prompt==null&&e.outputSchema==null&&e._isCustomCode!==!0,i=e instanceof L?e:new L(s?{...e,_isRouter:!0}:e);return i.name=t,this.nodes.set(t,i),r.prompt?this.nodePrompts.set(t,r.prompt):typeof e?.prompt=="string"&&e.prompt.trim()&&this.nodePrompts.set(t,e.prompt),Object.keys(r).length>0&&this.nodeOptions.set(t,r),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:r}={}){return this.edges.set(t,{conditional:!0,routes:e,labels:r}),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,r,s,i){let n=r;for(let a=t.length-1;a>=0;a--){let u=t[a],p=n;n=()=>u(e,p,s,i)}return n()}serialize(){let t=[],e={};for(let[c,l]of this.nodes){let y=this.nodeTypeMap.get(c)||(l?.config?._isRouter===!0?"decision":c);t.push({id:c,type:y,data:{nodeType:y,label:c}});let w={};l._isCustomCode&&typeof l.execute=="function"&&(w.customCode=l.execute.toString());let $=typeof l?.config?.description=="string"&&l.config.description.trim()?l.config.description:typeof l?.description=="string"&&l.description.trim()?l.description:null;$&&(w.description=$);let v=this.nodePrompts.get(c);if(v)w.prompt=v;else if(typeof l.prompt=="function")try{let d=l.prompt({});typeof d=="string"&&d.trim()&&(w.prompt=d,w.promptIsCode=!0)}catch{}if(typeof l.customExecute=="function"&&(w.executeCode=l.customExecute.toString()),typeof l?.config?.dispatchesWorkflow=="string"&&l.config.dispatchesWorkflow.trim()&&(w.dispatchesWorkflow=l.config.dispatchesWorkflow.trim()),l.outputSchema)if(typeof l.outputSchema._def<"u"){let d=null;if(typeof lt?.toJSONSchema=="function")try{d=lt.toJSONSchema(l.outputSchema)}catch{}if(!d)try{d=ge(l.outputSchema,{target:"openApi3"})}catch{}w.outputSchema=d?{jsonSchema:d,variables:this._flattenJsonSchemaToVariables(d)}:{schema:l.outputSchema}}else w.outputSchema={schema:l.outputSchema};let b=(this.resolvedToolsMap||{})[c];b?.toolIds&&(w.tools=b.toolIds);let h=Array.isArray(l?.config?.skills)?l.config.skills:Array.isArray(l?.skills)?l.skills:null;h&&h.length>0&&(w.skills=[...h]);let f=Array.isArray(l?.config?.plugins)?l.config.plugins:Array.isArray(l?.plugins)?l.plugins:null;f&&f.length>0&&(w.plugins=f.map(d=>d&&typeof d=="object"?{...d}:d));let m=Array.isArray(l?.config?.stores)?l.config.stores:Array.isArray(l?.stores)?l.stores:null;m&&m.length>0&&(w.stores=m.map(d=>d&&typeof d=="object"?{...d}:d)),Object.keys(w).length>0&&(e[c]=w)}let r=[];for(let[c,l]of this.edges)if(typeof l=="string")r.push({source:c,target:l});else if(l.conditional){let y=this.conditionalCodeMap.get(c)||l.routes.toString(),w=this._inferConditionalTargets(l.routes,l.labels),$=l.labels||{},v=this.nodes.get(c),b=v?.config?._isRouter===!0||this.nodeTypeMap.get(c)==="decision"||!v,h=c;if(!b){let f=`${c}__branch`;t.push({id:f,type:"decision",data:{nodeType:"decision",label:f}}),r.push({source:c,target:f}),h=f}for(let f of w){let m={source:h,target:f,data:{conditionalCode:y}};$[f]&&(m.label=$[f]),r.push(m)}}let s=c=>{if(!c)return null;if(typeof lt?.toJSONSchema=="function")try{return lt.toJSONSchema(c)}catch{}try{return ge(c,{target:"openApi3"})}catch{return null}};this.entryPoint&&this.nodes.has(this.entryPoint)&&(t.unshift({id:"START",type:"start",data:{nodeType:"start",label:"Start"}}),r.unshift({source:"START",target:this.entryPoint}));let i=0;for(let c of r)if(c.target==="END"){i+=1;let l=`END__${i}`;c.target=l,t.push({id:l,type:"end",data:{nodeType:"end",label:"End"}})}for(let c of this.nodes.keys())if(!this.edges.has(c)){i+=1;let l=`END__${i}`;t.push({id:l,type:"end",data:{nodeType:"end",label:"End"}}),r.push({source:c,target:l})}let n=this._topoOrderNodes(t,r),a=this._runtimeSchema(),u=s(a||this.stateSchema),p=s(this.inputSchema),g=s(this.contextSchema);return{nodes:n,edges:r,nodeConfigs:e,stateSchema:u,inputSchema:p,contextSchema:g}}_topoOrderNodes(t,e){let r=new Map(t.map((c,l)=>[c.id,l])),s=new Map(t.map(c=>[c.id,c])),i=new Map(t.map(c=>[c.id,0])),n=new Map(t.map(c=>[c.id,[]]));for(let c of e)n.has(c.source)&&i.has(c.target)&&(n.get(c.source).push(c.target),i.set(c.target,i.get(c.target)+1));let a=new Set,u=new Set(r.keys()),p=[...u].filter(c=>i.get(c)===0),g=[];for(;g.length<t.length;){let c;if(p.length>0){if(p.sort((l,y)=>r.get(l)-r.get(y)),c=p.shift(),a.has(c))continue}else c=[...u].sort((l,y)=>r.get(l)-r.get(y))[0];a.add(c),u.delete(c),g.push(s.get(c));for(let l of n.get(c)||[])i.set(l,i.get(l)-1),i.get(l)<=0&&!a.has(l)&&p.push(l)}return g}_inferConditionalTargets(t,e){let r=t.toString(),s=new Set,i=/(['"])((?:\\.|(?!\1).)*?)\1|`((?:\\.|[^`$]|\$(?!\{))*?)`/g,n;for(;(n=i.exec(r))!==null;){let p=n[2]!==void 0?n[2]:n[3];p!==void 0&&p!==""&&s.add(p)}let a=new Set(["END","START","__end__","__start__"]);for(let p of this.nodes.keys())a.add(p);if(e&&typeof e=="object")for(let p of Object.keys(e))a.add(p);let u=new Set;for(let p of s)a.has(p)&&u.add(p);if(u.size===0){let p=/return\s+['"]([^'"]+)['"]/g,g;for(;(g=p.exec(r))!==null;)u.add(g[1])}return[...u]}_flattenJsonSchemaToVariables(t,e=""){let r=t;if(t.$ref&&t.definitions){let s=t.$ref.replace("#/definitions/","");r=t.definitions[s]||t}return this._flattenSchema(r,e)}_flattenSchema(t,e=""){if(!t||typeof t!="object")return[];let r=[],s=t.properties||{},i=t.required||[];for(let[n,a]of Object.entries(s)){let u=e?`${e}.${n}`:n;r.push({path:u,type:a.type||"unknown",label:a.description||this._formatLabel(n),optional:!i.includes(n)}),a.type==="object"&&a.properties&&r.push(...this._flattenSchema(a,u)),a.type==="array"&&a.items?.type==="object"&&a.items.properties&&r.push(...this._flattenSchema(a.items,`${u}[]`))}return r}_formatLabel(t){return t.replace(/([A-Z])/g," $1").replace(/^./,e=>e.toUpperCase()).trim()}_summarizeNodeOutput(t,e){if(!e||typeof e!="object")return[];let r=[];e.success!==void 0&&r.push(`Result: ${e.success?"passed":"failed"}`);for(let[s,i]of Object.entries(e))if(!(s==="success"||s==="raw"||s==="nextNode")){if(typeof i=="string"&&i.length<=80)r.push(`${s}: ${i}`);else if(Array.isArray(i)){let n=i.length,a=i.filter(p=>p?.passed===!0).length,u=i.some(p=>p?.passed!==void 0);r.push(u?`${s}: ${a}/${n} passed${n-a?`, ${n-a} failed`:""}`:`${s}: ${n} items`)}if(r.length>=4)break}return r}async run(t,e={},r={}){if(!this.entryPoint)throw new Error("No entry point set for graph");let s=new AbortController;r.signal&&(r.signal.aborted?s.abort():r.signal.addEventListener("abort",()=>s.abort(),{once:!0}));let i=r.strategyAbortTimeoutMs??e.config?.strategyAbortTimeoutMs??5e3,n=e.cwd||process.cwd();fr({path:H(n,".env")});let a=e.config||{};if(!a||Object.keys(a).length===0)try{let E=H(n,".zibby.config.js");vt(E)&&(a=(await import(E)).default||{})}catch{}process.env.EXECUTION_ID&&!a.agent?.strictMode&&(a.agent={...a.agent,strictMode:!0});let u=e.agentType;if(!u){let E=a?.agent;E?.provider?u=E.provider:E?.gemini?u="gemini":E?.claude?u="claude":E?.cursor?u="cursor":E?.codex?u="codex":u=process.env.AGENT_TYPE||"claude"}let p=e.contextConfig||t?.config?.contextConfig||t?.config?.context||a?.context||{},g=this._runtimeSchema();if(g){let E=g.safeParse(e);if(!E.success){let N=E.error.issues.map(R=>`${R.path.join(".")}: ${R.message}`);throw console.error("\u274C Initial state validation failed:"),N.forEach(R=>console.error(` - ${R}`)),new Error(`State validation failed: ${N.join(", ")}`)}x.step("State validated against schema")}let c=Sr(),l=e.sessionPath||c;l||yr();let{sessionPath:y,sessionTimestamp:w,sessionId:$}=Ir({cwd:n,config:a,traceFrom:"WorkflowGraph.run",initialState:{sessionPath:l,sessionTimestamp:e.sessionTimestamp}});x.step(`Session ${$}`);let v=await ct.loadContext(e.specPath||"",n,p);Object.keys(v).length>0&&x.step(`Context loaded: ${Object.keys(v).join(", ")}`);let b=e.outputPath;!b&&e.specPath&&(t?.calculateOutputPath?b=t.calculateOutputPath(e.specPath):console.warn(`\u26A0\uFE0F outputPath not resolved (specPath=${e.specPath})`));let h=new ot({...e,config:a,agentType:u,outputPath:b,sessionPath:y,sessionTimestamp:w,context:v,resolvedTools:this.resolvedToolsMap||{},_signal:s.signal}),f=new Map;try{await import("@zibby/skills")}catch{}let{getSkill:m}=await Promise.resolve().then(()=>(St(),Kt)),d=a.skills&&typeof a.skills=="object"?a.skills:{},I=Object.values(d).filter(E=>E&&typeof E=="object"&&typeof E.id=="string"),A=E=>{for(let N of I)if(N.id===E)return N;return m(E)},B=new Set;for(let[,E]of this.nodes)for(let N of E.config?.skills||[])B.add(N);for(let E of B){let N=A(E);if(typeof N?.middleware=="function")try{let R=await N.middleware();typeof R=="function"&&f.set(E,R)}catch{}}let S=this.entryPoint,Q=[],kt=a?.recursionLimit??100,we=0;try{for(;S&&S!=="END";){if(++we>kt)throw new Error(`Workflow exceeded recursion limit (${kt}) \u2014 likely a cyclic conditional route. Set config.recursionLimit if you need a higher cap.`);let N=H(y,Yt);if(vt(N)){try{dr(N)}catch{}s.abort()}if(s.signal.aborted)return console.warn(`
42
42
  \u{1F6D1} External stop requested \u2014 ending workflow.`),x.step("Workflow stopped externally"),{success:!0,state:h.getAll(),executionLog:Q,stoppedExternally:!0};let R=this.nodes.get(S);if(!R)throw new Error(`Node '${S}' not found in graph`);let Ot=JSON.stringify({sessionPath:y,sessionTimestamp:w,currentNode:S,createdAt:new Date().toISOString(),config:h.get("config")}),_e=H(y,Z);he(_e,Ot,"utf-8");let xt=h.get("config")?.paths?.output||it,Ie=H(n,xt,Z);Se(H(n,xt),{recursive:!0});try{he(Ie,Ot,"utf-8")}catch{}let Pt=e.onPipelineProgress;if(typeof Pt=="function")try{Pt({cwd:n,sessionPath:y,sessionId:$,outputBase:h.get("config")?.paths?.output||it,currentNode:S})}catch{}let Ee=(this.resolvedToolsMap||{})[S]||null;h.set("_currentNodeTools",Ee);let be=h.get("nodeConfigs")||{};h.set("_currentNodeConfig",be[S]||{}),x.nodeStart(S);let Nt=Date.now(),tt=this.nodePrompts.get(S);if(!this._invokeAgent){let k=await Promise.resolve().then(()=>(_t(),wt));this._invokeAgent=k.invokeAgent}let $e=this._invokeAgent,ut={},Te=R.config?.skills||[];for(let k of Te){let C=A(k);if(typeof C?.invokeAgentOptions=="function")try{let T=C.invokeAgentOptions(h.getAll(),{agentType:h.get("agentType"),nodeName:S});T&&typeof T=="object"&&(ut={...ut,...T})}catch(T){console.warn(`[graph] skill '${k}' invokeAgentOptions threw: ${T.message}`)}}let Rt=async(k,C,T={})=>{let M=$e(k,C,{...ut,...T,signal:s.signal});return M.catch(()=>{}),s.signal.aborted?M:Promise.race([M,new Promise((J,Y)=>{let D=()=>{setTimeout(()=>{let K=new Error(`Strategy ignored AbortSignal \u2014 engine deadman fired after ${i}ms`);K.name="AbortError",Y(K)},i)};s.signal.addEventListener("abort",D,{once:!0})})])},Ae=async(k={},C={})=>{let T=C.prompt||"";if(tt){let M=this._compiledPrompts.get(S);M||(M=hr.compile(tt,{noEscape:!0}),this._compiledPrompts.set(S,M));try{T=M(k)}catch(J){throw console.error(`\u274C Template rendering failed for node '${S}':`,J.message),new Error(`Template rendering failed: ${J.message}`,{cause:J})}}else if(!T)throw new Error(`No prompt template configured for node '${S}' and no prompt provided in options`);return Rt(T,{state:h.getAll(),images:C.images||[]},{model:C.model||h.get("model"),workspace:h.get("workspace"),schema:C.schema,...C,signal:s.signal})},Bt=h.getAll(),ve=["state","invokeAgent","_coreInvokeAgent","agent","nodeId","promptTemplate","getPromptTemplate"];for(let k of ve)Object.prototype.hasOwnProperty.call(Bt,k)&&console.warn(`[workflow] node "${S}": state key "${k}" is shadowed by the engine context prop; read it via context.state.get('${k}')`);let Ct={...Bt,state:h,invokeAgent:Ae,_coreInvokeAgent:Rt,agent:t,nodeId:S,promptTemplate:tt,getPromptTemplate:()=>tt};try{let k=(R.config?.skills||[]).map(D=>f.get(D)).filter(Boolean),C=[...this.middleware,...k],T;C.length>0?T=await this._composeMiddleware(C,S,async()=>R.execute(Ct,h),h.getAll(),h):T=await R.execute(Ct,h);let M=Date.now()-Nt;if(Q.push({node:S,success:T.success,duration:M,timestamp:new Date().toISOString()}),!T.success){if(s.signal.aborted)return x.step("Workflow stopped externally"),{success:!0,state:h.getAll(),executionLog:Q,stoppedExternally:!0};h.append("errors",{node:S,error:T.error});let D=R.config?.retries||0,K=`${S}_retries`,et=h.getAll()[K]||0;if(et<D){x.stepInfo(`Retrying (attempt ${et+1}/${D})`),h.update({[K]:et+1,[`${S}_raw`]:T.raw});continue}throw x.nodeFailed(S,T.error,{duration:M}),new Error(`Node '${S}' failed after ${et} attempts: ${T.error}`)}h.update({[S]:T.output});let J=this._summarizeNodeOutput(S,T.output);x.nodeComplete(S,{duration:M,details:J});let Y=this.edges.get(S);if(!Y)S="END";else if(Y.conditional){let D=Y.routes(h.getAll());x.route(S,D),S=D}else S=Y}catch(k){throw x.isInsideNode&&x.nodeFailed(S,k.message,{duration:Date.now()-Nt}),h.set("failed",!0),h.set("failedAt",S),k}}x.graphComplete();let E={success:!0,state:h.getAll(),executionLog:Q};return t&&typeof t.onComplete=="function"&&await t.onComplete(E),E}finally{if(t&&typeof t.cleanup=="function")try{await t.cleanup()}catch(E){console.warn(`[workflow] agent.cleanup() failed: ${E.message}`)}}}};export{me as WorkflowGraph,yr as clearInheritedSessionEnvForFreshRun,_r as generateWorkflowSessionId,Sr as readPinnedSessionPathFromEnv,Ir as resolveWorkflowSession,mr as shouldTrustInheritedSessionEnv,wr as syncProcessEnvToSession};
package/dist/index.js CHANGED
@@ -38,7 +38,7 @@ ${s}`);let a=r(),l=a.cwd||process.cwd(),u=a.sessionPath;try{if(u){let d=Be(u,U);
38
38
  `):i.every(n=>typeof n=="object")?Object.assign({},...i):i[i.length-1]}static async loadFile(e){let t=Fo(e,"utf-8");if(e.endsWith(".json"))return JSON.parse(t);if(e.endsWith(".js")||e.endsWith(".mjs")){let{pathToFileURL:r}=await import("url"),i=await import(r(e).href);return i.default||i}return t}};import{mkdirSync as Gt,existsSync as Ge,writeFileSync as Mt,unlinkSync as Go}from"node:fs";import{join as z,resolve as Ut}from"node:path";import{config as Uo}from"dotenv";import{zodToJsonSchema as Ft}from"zod-to-json-schema";import{z as ye}from"zod";import Wo from"handlebars";function Ho({traceFrom:o,sessionId:e,sessionPath:t,idSource:r,mkdirFresh:i}){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=${o} pid=${process.pid} ppid=${n} sessionId=${e} source=${r} mkdir=${i?"yes":"no"} path=${t}`;if(console.log(a),process.env.ZIBBY_TRACE_SESSION==="1"||process.env.ZIBBY_TRACE_SESSION==="true"){let f=(new Error("session trace").stack||"").split(`
39
39
  `).slice(2,14).join(`
40
40
  `);console.log(`[zibby:session] stack (${o}):
41
- ${f}`)}}function Wt(){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"}function Ht(){if(!(process.env.ZIBBY_PIN_SESSION_PATH==="1"||process.env.ZIBBY_PIN_SESSION_PATH==="true"))return;let e=process.env.ZIBBY_SESSION_PATH;if(!(e==null||String(e).trim()===""))try{return Ut(String(e).trim())}catch{return String(e).trim()}}function Jt(){Wt()||(delete process.env.ZIBBY_SESSION_PATH,delete process.env.ZIBBY_SESSION_ID)}function Yt({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 zt(o={}){let e=Ae.map(s=>process.env[s]).find(Boolean),t=Math.random().toString(36).slice(2,6),r=e||`${Date.now()}_${t}`,i=o.paths?.sessionPrefix;return i?`${i}_${r}`:r}function Zt({cwd:o=process.cwd(),config:e={},initialState:t={},traceFrom:r="resolveWorkflowSession"}={}){let i=t.sessionPath,s=t.sessionTimestamp,n="initialState.sessionPath";if(!i&&process.env.ZIBBY_SESSION_PATH)try{let u=Ut(String(process.env.ZIBBY_SESSION_PATH));u&&(i=u,n="ZIBBY_SESSION_PATH")}catch{}let a;if(i)a=String(i).split(/[/\\]/).filter(Boolean).pop(),s==null&&(s=Date.now());else{let u=process.env.ZIBBY_SESSION_ID&&String(process.env.ZIBBY_SESSION_ID).trim();if(u)a=u,n="ZIBBY_SESSION_ID";else{let d=e.sessionId!=null?String(e.sessionId).trim():"";d&&d!=="last"?(a=d,n="config.sessionId"):(a=zt(e),n="generated")}s=s??Date.now();let f=e.paths?.output||se;i=z(o,f,$e,a)}let l=!Ge(i);return l&&Gt(i,{recursive:!0}),(l||n!=="initialState.sessionPath")&&Ho({traceFrom:r,sessionId:a,sessionPath:i,idSource:n,mkdirFresh:l}),Yt({sessionPath:i,sessionId:a}),{sessionPath:i,sessionId:a,sessionTimestamp:s}}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.inputSchema=e.inputSchema||null,this.contextSchema=e.contextSchema||null,this.nodePrompts=new Map,this.nodeOptions=new Map,this._invokeAgent=e.invokeAgent||null,this._compiledPrompts=new Map}setInputSchema(e){return this.inputSchema=e,this}setContextSchema(e){return this.contextSchema=e,this}setStateSchema(e){return this.stateSchema=e,this}getInputSchema(){return this.inputSchema}getContextSchema(){return this.contextSchema}getStateSchema(){return this.stateSchema}_runtimeSchema(){if(this.inputSchema&&this.contextSchema)try{if(typeof this.inputSchema.merge=="function")return this.inputSchema.merge(this.contextSchema);if(typeof this.inputSchema.and=="function")return this.inputSchema.and(this.contextSchema)}catch{}return this.inputSchema&&!this.contextSchema?this.inputSchema:this.stateSchema}addNode(e,t,r={}){if(!(t instanceof M)&&t&&typeof t=="object"&&typeof t.workflow=="string"){let n=t,a={name:e,_isCustomCode:!0,dispatchesWorkflow:n.workflow,retries:n.retries,onComplete:n.onComplete,execute:async u=>{let f=u?.state&&typeof u.state.getAll=="function"?u.state.getAll():u,d;return typeof n.input=="function"?d=n.input(f):n.input&&typeof n.input=="object"?d=n.input:d={},Me(n.workflow,{input:d,async:n.async===!0,conversationId:typeof n.conversationId=="function"?n.conversationId(f):n.conversationId,output:n.output,timeoutMs:n.timeoutMs,pollIntervalMs:n.pollIntervalMs,signal:f?._signal,parentAgent:u?.agent})}},l=new M(a);return l.name=e,this.nodes.set(e,l),r.prompt&&this.nodePrompts.set(e,r.prompt),Object.keys(r).length>0&&this.nodeOptions.set(e,r),this}let i=!(t instanceof M)&&t&&typeof t=="object"&&typeof t.execute!="function"&&t.prompt==null&&t.outputSchema==null&&t._isCustomCode!==!0,s=t instanceof M?t:new M(i?{...t,_isRouter:!0}:t);return s.name=e,this.nodes.set(e,s),r.prompt?this.nodePrompts.set(e,r.prompt):typeof t?.prompt=="string"&&t.prompt.trim()&&this.nodePrompts.set(e,t.prompt),Object.keys(r).length>0&&this.nodeOptions.set(e,r),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,i,s){let n=r;for(let a=e.length-1;a>=0;a--){let l=e[a],u=n;n=()=>l(t,u,i,s)}return n()}serialize(){let e=[],t={};for(let[d,c]of this.nodes){let y=this.nodeTypeMap.get(d)||(c?.config?._isRouter===!0?"decision":d);e.push({id:d,type:y,data:{nodeType:y,label:d}});let g={};c._isCustomCode&&typeof c.execute=="function"&&(g.customCode=c.execute.toString());let S=typeof c?.config?.description=="string"&&c.config.description.trim()?c.config.description:typeof c?.description=="string"&&c.description.trim()?c.description:null;S&&(g.description=S);let b=this.nodePrompts.get(d);if(b)g.prompt=b;else if(typeof c.prompt=="function")try{let p=c.prompt({});typeof p=="string"&&p.trim()&&(g.prompt=p,g.promptIsCode=!0)}catch{}if(typeof c.customExecute=="function"&&(g.executeCode=c.customExecute.toString()),typeof c?.config?.dispatchesWorkflow=="string"&&c.config.dispatchesWorkflow.trim()&&(g.dispatchesWorkflow=c.config.dispatchesWorkflow.trim()),c.outputSchema)if(typeof c.outputSchema._def<"u"){let p=null;if(typeof ye?.toJSONSchema=="function")try{p=ye.toJSONSchema(c.outputSchema)}catch{}if(!p)try{p=Ft(c.outputSchema,{target:"openApi3"})}catch{}g.outputSchema=p?{jsonSchema:p,variables:this._flattenJsonSchemaToVariables(p)}:{schema:c.outputSchema}}else g.outputSchema={schema:c.outputSchema};let _=(this.resolvedToolsMap||{})[d];_?.toolIds&&(g.tools=_.toolIds);let m=Array.isArray(c?.config?.skills)?c.config.skills:Array.isArray(c?.skills)?c.skills:null;m&&m.length>0&&(g.skills=[...m]);let h=Array.isArray(c?.config?.plugins)?c.config.plugins:Array.isArray(c?.plugins)?c.plugins:null;h&&h.length>0&&(g.plugins=h.map(p=>p&&typeof p=="object"?{...p}:p));let w=Array.isArray(c?.config?.stores)?c.config.stores:Array.isArray(c?.stores)?c.stores:null;w&&w.length>0&&(g.stores=w.map(p=>p&&typeof p=="object"?{...p}:p)),Object.keys(g).length>0&&(t[d]=g)}let r=[];for(let[d,c]of this.edges)if(typeof c=="string")r.push({source:d,target:c});else if(c.conditional){let y=this.conditionalCodeMap.get(d)||c.routes.toString(),g=this._inferConditionalTargets(c.routes,c.labels),S=c.labels||{},b=this.nodes.get(d),_=b?.config?._isRouter===!0||this.nodeTypeMap.get(d)==="decision"||!b,m=d;if(!_){let h=`${d}__branch`;e.push({id:h,type:"decision",data:{nodeType:"decision",label:h}}),r.push({source:d,target:h}),m=h}for(let h of g){let w={source:m,target:h,data:{conditionalCode:y}};S[h]&&(w.label=S[h]),r.push(w)}}let i=d=>{if(!d)return null;if(typeof ye?.toJSONSchema=="function")try{return ye.toJSONSchema(d)}catch{}try{return Ft(d,{target:"openApi3"})}catch{return null}};this.entryPoint&&this.nodes.has(this.entryPoint)&&(e.unshift({id:"START",type:"start",data:{nodeType:"start",label:"Start"}}),r.unshift({source:"START",target:this.entryPoint}));let s=0;for(let d of r)if(d.target==="END"){s+=1;let c=`END__${s}`;d.target=c,e.push({id:c,type:"end",data:{nodeType:"end",label:"End"}})}for(let d of this.nodes.keys())if(!this.edges.has(d)){s+=1;let c=`END__${s}`;e.push({id:c,type:"end",data:{nodeType:"end",label:"End"}}),r.push({source:d,target:c})}let n=this._topoOrderNodes(e,r),a=this._runtimeSchema(),l=i(a||this.stateSchema),u=i(this.inputSchema),f=i(this.contextSchema);return{nodes:n,edges:r,nodeConfigs:t,stateSchema:l,inputSchema:u,contextSchema:f}}_topoOrderNodes(e,t){let r=new Map(e.map((d,c)=>[d.id,c])),i=new Map(e.map(d=>[d.id,d])),s=new Map(e.map(d=>[d.id,0])),n=new Map(e.map(d=>[d.id,[]]));for(let d of t)n.has(d.source)&&s.has(d.target)&&(n.get(d.source).push(d.target),s.set(d.target,s.get(d.target)+1));let a=new Set,l=new Set(r.keys()),u=[...l].filter(d=>s.get(d)===0),f=[];for(;f.length<e.length;){let d;if(u.length>0){if(u.sort((c,y)=>r.get(c)-r.get(y)),d=u.shift(),a.has(d))continue}else d=[...l].sort((c,y)=>r.get(c)-r.get(y))[0];a.add(d),l.delete(d),f.push(i.get(d));for(let c of n.get(d)||[])s.set(c,s.get(c)-1),s.get(c)<=0&&!a.has(c)&&u.push(c)}return f}_inferConditionalTargets(e,t){let r=e.toString(),i=new Set,s=/(['"])((?:\\.|(?!\1).)*?)\1|`((?:\\.|[^`$]|\$(?!\{))*?)`/g,n;for(;(n=s.exec(r))!==null;){let u=n[2]!==void 0?n[2]:n[3];u!==void 0&&u!==""&&i.add(u)}let a=new Set(["END","START","__end__","__start__"]);for(let u of this.nodes.keys())a.add(u);if(t&&typeof t=="object")for(let u of Object.keys(t))a.add(u);let l=new Set;for(let u of i)a.has(u)&&l.add(u);if(l.size===0){let u=/return\s+['"]([^'"]+)['"]/g,f;for(;(f=u.exec(r))!==null;)l.add(f[1])}return[...l]}_flattenJsonSchemaToVariables(e,t=""){let r=e;if(e.$ref&&e.definitions){let i=e.$ref.replace("#/definitions/","");r=e.definitions[i]||e}return this._flattenSchema(r,t)}_flattenSchema(e,t=""){if(!e||typeof e!="object")return[];let r=[],i=e.properties||{},s=e.required||[];for(let[n,a]of Object.entries(i)){let l=t?`${t}.${n}`:n;r.push({path:l,type:a.type||"unknown",label:a.description||this._formatLabel(n),optional:!s.includes(n)}),a.type==="object"&&a.properties&&r.push(...this._flattenSchema(a,l)),a.type==="array"&&a.items?.type==="object"&&a.items.properties&&r.push(...this._flattenSchema(a.items,`${l}[]`))}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[i,s]of Object.entries(t))if(!(i==="success"||i==="raw"||i==="nextNode")){if(typeof s=="string"&&s.length<=80)r.push(`${i}: ${s}`);else if(Array.isArray(s)){let n=s.length,a=s.filter(u=>u?.passed===!0).length,l=s.some(u=>u?.passed!==void 0);r.push(l?`${i}: ${a}/${n} passed${n-a?`, ${n-a} failed`:""}`:`${i}: ${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 i=new AbortController;r.signal&&(r.signal.aborted?i.abort():r.signal.addEventListener("abort",()=>i.abort(),{once:!0}));let s=r.strategyAbortTimeoutMs??t.config?.strategyAbortTimeoutMs??5e3,n=t.cwd||process.cwd();Uo({path:z(n,".env")});let a=t.config||{};if(!a||Object.keys(a).length===0)try{let v=z(n,".zibby.config.js");Ge(v)&&(a=(await import(v)).default||{})}catch{}process.env.EXECUTION_ID&&!a.agent?.strictMode&&(a.agent={...a.agent,strictMode:!0});let l=t.agentType;if(!l){let v=a?.agent;v?.provider?l=v.provider:v?.gemini?l="gemini":v?.claude?l="claude":v?.cursor?l="cursor":v?.codex?l="codex":l=process.env.AGENT_TYPE||"cursor"}let u=t.contextConfig||e?.config?.contextConfig||e?.config?.context||a?.context||{},f=this._runtimeSchema();if(f){let v=f.safeParse(t);if(!v.success){let P=v.error.issues.map(C=>`${C.path.join(".")}: ${C.message}`);throw console.error("\u274C Initial state validation failed:"),P.forEach(C=>console.error(` - ${C}`)),new Error(`State validation failed: ${P.join(", ")}`)}N.step("State validated against schema")}let d=Ht(),c=t.sessionPath||d;c||Jt();let{sessionPath:y,sessionTimestamp:g,sessionId:S}=Zt({cwd:n,config:a,traceFrom:"WorkflowGraph.run",initialState:{sessionPath:c,sessionTimestamp:t.sessionTimestamp}});N.step(`Session ${S}`);let b=await le.loadContext(t.specPath||"",n,u);Object.keys(b).length>0&&N.step(`Context loaded: ${Object.keys(b).join(", ")}`);let _=t.outputPath;!_&&t.specPath&&(e?.calculateOutputPath?_=e.calculateOutputPath(t.specPath):console.warn(`\u26A0\uFE0F outputPath not resolved (specPath=${t.specPath})`));let m=new te({...t,config:a,agentType:l,outputPath:_,sessionPath:y,sessionTimestamp:g,context:b,resolvedTools:this.resolvedToolsMap||{},_signal:i.signal}),h=new Map;try{await import("@zibby/skills")}catch{}let{getSkill:w}=await Promise.resolve().then(()=>(ie(),St)),p=a.skills&&typeof a.skills=="object"?a.skills:{},T=Object.values(p).filter(v=>v&&typeof v=="object"&&typeof v.id=="string"),k=v=>{for(let P of T)if(P.id===v)return P;return w(v)},R=new Set;for(let[,v]of this.nodes)for(let P of v.config?.skills||[])R.add(P);for(let v of R){let P=k(v);if(typeof P?.middleware=="function")try{let C=await P.middleware();typeof C=="function"&&h.set(v,C)}catch{}}let E=this.entryPoint,ue=[],Ze=a?.recursionLimit??100,Xt=0;try{for(;E&&E!=="END";){if(++Xt>Ze)throw new Error(`Workflow exceeded recursion limit (${Ze}) \u2014 likely a cyclic conditional route. Set config.recursionLimit if you need a higher cap.`);let P=z(y,ke);if(Ge(P)){try{Go(P)}catch{}i.abort()}if(i.signal.aborted)return console.warn(`
41
+ ${f}`)}}function Wt(){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"}function Ht(){if(!(process.env.ZIBBY_PIN_SESSION_PATH==="1"||process.env.ZIBBY_PIN_SESSION_PATH==="true"))return;let e=process.env.ZIBBY_SESSION_PATH;if(!(e==null||String(e).trim()===""))try{return Ut(String(e).trim())}catch{return String(e).trim()}}function Jt(){Wt()||(delete process.env.ZIBBY_SESSION_PATH,delete process.env.ZIBBY_SESSION_ID)}function Yt({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 zt(o={}){let e=Ae.map(s=>process.env[s]).find(Boolean),t=Math.random().toString(36).slice(2,6),r=e||`${Date.now()}_${t}`,i=o.paths?.sessionPrefix;return i?`${i}_${r}`:r}function Zt({cwd:o=process.cwd(),config:e={},initialState:t={},traceFrom:r="resolveWorkflowSession"}={}){let i=t.sessionPath,s=t.sessionTimestamp,n="initialState.sessionPath";if(!i&&process.env.ZIBBY_SESSION_PATH)try{let u=Ut(String(process.env.ZIBBY_SESSION_PATH));u&&(i=u,n="ZIBBY_SESSION_PATH")}catch{}let a;if(i)a=String(i).split(/[/\\]/).filter(Boolean).pop(),s==null&&(s=Date.now());else{let u=process.env.ZIBBY_SESSION_ID&&String(process.env.ZIBBY_SESSION_ID).trim();if(u)a=u,n="ZIBBY_SESSION_ID";else{let d=e.sessionId!=null?String(e.sessionId).trim():"";d&&d!=="last"?(a=d,n="config.sessionId"):(a=zt(e),n="generated")}s=s??Date.now();let f=e.paths?.output||se;i=z(o,f,$e,a)}let l=!Ge(i);return l&&Gt(i,{recursive:!0}),(l||n!=="initialState.sessionPath")&&Ho({traceFrom:r,sessionId:a,sessionPath:i,idSource:n,mkdirFresh:l}),Yt({sessionPath:i,sessionId:a}),{sessionPath:i,sessionId:a,sessionTimestamp:s}}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.inputSchema=e.inputSchema||null,this.contextSchema=e.contextSchema||null,this.nodePrompts=new Map,this.nodeOptions=new Map,this._invokeAgent=e.invokeAgent||null,this._compiledPrompts=new Map}setInputSchema(e){return this.inputSchema=e,this}setContextSchema(e){return this.contextSchema=e,this}setStateSchema(e){return this.stateSchema=e,this}getInputSchema(){return this.inputSchema}getContextSchema(){return this.contextSchema}getStateSchema(){return this.stateSchema}_runtimeSchema(){if(this.inputSchema&&this.contextSchema)try{if(typeof this.inputSchema.merge=="function")return this.inputSchema.merge(this.contextSchema);if(typeof this.inputSchema.and=="function")return this.inputSchema.and(this.contextSchema)}catch{}return this.inputSchema&&!this.contextSchema?this.inputSchema:this.stateSchema}addNode(e,t,r={}){if(!(t instanceof M)&&t&&typeof t=="object"&&typeof t.workflow=="string"){let n=t,a={name:e,_isCustomCode:!0,dispatchesWorkflow:n.workflow,retries:n.retries,onComplete:n.onComplete,execute:async u=>{let f=u?.state&&typeof u.state.getAll=="function"?u.state.getAll():u,d;return typeof n.input=="function"?d=n.input(f):n.input&&typeof n.input=="object"?d=n.input:d={},Me(n.workflow,{input:d,async:n.async===!0,conversationId:typeof n.conversationId=="function"?n.conversationId(f):n.conversationId,output:n.output,timeoutMs:n.timeoutMs,pollIntervalMs:n.pollIntervalMs,signal:f?._signal,parentAgent:u?.agent})}},l=new M(a);return l.name=e,this.nodes.set(e,l),r.prompt&&this.nodePrompts.set(e,r.prompt),Object.keys(r).length>0&&this.nodeOptions.set(e,r),this}let i=!(t instanceof M)&&t&&typeof t=="object"&&typeof t.execute!="function"&&t.prompt==null&&t.outputSchema==null&&t._isCustomCode!==!0,s=t instanceof M?t:new M(i?{...t,_isRouter:!0}:t);return s.name=e,this.nodes.set(e,s),r.prompt?this.nodePrompts.set(e,r.prompt):typeof t?.prompt=="string"&&t.prompt.trim()&&this.nodePrompts.set(e,t.prompt),Object.keys(r).length>0&&this.nodeOptions.set(e,r),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,i,s){let n=r;for(let a=e.length-1;a>=0;a--){let l=e[a],u=n;n=()=>l(t,u,i,s)}return n()}serialize(){let e=[],t={};for(let[d,c]of this.nodes){let y=this.nodeTypeMap.get(d)||(c?.config?._isRouter===!0?"decision":d);e.push({id:d,type:y,data:{nodeType:y,label:d}});let g={};c._isCustomCode&&typeof c.execute=="function"&&(g.customCode=c.execute.toString());let S=typeof c?.config?.description=="string"&&c.config.description.trim()?c.config.description:typeof c?.description=="string"&&c.description.trim()?c.description:null;S&&(g.description=S);let b=this.nodePrompts.get(d);if(b)g.prompt=b;else if(typeof c.prompt=="function")try{let p=c.prompt({});typeof p=="string"&&p.trim()&&(g.prompt=p,g.promptIsCode=!0)}catch{}if(typeof c.customExecute=="function"&&(g.executeCode=c.customExecute.toString()),typeof c?.config?.dispatchesWorkflow=="string"&&c.config.dispatchesWorkflow.trim()&&(g.dispatchesWorkflow=c.config.dispatchesWorkflow.trim()),c.outputSchema)if(typeof c.outputSchema._def<"u"){let p=null;if(typeof ye?.toJSONSchema=="function")try{p=ye.toJSONSchema(c.outputSchema)}catch{}if(!p)try{p=Ft(c.outputSchema,{target:"openApi3"})}catch{}g.outputSchema=p?{jsonSchema:p,variables:this._flattenJsonSchemaToVariables(p)}:{schema:c.outputSchema}}else g.outputSchema={schema:c.outputSchema};let _=(this.resolvedToolsMap||{})[d];_?.toolIds&&(g.tools=_.toolIds);let m=Array.isArray(c?.config?.skills)?c.config.skills:Array.isArray(c?.skills)?c.skills:null;m&&m.length>0&&(g.skills=[...m]);let h=Array.isArray(c?.config?.plugins)?c.config.plugins:Array.isArray(c?.plugins)?c.plugins:null;h&&h.length>0&&(g.plugins=h.map(p=>p&&typeof p=="object"?{...p}:p));let w=Array.isArray(c?.config?.stores)?c.config.stores:Array.isArray(c?.stores)?c.stores:null;w&&w.length>0&&(g.stores=w.map(p=>p&&typeof p=="object"?{...p}:p)),Object.keys(g).length>0&&(t[d]=g)}let r=[];for(let[d,c]of this.edges)if(typeof c=="string")r.push({source:d,target:c});else if(c.conditional){let y=this.conditionalCodeMap.get(d)||c.routes.toString(),g=this._inferConditionalTargets(c.routes,c.labels),S=c.labels||{},b=this.nodes.get(d),_=b?.config?._isRouter===!0||this.nodeTypeMap.get(d)==="decision"||!b,m=d;if(!_){let h=`${d}__branch`;e.push({id:h,type:"decision",data:{nodeType:"decision",label:h}}),r.push({source:d,target:h}),m=h}for(let h of g){let w={source:m,target:h,data:{conditionalCode:y}};S[h]&&(w.label=S[h]),r.push(w)}}let i=d=>{if(!d)return null;if(typeof ye?.toJSONSchema=="function")try{return ye.toJSONSchema(d)}catch{}try{return Ft(d,{target:"openApi3"})}catch{return null}};this.entryPoint&&this.nodes.has(this.entryPoint)&&(e.unshift({id:"START",type:"start",data:{nodeType:"start",label:"Start"}}),r.unshift({source:"START",target:this.entryPoint}));let s=0;for(let d of r)if(d.target==="END"){s+=1;let c=`END__${s}`;d.target=c,e.push({id:c,type:"end",data:{nodeType:"end",label:"End"}})}for(let d of this.nodes.keys())if(!this.edges.has(d)){s+=1;let c=`END__${s}`;e.push({id:c,type:"end",data:{nodeType:"end",label:"End"}}),r.push({source:d,target:c})}let n=this._topoOrderNodes(e,r),a=this._runtimeSchema(),l=i(a||this.stateSchema),u=i(this.inputSchema),f=i(this.contextSchema);return{nodes:n,edges:r,nodeConfigs:t,stateSchema:l,inputSchema:u,contextSchema:f}}_topoOrderNodes(e,t){let r=new Map(e.map((d,c)=>[d.id,c])),i=new Map(e.map(d=>[d.id,d])),s=new Map(e.map(d=>[d.id,0])),n=new Map(e.map(d=>[d.id,[]]));for(let d of t)n.has(d.source)&&s.has(d.target)&&(n.get(d.source).push(d.target),s.set(d.target,s.get(d.target)+1));let a=new Set,l=new Set(r.keys()),u=[...l].filter(d=>s.get(d)===0),f=[];for(;f.length<e.length;){let d;if(u.length>0){if(u.sort((c,y)=>r.get(c)-r.get(y)),d=u.shift(),a.has(d))continue}else d=[...l].sort((c,y)=>r.get(c)-r.get(y))[0];a.add(d),l.delete(d),f.push(i.get(d));for(let c of n.get(d)||[])s.set(c,s.get(c)-1),s.get(c)<=0&&!a.has(c)&&u.push(c)}return f}_inferConditionalTargets(e,t){let r=e.toString(),i=new Set,s=/(['"])((?:\\.|(?!\1).)*?)\1|`((?:\\.|[^`$]|\$(?!\{))*?)`/g,n;for(;(n=s.exec(r))!==null;){let u=n[2]!==void 0?n[2]:n[3];u!==void 0&&u!==""&&i.add(u)}let a=new Set(["END","START","__end__","__start__"]);for(let u of this.nodes.keys())a.add(u);if(t&&typeof t=="object")for(let u of Object.keys(t))a.add(u);let l=new Set;for(let u of i)a.has(u)&&l.add(u);if(l.size===0){let u=/return\s+['"]([^'"]+)['"]/g,f;for(;(f=u.exec(r))!==null;)l.add(f[1])}return[...l]}_flattenJsonSchemaToVariables(e,t=""){let r=e;if(e.$ref&&e.definitions){let i=e.$ref.replace("#/definitions/","");r=e.definitions[i]||e}return this._flattenSchema(r,t)}_flattenSchema(e,t=""){if(!e||typeof e!="object")return[];let r=[],i=e.properties||{},s=e.required||[];for(let[n,a]of Object.entries(i)){let l=t?`${t}.${n}`:n;r.push({path:l,type:a.type||"unknown",label:a.description||this._formatLabel(n),optional:!s.includes(n)}),a.type==="object"&&a.properties&&r.push(...this._flattenSchema(a,l)),a.type==="array"&&a.items?.type==="object"&&a.items.properties&&r.push(...this._flattenSchema(a.items,`${l}[]`))}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[i,s]of Object.entries(t))if(!(i==="success"||i==="raw"||i==="nextNode")){if(typeof s=="string"&&s.length<=80)r.push(`${i}: ${s}`);else if(Array.isArray(s)){let n=s.length,a=s.filter(u=>u?.passed===!0).length,l=s.some(u=>u?.passed!==void 0);r.push(l?`${i}: ${a}/${n} passed${n-a?`, ${n-a} failed`:""}`:`${i}: ${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 i=new AbortController;r.signal&&(r.signal.aborted?i.abort():r.signal.addEventListener("abort",()=>i.abort(),{once:!0}));let s=r.strategyAbortTimeoutMs??t.config?.strategyAbortTimeoutMs??5e3,n=t.cwd||process.cwd();Uo({path:z(n,".env")});let a=t.config||{};if(!a||Object.keys(a).length===0)try{let v=z(n,".zibby.config.js");Ge(v)&&(a=(await import(v)).default||{})}catch{}process.env.EXECUTION_ID&&!a.agent?.strictMode&&(a.agent={...a.agent,strictMode:!0});let l=t.agentType;if(!l){let v=a?.agent;v?.provider?l=v.provider:v?.gemini?l="gemini":v?.claude?l="claude":v?.cursor?l="cursor":v?.codex?l="codex":l=process.env.AGENT_TYPE||"claude"}let u=t.contextConfig||e?.config?.contextConfig||e?.config?.context||a?.context||{},f=this._runtimeSchema();if(f){let v=f.safeParse(t);if(!v.success){let P=v.error.issues.map(C=>`${C.path.join(".")}: ${C.message}`);throw console.error("\u274C Initial state validation failed:"),P.forEach(C=>console.error(` - ${C}`)),new Error(`State validation failed: ${P.join(", ")}`)}N.step("State validated against schema")}let d=Ht(),c=t.sessionPath||d;c||Jt();let{sessionPath:y,sessionTimestamp:g,sessionId:S}=Zt({cwd:n,config:a,traceFrom:"WorkflowGraph.run",initialState:{sessionPath:c,sessionTimestamp:t.sessionTimestamp}});N.step(`Session ${S}`);let b=await le.loadContext(t.specPath||"",n,u);Object.keys(b).length>0&&N.step(`Context loaded: ${Object.keys(b).join(", ")}`);let _=t.outputPath;!_&&t.specPath&&(e?.calculateOutputPath?_=e.calculateOutputPath(t.specPath):console.warn(`\u26A0\uFE0F outputPath not resolved (specPath=${t.specPath})`));let m=new te({...t,config:a,agentType:l,outputPath:_,sessionPath:y,sessionTimestamp:g,context:b,resolvedTools:this.resolvedToolsMap||{},_signal:i.signal}),h=new Map;try{await import("@zibby/skills")}catch{}let{getSkill:w}=await Promise.resolve().then(()=>(ie(),St)),p=a.skills&&typeof a.skills=="object"?a.skills:{},T=Object.values(p).filter(v=>v&&typeof v=="object"&&typeof v.id=="string"),k=v=>{for(let P of T)if(P.id===v)return P;return w(v)},R=new Set;for(let[,v]of this.nodes)for(let P of v.config?.skills||[])R.add(P);for(let v of R){let P=k(v);if(typeof P?.middleware=="function")try{let C=await P.middleware();typeof C=="function"&&h.set(v,C)}catch{}}let E=this.entryPoint,ue=[],Ze=a?.recursionLimit??100,Xt=0;try{for(;E&&E!=="END";){if(++Xt>Ze)throw new Error(`Workflow exceeded recursion limit (${Ze}) \u2014 likely a cyclic conditional route. Set config.recursionLimit if you need a higher cap.`);let P=z(y,ke);if(Ge(P)){try{Go(P)}catch{}i.abort()}if(i.signal.aborted)return console.warn(`
42
42
  \u{1F6D1} External stop requested \u2014 ending workflow.`),N.step("Workflow stopped externally"),{success:!0,state:m.getAll(),executionLog:ue,stoppedExternally:!0};let C=this.nodes.get(E);if(!C)throw new Error(`Node '${E}' not found in graph`);let Ke=JSON.stringify({sessionPath:y,sessionTimestamp:g,currentNode:E,createdAt:new Date().toISOString(),config:m.get("config")}),Qt=z(y,U);Mt(Qt,Ke,"utf-8");let Ve=m.get("config")?.paths?.output||se,eo=z(n,Ve,U);Gt(z(n,Ve),{recursive:!0});try{Mt(eo,Ke,"utf-8")}catch{}let qe=t.onPipelineProgress;if(typeof qe=="function")try{qe({cwd:n,sessionPath:y,sessionId:S,outputBase:m.get("config")?.paths?.output||se,currentNode:E})}catch{}let to=(this.resolvedToolsMap||{})[E]||null;m.set("_currentNodeTools",to);let oo=m.get("nodeConfigs")||{};m.set("_currentNodeConfig",oo[E]||{}),N.nodeStart(E);let Xe=Date.now(),pe=this.nodePrompts.get(E);if(!this._invokeAgent){let A=await Promise.resolve().then(()=>(X(),ae));this._invokeAgent=A.invokeAgent}let ro=this._invokeAgent,Ee={},no=C.config?.skills||[];for(let A of no){let B=k(A);if(typeof B?.invokeAgentOptions=="function")try{let $=B.invokeAgentOptions(m.getAll(),{agentType:m.get("agentType"),nodeName:E});$&&typeof $=="object"&&(Ee={...Ee,...$})}catch($){console.warn(`[graph] skill '${A}' invokeAgentOptions threw: ${$.message}`)}}let Qe=async(A,B,$={})=>{let j=ro(A,B,{...Ee,...$,signal:i.signal});return j.catch(()=>{}),i.signal.aborted?j:Promise.race([j,new Promise((Z,K)=>{let L=()=>{setTimeout(()=>{let ee=new Error(`Strategy ignored AbortSignal \u2014 engine deadman fired after ${s}ms`);ee.name="AbortError",K(ee)},s)};i.signal.addEventListener("abort",L,{once:!0})})])},so=async(A={},B={})=>{let $=B.prompt||"";if(pe){let j=this._compiledPrompts.get(E);j||(j=Wo.compile(pe,{noEscape:!0}),this._compiledPrompts.set(E,j));try{$=j(A)}catch(Z){throw console.error(`\u274C Template rendering failed for node '${E}':`,Z.message),new Error(`Template rendering failed: ${Z.message}`,{cause:Z})}}else if(!$)throw new Error(`No prompt template configured for node '${E}' and no prompt provided in options`);return Qe($,{state:m.getAll(),images:B.images||[]},{model:B.model||m.get("model"),workspace:m.get("workspace"),schema:B.schema,...B,signal:i.signal})},et=m.getAll(),io=["state","invokeAgent","_coreInvokeAgent","agent","nodeId","promptTemplate","getPromptTemplate"];for(let A of io)Object.prototype.hasOwnProperty.call(et,A)&&console.warn(`[workflow] node "${E}": state key "${A}" is shadowed by the engine context prop; read it via context.state.get('${A}')`);let tt={...et,state:m,invokeAgent:so,_coreInvokeAgent:Qe,agent:e,nodeId:E,promptTemplate:pe,getPromptTemplate:()=>pe};try{let A=(C.config?.skills||[]).map(L=>h.get(L)).filter(Boolean),B=[...this.middleware,...A],$;B.length>0?$=await this._composeMiddleware(B,E,async()=>C.execute(tt,m),m.getAll(),m):$=await C.execute(tt,m);let j=Date.now()-Xe;if(ue.push({node:E,success:$.success,duration:j,timestamp:new Date().toISOString()}),!$.success){if(i.signal.aborted)return N.step("Workflow stopped externally"),{success:!0,state:m.getAll(),executionLog:ue,stoppedExternally:!0};m.append("errors",{node:E,error:$.error});let L=C.config?.retries||0,ee=`${E}_retries`,fe=m.getAll()[ee]||0;if(fe<L){N.stepInfo(`Retrying (attempt ${fe+1}/${L})`),m.update({[ee]:fe+1,[`${E}_raw`]:$.raw});continue}throw N.nodeFailed(E,$.error,{duration:j}),new Error(`Node '${E}' failed after ${fe} attempts: ${$.error}`)}m.update({[E]:$.output});let Z=this._summarizeNodeOutput(E,$.output);N.nodeComplete(E,{duration:j,details:Z});let K=this.edges.get(E);if(!K)E="END";else if(K.conditional){let L=K.routes(m.getAll());N.route(E,L),E=L}else E=K}catch(A){throw N.isInsideNode&&N.nodeFailed(E,A.message,{duration:Date.now()-Xe}),m.set("failed",!0),m.set("failedAt",E),A}}N.graphComplete();let v={success:!0,state:m.getAll(),executionLog:ue};return e&&typeof e.onComplete=="function"&&await e.onComplete(v),v}finally{if(e&&typeof e.cleanup=="function")try{await e.cleanup()}catch(v){console.warn(`[workflow] agent.cleanup() failed: ${v.message}`)}}}};var Ue=Symbol.for("@zibby/agent-workflow.nodes");globalThis[Ue]||(globalThis[Ue]=new Map);var de=globalThis[Ue];function Kt(o,e){de.set(o,e)}function We(o){return de.get(o)}function we(o){return de.has(o)}function Jo(){return Array.from(de.keys())}function He(o){let e=de.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}Kt("ai_agent",{name:"ai_agent",factory:!0,create:(o,e={})=>({name:o,_isCustomCode:!0,execute:async t=>{let r=t?._coreInvokeAgent;r||(r=(await Promise.resolve().then(()=>(X(),ae))).invokeAgent);let i=e.extraPromptInstructions||"Execute the task based on the current state.",s=Yo(i,t),n=await r(s,{cwd:t.workspace||process.cwd(),model:t.model,tools:e.resolvedTools||null});return{success:!0,output:{raw:n,nodeId:o},raw:typeof n=="string"?n:n.raw}}})});function Yo(o,e){let t=/@([\w.]+)/g,r=new Set,i;for(;(i=t.exec(o))!==null;)r.add(i[1]);if(r.size===0)return o;let s=[],n=new Set;for(let a of r){let l=a.split(".")[0];if(n.has(l))continue;let u=a.split(".").reduce((c,y)=>c?.[y],e);if(u===void 0)continue;let f=typeof u=="string"?u:u?.raw??JSON.stringify(u,null,2),d=a.replace(/_/g," ").replace(/\b\w/g,c=>c.toUpperCase());s.push(`## ${d}
43
43
  ${f}`),a.includes(".")||n.add(l)}return s.length===0?o:`${o}
44
44
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zibby/agent-workflow",
3
- "version": "0.4.33",
3
+ "version": "0.4.34",
4
4
  "description": "Graph-based AI agent workflow orchestration. Bring your own agent strategies.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",