@zibby/agent-workflow 0.1.4 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -5,7 +5,9 @@
5
5
  [![Types](https://img.shields.io/npm/types/@zibby/agent-workflow.svg)](https://www.npmjs.com/package/@zibby/agent-workflow)
6
6
  [![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](./LICENSE)
7
7
 
8
- > **Run agents inside a workflow.** Graph-based JavaScript engine for orchestrating real coding agents — Claude Code, Cursor, Codex, Gemini, OpenAI Assistants — with structured I/O between nodes.
8
+ 📖 **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)
9
+
10
+ > **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.
9
11
 
10
12
  ```
11
13
  ┌──────────┐ ┌──────────┐ ┌──────────┐
@@ -27,6 +29,8 @@ graph
27
29
  .addNode('verify', { prompt, outputSchema: Result, agent: 'codex' });
28
30
  ```
29
31
 
32
+ 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.
33
+
30
34
  ---
31
35
 
32
36
  ## ⚡ Try it in 60 seconds
@@ -1,15 +1,15 @@
1
- var R=Object.defineProperty;var N=(e,o)=>()=>(e&&(o=e(e=0)),o);var D=(e,o)=>{for(var n in o)R(e,n,{get:o[n],enumerable:!0})};function $(e){return L.get(e)||null}var L,v=N(()=>{L=new Map});var _,M,T,k,x=N(()=>{_=()=>{},M={debug:_,info:_,warn:(...e)=>console.warn("[workflow]",...e),error:(...e)=>console.error("[workflow]",...e)},T={impl:M},k={debug:(...e)=>T.impl.debug?.(...e),info:(...e)=>T.impl.info?.(...e),warn:(...e)=>T.impl.warn?.(...e),error:(...e)=>T.impl.error?.(...e)}});var A=N(()=>{});var C={};D(C,{getAgentStrategy:()=>b,invokeAgent:()=>G,listStrategies:()=>B,registerStrategy:()=>F});function F(e){if(!e||typeof e.getName!="function"||typeof e.invoke!="function")throw new Error("strategy must implement getName() and invoke() (AgentStrategy shape)");let o=m.findIndex(n=>n.getName()===e.getName());o>=0?m[o]=e:m.push(e)}function B(){return m.map(e=>e.getName())}function b(e={}){let{state:o={},preferredAgent:n=null}=e,r=n||o.agentType||process.env.AGENT_TYPE;if(!r){let s=m.map(t=>t.getName()).join(", ")||"none registered";throw new Error(`No agent specified. Set agentType in state or AGENT_TYPE env var. Available: ${s}`)}k.debug(`[workflow] agent selection: requested=${r}`);let i=m.find(s=>s.getName()===r);if(!i){let s=m.map(t=>t.getName()).join(", ")||"none registered";throw new Error(`Unknown agent '${r}'. Available: ${s}`)}if(!i.canHandle(e))throw new Error(`Agent '${r}' is not available in this environment. Check credentials/environment.`);return k.debug(`[workflow] using agent: ${i.getName()}`),i}async function G(e,o={},n={}){let r=b(o),i=o.state?.config||n.config||{},s=i.models||{},t=n.nodeName&&s[n.nodeName]||null,a=s.default||null,c=i.agent?.[r.name]?.model||null,l=t||a||c||n.model||null,p={...n,model:l,workspace:o.state?.workspace||n.workspace,schema:n.schema||o.schema,images:n.images||o.images||[],skills:n.skills||o.skills||[],config:i},f=e,g=p.skills||[];if(g.length>0&&!n.skipPromptFragments){let d=g.map(y=>{let u=$(y)?.promptFragment;return typeof u=="function"?u():u}).filter(Boolean);d.length>0&&(f+=`
1
+ var L=Object.defineProperty;var k=(e,o)=>()=>(e&&(o=e(e=0)),o);var M=(e,o)=>{for(var n in o)L(e,n,{get:o[n],enumerable:!0})};function S(e){return G.get(e)||null}var $,G,v=k(()=>{$=Symbol.for("@zibby/agent-workflow.skills");globalThis[$]||(globalThis[$]=new Map);G=globalThis[$]});var _,z,N,T,x=k(()=>{_=()=>{},z={debug:_,info:_,warn:(...e)=>console.warn("[workflow]",...e),error:(...e)=>console.error("[workflow]",...e)},N={impl:z},T={debug:(...e)=>N.impl.debug?.(...e),info:(...e)=>N.impl.info?.(...e),warn:(...e)=>N.impl.warn?.(...e),error:(...e)=>N.impl.error?.(...e)}});var C=k(()=>{});var j={};M(j,{getAgentStrategy:()=>I,invokeAgent:()=>Y,listStrategies:()=>B,registerStrategy:()=>F});function F(e){if(!e||typeof e.getName!="function"||typeof e.invoke!="function")throw new Error("strategy must implement getName() and invoke() (AgentStrategy shape)");let o=m.findIndex(n=>n.getName()===e.getName());o>=0?m[o]=e:m.push(e)}function B(){return m.map(e=>e.getName())}function I(e={}){let{state:o={},preferredAgent:n=null}=e,r=n||o.agentType||process.env.AGENT_TYPE;if(!r){let s=m.map(t=>t.getName()).join(", ")||"none registered";throw new Error(`No agent specified. Set agentType in state or AGENT_TYPE env var. Available: ${s}`)}T.debug(`[workflow] agent selection: requested=${r}`);let i=m.find(s=>s.getName()===r);if(!i){let s=m.map(t=>t.getName()).join(", ")||"none registered";throw new Error(`Unknown agent '${r}'. Available: ${s}`)}if(!i.canHandle(e))throw new Error(`Agent '${r}' is not available in this environment. Check credentials/environment.`);return T.debug(`[workflow] using agent: ${i.getName()}`),i}async function Y(e,o={},n={}){let r=I(o),i=o.state?.config||n.config||{},s=i.models||{},t=n.nodeName&&s[n.nodeName]||null,a=s.default||null,c=i.agent?.[r.name]?.model||null,l=t||a||c||n.model||null,p={...n,model:l,workspace:o.state?.workspace||n.workspace,schema:n.schema||o.schema,images:n.images||o.images||[],skills:n.skills||o.skills||[],config:i},u=e,g=p.skills||[];if(g.length>0&&!n.skipPromptFragments){let d=g.map(y=>{let f=S(y)?.promptFragment;return typeof f=="function"?f():f}).filter(Boolean);d.length>0&&(u+=`
2
2
 
3
3
  ${d.join(`
4
4
 
5
- `)}`)}let h=o.state?._currentNodeConfig?.extraPromptInstructions?.trim();return h&&(f+=`
5
+ `)}`)}let h=o.state?._currentNodeConfig?.extraPromptInstructions?.trim();return h&&(u+=`
6
6
 
7
7
  \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
8
8
  PRIORITY OVERRIDE \u2014 THE FOLLOWING INSTRUCTIONS TAKE PRECEDENCE OVER ALL PREVIOUS CONTENT
9
9
  \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
10
10
 
11
11
  ${h}
12
- `),k.debug(`[workflow] prompt length: ${f.length} chars`),r.invoke(f,p)}var S,m,j=N(()=>{A();x();v();S=Symbol.for("@zibby/agent-workflow.strategies");globalThis[S]||(globalThis[S]=[]);m=globalThis[S]});v();x();var E={};var I=new Map;function z(e,o){I.set(e,o)}function O(e){let o=I.get(e);return o?o.factory&&typeof o.create=="function"?o.create.toString():typeof o.execute=="function"?o.execute.toString():typeof o=="function"?o.toString():null:null}z("ai_agent",{name:"ai_agent",factory:!0,create:(e,o={})=>({name:e,_isCustomCode:!0,execute:async n=>{let r=n?._coreInvokeAgent;r||(r=(await Promise.resolve().then(()=>(j(),C))).invokeAgent);let i=o.extraPromptInstructions||"Execute the task based on the current state.",s=U(i,n),t=await r(s,{cwd:n.workspace||process.cwd(),model:n.model,tools:o.resolvedTools||null});return{success:!0,output:{raw:t,nodeId:e},raw:typeof t=="string"?t:t.raw}}})});function U(e,o){let n=/@([\w.]+)/g,r=new Set,i;for(;(i=n.exec(e))!==null;)r.add(i[1]);if(r.size===0)return e;let s=[],t=new Set;for(let a of r){let c=a.split(".")[0];if(t.has(c))continue;let l=a.split(".").reduce((g,h)=>g?.[h],o);if(l===void 0)continue;let p=typeof l=="string"?l:l?.raw??JSON.stringify(l,null,2),f=a.replace(/_/g," ").replace(/\b\w/g,g=>g.toUpperCase());s.push(`## ${f}
12
+ `),T.debug(`[workflow] prompt length: ${u.length} chars`),r.invoke(u,p)}var E,m,O=k(()=>{C();x();v();E=Symbol.for("@zibby/agent-workflow.strategies");globalThis[E]||(globalThis[E]=[]);m=globalThis[E]});v();x();var A={};var b=Symbol.for("@zibby/agent-workflow.nodes");globalThis[b]||(globalThis[b]=new Map);var R=globalThis[b];function U(e,o){R.set(e,o)}function P(e){let o=R.get(e);return o?o.factory&&typeof o.create=="function"?o.create.toString():typeof o.execute=="function"?o.execute.toString():typeof o=="function"?o.toString():null:null}U("ai_agent",{name:"ai_agent",factory:!0,create:(e,o={})=>({name:e,_isCustomCode:!0,execute:async n=>{let r=n?._coreInvokeAgent;r||(r=(await Promise.resolve().then(()=>(O(),j))).invokeAgent);let i=o.extraPromptInstructions||"Execute the task based on the current state.",s=V(i,n),t=await r(s,{cwd:n.workspace||process.cwd(),model:n.model,tools:o.resolvedTools||null});return{success:!0,output:{raw:t,nodeId:e},raw:typeof t=="string"?t:t.raw}}})});function V(e,o){let n=/@([\w.]+)/g,r=new Set,i;for(;(i=n.exec(e))!==null;)r.add(i[1]);if(r.size===0)return e;let s=[],t=new Set;for(let a of r){let c=a.split(".")[0];if(t.has(c))continue;let l=a.split(".").reduce((g,h)=>g?.[h],o);if(l===void 0)continue;let p=typeof l=="string"?l:l?.raw??JSON.stringify(l,null,2),u=a.replace(/_/g," ").replace(/\b\w/g,g=>g.toUpperCase());s.push(`## ${u}
13
13
  ${p}`),a.includes(".")||t.add(c)}return s.length===0?e:`${e}
14
14
 
15
15
  ---
@@ -17,13 +17,13 @@ ${p}`),a.includes(".")||t.add(c)}return s.length===0?e:`${e}
17
17
 
18
18
  ${s.join(`
19
19
 
20
- `)}`}function pe(e,o={}){let{nodes:n,edges:r,nodeConfigs:i={}}=e,s=new Set,t=[],a=new Map;for(let u of n){let w=u.data?.nodeType||u.type;a.set(u.id,w),w==="decision"?s.add(u.id):t.push({id:u.id,nodeType:w,label:u.data?.label||u.id})}let c=t.some(u=>{let w=i[u.id]||{};return!w.customCode&&!w.executeCode}),{toolsPerNode:l,toolIdsByVar:p}=Z(t,i),{simpleEdges:f,conditionalEdges:g}=q(r,s),h=Q(t,r,s),d=[],y=o.workflowType||"workflow";return d.push(V(o)),d.push(H(y,{usesRegisteredNodes:c})),d.push(W(p)),d.push(Y(y)),d.push(J(t,i)),d.push(K(t,h,f,g,l,y)),d.filter(Boolean).join(`
21
- `)}function ge(e){let o={};for(let[n,r]of Object.entries(e)){let{tools:i,...s}=r;Object.keys(s).length>0&&(o[n]=s)}return o}function V(e){let o=e.workflowType||"workflow";return["// Generated workflow",`// ${e.projectId?`Project: ${e.projectId} | `:""}Type: ${o} | Version: ${e.version??0}`,`// Downloaded: ${new Date().toISOString()}`,""].join(`
22
- `)}function H(e,{usesRegisteredNodes:o=!0}={}){let n=["import { WorkflowGraph, invokeAgent, getResolvedToolDefinitions } from '@zibby/agent-workflow';"];return o&&n.push("// import './register-nodes.js'; // register custom node types here"),n.push("import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'node:fs';","import { join, dirname } from 'node:path';","import { fileURLToPath } from 'node:url';",""),n.join(`
20
+ `)}`}function me(e,o={}){let{nodes:n,edges:r,nodeConfigs:i={}}=e,s=new Set,t=[],a=new Map;for(let f of n){let w=f.data?.nodeType||f.type;a.set(f.id,w),w==="decision"?s.add(f.id):t.push({id:f.id,nodeType:w,label:f.data?.label||f.id})}let c=t.some(f=>{let w=i[f.id]||{};return!w.customCode&&!w.executeCode}),{toolsPerNode:l,toolIdsByVar:p}=Q(t,i),{simpleEdges:u,conditionalEdges:g}=X(r,s),h=ee(t,r,s),d=[],y=o.workflowType||"workflow";return d.push(H(o)),d.push(K(y,{usesRegisteredNodes:c})),d.push(W(p)),d.push(J(y)),d.push(Z(t,i)),d.push(q(t,h,u,g,l,y)),d.filter(Boolean).join(`
21
+ `)}function he(e){let o={};for(let[n,r]of Object.entries(e)){let{tools:i,...s}=r;Object.keys(s).length>0&&(o[n]=s)}return o}function H(e){let o=e.workflowType||"workflow";return["// Generated workflow",`// ${e.projectId?`Project: ${e.projectId} | `:""}Type: ${o} | Version: ${e.version??0}`,`// Downloaded: ${new Date().toISOString()}`,""].join(`
22
+ `)}function K(e,{usesRegisteredNodes:o=!0}={}){let n=["import { WorkflowGraph, invokeAgent, getResolvedToolDefinitions } from '@zibby/agent-workflow';"];return o&&n.push("// import './register-nodes.js'; // register custom node types here"),n.push("import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'node:fs';","import { join, dirname } from 'node:path';","import { fileURLToPath } from 'node:url';",""),n.join(`
23
23
  `)}function W(e){if(e.size===0)return"";let o=["// \u2500\u2500 Tool Bindings \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"];for(let[n,r]of e)o.push(`const ${n} = getResolvedToolDefinitions(${JSON.stringify(r)}); // ${r.join(", ")}`);return o.push(""),o.join(`
24
- `)}function Y(e){return["// \u2500\u2500 Node Configs \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500","const __filename = fileURLToPath(import.meta.url);","const __dirname = dirname(__filename);",`const configPath = join(__dirname, 'workflow-${e}.config.json');`,"const nodeConfigs = existsSync(configPath) ? JSON.parse(readFileSync(configPath, 'utf-8')) : {};",""].join(`
25
- `)}function J(e,o){let n=["// \u2500\u2500 Node Implementations \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500",""];for(let r of e){let i=P(r.id),s=o[r.id]?.customCode;if(s)n.push(`// @custom \u2014 modified from default "${r.nodeType}" template`),n.push(`const ${i}_execute = ${s};`);else{let t=O(r.nodeType);t?(n.push(`// Default "${r.nodeType}" implementation`),n.push(`const ${i}_execute = ${t};`)):(n.push(`// No template for "${r.nodeType}" \u2014 passthrough`),n.push(`const ${i}_execute = async (state) => ({ success: true, output: {}, raw: null });`))}n.push("")}return n.join(`
26
- `)}function K(e,o,n,r,i,s){let t=["// \u2500\u2500 Graph Builder \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"];t.push("export function buildGraph(options = {}) {"),t.push(" const graph = new WorkflowGraph(options);",""),t.push(" // Nodes");for(let c of e){let l=P(c.id);t.push(` graph.addNode('${c.id}', { name: '${c.id}', execute: ${l}_execute });`),t.push(` graph.setNodeType('${c.id}', '${c.nodeType}');`)}t.push("",` graph.setEntryPoint('${o}');`,""),(n.length>0||r.length>0)&&t.push(" // Edges");for(let c of n)t.push(` graph.addEdge('${c.source}', '${c.target}');`);for(let c of r){let l=c.code.split(`
27
- `).map((p,f)=>f===0?p:` ${p}`).join(`
24
+ `)}function J(e){return["// \u2500\u2500 Node Configs \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500","const __filename = fileURLToPath(import.meta.url);","const __dirname = dirname(__filename);",`const configPath = join(__dirname, 'workflow-${e}.config.json');`,"const nodeConfigs = existsSync(configPath) ? JSON.parse(readFileSync(configPath, 'utf-8')) : {};",""].join(`
25
+ `)}function Z(e,o){let n=["// \u2500\u2500 Node Implementations \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500",""];for(let r of e){let i=D(r.id),s=o[r.id]?.customCode;if(s)n.push(`// @custom \u2014 modified from default "${r.nodeType}" template`),n.push(`const ${i}_execute = ${s};`);else{let t=P(r.nodeType);t?(n.push(`// Default "${r.nodeType}" implementation`),n.push(`const ${i}_execute = ${t};`)):(n.push(`// No template for "${r.nodeType}" \u2014 passthrough`),n.push(`const ${i}_execute = async (state) => ({ success: true, output: {}, raw: null });`))}n.push("")}return n.join(`
26
+ `)}function q(e,o,n,r,i,s){let t=["// \u2500\u2500 Graph Builder \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"];t.push("export function buildGraph(options = {}) {"),t.push(" const graph = new WorkflowGraph(options);",""),t.push(" // Nodes");for(let c of e){let l=D(c.id);t.push(` graph.addNode('${c.id}', { name: '${c.id}', execute: ${l}_execute });`),t.push(` graph.setNodeType('${c.id}', '${c.nodeType}');`)}t.push("",` graph.setEntryPoint('${o}');`,""),(n.length>0||r.length>0)&&t.push(" // Edges");for(let c of n)t.push(` graph.addEdge('${c.source}', '${c.target}');`);for(let c of r){let l=c.code.split(`
27
+ `).map((p,u)=>u===0?p:` ${p}`).join(`
28
28
  `);t.push(` graph.addConditionalEdges('${c.source}', ${l});`)}let a=[];for(let c of e){let l=i.get(c.id);l&&a.push(` '${c.id}': ${l},`)}return a.length>0&&t.push(""," graph.resolvedToolsMap = {",...a," };"),t.push(""," return graph;","}",""),t.push("export { nodeConfigs };",""),t.join(`
29
- `)}function Z(e,o){let n=new Map,r=new Map;for(let i of e){let s=o[i.id]?.tools,t;if(Array.isArray(s)&&s.length>0)t=[...s].sort();else{let a=E[i.nodeType];a?.length>0&&(t=[...a].sort())}if(t){let a=`${t.map(c=>c.replace(/[^a-zA-Z0-9]/g,"")).join("And")}Tools`;n.set(i.id,a),r.has(a)||r.set(a,t)}}return{toolsPerNode:n,toolIdsByVar:r}}function q(e,o){let n=[],r=[],i=new Map,s=new Set;for(let t of e)i.has(t.source)||i.set(t.source,[]),i.get(t.source).push(t);for(let t of e)if(!o.has(t.source))if(o.has(t.target)){if(s.has(t.target))continue;s.add(t.target);let c=(i.get(t.target)||[]).find(l=>l.data?.conditionalCode||l.conditionalCode);c&&r.push({source:t.source,code:c.data?.conditionalCode||c.conditionalCode})}else n.push({source:t.source,target:t.target});return{simpleEdges:n,conditionalEdges:r}}function Q(e,o,n){let r=new Set;for(let s of o)n.has(s.target)||r.add(s.target);let i=e.find(s=>!r.has(s.id));return i?i.id:e[0]?.id}function P(e){return e.replace(/[^a-zA-Z0-9]/g,"_")}export{ge as generateNodeConfigsJson,pe as generateWorkflowCode};
29
+ `)}function Q(e,o){let n=new Map,r=new Map;for(let i of e){let s=o[i.id]?.tools,t;if(Array.isArray(s)&&s.length>0)t=[...s].sort();else{let a=A[i.nodeType];a?.length>0&&(t=[...a].sort())}if(t){let a=`${t.map(c=>c.replace(/[^a-zA-Z0-9]/g,"")).join("And")}Tools`;n.set(i.id,a),r.has(a)||r.set(a,t)}}return{toolsPerNode:n,toolIdsByVar:r}}function X(e,o){let n=[],r=[],i=new Map,s=new Set;for(let t of e)i.has(t.source)||i.set(t.source,[]),i.get(t.source).push(t);for(let t of e)if(!o.has(t.source))if(o.has(t.target)){if(s.has(t.target))continue;s.add(t.target);let c=(i.get(t.target)||[]).find(l=>l.data?.conditionalCode||l.conditionalCode);c&&r.push({source:t.source,code:c.data?.conditionalCode||c.conditionalCode})}else n.push({source:t.source,target:t.target});return{simpleEdges:n,conditionalEdges:r}}function ee(e,o,n){let r=new Set;for(let s of o)n.has(s.target)||r.add(s.target);let i=e.find(s=>!r.has(s.id));return i?i.id:e[0]?.id}function D(e){return e.replace(/[^a-zA-Z0-9]/g,"_")}export{he as generateNodeConfigsJson,me as generateWorkflowCode};
@@ -4,8 +4,13 @@
4
4
  export const DEFAULT_OUTPUT_BASE: ".zibby/output";
5
5
  export const SESSIONS_DIR: "sessions";
6
6
  export const SESSION_INFO_FILE: ".session-info.json";
7
- /** Written by Zibby Studio / CLI bridge when user stops a run; WorkflowGraph polls and exits. */
8
- export const STUDIO_STOP_REQUEST_FILE: ".zibby-studio-stop";
7
+ /**
8
+ * Written by any consumer (CLI Ctrl+C handler, IDE plugin, desktop app) to
9
+ * request that an in-flight workflow stop at the next abort-checkpoint.
10
+ * WorkflowGraph polls for this file between nodes and exits cleanly.
11
+ * Consumers should prefer the AbortSignal contract (`graph.run({ signal })`).
12
+ */
13
+ export const STOP_REQUEST_FILE: ".zibby-stop";
9
14
  export const RESULT_FILE: "result.json";
10
15
  export const RAW_OUTPUT_FILE: "raw_stream_output.txt";
11
16
  export const EVENTS_FILE: "events.json";
package/dist/constants.js CHANGED
@@ -1 +1 @@
1
- var o=".zibby/output",t="sessions",s=".session-info.json",_=".zibby-studio-stop",I="result.json",r="raw_stream_output.txt",E="events.json",e={BROWSER:"browser",JIRA:"jira",GITHUB:"github",SLACK:"slack",MEMORY:"memory",CHAT_MEMORY:"chat-memory",RUNNER:"runner",SKILL_INSTALLER:"skill-installer",CORE_TOOLS:"core-tools",WORKFLOW_BUILDER:"workflow-builder"},S=["CI_JOB_ID","GITHUB_RUN_ID","CIRCLE_WORKFLOW_ID","BUILD_ID"];export{S as CI_ENV_VARS,o as DEFAULT_OUTPUT_BASE,E as EVENTS_FILE,r as RAW_OUTPUT_FILE,I as RESULT_FILE,t as SESSIONS_DIR,s as SESSION_INFO_FILE,e as SKILLS,_ as STUDIO_STOP_REQUEST_FILE};
1
+ var o=".zibby/output",t="sessions",s=".session-info.json",_=".zibby-stop",I="result.json",r="raw_stream_output.txt",E="events.json",e={BROWSER:"browser",JIRA:"jira",GITHUB:"github",SLACK:"slack",MEMORY:"memory",CHAT_MEMORY:"chat-memory",RUNNER:"runner",SKILL_INSTALLER:"skill-installer",CORE_TOOLS:"core-tools",WORKFLOW_BUILDER:"workflow-builder"},L=["CI_JOB_ID","GITHUB_RUN_ID","CIRCLE_WORKFLOW_ID","BUILD_ID"];export{L as CI_ENV_VARS,o as DEFAULT_OUTPUT_BASE,E as EVENTS_FILE,r as RAW_OUTPUT_FILE,I as RESULT_FILE,t as SESSIONS_DIR,s as SESSION_INFO_FILE,e as SKILLS,_ as STOP_REQUEST_FILE};
@@ -1,45 +1,45 @@
1
- var Qe=Object.defineProperty;var oe=(o=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(o,{get:(e,t)=>(typeof require<"u"?require:e)[t]}):o)(function(o){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+o+'" is not supported')});var J=(o,e)=>()=>(o&&(e=o(o=0)),e);var $e=(o,e)=>{for(var t in e)Qe(o,t,{get:e[t],enumerable:!0})};var Ee,tt,z,w,D=J(()=>{Ee=()=>{},tt={debug:Ee,info:Ee,warn:(...o)=>console.warn("[workflow]",...o),error:(...o)=>console.error("[workflow]",...o)},z={impl:tt},w={debug:(...o)=>z.impl.debug?.(...o),info:(...o)=>z.impl.info?.(...o),warn:(...o)=>z.impl.warn?.(...o),error:(...o)=>z.impl.error?.(...o)}});var Pe=J(()=>{});var Re={};$e(Re,{clearSkills:()=>ct,getAllSkills:()=>it,getSkill:()=>L,hasSkill:()=>nt,listSkillIds:()=>at,registerSkill:()=>st});function st(o){if(!o||typeof o.id!="string")throw new Error("Skill definition must include a string id");W.set(o.id,Object.freeze({...o}))}function L(o){return W.get(o)||null}function nt(o){return W.has(o)}function it(){return new Map(W)}function at(){return Array.from(W.keys())}function ct(){W.clear()}var W,q=J(()=>{W=new Map});var j={};$e(j,{getAgentStrategy:()=>We,invokeAgent:()=>dt,listStrategies:()=>ut,registerStrategy:()=>lt});function lt(o){if(!o||typeof o.getName!="function"||typeof o.invoke!="function")throw new Error("strategy must implement getName() and invoke() (AgentStrategy shape)");let e=C.findIndex(t=>t.getName()===o.getName());e>=0?C[e]=o:C.push(o)}function ut(){return C.map(o=>o.getName())}function We(o={}){let{state:e={},preferredAgent:t=null}=o,r=t||e.agentType||process.env.AGENT_TYPE;if(!r){let s=C.map(a=>a.getName()).join(", ")||"none registered";throw new Error(`No agent specified. Set agentType in state or AGENT_TYPE env var. Available: ${s}`)}w.debug(`[workflow] agent selection: requested=${r}`);let n=C.find(s=>s.getName()===r);if(!n){let s=C.map(a=>a.getName()).join(", ")||"none registered";throw new Error(`Unknown agent '${r}'. Available: ${s}`)}if(!n.canHandle(o))throw new Error(`Agent '${r}' is not available in this environment. Check credentials/environment.`);return w.debug(`[workflow] using agent: ${n.getName()}`),n}async function dt(o,e={},t={}){let r=We(e),n=e.state?.config||t.config||{},s=n.models||{},a=t.nodeName&&s[t.nodeName]||null,i=s.default||null,c=n.agent?.[r.name]?.model||null,l=a||i||c||t.model||null,m={...t,model:l,workspace:e.state?.workspace||t.workspace,schema:t.schema||e.schema,images:t.images||e.images||[],skills:t.skills||e.skills||[],config:n},d=o,u=m.skills||[];if(u.length>0&&!t.skipPromptFragments){let p=u.map(_=>{let N=L(_)?.promptFragment;return typeof N=="function"?N():N}).filter(Boolean);p.length>0&&(d+=`
1
+ var it=Object.defineProperty;var ie=(o=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(o,{get:(e,t)=>(typeof require<"u"?require:e)[t]}):o)(function(o){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+o+'" is not supported')});var V=(o,e)=>()=>(o&&(e=o(o=0)),e);var ke=(o,e)=>{for(var t in e)it(o,t,{get:e[t],enumerable:!0})};var Te,ct,Q,S,G=V(()=>{Te=()=>{},ct={debug:Te,info:Te,warn:(...o)=>console.warn("[workflow]",...o),error:(...o)=>console.error("[workflow]",...o)},Q={impl:ct},S={debug:(...o)=>Q.impl.debug?.(...o),info:(...o)=>Q.impl.info?.(...o),warn:(...o)=>Q.impl.warn?.(...o),error:(...o)=>Q.impl.error?.(...o)}});var Le=V(()=>{});var Fe={};ke(Fe,{clearSkills:()=>mt,getAllSkills:()=>ft,getSkill:()=>U,hasSkill:()=>pt,listSkillIds:()=>ht,registerSkill:()=>dt});function dt(o){if(!o||typeof o.id!="string")throw new Error("Skill definition must include a string id");F.set(o.id,Object.freeze({...o}))}function U(o){return F.get(o)||null}function pt(o){return F.has(o)}function ft(){return new Map(F)}function ht(){return Array.from(F.keys())}function mt(){F.clear()}var de,F,te=V(()=>{de=Symbol.for("@zibby/agent-workflow.skills");globalThis[de]||(globalThis[de]=new Map);F=globalThis[de]});var H={};ke(H,{getAgentStrategy:()=>je,invokeAgent:()=>St,listStrategies:()=>wt,registerStrategy:()=>gt});function gt(o){if(!o||typeof o.getName!="function"||typeof o.invoke!="function")throw new Error("strategy must implement getName() and invoke() (AgentStrategy shape)");let e=R.findIndex(t=>t.getName()===o.getName());e>=0?R[e]=o:R.push(o)}function wt(){return R.map(o=>o.getName())}function je(o={}){let{state:e={},preferredAgent:t=null}=o,r=t||e.agentType||process.env.AGENT_TYPE;if(!r){let i=R.map(a=>a.getName()).join(", ")||"none registered";throw new Error(`No agent specified. Set agentType in state or AGENT_TYPE env var. Available: ${i}`)}S.debug(`[workflow] agent selection: requested=${r}`);let s=R.find(i=>i.getName()===r);if(!s){let i=R.map(a=>a.getName()).join(", ")||"none registered";throw new Error(`Unknown agent '${r}'. Available: ${i}`)}if(!s.canHandle(o))throw new Error(`Agent '${r}' is not available in this environment. Check credentials/environment.`);return S.debug(`[workflow] using agent: ${s.getName()}`),s}async function St(o,e={},t={}){let r=je(e),s=e.state?.config||t.config||{},i=s.models||{},a=t.nodeName&&i[t.nodeName]||null,n=i.default||null,c=s.agent?.[r.name]?.model||null,u=a||n||c||t.model||null,h={...t,model:u,workspace:e.state?.workspace||t.workspace,schema:t.schema||e.schema,images:t.images||e.images||[],skills:t.skills||e.skills||[],config:s},d=o,l=h.skills||[];if(l.length>0&&!t.skipPromptFragments){let _=l.map(w=>{let N=U(w)?.promptFragment;return typeof N=="function"?N():N}).filter(Boolean);_.length>0&&(d+=`
2
2
 
3
- ${p.join(`
3
+ ${_.join(`
4
4
 
5
- `)}`)}let g=e.state?._currentNodeConfig?.extraPromptInstructions?.trim();return g&&(d+=`
5
+ `)}`)}let m=e.state?._currentNodeConfig?.extraPromptInstructions?.trim();return m&&(d+=`
6
6
 
7
7
  \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
8
8
  PRIORITY OVERRIDE \u2014 THE FOLLOWING INSTRUCTIONS TAKE PRECEDENCE OVER ALL PREVIOUS CONTENT
9
9
  \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
10
10
 
11
- ${g}
12
- `),w.debug(`[workflow] prompt length: ${d.length} chars`),r.invoke(d,m)}var ae,C,U=J(()=>{Pe();D();q();ae=Symbol.for("@zibby/agent-workflow.strategies");globalThis[ae]||(globalThis[ae]=[]);C=globalThis[ae]});var et=new Set(["__proto__","constructor","prototype"]);function re(o){if(et.has(o))throw new Error(`Invalid state key: "${o}"`)}var H=class{constructor(e={}){this._state=Object.create(null),Object.assign(this._state,{messages:[],errors:[],artifacts:{},metadata:{},...e}),this._history=[]}get(e){return this._state[e]}set(e,t){re(e),this._history.push({...this._state}),this._state[e]=t}update(e){let t=Object.getOwnPropertyNames(e);for(let r of t)re(r);this._history.push({...this._state});for(let r of t)this._state[r]=e[r]}append(e,t){re(e),this._history.push({...this._state}),Array.isArray(this._state[e])||(this._state[e]=[]),this._state[e].push(t)}getAll(){return{...this._state}}rollback(){this._history.length>0&&(this._state=this._history.pop())}};var K=class{constructor(e){this.schema=e}parse(e){let t=e.match(/```json\s*([\s\S]*?)\s*```/);if(t)return this.validate(JSON.parse(t[1]));let r=e.match(/\{[\s\S]*\}/);return r?this.validate(JSON.parse(r[0])):this.validate({result:e.trim()})}validate(e){let t=[];for(let[r,n]of Object.entries(this.schema)){if(n.required&&!(r in e)&&t.push(`Missing required field: ${r}`),r in e&&n.type){let s=typeof e[r];s!==n.type&&t.push(`Field '${r}' expected ${n.type}, got ${s}`)}if(n.validate&&r in e){let s=n.validate(e[r]);s&&t.push(`Field '${r}': ${s}`)}}if(t.length>0)throw new Error(`Output validation failed:
11
+ ${m}
12
+ `),S.debug(`[workflow] prompt length: ${d.length} chars`),r.invoke(d,h)}var pe,R,J=V(()=>{Le();G();te();pe=Symbol.for("@zibby/agent-workflow.strategies");globalThis[pe]||(globalThis[pe]=[]);R=globalThis[pe]});var at=new Set(["__proto__","constructor","prototype"]);function ae(o){if(at.has(o))throw new Error(`Invalid state key: "${o}"`)}var q=class{constructor(e={}){this._state=Object.create(null),Object.assign(this._state,{messages:[],errors:[],artifacts:{},metadata:{},...e}),this._history=[]}get(e){return this._state[e]}set(e,t){ae(e),this._history.push({...this._state}),this._state[e]=t}update(e){let t=Object.getOwnPropertyNames(e);for(let r of t)ae(r);this._history.push({...this._state});for(let r of t)this._state[r]=e[r]}append(e,t){ae(e),this._history.push({...this._state}),Array.isArray(this._state[e])||(this._state[e]=[]),this._state[e].push(t)}getAll(){return{...this._state}}rollback(){this._history.length>0&&(this._state=this._history.pop())}};var X=class{constructor(e){this.schema=e}parse(e){let t=e.match(/```json\s*([\s\S]*?)\s*```/);if(t)return this.validate(JSON.parse(t[1]));let r=[e.match(/\{[\s\S]*?\}/),e.match(/\{[\s\S]*\}/)].filter(Boolean).map(s=>s[0]);for(let s of r)try{return this.validate(JSON.parse(s))}catch(i){if(!(i instanceof SyntaxError))throw i}return this.validate({result:e.trim()})}validate(e){let t=[];for(let[r,s]of Object.entries(this.schema)){if(s.required&&!(r in e)&&t.push(`Missing required field: ${r}`),r in e&&s.type){let i=typeof e[r];i!==s.type&&t.push(`Field '${r}' expected ${s.type}, got ${i}`)}if(s.validate&&r in e){let i=s.validate(e[r]);i&&t.push(`Field '${r}': ${i}`)}}if(t.length>0)throw new Error(`Output validation failed:
13
13
  ${t.join(`
14
- `)}`);return e}};D();import{writeFileSync as ce,readFileSync as Me,existsSync as Be,mkdirSync as pt}from"node:fs";import{join as le,dirname as ft}from"node:path";import y from"chalk";var ot="__WORKFLOW_GRAPH_LOG__",F=y.gray("\u2502"),rt=y.gray("\u250C"),Ie=y.gray("\u2514"),se=y.green("\u25C6"),ve=y.hex("#c084fc")("\u25C6"),Ne=y.hex("#2dd4bf")("\u25C6"),ne=y.red("\u25C6"),ke=`${F} `,xe=2;function Oe(o){return o<1e3?`${o}ms`:`${(o/1e3).toFixed(1)}s`}function Te(o,e){return(t,r,n)=>{if(typeof t!="string")return o(t,r,n);let s=process.stdout.columns||120,a="";for(let i=0;i<t.length;i++){let c=t[i];e.lineStart&&(a+=ke,e.col=xe,e.lineStart=!1),c===`
15
- `?(a+=c,e.lineStart=!0,e.col=0,e.inEsc=!1):c==="\x1B"?(e.inEsc=!0,a+=c):e.inEsc?(a+=c,(c>="A"&&c<="Z"||c>="a"&&c<="z")&&(e.inEsc=!1)):(e.col++,a+=c,e.col>=s&&(a+=`
16
- ${ke}`,e.col=xe))}return o(a,r,n)}}var ie=class{constructor(){this._currentNode=null,this._origStdoutWrite=null,this._origStderrWrite=null;let e=String(process.env.ZIBBY_RUN_SOURCE||"").trim().toLowerCase(),t=String(process.env.ZIBBY_WORKFLOW_GRAPH_LOG_MARKERS||"").trim()==="1";this._emitWorkflowGraphMarkers=t||e==="studio"}get isInsideNode(){return this._currentNode!==null}_startIntercepting(){this._origStdoutWrite=process.stdout.write.bind(process.stdout),this._origStderrWrite=process.stderr.write.bind(process.stderr);let e={lineStart:!0,col:0,inEsc:!1},t={lineStart:!0,col:0,inEsc:!1};this._outState=e,this._errState=t,process.stdout.write=Te(this._origStdoutWrite,e),process.stderr.write=Te(this._origStderrWrite,t)}_stopIntercepting(){this._origStdoutWrite&&(this._outState&&!this._outState.lineStart&&this._origStdoutWrite(`
14
+ `)}`);return e}};G();import{writeFileSync as fe,readFileSync as Ye,existsSync as Ge,mkdirSync as _t}from"node:fs";import{join as he,dirname as yt}from"node:path";import E from"chalk";var lt="__WORKFLOW_GRAPH_LOG__",Z=E.gray("\u2502"),ut=E.gray("\u250C"),xe=E.gray("\u2514"),ce=E.green("\u25C6"),Ae=E.hex("#c084fc")("\u25C6"),Oe=E.hex("#2dd4bf")("\u25C6"),le=E.red("\u25C6"),Ce=`${Z} `,Pe=2;function Re(o){return o<1e3?`${o}ms`:`${(o/1e3).toFixed(1)}s`}function We(o,e){return(t,r,s)=>{if(typeof t!="string")return o(t,r,s);let i=process.stdout.columns||120,a="";for(let n=0;n<t.length;n++){let c=t[n];e.lineStart&&(a+=Ce,e.col=Pe,e.lineStart=!1),c===`
15
+ `?(a+=c,e.lineStart=!0,e.col=0,e.inEsc=!1):c==="\x1B"?(e.inEsc=!0,a+=c):e.inEsc?(a+=c,(c>="A"&&c<="Z"||c>="a"&&c<="z")&&(e.inEsc=!1)):(e.col++,a+=c,e.col>=i&&(a+=`
16
+ ${Ce}`,e.col=Pe))}return o(a,r,s)}}var ue=class{constructor(){this._currentNode=null,this._origStdoutWrite=null,this._origStderrWrite=null,this._emitWorkflowGraphMarkers=String(process.env.ZIBBY_EMIT_GRAPH_MARKERS||"").trim()==="1"||String(process.env.ZIBBY_WORKFLOW_GRAPH_LOG_MARKERS||"").trim()==="1"}get isInsideNode(){return this._currentNode!==null}_startIntercepting(){this._origStdoutWrite=process.stdout.write.bind(process.stdout),this._origStderrWrite=process.stderr.write.bind(process.stderr);let e={lineStart:!0,col:0,inEsc:!1},t={lineStart:!0,col:0,inEsc:!1};this._outState=e,this._errState=t,process.stdout.write=We(this._origStdoutWrite,e),process.stderr.write=We(this._origStderrWrite,t)}_stopIntercepting(){this._origStdoutWrite&&(this._outState&&!this._outState.lineStart&&this._origStdoutWrite(`
17
17
  `),process.stdout.write=this._origStdoutWrite),this._origStderrWrite&&(this._errState&&!this._errState.lineStart&&this._origStderrWrite(`
18
18
  `),process.stderr.write=this._origStderrWrite),this._origStdoutWrite=null,this._origStderrWrite=null}_rawWrite(e){(this._origStdoutWrite||process.stdout.write.bind(process.stdout))(`${e}
19
- `)}_emitGraphLogMarker(e){if(!this._emitWorkflowGraphMarkers)return;let t=`${ot}${JSON.stringify(e)}
19
+ `)}_emitGraphLogMarker(e){if(!this._emitWorkflowGraphMarkers)return;let t=`${lt}${JSON.stringify(e)}
20
20
  `;this._origStdoutWrite?this._origStdoutWrite(t):process.stdout.write(t)}_writeDot(e,t){this._origStdoutWrite?(this._outState&&!this._outState.lineStart&&(this._origStdoutWrite(`
21
21
  `),this._outState.lineStart=!0,this._outState.col=0),this._origStdoutWrite(`${e} ${t}
22
22
  `)):process.stdout.write.bind(process.stdout)(`${e} ${t}
23
- `)}step(e){this._origStdoutWrite?this._writeDot(se,e):process.stdout.write.bind(process.stdout)(`${F} ${se} ${e}
24
- `)}stepInfo(e){this.step(e)}stepTool(e){this._origStdoutWrite?this._writeDot(ve,e):process.stdout.write.bind(process.stdout)(`${F} ${ve} ${e}
25
- `)}stepMemory(e){let t=y.hex("#2dd4bf")(e);this._origStdoutWrite?this._writeDot(Ne,t):process.stdout.write.bind(process.stdout)(`${F} ${Ne} ${t}
26
- `)}stepFail(e){this._origStdoutWrite?this._writeDot(ne,y.red(e)):process.stdout.write.bind(process.stdout)(`${F} ${ne} ${y.red(e)}
27
- `)}nodeStart(e){this._currentNode=e,this._emitGraphLogMarker({phase:"node_begin",node:e}),this._rawWrite(`${rt} ${e}`),this._startIntercepting()}nodeComplete(e,t={}){this._stopIntercepting();let{duration:r,details:n}=t;if(n)for(let a of n)this._rawWrite(`${se} ${a}`);let s=r?y.dim(` ${Oe(r)}`):"";this._rawWrite(`${Ie} ${y.green("done")}${s}`),this._emitGraphLogMarker({phase:"node_end",node:e}),this._rawWrite("")}nodeFailed(e,t,r={}){this._stopIntercepting();let{duration:n}=r,s=n?y.dim(` ${Oe(n)}`):"";this._rawWrite(`${ne} ${y.red(t)}`),this._rawWrite(`${Ie} ${y.red("failed")}${s}`),this._emitGraphLogMarker({phase:"node_end",node:e}),this._rawWrite("")}route(e,t){this._rawWrite(y.dim(` ${e} \u2192 ${t}`)),this._rawWrite("")}graphComplete(){this._rawWrite(y.green.bold("\u2713 Workflow completed"))}},E=new ie;var V=".zibby/output",be="sessions",R=".session-info.json",Ae=".zibby-studio-stop";var Ce=["CI_JOB_ID","GITHUB_RUN_ID","CIRCLE_WORKFLOW_ID","BUILD_ID"];var M=class{constructor(e){if(this.config=e,this.name=e.name,this.prompt=e.prompt,this.outputSchema=e.outputSchema,!this.outputSchema&&!e._isCustomCode)throw new Error(`Node '${this.name}' must define outputSchema (Zod schema). This defines the contract for what the node returns to state.`);this.isZodSchema=this.outputSchema&&typeof this.outputSchema._def<"u",this.parser=e.outputSchema&&!this.isZodSchema?new K(e.outputSchema):null,this.retries=e.retries||0,this.onComplete=e.onComplete,this.customExecute=e.execute}async execute(e,t){let r=()=>t&&typeof t.getAll=="function"?t.getAll():e,n=d=>t&&typeof t.get=="function"?t.get(d):e?.[d];if(typeof this.customExecute=="function"){w.debug(`[workflow] node '${this.name}': custom execute (skipping LLM)`);try{let d=await this.customExecute(e);return typeof d=="object"&&d!==null&&d.success===!1?{success:!1,error:d.error||"Node execution failed",raw:d.raw||null}:this.isZodSchema?(w.debug(`[workflow] node '${this.name}': validating output schema`),{success:!0,output:this.outputSchema.parse(d),raw:null}):{success:!0,output:d,raw:null}}catch(d){return w.error(`[workflow] node '${this.name}' failed: ${d.message}`),d.name==="ZodError"&&w.error(`Schema errors: ${JSON.stringify(d.errors,null,2)}`),{success:!1,error:d.message,raw:null}}}let s=typeof this.prompt=="function"?this.prompt(r()):this.prompt,a=n("_skillHints");a&&(s=`${a}
23
+ `)}step(e){this._origStdoutWrite?this._writeDot(ce,e):process.stdout.write.bind(process.stdout)(`${Z} ${ce} ${e}
24
+ `)}stepInfo(e){this.step(e)}stepTool(e){this._origStdoutWrite?this._writeDot(Ae,e):process.stdout.write.bind(process.stdout)(`${Z} ${Ae} ${e}
25
+ `)}stepMemory(e){let t=E.hex("#2dd4bf")(e);this._origStdoutWrite?this._writeDot(Oe,t):process.stdout.write.bind(process.stdout)(`${Z} ${Oe} ${t}
26
+ `)}stepFail(e){this._origStdoutWrite?this._writeDot(le,E.red(e)):process.stdout.write.bind(process.stdout)(`${Z} ${le} ${E.red(e)}
27
+ `)}nodeStart(e){this._currentNode=e,this._emitGraphLogMarker({phase:"node_begin",node:e}),this._rawWrite(`${ut} ${e}`),this._startIntercepting()}nodeComplete(e,t={}){this._stopIntercepting();let{duration:r,details:s}=t;if(s)for(let a of s)this._rawWrite(`${ce} ${a}`);let i=r?E.dim(` ${Re(r)}`):"";this._rawWrite(`${xe} ${E.green("done")}${i}`),this._emitGraphLogMarker({phase:"node_end",node:e}),this._rawWrite("")}nodeFailed(e,t,r={}){this._stopIntercepting();let{duration:s}=r,i=s?E.dim(` ${Re(s)}`):"";this._rawWrite(`${le} ${E.red(t)}`),this._rawWrite(`${xe} ${E.red("failed")}${i}`),this._emitGraphLogMarker({phase:"node_end",node:e}),this._rawWrite("")}route(e,t){this._rawWrite(E.dim(` ${e} \u2192 ${t}`)),this._rawWrite("")}graphComplete(){this._rawWrite(E.green.bold("\u2713 Workflow completed"))}},v=new ue;var ee=".zibby/output",Me="sessions",L=".session-info.json",Be=".zibby-stop";var De=["CI_JOB_ID","GITHUB_RUN_ID","CIRCLE_WORKFLOW_ID","BUILD_ID"];var j=class{constructor(e){if(this.config=e,this.name=e.name,this.prompt=e.prompt,this.outputSchema=e.outputSchema,!this.outputSchema&&!e._isCustomCode)throw new Error(`Node '${this.name}' must define outputSchema (Zod schema). This defines the contract for what the node returns to state.`);this.isZodSchema=this.outputSchema&&typeof this.outputSchema._def<"u",this.parser=e.outputSchema&&!this.isZodSchema?new X(e.outputSchema):null,this.retries=e.retries||0,this.onComplete=e.onComplete,this.customExecute=e.execute}async execute(e,t){let r=()=>t&&typeof t.getAll=="function"?t.getAll():e,s=d=>t&&typeof t.get=="function"?t.get(d):e?.[d];if(typeof this.customExecute=="function"){S.debug(`[workflow] node '${this.name}': custom execute (skipping LLM)`);try{let d=await this.customExecute(e);return typeof d=="object"&&d!==null&&d.success===!1?{success:!1,error:d.error||"Node execution failed",raw:d.raw||null}:this.isZodSchema?(S.debug(`[workflow] node '${this.name}': validating output schema`),{success:!0,output:this.outputSchema.parse(d),raw:null}):{success:!0,output:d,raw:null}}catch(d){return S.error(`[workflow] node '${this.name}' failed: ${d.message}`),d.name==="ZodError"&&S.error(`Schema errors: ${JSON.stringify(d.issues||d.errors,null,2)}`),{success:!1,error:d.message,raw:null}}}let i=typeof this.prompt=="function"?this.prompt(r()):this.prompt,a=s("_skillHints");a&&(i=`${a}
28
28
 
29
- ${s}`);let i=r(),c=i.cwd||process.cwd(),l=i.sessionPath;try{if(l){let d=le(l,R);if(Be(d)){let g=JSON.parse(Me(d,"utf-8"));g.currentNode=this.name,ce(d,JSON.stringify(g,null,2),"utf-8")}let u=le(l,"..",R);if(Be(u))try{let g=JSON.parse(Me(u,"utf-8"));g.currentNode=this.name,ce(u,JSON.stringify(g,null,2),"utf-8")}catch{}}}catch(d){w.debug(`[workflow] could not update session info: ${d.message}`)}let m=null;for(let d=0;d<=this.retries;d++)try{w.debug(`[workflow] node '${this.name}' attempt ${d}`);let u=r().config||{},g=u.agents||{},p=this.config.agent??g[this.name]??null,_={state:r()};p&&(_.preferredAgent=p);let N={workspace:c,schema:this.isZodSchema?this.outputSchema:null,skills:this.config.skills||[],sessionPath:l,config:u,nodeName:this.name,timeout:this.config?.timeout||3e5},v=e?._coreInvokeAgent;v||(v=(await Promise.resolve().then(()=>(U(),j))).invokeAgent);let f=await v(s,_,N),S,k;if(typeof f=="string"?(S=f,k=null):f.structured?(S=f.raw||JSON.stringify(f.structured,null,2),k=f.structured):(S=f.raw||JSON.stringify(f,null,2),k=f.extracted||null),l)try{let h=le(l,this.name,"raw_stream_output.txt");pt(ft(h),{recursive:!0}),ce(h,typeof S=="string"?S:JSON.stringify(S),"utf-8")}catch(h){w.debug(`[workflow] could not save raw output: ${h.message}`)}if(this.isZodSchema&&k){w.info(`[workflow] node '${this.name}': output validated: ${JSON.stringify(k,null,2)}`);let h=k;if(typeof this.onComplete=="function")try{h=await this.onComplete(r(),k)}catch($){w.warn(`[workflow] onComplete hook failed: ${$.message}`)}return{success:!0,output:h,raw:S}}if(typeof this.onComplete=="function")try{return{success:!0,output:await this.onComplete(r(),{raw:S}),raw:S}}catch(h){throw new Error(`onComplete failed: ${h.message}`,{cause:h})}if(this.parser){let h=this.parser.parse(S);return w.info(`[workflow] node '${this.name}': parsed output: ${JSON.stringify(h,null,2)}`),E.step("Output parsed"),{success:!0,output:h,raw:S}}return{success:!0,output:S,raw:S}}catch(u){m=u,d<this.retries&&w.info(`[workflow] node '${this.name}' failed, retrying (${d+1}/${this.retries})\u2026`)}return{success:!1,error:m.message,raw:null}}},X=class extends M{constructor(e){super({...e,_isCustomCode:!0}),this.condition=e.condition}async execute(e,t){let r=t&&typeof t.getAll=="function"?t.getAll():e;return{success:!0,output:{nextNode:this.condition(r)},raw:null}}};import{existsSync as De,readFileSync as ht}from"node:fs";import{join as ue,dirname as Fe}from"node:path";var Q=class{static async loadContext(e,t,r={}){let n={},s=r.filenames||["CONTEXT.md","AGENTS.md"];if(e){let i=Fe(ue(t,e));for(let c of s){let l=await this.findAndMergeContextFiles(c,i,t);if(l){let m=c.replace(/\.[^.]+$/,"").toLowerCase();n[m]=l}}}let a=r.discovery||{};for(let[i,c]of Object.entries(a))try{let l=ue(t,c);De(l)&&(n[i]=await this.loadFile(l))}catch(l){console.warn(`[workflow] could not load context '${i}' from '${c}': ${l.message}`)}return n}static async findAndMergeContextFiles(e,t,r){let n=[],s=t;for(;s.startsWith(r);){let a=ue(s,e);if(De(a))try{n.unshift(await this.loadFile(a))}catch(c){console.warn(`[workflow] could not load ${e} from ${a}: ${c.message}`)}let i=Fe(s);if(i===s)break;s=i}return n.length===0?null:n.every(a=>typeof a=="string")?n.join(`
29
+ ${i}`);let n=r(),c=n.cwd||process.cwd(),u=n.sessionPath;try{if(u){let d=he(u,L);if(Ge(d)){let m=JSON.parse(Ye(d,"utf-8"));m.currentNode=this.name,fe(d,JSON.stringify(m,null,2),"utf-8")}let l=he(u,"..",L);if(Ge(l))try{let m=JSON.parse(Ye(l,"utf-8"));m.currentNode=this.name,fe(l,JSON.stringify(m,null,2),"utf-8")}catch{}}}catch(d){S.debug(`[workflow] could not update session info: ${d.message}`)}let h=null;for(let d=0;d<=this.retries;d++)try{S.debug(`[workflow] node '${this.name}' attempt ${d}`);let l=r().config||{},m=l.agents||{},_=this.config.agent??m[this.name]??null,w={state:r()};_&&(w.preferredAgent=_);let N={workspace:c,schema:this.isZodSchema?this.outputSchema:null,skills:this.config.skills||[],sessionPath:u,config:l,nodeName:this.name,timeout:this.config?.timeout||3e5},f=e?._coreInvokeAgent;f||(f=(await Promise.resolve().then(()=>(J(),H))).invokeAgent);let $=await f(i,w,N),y,x;if(typeof $=="string"?(y=$,x=null):$.structured?(y=$.raw||JSON.stringify($.structured,null,2),x=$.structured):(y=$.raw||JSON.stringify($,null,2),x=$.extracted||null),u)try{let p=he(u,this.name,"raw_stream_output.txt");_t(yt(p),{recursive:!0}),fe(p,typeof y=="string"?y:JSON.stringify(y),"utf-8")}catch(p){S.debug(`[workflow] could not save raw output: ${p.message}`)}if(this.isZodSchema&&x){S.info(`[workflow] node '${this.name}': output validated: ${JSON.stringify(x,null,2)}`);let p=x;if(typeof this.onComplete=="function")try{p=await this.onComplete(r(),x)}catch(M){S.warn(`[workflow] onComplete hook failed: ${M.message}`)}return{success:!0,output:p,raw:y}}if(typeof this.onComplete=="function")try{return{success:!0,output:await this.onComplete(r(),{raw:y}),raw:y}}catch(p){throw new Error(`onComplete failed: ${p.message}`,{cause:p})}if(this.parser){let p=this.parser.parse(y);return S.info(`[workflow] node '${this.name}': parsed output: ${JSON.stringify(p,null,2)}`),v.step("Output parsed"),{success:!0,output:p,raw:y}}return{success:!0,output:y,raw:y}}catch(l){h=l,d<this.retries&&S.info(`[workflow] node '${this.name}' failed, retrying (${d+1}/${this.retries})\u2026`)}return{success:!1,error:h.message,raw:null}}},oe=class extends j{constructor(e){super({...e,_isCustomCode:!0}),this.condition=e.condition}async execute(e,t){let r=t&&typeof t.getAll=="function"?t.getAll():e;return{success:!0,output:{nextNode:this.condition(r)},raw:null}}};import{existsSync as Ze,readFileSync as Et}from"node:fs";import{join as me,dirname as Ue}from"node:path";var re=class{static async loadContext(e,t,r={}){let s={},i=r.filenames||["CONTEXT.md","AGENTS.md"];if(e){let n=Ue(me(t,e));for(let c of i){let u=await this.findAndMergeContextFiles(c,n,t);if(u){let h=c.replace(/\.[^.]+$/,"").toLowerCase();s[h]=u}}}let a=r.discovery||{};for(let[n,c]of Object.entries(a))try{let u=me(t,c);Ze(u)&&(s[n]=await this.loadFile(u))}catch(u){console.warn(`[workflow] could not load context '${n}' from '${c}': ${u.message}`)}return s}static async findAndMergeContextFiles(e,t,r){let s=[],i=t;for(;i.startsWith(r);){let a=me(i,e);if(Ze(a))try{s.unshift(await this.loadFile(a))}catch(c){console.warn(`[workflow] could not load ${e} from ${a}: ${c.message}`)}let n=Ue(i);if(n===i)break;i=n}return s.length===0?null:s.every(a=>typeof a=="string")?s.join(`
30
30
 
31
31
  ---
32
32
 
33
- `):n.every(a=>typeof a=="object")?Object.assign({},...n):n[n.length-1]}static async loadFile(e){let t=ht(e,"utf-8");if(e.endsWith(".json"))return JSON.parse(t);if(e.endsWith(".js")||e.endsWith(".mjs")){let{pathToFileURL:r}=await import("url"),n=await import(r(e).href);return n.default||n}return t}};import{mkdirSync as Ue,existsSync as de,writeFileSync as Le,unlinkSync as mt}from"node:fs";import{join as P,resolve as Ye}from"node:path";import{config as gt}from"dotenv";import{zodToJsonSchema as je}from"zod-to-json-schema";import St from"handlebars";function wt({traceFrom:o,sessionId:e,sessionPath:t,idSource:r,mkdirFresh:n}){if(!(process.env.ZIBBY_SESSION_LOG==="1"||process.env.ZIBBY_SESSION_LOG==="true"))return;let a=typeof process.ppid=="number"?process.ppid:"n/a",i=`[zibby:session] from=${o} pid=${process.pid} ppid=${a} sessionId=${e} source=${r} mkdir=${n?"yes":"no"} path=${t}`;if(console.log(i),process.env.ZIBBY_TRACE_SESSION==="1"||process.env.ZIBBY_TRACE_SESSION==="true"){let m=(new Error("session trace").stack||"").split(`
33
+ `):s.every(a=>typeof a=="object")?Object.assign({},...s):s[s.length-1]}static async loadFile(e){let t=Et(e,"utf-8");if(e.endsWith(".json"))return JSON.parse(t);if(e.endsWith(".js")||e.endsWith(".mjs")){let{pathToFileURL:r}=await import("url"),s=await import(r(e).href);return s.default||s}return t}};import{mkdirSync as Ke,existsSync as ge,writeFileSync as He,unlinkSync as $t}from"node:fs";import{join as W,resolve as ze}from"node:path";import{config as It}from"dotenv";import{zodToJsonSchema as Je}from"zod-to-json-schema";import vt from"handlebars";function Nt({traceFrom:o,sessionId:e,sessionPath:t,idSource:r,mkdirFresh:s}){if(!(process.env.ZIBBY_SESSION_LOG==="1"||process.env.ZIBBY_SESSION_LOG==="true"))return;let a=typeof process.ppid=="number"?process.ppid:"n/a",n=`[zibby:session] from=${o} pid=${process.pid} ppid=${a} sessionId=${e} source=${r} mkdir=${s?"yes":"no"} path=${t}`;if(console.log(n),process.env.ZIBBY_TRACE_SESSION==="1"||process.env.ZIBBY_TRACE_SESSION==="true"){let h=(new Error("session trace").stack||"").split(`
34
34
  `).slice(2,14).join(`
35
35
  `);console.log(`[zibby:session] stack (${o}):
36
- ${m}`)}}function _t(){return process.env.ZIBBY_RUN_SOURCE==="studio"||process.env.ZIBBY_KEEP_SESSION_ENV==="1"||process.env.ZIBBY_KEEP_SESSION_ENV==="true"}function yt(){if(process.env.ZIBBY_RUN_SOURCE!=="studio")return;let o=process.env.ZIBBY_SESSION_PATH;if(!(o==null||String(o).trim()===""))try{return Ye(String(o).trim())}catch{return String(o).trim()}}function $t(){_t()||(delete process.env.ZIBBY_SESSION_PATH,delete process.env.ZIBBY_SESSION_ID)}function Et({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 It(o={}){let e=Ce.map(s=>process.env[s]).find(Boolean),t=Math.random().toString(36).slice(2,6),r=e||`${Date.now()}_${t}`,n=o.paths?.sessionPrefix;return n?`${n}_${r}`:r}function vt({cwd:o=process.cwd(),config:e={},initialState:t={},traceFrom:r="resolveWorkflowSession"}={}){let n=t.sessionPath,s=t.sessionTimestamp,a="initialState.sessionPath";if(!n&&process.env.ZIBBY_SESSION_PATH)try{let l=Ye(String(process.env.ZIBBY_SESSION_PATH));l&&(n=l,a="ZIBBY_SESSION_PATH")}catch{}let i;if(n)i=String(n).split(/[/\\]/).filter(Boolean).pop(),s==null&&(s=Date.now());else{let l=process.env.ZIBBY_SESSION_ID&&String(process.env.ZIBBY_SESSION_ID).trim();if(l)i=l,a="ZIBBY_SESSION_ID";else{let d=e.sessionId!=null?String(e.sessionId).trim():"";d&&d!=="last"?(i=d,a="config.sessionId"):(i=It(e),a="generated")}s=s??Date.now();let m=e.paths?.output||V;n=P(o,m,be,i)}let c=!de(n);return c&&Ue(n,{recursive:!0}),(c||a!=="initialState.sessionPath")&&wt({traceFrom:r,sessionId:i,sessionPath:n,idSource:a,mkdirFresh:c}),Et({sessionPath:n,sessionId:i}),{sessionPath:n,sessionId:i,sessionTimestamp:s}}var ee=class{constructor(e={}){this.nodes=new Map,this.edges=new Map,this.entryPoint=null,this.middleware=Array.isArray(e.middleware)?[...e.middleware]:[],e.nodeMiddleware&&this.middleware.push(e.nodeMiddleware),this.nodeTypeMap=new Map,this.conditionalCodeMap=new Map,this.stateSchema=e.stateSchema||null,this.nodePrompts=new Map,this.nodeOptions=new Map,this._invokeAgent=e.invokeAgent||null}setStateSchema(e){return this.stateSchema=e,this}getStateSchema(){return this.stateSchema}addNode(e,t,r={}){let n=t instanceof M?t:new M(t);return n.name=e,this.nodes.set(e,n),r.prompt&&this.nodePrompts.set(e,r.prompt),Object.keys(r).length>0&&this.nodeOptions.set(e,r),this}addConditionalNode(e,t){return this.nodes.set(e,new X({...t,name:e})),this}addEdge(e,t){return this.edges.set(e,t),this}setNodeType(e,t){return this.nodeTypeMap.set(e,t),this}addConditionalEdges(e,t,{labels:r}={}){return this.edges.set(e,{conditional:!0,routes:t,labels:r}),typeof t=="function"&&this.conditionalCodeMap.set(e,t.toString()),this}setEntryPoint(e){return this.entryPoint=e,this}use(e){return typeof e=="function"&&this.middleware.push(e),this}_composeMiddleware(e,t,r,n,s){let a=r;for(let i=e.length-1;i>=0;i--){let c=e[i],l=a;a=()=>c(t,l,n,s)}return a()}serialize(){let e=[],t={};for(let[s,a]of this.nodes){let i=this.nodeTypeMap.get(s)||s;e.push({id:s,type:i,data:{nodeType:i,label:s}});let c={};a._isCustomCode&&typeof a.execute=="function"&&(c.customCode=a.execute.toString());let l=this.nodePrompts.get(s);if(l&&(c.prompt=l),typeof a.customExecute=="function"&&(c.executeCode=a.customExecute.toString()),a.outputSchema)try{if(typeof a.outputSchema._def<"u"){let d=je(a.outputSchema,{target:"openApi3"});c.outputSchema={jsonSchema:d,variables:this._flattenJsonSchemaToVariables(d)}}else c.outputSchema={schema:a.outputSchema}}catch(d){console.warn(`[workflow] failed to convert schema for ${s}:`,d.message)}let m=(this.resolvedToolsMap||{})[s];m?.toolIds&&(c.tools=m.toolIds),Object.keys(c).length>0&&(t[s]=c)}let r=[];for(let[s,a]of this.edges)if(typeof a=="string")r.push({source:s,target:a});else if(a.conditional){let i=this.conditionalCodeMap.get(s)||a.routes.toString(),c=this._inferConditionalTargets(a.routes),l=a.labels||{};for(let m of c){let d={source:s,target:m,data:{conditionalCode:i}};l[m]&&(d.label=l[m]),r.push(d)}}let n=null;if(this.stateSchema)try{n=je(this.stateSchema,{target:"openApi3"})}catch{n=this.stateSchema}return{nodes:e,edges:r,nodeConfigs:t,stateSchema:n}}_inferConditionalTargets(e){let t=e.toString(),r=new Set,n=/return\s+['"]([^'"]+)['"]/g,s;for(;(s=n.exec(t))!==null;)r.add(s[1]);return[...r]}_flattenJsonSchemaToVariables(e,t=""){let r=e;if(e.$ref&&e.definitions){let n=e.$ref.replace("#/definitions/","");r=e.definitions[n]||e}return this._flattenSchema(r,t)}_flattenSchema(e,t=""){if(!e||typeof e!="object")return[];let r=[],n=e.properties||{},s=e.required||[];for(let[a,i]of Object.entries(n)){let c=t?`${t}.${a}`:a;r.push({path:c,type:i.type||"unknown",label:i.description||this._formatLabel(a),optional:!s.includes(a)}),i.type==="object"&&i.properties&&r.push(...this._flattenSchema(i,c)),i.type==="array"&&i.items?.type==="object"&&i.items.properties&&r.push(...this._flattenSchema(i.items,`${c}[]`))}return r}_formatLabel(e){return e.replace(/([A-Z])/g," $1").replace(/^./,t=>t.toUpperCase()).trim()}_summarizeNodeOutput(e,t){if(!t||typeof t!="object")return[];let r=[];t.success!==void 0&&r.push(`Result: ${t.success?"passed":"failed"}`);for(let[n,s]of Object.entries(t))if(!(n==="success"||n==="raw"||n==="nextNode")){if(typeof s=="string"&&s.length<=80)r.push(`${n}: ${s}`);else if(Array.isArray(s)){let a=s.length,i=s.filter(l=>l?.passed===!0).length,c=s.some(l=>l?.passed!==void 0);r.push(c?`${n}: ${i}/${a} passed${a-i?`, ${a-i} failed`:""}`:`${n}: ${a} items`)}if(r.length>=4)break}return r}async run(e,t={}){if(!this.entryPoint)throw new Error("No entry point set for graph");let r=t.cwd||process.cwd();gt({path:P(r,".env")});let n=t.config||{};if(!n||Object.keys(n).length===0)try{let h=P(r,".zibby.config.js");de(h)&&(n=(await import(h)).default||{})}catch{}process.env.EXECUTION_ID&&!n.agent?.strictMode&&(n.agent={...n.agent,strictMode:!0});let s=t.agentType;if(!s){let h=n?.agent;h?.provider?s=h.provider:h?.gemini?s="gemini":h?.claude?s="claude":h?.cursor?s="cursor":h?.codex?s="codex":s=process.env.AGENT_TYPE||"cursor"}let a=t.contextConfig||e?.config?.contextConfig||e?.config?.context||n?.context||{};if(this.stateSchema){let h=this.stateSchema.safeParse(t);if(!h.success){let $=h.error.issues.map(x=>`${x.path.join(".")}: ${x.message}`);throw console.error("\u274C Initial state validation failed:"),$.forEach(x=>console.error(` - ${x}`)),new Error(`State validation failed: ${$.join(", ")}`)}E.step("State validated against schema")}let i=yt(),c=t.sessionPath||i;c||$t();let{sessionPath:l,sessionTimestamp:m,sessionId:d}=vt({cwd:r,config:n,traceFrom:"WorkflowGraph.run",initialState:{sessionPath:c,sessionTimestamp:t.sessionTimestamp}});E.step(`Session ${d}`);let u=await Q.loadContext(t.specPath||"",r,a);Object.keys(u).length>0&&E.step(`Context loaded: ${Object.keys(u).join(", ")}`);let g=t.outputPath;!g&&t.specPath&&(e?.calculateOutputPath?g=e.calculateOutputPath(t.specPath):console.warn(`\u26A0\uFE0F outputPath not resolved (specPath=${t.specPath})`));let p=new H({...t,config:n,agentType:s,outputPath:g,sessionPath:l,sessionTimestamp:m,context:u,resolvedTools:this.resolvedToolsMap||{}}),_=new Map;try{await import("@zibby/skills")}catch{}let{getSkill:N}=await Promise.resolve().then(()=>(q(),Re)),v=new Set;for(let[,h]of this.nodes)for(let $ of h.config?.skills||[])v.add($);for(let h of v){let $=N(h);if(typeof $?.middleware=="function")try{let x=await $.middleware();typeof x=="function"&&_.set(h,x)}catch{}}let f=this.entryPoint,S=[];for(;f&&f!=="END";){let h=P(l,Ae);if(de(h)){console.warn(`
37
- \u{1F6D1} Studio stop requested \u2014 ending workflow.`);try{mt(h)}catch{}if(e&&typeof e.cleanup=="function")try{await e.cleanup()}catch{}return E.step("Workflow stopped by Studio"),{success:!0,state:p.getAll(),executionLog:S,stoppedByStudio:!0}}let $=this.nodes.get(f);if(!$)throw new Error(`Node '${f}' not found in graph`);let x=JSON.stringify({sessionPath:l,sessionTimestamp:m,currentNode:f,createdAt:new Date().toISOString(),config:p.get("config")}),Ke=P(l,R);Le(Ke,x,"utf-8");let he=p.get("config")?.paths?.output||V,ze=P(r,he,R);Ue(P(r,he),{recursive:!0});try{Le(ze,x,"utf-8")}catch{}let me=t.onPipelineProgress;if(typeof me=="function")try{me({cwd:r,sessionPath:l,sessionId:d,outputBase:p.get("config")?.paths?.output||V,currentNode:f})}catch{}let Ve=(this.resolvedToolsMap||{})[f]||null;p.set("_currentNodeTools",Ve);let qe=p.get("nodeConfigs")||{};p.set("_currentNodeConfig",qe[f]||{}),E.nodeStart(f);let ge=Date.now(),Y=this.nodePrompts.get(f);if(!this._invokeAgent){let T=await Promise.resolve().then(()=>(U(),j));this._invokeAgent=T.invokeAgent}let Se=this._invokeAgent,we={state:p,invokeAgent:async(T={},b={})=>{let I=b.prompt||"";if(Y)try{I=St.compile(Y,{noEscape:!0})(T)}catch(A){throw console.error(`\u274C Template rendering failed for node '${f}':`,A.message),new Error(`Template rendering failed: ${A.message}`,{cause:A})}else if(!I)throw new Error(`No prompt template configured for node '${f}' and no prompt provided in options`);return Se(I,{state:p.getAll(),images:b.images||[]},{model:b.model||p.get("model"),workspace:p.get("workspace"),schema:b.schema,...b})},_coreInvokeAgent:Se,agent:e,nodeId:f,promptTemplate:Y,getPromptTemplate:()=>Y,...p.getAll()};try{let T=($.config?.skills||[]).map(B=>_.get(B)).filter(Boolean),b=[...this.middleware,...T],I;b.length>0?I=await this._composeMiddleware(b,f,async()=>$.execute(we,p),p.getAll(),p):I=await $.execute(we,p);let A=Date.now()-ge;if(S.push({node:f,success:I.success,duration:A,timestamp:new Date().toISOString()}),!I.success){if(String(I.error||"").includes("Stopped from Zibby Studio")){if(E.step("Workflow stopped by Studio"),p.set("stoppedByStudio",!0),e&&typeof e.cleanup=="function")try{await e.cleanup()}catch{}return{success:!0,state:p.getAll(),executionLog:S,stoppedByStudio:!0}}p.append("errors",{node:f,error:I.error});let _e=$.config?.retries||0,ye=`${f}_retries`,G=p.getAll()[ye]||0;if(G<_e){E.stepInfo(`Retrying (attempt ${G+1}/${_e})`),p.update({[ye]:G+1,[`${f}_raw`]:I.raw});continue}throw E.nodeFailed(f,I.error,{duration:A}),new Error(`Node '${f}' failed after ${G} attempts: ${I.error}`)}p.update({[f]:I.output});let Xe=this._summarizeNodeOutput(f,I.output);E.nodeComplete(f,{duration:A,details:Xe});let Z=this.edges.get(f);if(!Z)f="END";else if(Z.conditional){let B=Z.routes(p.getAll());E.route(f,B),f=B}else f=Z}catch(T){throw E.isInsideNode&&E.nodeFailed(f,T.message,{duration:Date.now()-ge}),p.set("failed",!0),p.set("failedAt",f),T}}E.graphComplete();let k={success:!0,state:p.getAll(),executionLog:S};return e&&typeof e.onComplete=="function"&&await e.onComplete(k),k}};var pe=new Map;function Nt(o,e){pe.set(o,e)}function Ze(o){return pe.get(o)}function fe(o){return pe.has(o)}Nt("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(()=>(U(),j))).invokeAgent);let n=e.extraPromptInstructions||"Execute the task based on the current state.",s=kt(n,t),a=await r(s,{cwd:t.workspace||process.cwd(),model:t.model,tools:e.resolvedTools||null});return{success:!0,output:{raw:a,nodeId:o},raw:typeof a=="string"?a:a.raw}}})});function kt(o,e){let t=/@([\w.]+)/g,r=new Set,n;for(;(n=t.exec(o))!==null;)r.add(n[1]);if(r.size===0)return o;let s=[],a=new Set;for(let i of r){let c=i.split(".")[0];if(a.has(c))continue;let l=i.split(".").reduce((u,g)=>u?.[g],e);if(l===void 0)continue;let m=typeof l=="string"?l:l?.raw??JSON.stringify(l,null,2),d=i.replace(/_/g," ").replace(/\b\w/g,u=>u.toUpperCase());s.push(`## ${d}
38
- ${m}`),i.includes(".")||a.add(c)}return s.length===0?o:`${o}
36
+ ${h}`)}}function bt(){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 kt(){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 ze(String(e).trim())}catch{return String(e).trim()}}function Tt(){bt()||(delete process.env.ZIBBY_SESSION_PATH,delete process.env.ZIBBY_SESSION_ID)}function xt({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 At(o={}){let e=De.map(i=>process.env[i]).find(Boolean),t=Math.random().toString(36).slice(2,6),r=e||`${Date.now()}_${t}`,s=o.paths?.sessionPrefix;return s?`${s}_${r}`:r}function Ot({cwd:o=process.cwd(),config:e={},initialState:t={},traceFrom:r="resolveWorkflowSession"}={}){let s=t.sessionPath,i=t.sessionTimestamp,a="initialState.sessionPath";if(!s&&process.env.ZIBBY_SESSION_PATH)try{let u=ze(String(process.env.ZIBBY_SESSION_PATH));u&&(s=u,a="ZIBBY_SESSION_PATH")}catch{}let n;if(s)n=String(s).split(/[/\\]/).filter(Boolean).pop(),i==null&&(i=Date.now());else{let u=process.env.ZIBBY_SESSION_ID&&String(process.env.ZIBBY_SESSION_ID).trim();if(u)n=u,a="ZIBBY_SESSION_ID";else{let d=e.sessionId!=null?String(e.sessionId).trim():"";d&&d!=="last"?(n=d,a="config.sessionId"):(n=At(e),a="generated")}i=i??Date.now();let h=e.paths?.output||ee;s=W(o,h,Me,n)}let c=!ge(s);return c&&Ke(s,{recursive:!0}),(c||a!=="initialState.sessionPath")&&Nt({traceFrom:r,sessionId:n,sessionPath:s,idSource:a,mkdirFresh:c}),xt({sessionPath:s,sessionId:n}),{sessionPath:s,sessionId:n,sessionTimestamp:i}}var se=class{constructor(e={}){this.nodes=new Map,this.edges=new Map,this.entryPoint=null,this.middleware=Array.isArray(e.middleware)?[...e.middleware]:[],e.nodeMiddleware&&this.middleware.push(e.nodeMiddleware),this.nodeTypeMap=new Map,this.conditionalCodeMap=new Map,this.stateSchema=e.stateSchema||null,this.nodePrompts=new Map,this.nodeOptions=new Map,this._invokeAgent=e.invokeAgent||null,this._compiledPrompts=new Map}setStateSchema(e){return this.stateSchema=e,this}getStateSchema(){return this.stateSchema}addNode(e,t,r={}){let s=t instanceof j?t:new j(t);return s.name=e,this.nodes.set(e,s),r.prompt&&this.nodePrompts.set(e,r.prompt),Object.keys(r).length>0&&this.nodeOptions.set(e,r),this}addConditionalNode(e,t){return this.nodes.set(e,new oe({...t,name:e})),this}addEdge(e,t){return this.edges.set(e,t),this}setNodeType(e,t){return this.nodeTypeMap.set(e,t),this}addConditionalEdges(e,t,{labels:r}={}){return this.edges.set(e,{conditional:!0,routes:t,labels:r}),typeof t=="function"&&this.conditionalCodeMap.set(e,t.toString()),this}setEntryPoint(e){return this.entryPoint=e,this}use(e){return typeof e=="function"&&this.middleware.push(e),this}_composeMiddleware(e,t,r,s,i){let a=r;for(let n=e.length-1;n>=0;n--){let c=e[n],u=a;a=()=>c(t,u,s,i)}return a()}serialize(){let e=[],t={};for(let[i,a]of this.nodes){let n=this.nodeTypeMap.get(i)||i;e.push({id:i,type:n,data:{nodeType:n,label:i}});let c={};a._isCustomCode&&typeof a.execute=="function"&&(c.customCode=a.execute.toString());let u=this.nodePrompts.get(i);if(u&&(c.prompt=u),typeof a.customExecute=="function"&&(c.executeCode=a.customExecute.toString()),a.outputSchema)try{if(typeof a.outputSchema._def<"u"){let d=Je(a.outputSchema,{target:"openApi3"});c.outputSchema={jsonSchema:d,variables:this._flattenJsonSchemaToVariables(d)}}else c.outputSchema={schema:a.outputSchema}}catch(d){console.warn(`[workflow] failed to convert schema for ${i}:`,d.message)}let h=(this.resolvedToolsMap||{})[i];h?.toolIds&&(c.tools=h.toolIds),Object.keys(c).length>0&&(t[i]=c)}let r=[];for(let[i,a]of this.edges)if(typeof a=="string")r.push({source:i,target:a});else if(a.conditional){let n=this.conditionalCodeMap.get(i)||a.routes.toString(),c=this._inferConditionalTargets(a.routes),u=a.labels||{};for(let h of c){let d={source:i,target:h,data:{conditionalCode:n}};u[h]&&(d.label=u[h]),r.push(d)}}let s=null;if(this.stateSchema)try{s=Je(this.stateSchema,{target:"openApi3"})}catch{s=this.stateSchema}return{nodes:e,edges:r,nodeConfigs:t,stateSchema:s}}_inferConditionalTargets(e){let t=e.toString(),r=new Set,s=/return\s+['"]([^'"]+)['"]/g,i;for(;(i=s.exec(t))!==null;)r.add(i[1]);return[...r]}_flattenJsonSchemaToVariables(e,t=""){let r=e;if(e.$ref&&e.definitions){let s=e.$ref.replace("#/definitions/","");r=e.definitions[s]||e}return this._flattenSchema(r,t)}_flattenSchema(e,t=""){if(!e||typeof e!="object")return[];let r=[],s=e.properties||{},i=e.required||[];for(let[a,n]of Object.entries(s)){let c=t?`${t}.${a}`:a;r.push({path:c,type:n.type||"unknown",label:n.description||this._formatLabel(a),optional:!i.includes(a)}),n.type==="object"&&n.properties&&r.push(...this._flattenSchema(n,c)),n.type==="array"&&n.items?.type==="object"&&n.items.properties&&r.push(...this._flattenSchema(n.items,`${c}[]`))}return r}_formatLabel(e){return e.replace(/([A-Z])/g," $1").replace(/^./,t=>t.toUpperCase()).trim()}_summarizeNodeOutput(e,t){if(!t||typeof t!="object")return[];let r=[];t.success!==void 0&&r.push(`Result: ${t.success?"passed":"failed"}`);for(let[s,i]of Object.entries(t))if(!(s==="success"||s==="raw"||s==="nextNode")){if(typeof i=="string"&&i.length<=80)r.push(`${s}: ${i}`);else if(Array.isArray(i)){let a=i.length,n=i.filter(u=>u?.passed===!0).length,c=i.some(u=>u?.passed!==void 0);r.push(c?`${s}: ${n}/${a} passed${a-n?`, ${a-n} failed`:""}`:`${s}: ${a} 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 s=new AbortController;r.signal&&(r.signal.aborted?s.abort():r.signal.addEventListener("abort",()=>s.abort(),{once:!0}));let i=r.strategyAbortTimeoutMs??t.config?.strategyAbortTimeoutMs??5e3,a=t.cwd||process.cwd();It({path:W(a,".env")});let n=t.config||{};if(!n||Object.keys(n).length===0)try{let g=W(a,".zibby.config.js");ge(g)&&(n=(await import(g)).default||{})}catch{}process.env.EXECUTION_ID&&!n.agent?.strictMode&&(n.agent={...n.agent,strictMode:!0});let c=t.agentType;if(!c){let g=n?.agent;g?.provider?c=g.provider:g?.gemini?c="gemini":g?.claude?c="claude":g?.cursor?c="cursor":g?.codex?c="codex":c=process.env.AGENT_TYPE||"cursor"}let u=t.contextConfig||e?.config?.contextConfig||e?.config?.context||n?.context||{};if(this.stateSchema){let g=this.stateSchema.safeParse(t);if(!g.success){let T=g.error.issues.map(b=>`${b.path.join(".")}: ${b.message}`);throw console.error("\u274C Initial state validation failed:"),T.forEach(b=>console.error(` - ${b}`)),new Error(`State validation failed: ${T.join(", ")}`)}v.step("State validated against schema")}let h=kt(),d=t.sessionPath||h;d||Tt();let{sessionPath:l,sessionTimestamp:m,sessionId:_}=Ot({cwd:a,config:n,traceFrom:"WorkflowGraph.run",initialState:{sessionPath:d,sessionTimestamp:t.sessionTimestamp}});v.step(`Session ${_}`);let w=await re.loadContext(t.specPath||"",a,u);Object.keys(w).length>0&&v.step(`Context loaded: ${Object.keys(w).join(", ")}`);let N=t.outputPath;!N&&t.specPath&&(e?.calculateOutputPath?N=e.calculateOutputPath(t.specPath):console.warn(`\u26A0\uFE0F outputPath not resolved (specPath=${t.specPath})`));let f=new q({...t,config:n,agentType:c,outputPath:N,sessionPath:l,sessionTimestamp:m,context:w,resolvedTools:this.resolvedToolsMap||{},_signal:s.signal}),$=new Map;try{await import("@zibby/skills")}catch{}let{getSkill:y}=await Promise.resolve().then(()=>(te(),Fe)),x=new Set;for(let[,g]of this.nodes)for(let T of g.config?.skills||[])x.add(T);for(let g of x){let T=y(g);if(typeof T?.middleware=="function")try{let b=await T.middleware();typeof b=="function"&&$.set(g,b)}catch{}}let p=this.entryPoint,M=[],ye=n?.recursionLimit??100,et=0;try{for(;p&&p!=="END";){if(++et>ye)throw new Error(`Workflow exceeded recursion limit (${ye}) \u2014 likely a cyclic conditional route. Set config.recursionLimit if you need a higher cap.`);let T=W(l,Be);if(ge(T)){try{$t(T)}catch{}s.abort()}if(s.signal.aborted)return console.warn(`
37
+ \u{1F6D1} External stop requested \u2014 ending workflow.`),v.step("Workflow stopped externally"),{success:!0,state:f.getAll(),executionLog:M,stoppedExternally:!0};let b=this.nodes.get(p);if(!b)throw new Error(`Node '${p}' not found in graph`);let Ee=JSON.stringify({sessionPath:l,sessionTimestamp:m,currentNode:p,createdAt:new Date().toISOString(),config:f.get("config")}),tt=W(l,L);He(tt,Ee,"utf-8");let $e=f.get("config")?.paths?.output||ee,ot=W(a,$e,L);Ke(W(a,$e),{recursive:!0});try{He(ot,Ee,"utf-8")}catch{}let Ie=t.onPipelineProgress;if(typeof Ie=="function")try{Ie({cwd:a,sessionPath:l,sessionId:_,outputBase:f.get("config")?.paths?.output||ee,currentNode:p})}catch{}let rt=(this.resolvedToolsMap||{})[p]||null;f.set("_currentNodeTools",rt);let st=f.get("nodeConfigs")||{};f.set("_currentNodeConfig",st[p]||{}),v.nodeStart(p);let ve=Date.now(),K=this.nodePrompts.get(p);if(!this._invokeAgent){let A=await Promise.resolve().then(()=>(J(),H));this._invokeAgent=A.invokeAgent}let nt=this._invokeAgent,Ne=async(A,O,I={})=>{let k=nt(A,O,{...I,signal:s.signal});return k.catch(()=>{}),s.signal.aborted?k:Promise.race([k,new Promise((B,D)=>{let P=()=>{setTimeout(()=>{let Y=new Error(`Strategy ignored AbortSignal \u2014 engine deadman fired after ${i}ms`);Y.name="AbortError",D(Y)},i)};s.signal.addEventListener("abort",P,{once:!0})})])},be={state:f,invokeAgent:async(A={},O={})=>{let I=O.prompt||"";if(K){let k=this._compiledPrompts.get(p);k||(k=vt.compile(K,{noEscape:!0}),this._compiledPrompts.set(p,k));try{I=k(A)}catch(B){throw console.error(`\u274C Template rendering failed for node '${p}':`,B.message),new Error(`Template rendering failed: ${B.message}`,{cause:B})}}else if(!I)throw new Error(`No prompt template configured for node '${p}' and no prompt provided in options`);return Ne(I,{state:f.getAll(),images:O.images||[]},{model:O.model||f.get("model"),workspace:f.get("workspace"),schema:O.schema,...O,signal:s.signal})},_coreInvokeAgent:Ne,agent:e,nodeId:p,promptTemplate:K,getPromptTemplate:()=>K,...f.getAll()};try{let A=(b.config?.skills||[]).map(P=>$.get(P)).filter(Boolean),O=[...this.middleware,...A],I;O.length>0?I=await this._composeMiddleware(O,p,async()=>b.execute(be,f),f.getAll(),f):I=await b.execute(be,f);let k=Date.now()-ve;if(M.push({node:p,success:I.success,duration:k,timestamp:new Date().toISOString()}),!I.success){if(s.signal.aborted)return v.step("Workflow stopped externally"),{success:!0,state:f.getAll(),executionLog:M,stoppedExternally:!0};f.append("errors",{node:p,error:I.error});let P=b.config?.retries||0,Y=`${p}_retries`,z=f.getAll()[Y]||0;if(z<P){v.stepInfo(`Retrying (attempt ${z+1}/${P})`),f.update({[Y]:z+1,[`${p}_raw`]:I.raw});continue}throw v.nodeFailed(p,I.error,{duration:k}),new Error(`Node '${p}' failed after ${z} attempts: ${I.error}`)}f.update({[p]:I.output});let B=this._summarizeNodeOutput(p,I.output);v.nodeComplete(p,{duration:k,details:B});let D=this.edges.get(p);if(!D)p="END";else if(D.conditional){let P=D.routes(f.getAll());v.route(p,P),p=P}else p=D}catch(A){throw v.isInsideNode&&v.nodeFailed(p,A.message,{duration:Date.now()-ve}),f.set("failed",!0),f.set("failedAt",p),A}}v.graphComplete();let g={success:!0,state:f.getAll(),executionLog:M};return e&&typeof e.onComplete=="function"&&await e.onComplete(g),g}finally{if(e&&typeof e.cleanup=="function")try{await e.cleanup()}catch(g){console.warn(`[workflow] agent.cleanup() failed: ${g.message}`)}}}};var we=Symbol.for("@zibby/agent-workflow.nodes");globalThis[we]||(globalThis[we]=new Map);var Se=globalThis[we];function Ct(o,e){Se.set(o,e)}function Ve(o){return Se.get(o)}function _e(o){return Se.has(o)}Ct("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(()=>(J(),H))).invokeAgent);let s=e.extraPromptInstructions||"Execute the task based on the current state.",i=Pt(s,t),a=await r(i,{cwd:t.workspace||process.cwd(),model:t.model,tools:e.resolvedTools||null});return{success:!0,output:{raw:a,nodeId:o},raw:typeof a=="string"?a:a.raw}}})});function Pt(o,e){let t=/@([\w.]+)/g,r=new Set,s;for(;(s=t.exec(o))!==null;)r.add(s[1]);if(r.size===0)return o;let i=[],a=new Set;for(let n of r){let c=n.split(".")[0];if(a.has(c))continue;let u=n.split(".").reduce((l,m)=>l?.[m],e);if(u===void 0)continue;let h=typeof u=="string"?u:u?.raw??JSON.stringify(u,null,2),d=n.replace(/_/g," ").replace(/\b\w/g,l=>l.toUpperCase());i.push(`## ${d}
38
+ ${h}`),n.includes(".")||a.add(c)}return i.length===0?o:`${o}
39
39
 
40
40
  ---
41
41
  # Referenced Context
42
42
 
43
- ${s.join(`
43
+ ${i.join(`
44
44
 
45
- `)}`}q();D();var xt={};function Je(o,e){if(Array.isArray(e))return Ge(e);let t=xt[o];return!t||t.length===0?null:Ge(t)}function Ge(o){if(!Array.isArray(o)||o.length===0)return null;let e=[],t={},r=[];for(let n of o){let s=L(n);if(!s){w.warn(`[workflow] unknown skill "${n}" \u2014 skipping`);continue}r.push(n);for(let a of s.tools||[])e.push({name:a.name,description:a.description,input_schema:a.input_schema||{type:"object",properties:{}}});if(!t[s.serverName])if(typeof s.resolve=="function"){let a=s.resolve();a&&(t[s.serverName]={...a,toolPrefix:n})}else{let a={};for(let i of s.envKeys||[]){let c=process.env[i];c&&(a[i]=c)}t[s.serverName]={command:s.command,args:[...s.args||[]],env:a,toolPrefix:n}}}return r.length===0?null:{toolIds:r,claudeTools:e,mcpServers:t}}D();function _o(o,e={}){let{nodes:t,edges:r,nodeConfigs:n={}}=o;if(!Array.isArray(t)||t.length===0)throw new O("Graph must have at least one node");if(!Array.isArray(r))throw new O("Graph edges must be an array");let s=new ee(e);e.stateSchema&&s.setStateSchema(e.stateSchema);let a=new Set,i=new Map,c={};for(let u of t){let g=te(u);i.set(u.id,{...u,resolvedType:g}),g==="decision"&&a.add(u.id)}for(let[u,g]of i){if(a.has(u))continue;let p=g.resolvedType,_=n[u]||{},N=Je(p,_.tools);N&&(c[u]=N);let v={};_.prompt&&(v.prompt=_.prompt);let f=fe(p);if(w.debug(`[workflow] compiler: node "${u}" type="${p}" registered=${f}`),_.customCode&&!f)s.addNode(u,He(u,_.customCode,_),v),s.setNodeType(u,p);else if(f){let S=Ze(p);S.factory?s.addNode(u,S.create(u,{..._,resolvedTools:N}),v):s.addNode(u,S,v),s.setNodeType(u,p)}else if(_.executeCode)s.addNode(u,He(u,_.executeCode,_),v),s.setNodeType(u,p);else throw new O(`Unknown node type "${p}" for node "${u}". Did you forget to register it?`)}s.resolvedToolsMap=c;let l=new Set;for(let u of r)a.has(u.target)||l.add(u.target);let m=t.find(u=>!a.has(u.id)&&!l.has(u.id));if(!m)throw new O("Could not determine entry point: no node without incoming edges found");s.setEntryPoint(m.id);let d=Ot(r,"source");for(let u of r)if(!a.has(u.source))if(a.has(u.target)){let g=u.target,p=d.get(g)||[];if(p.length===0)throw new O(`Decision node "${g}" has no outgoing edges`);let _=Tt(g,p,a);s.addConditionalEdges(u.source,_)}else s.addEdge(u.source,u.target);return s}function yo(o){let e=[];if(!o||typeof o!="object")return{valid:!1,errors:["Config must be a non-null object"]};if((!Array.isArray(o.nodes)||o.nodes.length===0)&&e.push("Graph must have at least one node"),Array.isArray(o.edges)||e.push("Graph edges must be an array"),e.length>0)return{valid:!1,errors:e};let t=o.nodeConfigs||{};for(let i of o.nodes){let c=te(i);if(c==="decision"||fe(c))continue;let l=t[i.id]||{};l.customCode||l.executeCode||e.push(`Unknown node type "${c}" for node "${i.id}". Register it or provide customCode/executeCode.`)}let r=new Set(o.nodes.map(i=>i.id));for(let i of o.edges)r.has(i.source)||e.push(`Edge references unknown source node "${i.source}"`),r.has(i.target)||e.push(`Edge references unknown target node "${i.target}"`);let n=new Set(o.nodes.filter(i=>te(i)==="decision").map(i=>i.id)),s=new Set;for(let i of o.edges)n.has(i.target)||s.add(i.target);let a=o.nodes.filter(i=>!n.has(i.id)&&!s.has(i.id));a.length===0?e.push("No entry point found (every node has incoming edges)"):a.length>1&&e.push(`Multiple entry points found: ${a.map(i=>i.id).join(", ")}`);for(let i of n){let c=o.edges.filter(m=>m.source===i);c.length===0&&e.push(`Decision node "${i}" has no outgoing edges`),c.some(m=>m.data?.conditionalCode||m.conditionalCode)||e.push(`Decision node "${i}" outgoing edges have no conditionalCode`)}return{valid:e.length===0,errors:e}}function $o(o){return!o||!Array.isArray(o.nodes)?[]:o.nodes.filter(e=>te(e)!=="decision").map(e=>e.id)}function te(o){let e=o.data?.nodeType||o.data?.type||o.type;return e==="workflowNode"||e==="custom"||e==="default"?o.id:e}function Ot(o,e){let t=new Map;for(let r of o){let n=r[e];t.has(n)||t.set(n,[]),t.get(n).push(r)}return t}function Tt(o,e,t){let r=e.find(i=>i.data?.conditionalCode||i.conditionalCode);if(!r)throw new O(`Decision node "${o}" has no conditionalCode on its outgoing edges`);let n=r.data?.conditionalCode||r.conditionalCode,s=new Set(e.map(i=>i.target).filter(i=>!t.has(i))),a;try{let c=new Function(`return (${n})`)();a=l=>{let m=c(l);return s.has(m)||w.warn(`[workflow] conditional route from "${o}" returned "${m}" which is not in valid targets: ${[...s].join(", ")}`),m}}catch(i){throw new O(`Failed to compile conditionalCode for "${o}": ${i.message}`)}return a}function He(o,e,t={}){let r;try{r=new Function("invokeAgent","require","console",`return (${e})`)}catch(a){throw new O(`Failed to compile customCode for node "${o}": ${a.message}`)}let n=r(async(...a)=>{let{invokeAgent:i}=await Promise.resolve().then(()=>(U(),j));return i(...a)},typeof oe<"u"?oe:void 0,console),s=null;return t.outputSchema&&(s=t.outputSchema.jsonSchema||t.outputSchema),{name:o,_isCustomCode:!0,outputSchema:s,execute:async a=>{try{let i=await n(a);return typeof i=="object"&&"success"in i?i:{success:!0,output:i,raw:null}}catch(i){return{success:!1,error:i.message,raw:null}}}}}var O=class extends Error{constructor(e){super(e),this.name="CompilationError"}};export{O as CompilationError,_o as compileGraph,$o as extractSteps,yo as validateGraphConfig};
45
+ `)}`}te();G();var Rt={};function Xe(o,e){if(Array.isArray(e))return qe(e);let t=Rt[o];return!t||t.length===0?null:qe(t)}function qe(o){if(!Array.isArray(o)||o.length===0)return null;let e=[],t={},r=[];for(let s of o){let i=U(s);if(!i){S.warn(`[workflow] unknown skill "${s}" \u2014 skipping`);continue}r.push(s);for(let a of i.tools||[])e.push({name:a.name,description:a.description,input_schema:a.input_schema||{type:"object",properties:{}}});if(!t[i.serverName])if(typeof i.resolve=="function"){let a=i.resolve();a&&(t[i.serverName]={...a,toolPrefix:s})}else{let a={};for(let n of i.envKeys||[]){let c=process.env[n];c&&(a[n]=c)}t[i.serverName]={command:i.command,args:[...i.args||[]],env:a,toolPrefix:s}}}return r.length===0?null:{toolIds:r,claudeTools:e,mcpServers:t}}G();function bo(o,e={}){let{nodes:t,edges:r,nodeConfigs:s={}}=o;if(!Array.isArray(t)||t.length===0)throw new C("Graph must have at least one node");if(!Array.isArray(r))throw new C("Graph edges must be an array");let i=new se(e);e.stateSchema&&i.setStateSchema(e.stateSchema);let a=new Set,n=new Map,c={};for(let l of t){let m=ne(l);n.set(l.id,{...l,resolvedType:m}),m==="decision"&&a.add(l.id)}for(let[l,m]of n){if(a.has(l))continue;let _=m.resolvedType,w=s[l]||{},N=Xe(_,w.tools);N&&(c[l]=N);let f={};w.prompt&&(f.prompt=w.prompt);let $=_e(_);if(S.debug(`[workflow] compiler: node "${l}" type="${_}" registered=${$}`),w.customCode&&!$)i.addNode(l,Qe(l,w.customCode,w),f),i.setNodeType(l,_);else if($){let y=Ve(_);y.factory?i.addNode(l,y.create(l,{...w,resolvedTools:N}),f):i.addNode(l,y,f),i.setNodeType(l,_)}else if(w.executeCode)i.addNode(l,Qe(l,w.executeCode,w),f),i.setNodeType(l,_);else throw new C(`Unknown node type "${_}" for node "${l}". Did you forget to register it?`)}i.resolvedToolsMap=c;let u=new Set;for(let l of r)a.has(l.target)||u.add(l.target);let h=t.find(l=>!a.has(l.id)&&!u.has(l.id));if(!h)throw new C("Could not determine entry point: no node without incoming edges found");i.setEntryPoint(h.id);let d=Wt(r,"source");for(let l of r)if(!a.has(l.source))if(a.has(l.target)){let m=l.target,_=d.get(m)||[];if(_.length===0)throw new C(`Decision node "${m}" has no outgoing edges`);let w=Mt(m,_,a);i.addConditionalEdges(l.source,w)}else i.addEdge(l.source,l.target);return i}function ko(o){let e=[];if(!o||typeof o!="object")return{valid:!1,errors:["Config must be a non-null object"]};if((!Array.isArray(o.nodes)||o.nodes.length===0)&&e.push("Graph must have at least one node"),Array.isArray(o.edges)||e.push("Graph edges must be an array"),e.length>0)return{valid:!1,errors:e};let t=o.nodeConfigs||{};for(let n of o.nodes){let c=ne(n);if(c==="decision"||_e(c))continue;let u=t[n.id]||{};u.customCode||u.executeCode||e.push(`Unknown node type "${c}" for node "${n.id}". Register it or provide customCode/executeCode.`)}let r=new Set(o.nodes.map(n=>n.id));for(let n of o.edges)r.has(n.source)||e.push(`Edge references unknown source node "${n.source}"`),r.has(n.target)||e.push(`Edge references unknown target node "${n.target}"`);let s=new Set(o.nodes.filter(n=>ne(n)==="decision").map(n=>n.id)),i=new Set;for(let n of o.edges)s.has(n.target)||i.add(n.target);let a=o.nodes.filter(n=>!s.has(n.id)&&!i.has(n.id));a.length===0?e.push("No entry point found (every node has incoming edges)"):a.length>1&&e.push(`Multiple entry points found: ${a.map(n=>n.id).join(", ")}`);for(let n of s){let c=o.edges.filter(h=>h.source===n);c.length===0&&e.push(`Decision node "${n}" has no outgoing edges`),c.some(h=>h.data?.conditionalCode||h.conditionalCode)||e.push(`Decision node "${n}" outgoing edges have no conditionalCode`)}return{valid:e.length===0,errors:e}}function To(o){return!o||!Array.isArray(o.nodes)?[]:o.nodes.filter(e=>ne(e)!=="decision").map(e=>e.id)}function ne(o){let e=o.data?.nodeType||o.data?.type||o.type;return e==="workflowNode"||e==="custom"||e==="default"?o.id:e}function Wt(o,e){let t=new Map;for(let r of o){let s=r[e];t.has(s)||t.set(s,[]),t.get(s).push(r)}return t}function Mt(o,e,t){let r=e.find(n=>n.data?.conditionalCode||n.conditionalCode);if(!r)throw new C(`Decision node "${o}" has no conditionalCode on its outgoing edges`);let s=r.data?.conditionalCode||r.conditionalCode,i=new Set(e.map(n=>n.target).filter(n=>!t.has(n))),a;try{let c=new Function(`return (${s})`)();a=u=>{let h=c(u);return i.has(h)||S.warn(`[workflow] conditional route from "${o}" returned "${h}" which is not in valid targets: ${[...i].join(", ")}`),h}}catch(n){throw new C(`Failed to compile conditionalCode for "${o}": ${n.message}`)}return a}function Qe(o,e,t={}){let r;try{r=new Function("invokeAgent","require","console",`return (${e})`)}catch(a){throw new C(`Failed to compile customCode for node "${o}": ${a.message}`)}let s=r(async(...a)=>{let{invokeAgent:n}=await Promise.resolve().then(()=>(J(),H));return n(...a)},typeof ie<"u"?ie:void 0,console),i=null;return t.outputSchema&&(i=t.outputSchema.jsonSchema||t.outputSchema),{name:o,_isCustomCode:!0,outputSchema:i,execute:async a=>{try{let n=await s(a);return typeof n=="object"&&"success"in n?n:{success:!0,output:n,raw:null}}catch(n){return{success:!1,error:n.message,raw:null}}}}}var C=class extends Error{constructor(e){super(e),this.name="CompilationError"}};export{C as CompilationError,bo as compileGraph,To as extractSteps,ko as validateGraphConfig};
package/dist/graph.d.ts CHANGED
@@ -1,15 +1,21 @@
1
1
  /**
2
- * Studio spawns `zibby run` with ZIBBY_SESSION_* already set do not strip.
3
- * Set ZIBBY_KEEP_SESSION_ENV=1 to allow inherited session env for advanced CLI use.
2
+ * Returns true when the host process has spawned this workflow with
3
+ * ZIBBY_SESSION_* env vars that should be preserved (not cleared by
4
+ * `clearInheritedSessionEnvForFreshRun`). Set either:
5
+ * - `ZIBBY_TRUST_SESSION_ENV=1` (canonical, consumer-agnostic)
6
+ * - `ZIBBY_KEEP_SESSION_ENV=1` (legacy CLI-side opt-in, equivalent)
4
7
  */
5
8
  export function shouldTrustInheritedSessionEnv(): boolean;
6
9
  /**
7
- * Studio sets `ZIBBY_RUN_SOURCE=studio` and `ZIBBY_SESSION_PATH` before spawning `zibby run`.
8
- * Snapshot this path *before* `clearInheritedSessionEnvForFreshRun()` so we still pin the folder when:
9
- * - an older global `@zibby/core` clears session env unconditionally, or
10
- * - `--session-path` is dropped by shell/argv quirks but env was set.
10
+ * If the host has pinned a specific session folder via env (e.g. a desktop
11
+ * app spawning the CLI with ZIBBY_SESSION_PATH already set), return its
12
+ * resolved absolute path. Returns undefined when the host hasn't pinned one.
13
+ *
14
+ * Gated on `ZIBBY_PIN_SESSION_PATH=1` so an unrelated process that happens
15
+ * to have `ZIBBY_SESSION_PATH` in its environment doesn't accidentally land
16
+ * in someone else's session folder.
11
17
  */
12
- export function readStudioPinnedSessionPathFromEnv(): any;
18
+ export function readPinnedSessionPathFromEnv(): any;
13
19
  /** Drop stale shell exports so graph + children do not write to an old session folder. */
14
20
  export function clearInheritedSessionEnvForFreshRun(): void;
15
21
  /**
@@ -51,6 +57,7 @@ export class WorkflowGraph {
51
57
  nodePrompts: Map<any, any>;
52
58
  nodeOptions: Map<any, any>;
53
59
  _invokeAgent: any;
60
+ _compiledPrompts: Map<any, any>;
54
61
  setStateSchema(schema: any): this;
55
62
  getStateSchema(): any;
56
63
  addNode(name: any, nodeOrConfig: any, options?: {}): this;
@@ -88,7 +95,28 @@ export class WorkflowGraph {
88
95
  _flattenSchema(schema: any, prefix?: string): any;
89
96
  _formatLabel(str: any): any;
90
97
  _summarizeNodeOutput(nodeName: any, output: any): string[];
91
- run(agent: any, initialState?: {}): Promise<{
98
+ /**
99
+ * Execute the graph.
100
+ *
101
+ * @param {object} agent User-supplied agent shell (calculateOutputPath, onComplete, cleanup hooks).
102
+ * @param {object} [initialState] Initial state values (cwd, input, config, sessionPath, etc.).
103
+ * @param {object} [options] Run-level options.
104
+ * @param {AbortSignal} [options.signal] External abort signal. When aborted, the engine stops at the next
105
+ * abort-checkpoint, returns `{ stoppedExternally: true }`, and runs cleanup.
106
+ * The legacy stop-file watcher (`.zibby-stop` / `.zibby-studio-stop`) feeds
107
+ * the same internal abort, so all stop paths converge to one return shape.
108
+ * @param {number} [options.strategyAbortTimeoutMs=5000]
109
+ * Engine deadman timer. After abort fires, if a strategy.invoke() call
110
+ * hasn't settled within this many ms, the engine throws AbortError on
111
+ * behalf of graph.run, runs cleanup, and abandons the strategy promise.
112
+ * Protects against strategies (especially third-party) that ignore
113
+ * AbortSignal entirely. Set higher if you have legitimately long-running
114
+ * cleanup paths inside a strategy's abort handler.
115
+ */
116
+ run(agent: object, initialState?: object, options?: {
117
+ signal?: AbortSignal;
118
+ strategyAbortTimeoutMs?: number;
119
+ }): Promise<{
92
120
  success: boolean;
93
121
  state: any;
94
122
  executionLog: {