@zibby/core 0.1.31 → 0.1.33
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/framework/graph.js +3 -3
- package/dist/package.json +1 -1
- package/package.json +1 -1
package/dist/framework/graph.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import{WorkflowState as ee}from"./state.js";import{Node as L,ConditionalNode as te}from"./node.js";import{ContextLoader as oe}from"./context-loader.js";import{mkdirSync as W,existsSync as b,writeFileSync as z,unlinkSync as se}from"fs";import{join as E,resolve as G}from"path";import{config as ne}from"dotenv";import{zodToJsonSchema as H}from"zod-to-json-schema";import re from"handlebars";import{DEFAULT_OUTPUT_BASE as
|
|
1
|
+
import{WorkflowState as ee}from"./state.js";import{Node as L,ConditionalNode as te}from"./node.js";import{ContextLoader as oe}from"./context-loader.js";import{mkdirSync as W,existsSync as b,writeFileSync as z,unlinkSync as se}from"fs";import{join as E,resolve as G}from"path";import{config as ne}from"dotenv";import{zodToJsonSchema as H}from"zod-to-json-schema";import re from"handlebars";import{DEFAULT_OUTPUT_BASE as x,SESSIONS_DIR as ie,SESSION_INFO_FILE as V,CI_ENV_VARS as ce,STUDIO_STOP_REQUEST_FILE as ae}from"./constants.js";import{timeline as S}from"../utils/timeline.js";function de({traceFrom:f,sessionId:e,sessionPath:t,idSource:s,mkdirFresh:o}){if(process.env.ZIBBY_SESSION_LOG==="0"||process.env.ZIBBY_SESSION_LOG==="false")return;const n=typeof process.ppid=="number"?process.ppid:"n/a",r=`[zibby:session] from=${f} pid=${process.pid} ppid=${n} sessionId=${e} source=${s} mkdir=${o?"yes":"no"} path=${t}`;if(console.log(r),(process.env.ZIBBY_TRACE_SESSION==="1"||process.env.ZIBBY_TRACE_SESSION==="true")&&process.env.ZIBBY_SESSION_LOG!=="0"&&process.env.ZIBBY_SESSION_LOG!=="false"){const i=(new Error("session trace").stack||"").split(`
|
|
2
2
|
`).slice(2,14).join(`
|
|
3
3
|
`);console.log(`[zibby:session] stack (${f}):
|
|
4
|
-
${i}`)}}function le(){return process.env.ZIBBY_RUN_SOURCE==="studio"||process.env.ZIBBY_KEEP_SESSION_ENV==="1"||process.env.ZIBBY_KEEP_SESSION_ENV==="true"}function pe(){if(process.env.ZIBBY_RUN_SOURCE!=="studio")return;const f=process.env.ZIBBY_SESSION_PATH;if(!(f==null||String(f).trim()===""))try{return G(String(f).trim())}catch{return String(f).trim()}}function fe(){le()||(delete process.env.ZIBBY_SESSION_PATH,delete process.env.ZIBBY_SESSION_ID)}function ue({sessionPath:f,sessionId:e}){f&&typeof f=="string"&&(process.env.ZIBBY_SESSION_PATH=f),e!=null&&String(e).trim()!==""&&(process.env.ZIBBY_SESSION_ID=String(e).trim())}function he(f={}){const e=ce.map(n=>process.env[n]).find(Boolean),t=Math.random().toString(36).slice(2,6),s=e||`${Date.now()}_${t}`,o=f.paths?.sessionPrefix;return o?`${o}_${s}`:s}function me({cwd:f=process.cwd(),config:e={},initialState:t={},traceFrom:s="resolveWorkflowSession"}={}){let o=t.sessionPath,n=t.sessionTimestamp,r="initialState.sessionPath";if(!o&&process.env.ZIBBY_SESSION_PATH)try{const i=G(String(process.env.ZIBBY_SESSION_PATH));i&&(o=i,r="ZIBBY_SESSION_PATH")}catch{}let c;if(o)c=String(o).split(/[/\\]/).filter(Boolean).pop(),n==null&&(n=Date.now());else{const i=process.env.ZIBBY_SESSION_ID&&String(process.env.ZIBBY_SESSION_ID).trim();if(i)c=i,r="ZIBBY_SESSION_ID";else{const g=e.sessionId!=null?String(e.sessionId).trim():"";g&&g!=="last"?(c=g,r="config.sessionId"):(c=he(e),r="generated")}n=n??Date.now();const u=e.paths?.output||
|
|
5
|
-
\u{1F6D1} Studio stop requested \u2014 ending workflow.`);try{se(l)}catch{}if(e&&typeof e.cleanup=="function")try{await e.cleanup()}catch{}return S.step("Workflow stopped by Studio"),{success:!0,state:d.getAll(),executionLog:O,stoppedByStudio:!0}}const m=this.nodes.get(a);if(!m)throw new Error(`Node '${a}' not found in graph`);const w=JSON.stringify({sessionPath:i,sessionTimestamp:u,currentNode:a,createdAt:new Date().toISOString(),config:d.get("config")}),q=E(i,V);z(q,w,"utf-8");const D=d.get("config")?.paths?.output||
|
|
4
|
+
${i}`)}}function le(){return process.env.ZIBBY_RUN_SOURCE==="studio"||process.env.ZIBBY_KEEP_SESSION_ENV==="1"||process.env.ZIBBY_KEEP_SESSION_ENV==="true"}function pe(){if(process.env.ZIBBY_RUN_SOURCE!=="studio")return;const f=process.env.ZIBBY_SESSION_PATH;if(!(f==null||String(f).trim()===""))try{return G(String(f).trim())}catch{return String(f).trim()}}function fe(){le()||(delete process.env.ZIBBY_SESSION_PATH,delete process.env.ZIBBY_SESSION_ID)}function ue({sessionPath:f,sessionId:e}){f&&typeof f=="string"&&(process.env.ZIBBY_SESSION_PATH=f),e!=null&&String(e).trim()!==""&&(process.env.ZIBBY_SESSION_ID=String(e).trim())}function he(f={}){const e=ce.map(n=>process.env[n]).find(Boolean),t=Math.random().toString(36).slice(2,6),s=e||`${Date.now()}_${t}`,o=f.paths?.sessionPrefix;return o?`${o}_${s}`:s}function me({cwd:f=process.cwd(),config:e={},initialState:t={},traceFrom:s="resolveWorkflowSession"}={}){let o=t.sessionPath,n=t.sessionTimestamp,r="initialState.sessionPath";if(!o&&process.env.ZIBBY_SESSION_PATH)try{const i=G(String(process.env.ZIBBY_SESSION_PATH));i&&(o=i,r="ZIBBY_SESSION_PATH")}catch{}let c;if(o)c=String(o).split(/[/\\]/).filter(Boolean).pop(),n==null&&(n=Date.now());else{const i=process.env.ZIBBY_SESSION_ID&&String(process.env.ZIBBY_SESSION_ID).trim();if(i)c=i,r="ZIBBY_SESSION_ID";else{const g=e.sessionId!=null?String(e.sessionId).trim():"";g&&g!=="last"?(c=g,r="config.sessionId"):(c=he(e),r="generated")}n=n??Date.now();const u=e.paths?.output||x;o=E(f,u,ie,c)}const p=!b(o);return p&&W(o,{recursive:!0}),de({traceFrom:s,sessionId:c,sessionPath:o,idSource:r,mkdirFresh:p}),ue({sessionPath:o,sessionId:c}),{sessionPath:o,sessionId:c,sessionTimestamp:n}}class Oe{constructor(e={}){this.nodes=new Map,this.edges=new Map,this.entryPoint=null,this.middleware=Array.isArray(e.middleware)?[...e.middleware]:[],e.nodeMiddleware&&this.middleware.push(e.nodeMiddleware),this.nodeTypeMap=new Map,this.conditionalCodeMap=new Map,this.stateSchema=e.stateSchema||null,this.nodePrompts=new Map,this.nodeOptions=new Map,this._invokeAgent=e.invokeAgent||null}setStateSchema(e){return this.stateSchema=e,this}getStateSchema(){return this.stateSchema}addNode(e,t,s={}){const o=t instanceof L?t:new L(t);return o.name=e,this.nodes.set(e,o),s.prompt&&this.nodePrompts.set(e,s.prompt),Object.keys(s).length>0&&this.nodeOptions.set(e,s),this}addConditionalNode(e,t){const s=new te({...t,name:e});return this.nodes.set(e,s),this}addEdge(e,t){return this.edges.set(e,t),this}setNodeType(e,t){return this.nodeTypeMap.set(e,t),this}addConditionalEdges(e,t,{labels:s}={}){return this.edges.set(e,{conditional:!0,routes:t,labels:s}),typeof t=="function"&&this.conditionalCodeMap.set(e,t.toString()),this}setEntryPoint(e){return this.entryPoint=e,this}use(e){return typeof e=="function"&&this.middleware.push(e),this}_composeMiddleware(e,t,s,o,n){let r=s;for(let c=e.length-1;c>=0;c--){const p=e[c],i=r;r=()=>p(t,i,o,n)}return r()}serialize(){const e=[],t={};for(const[n,r]of this.nodes){const c=this.nodeTypeMap.get(n)||n;e.push({id:n,type:c,data:{nodeType:c,label:n}});const p=r._isCustomCode||!1,i={};p&&typeof r.execute=="function"&&(i.customCode=r.execute.toString());const u=this.nodePrompts.get(n);if(u&&(i.prompt=u),typeof r.customExecute=="function"&&(i.executeCode=r.customExecute.toString()),r.outputSchema)try{if(typeof r.outputSchema._def<"u"){const P=H(r.outputSchema,{target:"openApi3"}),d=this._flattenJsonSchemaToVariables(P);i.outputSchema={jsonSchema:P,variables:d}}else i.outputSchema={schema:r.outputSchema}}catch(v){console.warn(`Failed to convert schema for ${n}:`,v.message)}const g=(this.resolvedToolsMap||{})[n];g?.toolIds&&(i.tools=g.toolIds),Object.keys(i).length>0&&(t[n]=i)}const s=[];for(const[n,r]of this.edges)if(typeof r=="string")s.push({source:n,target:r});else if(r.conditional){const c=this.conditionalCodeMap.get(n)||r.routes.toString(),p=this._inferConditionalTargets(r.routes),i=r.labels||{};for(const u of p){const g={source:n,target:u,data:{conditionalCode:c}};i[u]&&(g.label=i[u]),s.push(g)}}let o=null;if(this.stateSchema)try{o=H(this.stateSchema,{target:"openApi3"})}catch{o=this.stateSchema}return{nodes:e,edges:s,nodeConfigs:t,stateSchema:o}}_inferConditionalTargets(e){const t=e.toString(),s=new Set,o=/return\s+['"]([^'"]+)['"]/g;let n;for(;(n=o.exec(t))!==null;)s.add(n[1]);return[...s]}_flattenJsonSchemaToVariables(e,t=""){let s=e;if(e.$ref&&e.definitions){const o=e.$ref.replace("#/definitions/","");s=e.definitions[o]||e}return this._flattenSchema(s,t)}_flattenSchema(e,t=""){if(!e||typeof e!="object")return[];const s=[],o=e.properties||{},n=e.required||[];for(const[r,c]of Object.entries(o)){const p=t?`${t}.${r}`:r,i=!n.includes(r);if(s.push({path:p,type:c.type||"unknown",label:c.description||this._formatLabel(r),optional:i}),c.type==="object"&&c.properties){const u=this._flattenSchema(c,p);s.push(...u)}if(c.type==="array"&&c.items?.type==="object"&&c.items.properties){const u=this._flattenSchema(c.items,`${p}[]`);s.push(...u)}}return s}_formatLabel(e){return e.replace(/([A-Z])/g," $1").replace(/^./,t=>t.toUpperCase()).trim()}_summarizeNodeOutput(e,t){if(!t||typeof t!="object")return[];const s=[];t.success!==void 0&&s.push(`Result: ${t.success?"passed":"failed"}`);for(const[o,n]of Object.entries(t))if(!(o==="success"||o==="raw"||o==="nextNode")){if(typeof n=="string"&&n.length<=80)s.push(`${o}: ${n}`);else if(Array.isArray(n)){const r=n.length,c=n.filter(i=>i?.passed===!0).length;if(n.some(i=>i?.passed!==void 0)){const i=r-c;s.push(`${o}: ${c}/${r} passed${i?`, ${i} failed`:""}`)}else s.push(`${o}: ${r} items`)}if(s.length>=4)break}return s}async run(e,t={}){if(!this.entryPoint)throw new Error("No entry point set for graph");const s=t.cwd||process.cwd();ne({path:E(s,".env")});let o=t.config||{};if(!o||Object.keys(o).length===0)try{const l=E(s,".zibby.config.js");b(l)&&(o=(await import(l)).default||{})}catch{}process.env.EXECUTION_ID&&!o.agent?.strictMode&&(o.agent={...o.agent,strictMode:!0});let n=t.agentType;if(!n){const l=o?.agent;l?.provider?n=l.provider:l?.gemini?n="gemini":l?.claude?n="claude":l?.cursor?n="cursor":l?.codex?n="codex":n=process.env.AGENT_TYPE||"cursor"}const r=t.contextConfig||e?.config?.contextConfig||e?.config?.context||o?.context||{};if(this.stateSchema){const l=this.stateSchema.safeParse(t);if(!l.success){const m=l.error.issues.map(w=>`${w.path.join(".")}: ${w.message}`);throw console.error("\u274C Initial state validation failed:"),m.forEach(w=>console.error(` - ${w}`)),new Error(`State validation failed: ${m.join(", ")}`)}S.step("State validated against schema")}const c=pe(),p=t.sessionPath||c;p||fe();const{sessionPath:i,sessionTimestamp:u,sessionId:g}=me({cwd:s,config:o,traceFrom:"WorkflowGraph.run",initialState:{sessionPath:p,sessionTimestamp:t.sessionTimestamp}});S.step(`Session ${g}`);const v=await oe.loadContext(t.specPath||"",s,r);Object.keys(v).length>0&&S.step(`Context loaded: ${Object.keys(v).join(", ")}`);let P=t.outputPath;!P&&t.specPath&&(e?.calculateOutputPath?P=e.calculateOutputPath(t.specPath):console.warn(`\u26A0\uFE0F outputPath not resolved (specPath=${t.specPath})`));const d=new ee({...t,config:o,agentType:n,outputPath:P,sessionPath:i,sessionTimestamp:u,context:v,resolvedTools:this.resolvedToolsMap||{}}),C=new Map;try{await import("@zibby/skills")}catch{}const{getSkill:J}=await import("./skill-registry.js"),M=new Set;for(const[,l]of this.nodes)for(const m of l.config?.skills||[])M.add(m);for(const l of M){const m=J(l);if(typeof m?.middleware=="function")try{const w=await m.middleware();typeof w=="function"&&C.set(l,w)}catch{}}let a=this.entryPoint;const O=[];for(;a&&a!=="END";){const l=E(i,ae);if(b(l)){console.warn(`
|
|
5
|
+
\u{1F6D1} Studio stop requested \u2014 ending workflow.`);try{se(l)}catch{}if(e&&typeof e.cleanup=="function")try{await e.cleanup()}catch{}return S.step("Workflow stopped by Studio"),{success:!0,state:d.getAll(),executionLog:O,stoppedByStudio:!0}}const m=this.nodes.get(a);if(!m)throw new Error(`Node '${a}' not found in graph`);const w=JSON.stringify({sessionPath:i,sessionTimestamp:u,currentNode:a,createdAt:new Date().toISOString(),config:d.get("config")}),q=E(i,V);z(q,w,"utf-8");const D=d.get("config")?.paths?.output||x,K=E(s,D,V);W(E(s,D),{recursive:!0});try{z(K,w,"utf-8")}catch{}const Y=t.onPipelineProgress;if(typeof Y=="function")try{Y({cwd:s,sessionPath:i,sessionId:g,outputBase:d.get("config")?.paths?.output||x,currentNode:a})}catch{}const Q=(this.resolvedToolsMap||{})[a]||null;d.set("_currentNodeTools",Q);const X=d.get("nodeConfigs")||{};d.set("_currentNodeConfig",X[a]||{}),S.nodeStart(a);const R=Date.now(),T=this.nodePrompts.get(a);if(!this._invokeAgent){const _=await import("./agents/index.js");this._invokeAgent=_.invokeAgent}const j=this._invokeAgent,F={state:d,invokeAgent:async(_={},I={})=>{let h=I.prompt||"";if(T)try{h=re.compile(T,{noEscape:!0})(_)}catch(y){throw console.error(`\u274C Template rendering failed for node '${a}':`,y.message),new Error(`Template rendering failed: ${y.message}`,{cause:y})}else if(!h)throw new Error(`No prompt template configured for node '${a}' and no prompt provided in options`);const B={state:d.getAll(),images:I.images||[]},A={model:I.model||d.get("model"),workspace:d.get("workspace"),schema:I.schema,...I};return j(h,B,A)},_coreInvokeAgent:j,agent:e,nodeId:a,promptTemplate:T,getPromptTemplate:()=>T,...d.getAll()};try{const _=(m.config?.skills||[]).map($=>C.get($)).filter(Boolean),I=[...this.middleware,..._];let h;I.length>0?h=await this._composeMiddleware(I,a,async()=>m.execute(F,d),d.getAll(),d):h=await m.execute(F,d);const B=Date.now()-R;if(O.push({node:a,success:h.success,duration:B,timestamp:new Date().toISOString()}),!h.success){if(String(h.error||"").includes("Stopped from Zibby Studio")){if(S.step("Workflow stopped by Studio"),d.set("stoppedByStudio",!0),e&&typeof e.cleanup=="function")try{await e.cleanup()}catch{}return{success:!0,state:d.getAll(),executionLog:O,stoppedByStudio:!0}}d.append("errors",{node:a,error:h.error});const N=m.config?.retries||0,U=`${a}_retries`,k=d.getAll()[U]||0;if(k<N){S.stepInfo(`Retrying (attempt ${k+1}/${N})`),d.update({[U]:k+1,[`${a}_raw`]:h.raw});continue}throw S.nodeFailed(a,h.error,{duration:B}),new Error(`Node '${a}' failed after ${k} attempts: ${h.error}`)}d.update({[a]:h.output});const A=this._summarizeNodeOutput(a,h.output);S.nodeComplete(a,{duration:B,details:A});const y=this.edges.get(a);if(!y)a="END";else if(y.conditional){const $=d.getAll(),N=y.routes($);S.route(a,N),a=N}else a=y}catch(_){throw S.isInsideNode&&S.nodeFailed(a,_.message,{duration:Date.now()-R}),d.set("failed",!0),d.set("failedAt",a),_}}S.graphComplete();const Z={success:!0,state:d.getAll(),executionLog:O};return e&&typeof e.onComplete=="function"&&await e.onComplete(Z),Z}}export{Oe as WorkflowGraph,fe as clearInheritedSessionEnvForFreshRun,he as generateWorkflowSessionId,pe as readStudioPinnedSessionPathFromEnv,me as resolveWorkflowSession,le as shouldTrustInheritedSessionEnv,ue as syncProcessEnvToSession};
|
package/dist/package.json
CHANGED