@zibby/agent-workflow 0.1.4 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md 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 D=Object.defineProperty;var T=(e,o)=>()=>(e&&(o=e(e=0)),o);var L=(e,o)=>{for(var n in o)D(e,n,{get:o[n],enumerable:!0})};function v(e){return M.get(e)||null}var $,M,S=T(()=>{$=Symbol.for("@zibby/agent-workflow.skills");globalThis[$]||(globalThis[$]=new Map);M=globalThis[$]});var _,F,N,k,x=T(()=>{_=()=>{},F={debug:_,info:_,warn:(...e)=>console.warn("[workflow]",...e),error:(...e)=>console.error("[workflow]",...e)},N={impl:F},k={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 A=T(()=>{});var I={};L(I,{getAgentStrategy:()=>C,invokeAgent:()=>B,listStrategies:()=>z,registerStrategy:()=>G});function G(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 z(){return m.map(e=>e.getName())}function C(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 B(e,o={},n={}){let r=C(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=v(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
+ `),k.debug(`[workflow] prompt length: ${u.length} chars`),r.invoke(u,p)}var E,m,j=T(()=>{A();x();S();E=Symbol.for("@zibby/agent-workflow.strategies");globalThis[E]||(globalThis[E]=[]);m=globalThis[E]});S();x();var b={};var O=new Map;function U(e,o){O.set(e,o)}function P(e){let o=O.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(()=>(j(),I))).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(`
20
+ `)}`}function ge(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}=Q(r,s),h=X(t,r,s),d=[],y=o.workflowType||"workflow";return d.push(Y(o)),d.push(H(y,{usesRegisteredNodes:c})),d.push(W(p)),d.push(J(y)),d.push(K(t,i)),d.push(Z(t,h,u,g,l,y)),d.filter(Boolean).join(`
21
+ `)}function me(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 Y(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
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(`
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 K(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=R(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 Z(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=R(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=b[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 X(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 R(e){return e.replace(/[^a-zA-Z0-9]/g,"_")}export{me as generateNodeConfigsJson,ge as generateWorkflowCode};
@@ -4,7 +4,20 @@
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. */
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
+ *
12
+ * The engine accepts BOTH this generic name and the legacy Studio-specific
13
+ * name during the AbortSignal-migration BC window. New consumers should
14
+ * use STOP_REQUEST_FILE.
15
+ */
16
+ export const STOP_REQUEST_FILE: ".zibby-stop";
17
+ /**
18
+ * @deprecated Use STOP_REQUEST_FILE. Will be removed in v2 once the
19
+ * AbortSignal contract is universally adopted across consumers.
20
+ */
8
21
  export const STUDIO_STOP_REQUEST_FILE: ".zibby-studio-stop";
9
22
  export const RESULT_FILE: "result.json";
10
23
  export const RAW_OUTPUT_FILE: "raw_stream_output.txt";
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",E=".zibby-studio-stop",I="result.json",r="raw_stream_output.txt",e="events.json",S={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,S as SKILLS,_ as STOP_REQUEST_FILE,E as STUDIO_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 ut=Object.defineProperty;var le=(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 q=(o,e)=>()=>(o&&(e=o(o=0)),e);var Oe=(o,e)=>{for(var t in e)ut(o,t,{get:e[t],enumerable:!0})};var ke,ft,ee,w,U=q(()=>{ke=()=>{},ft={debug:ke,info:ke,warn:(...o)=>console.warn("[workflow]",...o),error:(...o)=>console.error("[workflow]",...o)},ee={impl:ft},w={debug:(...o)=>ee.impl.debug?.(...o),info:(...o)=>ee.impl.info?.(...o),warn:(...o)=>ee.impl.warn?.(...o),error:(...o)=>ee.impl.error?.(...o)}});var Ze=q(()=>{});var je={};Oe(je,{clearSkills:()=>yt,getAllSkills:()=>wt,getSkill:()=>H,hasSkill:()=>St,listSkillIds:()=>_t,registerSkill:()=>gt});function gt(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 H(o){return F.get(o)||null}function St(o){return F.has(o)}function wt(){return new Map(F)}function _t(){return Array.from(F.keys())}function yt(){F.clear()}var he,F,oe=q(()=>{he=Symbol.for("@zibby/agent-workflow.skills");globalThis[he]||(globalThis[he]=new Map);F=globalThis[he]});var K={};Oe(K,{getAgentStrategy:()=>Ue,invokeAgent:()=>Nt,listStrategies:()=>It,registerStrategy:()=>Et});function Et(o){if(!o||typeof o.getName!="function"||typeof o.invoke!="function")throw new Error("strategy must implement getName() and invoke() (AgentStrategy shape)");let e=W.findIndex(t=>t.getName()===o.getName());e>=0?W[e]=o:W.push(o)}function It(){return W.map(o=>o.getName())}function Ue(o={}){let{state:e={},preferredAgent:t=null}=o,r=t||e.agentType||process.env.AGENT_TYPE;if(!r){let i=W.map(a=>a.getName()).join(", ")||"none registered";throw new Error(`No agent specified. Set agentType in state or AGENT_TYPE env var. Available: ${i}`)}w.debug(`[workflow] agent selection: requested=${r}`);let s=W.find(i=>i.getName()===r);if(!s){let i=W.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 w.debug(`[workflow] using agent: ${s.getName()}`),s}async function Nt(o,e={},t={}){let r=Ue(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,d=a||n||c||t.model||null,h={...t,model:d,workspace:e.state?.workspace||t.workspace,schema:t.schema||e.schema,images:t.images||e.images||[],skills:t.skills||e.skills||[],config:s},u=o,l=h.skills||[];if(l.length>0&&!t.skipPromptFragments){let _=l.map(S=>{let $=H(S)?.promptFragment;return typeof $=="function"?$():$}).filter(Boolean);_.length>0&&(u+=`
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&&(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
- ${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
+ `),w.debug(`[workflow] prompt length: ${u.length} chars`),r.invoke(u,h)}var me,W,z=q(()=>{Ze();U();oe();me=Symbol.for("@zibby/agent-workflow.strategies");globalThis[me]||(globalThis[me]=[]);W=globalThis[me]});var pt=new Set(["__proto__","constructor","prototype"]);function de(o){if(pt.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){de(e),this._history.push({...this._state}),this._state[e]=t}update(e){let t=Object.getOwnPropertyNames(e);for(let r of t)de(r);this._history.push({...this._state});for(let r of t)this._state[r]=e[r]}append(e,t){de(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}};U();import{writeFileSync as ge,readFileSync as Ge,existsSync as He,mkdirSync as vt}from"node:fs";import{join as Se,dirname as $t}from"node:path";import I from"chalk";var ht="__WORKFLOW_GRAPH_LOG__",G=I.gray("\u2502"),mt=I.gray("\u250C"),xe=I.gray("\u2514"),ue=I.green("\u25C6"),Ce=I.hex("#c084fc")("\u25C6"),Pe=I.hex("#2dd4bf")("\u25C6"),pe=I.red("\u25C6"),Re=`${G} `,Be=2;function We(o){return o<1e3?`${o}ms`:`${(o/1e3).toFixed(1)}s`}function Me(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+=Re,e.col=Be,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
+ ${Re}`,e.col=Be))}return o(a,r,s)}}var fe=class{constructor(){this._currentNode=null,this._origStdoutWrite=null,this._origStderrWrite=null;let e=String(process.env.ZIBBY_EMIT_GRAPH_MARKERS||"").trim()==="1"||String(process.env.ZIBBY_WORKFLOW_GRAPH_LOG_MARKERS||"").trim()==="1",t=!e&&String(process.env.ZIBBY_RUN_SOURCE||"").trim().toLowerCase()==="studio";t&&process.env.ZIBBY_NO_DEPRECATION_WARNINGS!=="1"&&console.warn("[zibby/agent-workflow] `ZIBBY_RUN_SOURCE=studio` env var is deprecated for graph-marker emission. Set `ZIBBY_EMIT_GRAPH_MARKERS=1` instead. The Studio-specific value will be ignored in v2. Suppress with ZIBBY_NO_DEPRECATION_WARNINGS=1."),this._emitWorkflowGraphMarkers=e||t}get isInsideNode(){return this._currentNode!==null}_startIntercepting(){this._origStdoutWrite=process.stdout.write.bind(process.stdout),this._origStderrWrite=process.stderr.write.bind(process.stderr);let e={lineStart:!0,col:0,inEsc:!1},t={lineStart:!0,col:0,inEsc:!1};this._outState=e,this._errState=t,process.stdout.write=Me(this._origStdoutWrite,e),process.stderr.write=Me(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=`${ht}${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(ue,e):process.stdout.write.bind(process.stdout)(`${G} ${ue} ${e}
24
+ `)}stepInfo(e){this.step(e)}stepTool(e){this._origStdoutWrite?this._writeDot(Ce,e):process.stdout.write.bind(process.stdout)(`${G} ${Ce} ${e}
25
+ `)}stepMemory(e){let t=I.hex("#2dd4bf")(e);this._origStdoutWrite?this._writeDot(Pe,t):process.stdout.write.bind(process.stdout)(`${G} ${Pe} ${t}
26
+ `)}stepFail(e){this._origStdoutWrite?this._writeDot(pe,I.red(e)):process.stdout.write.bind(process.stdout)(`${G} ${pe} ${I.red(e)}
27
+ `)}nodeStart(e){this._currentNode=e,this._emitGraphLogMarker({phase:"node_begin",node:e}),this._rawWrite(`${mt} ${e}`),this._startIntercepting()}nodeComplete(e,t={}){this._stopIntercepting();let{duration:r,details:s}=t;if(s)for(let a of s)this._rawWrite(`${ue} ${a}`);let i=r?I.dim(` ${We(r)}`):"";this._rawWrite(`${xe} ${I.green("done")}${i}`),this._emitGraphLogMarker({phase:"node_end",node:e}),this._rawWrite("")}nodeFailed(e,t,r={}){this._stopIntercepting();let{duration:s}=r,i=s?I.dim(` ${We(s)}`):"";this._rawWrite(`${pe} ${I.red(t)}`),this._rawWrite(`${xe} ${I.red("failed")}${i}`),this._emitGraphLogMarker({phase:"node_end",node:e}),this._rawWrite("")}route(e,t){this._rawWrite(I.dim(` ${e} \u2192 ${t}`)),this._rawWrite("")}graphComplete(){this._rawWrite(I.green.bold("\u2713 Workflow completed"))}},N=new fe;var te=".zibby/output",De="sessions",L=".session-info.json",Le=".zibby-stop",Fe=".zibby-studio-stop";var Ye=["CI_JOB_ID","GITHUB_RUN_ID","CIRCLE_WORKFLOW_ID","BUILD_ID"];var Y=class{constructor(e){if(this.config=e,this.name=e.name,this.prompt=e.prompt,this.outputSchema=e.outputSchema,!this.outputSchema&&!e._isCustomCode)throw new Error(`Node '${this.name}' must define outputSchema (Zod schema). This defines the contract for what the node returns to state.`);this.isZodSchema=this.outputSchema&&typeof this.outputSchema._def<"u",this.parser=e.outputSchema&&!this.isZodSchema?new 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=u=>t&&typeof t.get=="function"?t.get(u):e?.[u];if(typeof this.customExecute=="function"){w.debug(`[workflow] node '${this.name}': custom execute (skipping LLM)`);try{let u=await this.customExecute(e);return typeof u=="object"&&u!==null&&u.success===!1?{success:!1,error:u.error||"Node execution failed",raw:u.raw||null}:this.isZodSchema?(w.debug(`[workflow] node '${this.name}': validating output schema`),{success:!0,output:this.outputSchema.parse(u),raw:null}):{success:!0,output:u,raw:null}}catch(u){return w.error(`[workflow] node '${this.name}' failed: ${u.message}`),u.name==="ZodError"&&w.error(`Schema errors: ${JSON.stringify(u.issues||u.errors,null,2)}`),{success:!1,error:u.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(),d=n.sessionPath;try{if(d){let u=Se(d,L);if(He(u)){let m=JSON.parse(Ge(u,"utf-8"));m.currentNode=this.name,ge(u,JSON.stringify(m,null,2),"utf-8")}let l=Se(d,"..",L);if(He(l))try{let m=JSON.parse(Ge(l,"utf-8"));m.currentNode=this.name,ge(l,JSON.stringify(m,null,2),"utf-8")}catch{}}}catch(u){w.debug(`[workflow] could not update session info: ${u.message}`)}let h=null;for(let u=0;u<=this.retries;u++)try{w.debug(`[workflow] node '${this.name}' attempt ${u}`);let l=r().config||{},m=l.agents||{},_=this.config.agent??m[this.name]??null,S={state:r()};_&&(S.preferredAgent=_);let $={workspace:c,schema:this.isZodSchema?this.outputSchema:null,skills:this.config.skills||[],sessionPath:d,config:l,nodeName:this.name,timeout:this.config?.timeout||3e5},f=e?._coreInvokeAgent;f||(f=(await Promise.resolve().then(()=>(z(),K))).invokeAgent);let v=await f(i,S,$),y,A;if(typeof v=="string"?(y=v,A=null):v.structured?(y=v.raw||JSON.stringify(v.structured,null,2),A=v.structured):(y=v.raw||JSON.stringify(v,null,2),A=v.extracted||null),d)try{let p=Se(d,this.name,"raw_stream_output.txt");vt($t(p),{recursive:!0}),ge(p,typeof y=="string"?y:JSON.stringify(y),"utf-8")}catch(p){w.debug(`[workflow] could not save raw output: ${p.message}`)}if(this.isZodSchema&&A){w.info(`[workflow] node '${this.name}': output validated: ${JSON.stringify(A,null,2)}`);let p=A;if(typeof this.onComplete=="function")try{p=await this.onComplete(r(),A)}catch(R){w.warn(`[workflow] onComplete hook failed: ${R.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 w.info(`[workflow] node '${this.name}': parsed output: ${JSON.stringify(p,null,2)}`),N.step("Output parsed"),{success:!0,output:p,raw:y}}return{success:!0,output:y,raw:y}}catch(l){h=l,u<this.retries&&w.info(`[workflow] node '${this.name}' failed, retrying (${u+1}/${this.retries})\u2026`)}return{success:!1,error:h.message,raw:null}}},re=class extends Y{constructor(e){super({...e,_isCustomCode:!0}),this.condition=e.condition}async execute(e,t){let r=t&&typeof t.getAll=="function"?t.getAll():e;return{success:!0,output:{nextNode:this.condition(r)},raw:null}}};import{existsSync as Ke,readFileSync as bt}from"node:fs";import{join as we,dirname as ze}from"node:path";var se=class{static async loadContext(e,t,r={}){let s={},i=r.filenames||["CONTEXT.md","AGENTS.md"];if(e){let n=ze(we(t,e));for(let c of i){let d=await this.findAndMergeContextFiles(c,n,t);if(d){let h=c.replace(/\.[^.]+$/,"").toLowerCase();s[h]=d}}}let a=r.discovery||{};for(let[n,c]of Object.entries(a))try{let d=we(t,c);Ke(d)&&(s[n]=await this.loadFile(d))}catch(d){console.warn(`[workflow] could not load context '${n}' from '${c}': ${d.message}`)}return s}static async findAndMergeContextFiles(e,t,r){let s=[],i=t;for(;i.startsWith(r);){let a=we(i,e);if(Ke(a))try{s.unshift(await this.loadFile(a))}catch(c){console.warn(`[workflow] could not load ${e} from ${a}: ${c.message}`)}let n=ze(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=bt(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 Xe,existsSync as ne,writeFileSync as Je,unlinkSync as Ve}from"node:fs";import{join as P,resolve as et}from"node:path";import{config as Tt}from"dotenv";import{zodToJsonSchema as qe}from"zod-to-json-schema";import At from"handlebars";var Qe=new Set;function ie(o,e){Qe.has(o)||(Qe.add(o),process.env.ZIBBY_NO_DEPRECATION_WARNINGS!=="1"&&console.warn(`[zibby/agent-workflow] ${e}`))}function Ot({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 kt(){return process.env.ZIBBY_TRUST_SESSION_ENV==="1"||process.env.ZIBBY_TRUST_SESSION_ENV==="true"||process.env.ZIBBY_KEEP_SESSION_ENV==="1"||process.env.ZIBBY_KEEP_SESSION_ENV==="true"?!0:process.env.ZIBBY_RUN_SOURCE==="studio"?(ie("legacy-zibby-run-source","`ZIBBY_RUN_SOURCE=studio` env var is deprecated. Set `ZIBBY_TRUST_SESSION_ENV=1` (and `ZIBBY_PIN_SESSION_PATH=1` / `ZIBBY_EMIT_GRAPH_MARKERS=1` if you need those gates) instead. The Studio-specific value will be ignored in v2. Suppress with ZIBBY_NO_DEPRECATION_WARNINGS=1."),!0):!1}function xt(){let o=process.env.ZIBBY_PIN_SESSION_PATH==="1"||process.env.ZIBBY_PIN_SESSION_PATH==="true",e=!o&&process.env.ZIBBY_RUN_SOURCE==="studio";if(e&&ie("legacy-zibby-run-source","`ZIBBY_RUN_SOURCE=studio` env var is deprecated. Set `ZIBBY_PIN_SESSION_PATH=1` (and `ZIBBY_TRUST_SESSION_ENV=1` / `ZIBBY_EMIT_GRAPH_MARKERS=1` if you need those gates) instead. The Studio-specific value will be ignored in v2. Suppress with ZIBBY_NO_DEPRECATION_WARNINGS=1."),!o&&!e)return;let t=process.env.ZIBBY_SESSION_PATH;if(!(t==null||String(t).trim()===""))try{return et(String(t).trim())}catch{return String(t).trim()}}var Ct=xt;function Pt(){kt()||(delete process.env.ZIBBY_SESSION_PATH,delete process.env.ZIBBY_SESSION_ID)}function Rt({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 Bt(o={}){let e=Ye.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 Wt({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 d=et(String(process.env.ZIBBY_SESSION_PATH));d&&(s=d,a="ZIBBY_SESSION_PATH")}catch{}let n;if(s)n=String(s).split(/[/\\]/).filter(Boolean).pop(),i==null&&(i=Date.now());else{let d=process.env.ZIBBY_SESSION_ID&&String(process.env.ZIBBY_SESSION_ID).trim();if(d)n=d,a="ZIBBY_SESSION_ID";else{let u=e.sessionId!=null?String(e.sessionId).trim():"";u&&u!=="last"?(n=u,a="config.sessionId"):(n=Bt(e),a="generated")}i=i??Date.now();let h=e.paths?.output||te;s=P(o,h,De,n)}let c=!ne(s);return c&&Xe(s,{recursive:!0}),(c||a!=="initialState.sessionPath")&&Ot({traceFrom:r,sessionId:n,sessionPath:s,idSource:a,mkdirFresh:c}),Rt({sessionPath:s,sessionId:n}),{sessionPath:s,sessionId:n,sessionTimestamp:i}}var ae=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 Y?t:new Y(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 re({...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],d=a;a=()=>c(t,d,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 d=this.nodePrompts.get(i);if(d&&(c.prompt=d),typeof a.customExecute=="function"&&(c.executeCode=a.customExecute.toString()),a.outputSchema)try{if(typeof a.outputSchema._def<"u"){let u=qe(a.outputSchema,{target:"openApi3"});c.outputSchema={jsonSchema:u,variables:this._flattenJsonSchemaToVariables(u)}}else c.outputSchema={schema:a.outputSchema}}catch(u){console.warn(`[workflow] failed to convert schema for ${i}:`,u.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),d=a.labels||{};for(let h of c){let u={source:i,target:h,data:{conditionalCode:n}};d[h]&&(u.label=d[h]),r.push(u)}}let s=null;if(this.stateSchema)try{s=qe(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(d=>d?.passed===!0).length,c=i.some(d=>d?.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();Tt({path:P(a,".env")});let n=t.config||{};if(!n||Object.keys(n).length===0)try{let g=P(a,".zibby.config.js");ne(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 d=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(O=>`${O.path.join(".")}: ${O.message}`);throw console.error("\u274C Initial state validation failed:"),T.forEach(O=>console.error(` - ${O}`)),new Error(`State validation failed: ${T.join(", ")}`)}N.step("State validated against schema")}let h=Ct(),u=t.sessionPath||h;u||Pt();let{sessionPath:l,sessionTimestamp:m,sessionId:_}=Wt({cwd:a,config:n,traceFrom:"WorkflowGraph.run",initialState:{sessionPath:u,sessionTimestamp:t.sessionTimestamp}});N.step(`Session ${_}`);let S=await se.loadContext(t.specPath||"",a,d);Object.keys(S).length>0&&N.step(`Context loaded: ${Object.keys(S).join(", ")}`);let $=t.outputPath;!$&&t.specPath&&(e?.calculateOutputPath?$=e.calculateOutputPath(t.specPath):console.warn(`\u26A0\uFE0F outputPath not resolved (specPath=${t.specPath})`));let f=new Q({...t,config:n,agentType:c,outputPath:$,sessionPath:l,sessionTimestamp:m,context:S,resolvedTools:this.resolvedToolsMap||{},_signal:s.signal}),v=new Map;try{await import("@zibby/skills")}catch{}let{getSkill:y}=await Promise.resolve().then(()=>(oe(),je)),A=new Set;for(let[,g]of this.nodes)for(let T of g.config?.skills||[])A.add(T);for(let g of A){let T=y(g);if(typeof T?.middleware=="function")try{let O=await T.middleware();typeof O=="function"&&v.set(g,O)}catch{}}let p=this.entryPoint,R=[],Ee=n?.recursionLimit??100,nt=0;try{for(;p&&p!=="END";){if(++nt>Ee)throw new Error(`Workflow exceeded recursion limit (${Ee}) \u2014 likely a cyclic conditional route. Set config.recursionLimit if you need a higher cap.`);let T=P(l,Le),O=P(l,Fe);if(ne(T)){try{Ve(T)}catch{}s.abort()}if(ne(O)){try{Ve(O)}catch{}s.abort(),ie("legacy-stop-file","Detected legacy `.zibby-studio-stop` file. Consumers should migrate to either `.zibby-stop` (renamed) or pass an AbortSignal to graph.run. The legacy filename will be removed in v2. Suppress with ZIBBY_NO_DEPRECATION_WARNINGS=1.")}if(s.signal.aborted)return console.warn(`
37
+ \u{1F6D1} External stop requested \u2014 ending workflow.`),N.step("Workflow stopped externally"),{success:!0,state:f.getAll(),executionLog:R,stoppedExternally:!0,stoppedByStudio:!0};let Z=this.nodes.get(p);if(!Z)throw new Error(`Node '${p}' not found in graph`);let Ie=JSON.stringify({sessionPath:l,sessionTimestamp:m,currentNode:p,createdAt:new Date().toISOString(),config:f.get("config")}),it=P(l,L);Je(it,Ie,"utf-8");let Ne=f.get("config")?.paths?.output||te,at=P(a,Ne,L);Xe(P(a,Ne),{recursive:!0});try{Je(at,Ie,"utf-8")}catch{}let ve=t.onPipelineProgress;if(typeof ve=="function")try{ve({cwd:a,sessionPath:l,sessionId:_,outputBase:f.get("config")?.paths?.output||te,currentNode:p})}catch{}let ct=(this.resolvedToolsMap||{})[p]||null;f.set("_currentNodeTools",ct);let lt=f.get("nodeConfigs")||{};f.set("_currentNodeConfig",lt[p]||{}),N.nodeStart(p);let $e=Date.now(),J=this.nodePrompts.get(p);if(!this._invokeAgent){let k=await Promise.resolve().then(()=>(z(),K));this._invokeAgent=k.invokeAgent}let dt=this._invokeAgent,be=async(k,x,E={})=>{let b=dt(k,x,{...E,signal:s.signal});return b.catch(()=>{}),s.signal.aborted?b:Promise.race([b,new Promise((M,D)=>{let B=()=>{setTimeout(()=>{let j=new Error(`Strategy ignored AbortSignal \u2014 engine deadman fired after ${i}ms`);j.name="AbortError",D(j)},i)};s.signal.addEventListener("abort",B,{once:!0})})])},Te={state:f,invokeAgent:async(k={},x={})=>{let E=x.prompt||"";if(J){let b=this._compiledPrompts.get(p);b||(b=At.compile(J,{noEscape:!0}),this._compiledPrompts.set(p,b));try{E=b(k)}catch(M){throw console.error(`\u274C Template rendering failed for node '${p}':`,M.message),new Error(`Template rendering failed: ${M.message}`,{cause:M})}}else if(!E)throw new Error(`No prompt template configured for node '${p}' and no prompt provided in options`);return be(E,{state:f.getAll(),images:x.images||[]},{model:x.model||f.get("model"),workspace:f.get("workspace"),schema:x.schema,...x,signal:s.signal})},_coreInvokeAgent:be,agent:e,nodeId:p,promptTemplate:J,getPromptTemplate:()=>J,...f.getAll()};try{let k=(Z.config?.skills||[]).map(B=>v.get(B)).filter(Boolean),x=[...this.middleware,...k],E;x.length>0?E=await this._composeMiddleware(x,p,async()=>Z.execute(Te,f),f.getAll(),f):E=await Z.execute(Te,f);let b=Date.now()-$e;if(R.push({node:p,success:E.success,duration:b,timestamp:new Date().toISOString()}),!E.success){if(String(E.error||"").includes("Stopped from Zibby Studio"))return ie("legacy-error-string",'Strategy returned the legacy `Stopped from Zibby Studio` error string. Strategies should reject with `Error.name === "AbortError"` instead. The string-match fallback will be removed in v2. Suppress with ZIBBY_NO_DEPRECATION_WARNINGS=1.'),N.step("Workflow stopped externally"),f.set("stoppedExternally",!0),f.set("stoppedByStudio",!0),{success:!0,state:f.getAll(),executionLog:R,stoppedExternally:!0,stoppedByStudio:!0};if(s.signal.aborted)return N.step("Workflow stopped externally"),{success:!0,state:f.getAll(),executionLog:R,stoppedExternally:!0,stoppedByStudio:!0};f.append("errors",{node:p,error:E.error});let j=Z.config?.retries||0,Ae=`${p}_retries`,V=f.getAll()[Ae]||0;if(V<j){N.stepInfo(`Retrying (attempt ${V+1}/${j})`),f.update({[Ae]:V+1,[`${p}_raw`]:E.raw});continue}throw N.nodeFailed(p,E.error,{duration:b}),new Error(`Node '${p}' failed after ${V} attempts: ${E.error}`)}f.update({[p]:E.output});let M=this._summarizeNodeOutput(p,E.output);N.nodeComplete(p,{duration:b,details:M});let D=this.edges.get(p);if(!D)p="END";else if(D.conditional){let B=D.routes(f.getAll());N.route(p,B),p=B}else p=D}catch(k){throw N.isInsideNode&&N.nodeFailed(p,k.message,{duration:Date.now()-$e}),f.set("failed",!0),f.set("failedAt",p),k}}N.graphComplete();let g={success:!0,state:f.getAll(),executionLog:R};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 _e=new Map;function Mt(o,e){_e.set(o,e)}function tt(o){return _e.get(o)}function ye(o){return _e.has(o)}Mt("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(()=>(z(),K))).invokeAgent);let s=e.extraPromptInstructions||"Execute the task based on the current state.",i=Dt(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 Dt(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 d=n.split(".").reduce((l,m)=>l?.[m],e);if(d===void 0)continue;let h=typeof d=="string"?d:d?.raw??JSON.stringify(d,null,2),u=n.replace(/_/g," ").replace(/\b\w/g,l=>l.toUpperCase());i.push(`## ${u}
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
+ `)}`}oe();U();var Lt={};function rt(o,e){if(Array.isArray(e))return ot(e);let t=Lt[o];return!t||t.length===0?null:ot(t)}function ot(o){if(!Array.isArray(o)||o.length===0)return null;let e=[],t={},r=[];for(let s of o){let i=H(s);if(!i){w.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}}U();function xo(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 ae(e);e.stateSchema&&i.setStateSchema(e.stateSchema);let a=new Set,n=new Map,c={};for(let l of t){let m=ce(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,S=s[l]||{},$=rt(_,S.tools);$&&(c[l]=$);let f={};S.prompt&&(f.prompt=S.prompt);let v=ye(_);if(w.debug(`[workflow] compiler: node "${l}" type="${_}" registered=${v}`),S.customCode&&!v)i.addNode(l,st(l,S.customCode,S),f),i.setNodeType(l,_);else if(v){let y=tt(_);y.factory?i.addNode(l,y.create(l,{...S,resolvedTools:$}),f):i.addNode(l,y,f),i.setNodeType(l,_)}else if(S.executeCode)i.addNode(l,st(l,S.executeCode,S),f),i.setNodeType(l,_);else throw new C(`Unknown node type "${_}" for node "${l}". Did you forget to register it?`)}i.resolvedToolsMap=c;let d=new Set;for(let l of r)a.has(l.target)||d.add(l.target);let h=t.find(l=>!a.has(l.id)&&!d.has(l.id));if(!h)throw new C("Could not determine entry point: no node without incoming edges found");i.setEntryPoint(h.id);let u=Ft(r,"source");for(let l of r)if(!a.has(l.source))if(a.has(l.target)){let m=l.target,_=u.get(m)||[];if(_.length===0)throw new C(`Decision node "${m}" has no outgoing edges`);let S=Yt(m,_,a);i.addConditionalEdges(l.source,S)}else i.addEdge(l.source,l.target);return i}function Co(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=ce(n);if(c==="decision"||ye(c))continue;let d=t[n.id]||{};d.customCode||d.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=>ce(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 Po(o){return!o||!Array.isArray(o.nodes)?[]:o.nodes.filter(e=>ce(e)!=="decision").map(e=>e.id)}function ce(o){let e=o.data?.nodeType||o.data?.type||o.type;return e==="workflowNode"||e==="custom"||e==="default"?o.id:e}function Ft(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 Yt(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=d=>{let h=c(d);return i.has(h)||w.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 st(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(()=>(z(),K));return n(...a)},typeof le<"u"?le: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,xo as compileGraph,Po as extractSteps,Co as validateGraphConfig};
package/dist/graph.d.ts CHANGED
@@ -1,15 +1,23 @@
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`). True when ANY of:
5
+ * - `ZIBBY_TRUST_SESSION_ENV=1` (canonical, consumer-agnostic)
6
+ * - `ZIBBY_KEEP_SESSION_ENV=1` (legacy CLI-side opt-in)
7
+ * - `ZIBBY_RUN_SOURCE=studio` (legacy Studio-specific; deprecated)
4
8
  */
5
9
  export function shouldTrustInheritedSessionEnv(): boolean;
6
10
  /**
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.
11
+ * If the host has pinned a specific session folder via env (e.g. a desktop
12
+ * app spawning the CLI with ZIBBY_SESSION_PATH already set), return its
13
+ * resolved absolute path. Returns undefined when the host hasn't pinned one.
14
+ *
15
+ * Gated on `ZIBBY_PIN_SESSION_PATH=1` (canonical) OR the legacy
16
+ * `ZIBBY_RUN_SOURCE=studio` (deprecated) so an unrelated process that
17
+ * happens to have ZIBBY_SESSION_PATH in its environment doesn't accidentally
18
+ * land in someone else's session folder.
11
19
  */
12
- export function readStudioPinnedSessionPathFromEnv(): any;
20
+ export function readPinnedSessionPathFromEnv(): any;
13
21
  /** Drop stale shell exports so graph + children do not write to an old session folder. */
14
22
  export function clearInheritedSessionEnvForFreshRun(): void;
15
23
  /**
@@ -39,6 +47,17 @@ export function resolveWorkflowSession({ cwd, config, initialState, traceFrom, }
39
47
  sessionId: any;
40
48
  sessionTimestamp: any;
41
49
  };
50
+ /**
51
+ * If the host has pinned a specific session folder via env (e.g. a desktop
52
+ * app spawning the CLI with ZIBBY_SESSION_PATH already set), return its
53
+ * resolved absolute path. Returns undefined when the host hasn't pinned one.
54
+ *
55
+ * Gated on `ZIBBY_PIN_SESSION_PATH=1` (canonical) OR the legacy
56
+ * `ZIBBY_RUN_SOURCE=studio` (deprecated) so an unrelated process that
57
+ * happens to have ZIBBY_SESSION_PATH in its environment doesn't accidentally
58
+ * land in someone else's session folder.
59
+ */
60
+ export function readStudioPinnedSessionPathFromEnv(): any;
42
61
  export class WorkflowGraph {
43
62
  constructor(options?: {});
44
63
  nodes: Map<any, any>;
@@ -51,6 +70,7 @@ export class WorkflowGraph {
51
70
  nodePrompts: Map<any, any>;
52
71
  nodeOptions: Map<any, any>;
53
72
  _invokeAgent: any;
73
+ _compiledPrompts: Map<any, any>;
54
74
  setStateSchema(schema: any): this;
55
75
  getStateSchema(): any;
56
76
  addNode(name: any, nodeOrConfig: any, options?: {}): this;
@@ -88,7 +108,28 @@ export class WorkflowGraph {
88
108
  _flattenSchema(schema: any, prefix?: string): any;
89
109
  _formatLabel(str: any): any;
90
110
  _summarizeNodeOutput(nodeName: any, output: any): string[];
91
- run(agent: any, initialState?: {}): Promise<{
111
+ /**
112
+ * Execute the graph.
113
+ *
114
+ * @param {object} agent User-supplied agent shell (calculateOutputPath, onComplete, cleanup hooks).
115
+ * @param {object} [initialState] Initial state values (cwd, input, config, sessionPath, etc.).
116
+ * @param {object} [options] Run-level options.
117
+ * @param {AbortSignal} [options.signal] External abort signal. When aborted, the engine stops at the next
118
+ * abort-checkpoint, returns `{ stoppedExternally: true }`, and runs cleanup.
119
+ * The legacy stop-file watcher (`.zibby-stop` / `.zibby-studio-stop`) feeds
120
+ * the same internal abort, so all stop paths converge to one return shape.
121
+ * @param {number} [options.strategyAbortTimeoutMs=5000]
122
+ * Engine deadman timer. After abort fires, if a strategy.invoke() call
123
+ * hasn't settled within this many ms, the engine throws AbortError on
124
+ * behalf of graph.run, runs cleanup, and abandons the strategy promise.
125
+ * Protects against strategies (especially third-party) that ignore
126
+ * AbortSignal entirely. Set higher if you have legitimately long-running
127
+ * cleanup paths inside a strategy's abort handler.
128
+ */
129
+ run(agent: object, initialState?: object, options?: {
130
+ signal?: AbortSignal;
131
+ strategyAbortTimeoutMs?: number;
132
+ }): Promise<{
92
133
  success: boolean;
93
134
  state: any;
94
135
  executionLog: {