qlogicagent 2.18.7 → 2.18.9

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.
Files changed (48) hide show
  1. package/README.md +382 -382
  2. package/dist/cli.js +1 -1
  3. package/dist/default-project-knowledge/INSTRUCTIONS.md +7 -7
  4. package/dist/default-project-knowledge/rules/project-workflow.md +6 -6
  5. package/dist/index.js +469 -489
  6. package/dist/pet-host.js +19 -0
  7. package/dist/runtime/infra/mcp-bridge-server.js +275 -275
  8. package/dist/skills/builtin/desktop-screenshot/SKILL.md +62 -62
  9. package/dist/skills/builtin/office-doc-reading/SKILL.md +19 -19
  10. package/dist/skills/mcp/astraclaw-native-mcp-server.js +7 -7
  11. package/dist/types/cli/core-tools/registry.d.ts +1 -2
  12. package/dist/types/cli/handlers/turn-handler.d.ts +1 -1
  13. package/dist/types/cli/handlers/workflow-compute-handler.d.ts +8 -0
  14. package/dist/types/cli/rpc-registry.d.ts +0 -13
  15. package/dist/types/cli/stdio-rpc-handler-hosts.d.ts +2 -5
  16. package/dist/types/cli/stdio-server.d.ts +0 -3
  17. package/dist/types/contracts/structured-planner.d.ts +2 -0
  18. package/dist/types/orchestration/solo-evaluator.d.ts +7 -2
  19. package/dist/types/pet-host.d.ts +9 -0
  20. package/dist/types/protocol/wire/acp-protocol.d.ts +7 -0
  21. package/dist/types/runtime/pet/pet-reaction-engine.d.ts +1 -1
  22. package/dist/types/skills/mcp/mcp-manager.d.ts +4 -0
  23. package/dist/types/workflow-host.d.ts +33 -0
  24. package/dist/vendor/hatch-pet/LICENSE.txt +201 -201
  25. package/dist/vendor/hatch-pet/NOTICE.md +25 -25
  26. package/dist/vendor/hatch-pet/references/animation-rows.md +29 -29
  27. package/dist/vendor/hatch-pet/references/codex-pet-contract.md +35 -35
  28. package/dist/vendor/hatch-pet/references/qa-rubric.md +66 -66
  29. package/dist/vendor/hatch-pet/scripts/compose_atlas.py +169 -169
  30. package/dist/vendor/hatch-pet/scripts/derive_running_left_from_running_right.py +150 -150
  31. package/dist/vendor/hatch-pet/scripts/extract_strip_frames.py +408 -408
  32. package/dist/vendor/hatch-pet/scripts/inspect_frames.py +256 -256
  33. package/dist/vendor/hatch-pet/scripts/make_contact_sheet.py +96 -96
  34. package/dist/vendor/hatch-pet/scripts/prepare_pet_run.py +834 -834
  35. package/dist/vendor/hatch-pet/scripts/render_animation_previews.py +78 -78
  36. package/dist/vendor/hatch-pet/scripts/validate_atlas.py +157 -157
  37. package/dist/workflow-host.js +13 -0
  38. package/package.json +16 -2
  39. package/dist/types/cli/core-tools/cron-tool-bootstrap.d.ts +0 -8
  40. package/dist/types/cli/core-tools/cron-workflow-service.d.ts +0 -7
  41. package/dist/types/cli/handlers/pet-handler.d.ts +0 -49
  42. package/dist/types/cli/handlers/workflow-handler.d.ts +0 -182
  43. package/dist/types/cli/tool-bootstrap-workflow-registration.d.ts +0 -7
  44. package/dist/types/cli/workflow-host-adapter.d.ts +0 -31
  45. package/dist/types/orchestration/workflow/workflow-service.d.ts +0 -14
  46. package/dist/types/skills/tools/cron-tool.d.ts +0 -96
  47. package/dist/types/skills/tools/petdex-create-tool.d.ts +0 -47
  48. package/dist/types/skills/tools/workflow-tool.d.ts +0 -45
@@ -0,0 +1,13 @@
1
+ import{join as N}from"node:path";import{mkdir as it,readdir as st,rm as at}from"node:fs/promises";import{readFile as zt,writeFile as Yt,mkdir as Qt,rename as Xt,unlink as Zt}from"node:fs/promises";import{dirname as en,join as tn}from"node:path";import{randomUUID as nn}from"node:crypto";async function rn(r,e){let t=en(r);await Qt(t,{recursive:!0});let n=tn(t,`.tmp-${nn()}`);try{await Yt(n,e,"utf-8");let o;for(let i=0;i<3;i++)try{await Xt(n,r);return}catch(s){if(o=s,s.code!=="EPERM")throw s;await new Promise(a=>setTimeout(a,50*(i+1)))}throw o}catch(o){throw await Zt(n).catch(()=>{}),o}}async function D(r){try{let e=await zt(r,"utf-8");return JSON.parse(e)}catch(e){if(e.code==="ENOENT")return;throw e}}async function C(r,e){await rn(r,JSON.stringify(e,null,2)+`
2
+ `)}import{resolve as bn}from"node:path";import{join as wn}from"node:path";import{homedir as an}from"node:os";import{join as y}from"node:path";import{existsSync as Mo}from"node:fs";import{createHash as on}from"node:crypto";import{resolve as sn}from"node:path";function Z(r){return on("sha256").update(sn(r).toLowerCase()).digest("hex").slice(0,16)}var Fe=".qlogicagent";function E(){return process.env.QLOGICAGENT_HOME||y(an(),Fe)}function ee(){let r=process.env.QLOGIC_LLMROUTER_USER_ID?.trim();if(r)return r;let e=process.env.QLOGIC_IMPLICIT_OWNER_ID?.trim();if(e)return e;let t=process.env.QLOGIC_DEVICE_ID?.trim();return t?`oc_${t}`:"oc_local"}function dn(r){let e=r.trim();if(!e)throw new Error("ownerUserId is required for profile-scoped storage");return encodeURIComponent(e).replace(/\./g,"%2E")}function _(r=ee()){return y(E(),"profiles",dn(r))}function Le(r=ee()){return y(_(r),"memory")}var un="projectData";function he(){return y(E(),un)}function te(r){if(!r)throw new Error("getProjectDataDirById: projectId is required");return y(he(),r)}function Ke(){return y(E(),"plugins")}function Je(){return y(E(),"skills")}function Ge(){return y(_(),"settings.json")}function Ve(){return y(E(),"plugin-cache")}function ze(){return y(E(),"mcp.json")}function Ye(){return y(E(),"marketplace.json")}function H(r){if(!r)throw new Error("getProjectAgentDir: cwd is required (must not fall back to process.cwd())");return y(r,Fe)}function Qe(r){return y(H(r),"plugins")}function Xe(r){return y(H(r),"settings.json")}function Ze(r){return y(H(r),"INSTRUCTIONS.md")}function et(r){return y(H(r),"rules")}import{existsSync as ln,mkdirSync as Uo,readFileSync as fn,writeFileSync as Fo,readdirSync as Lo,renameSync as Ko}from"node:fs";import{dirname as Go,join as gn,resolve as Vo}from"node:path";var cn=()=>{},we;function tt(){return cn()!==void 0}function nt(){if(tt()){if(!we)throw new Error("host project authority negotiated but snapshot is not hydrated");return{activeProjectId:we.activeProjectId,projects:we.projects.map(r=>({...r}))}}}function pn(){return gn(E(),"projects.json")}function mn(){let r=nt();if(r)return{activeProjectId:r.activeProjectId,projects:r.projects};let e=pn();if(!ln(e))return{activeProjectId:null,projects:[]};try{let t=fn(e,"utf-8");return JSON.parse(t)}catch{return{activeProjectId:null,projects:[]}}}function rt(r){return mn().projects.find(t=>t.id===r)??null}function yn(r){return rt(r)?r:Z(r)}function kn(r){return te(yn(r))}function ot(r){return wn(kn(r),"sessions")}var ye=class{constructor(e={}){this.options=e}options;lastActiveWorkdir=null;getActiveProjectRoot(){return this.options.getActiveProjectRoot?.()??process.cwd()}setActiveWorkdir(e){let t=bn(e);this.lastActiveWorkdir=t,this.options.setActiveWorkdir?.(t)}getActiveWorkdir(){return this.lastActiveWorkdir??this.getActiveProjectRoot()}resolveProjectDir(e){return this.options.resolveProjectDir?.(e)}resolveActiveOwnerUserId(){return ee()}getUserAgentHome(){return E()}getOwnerProfileDir(e){return _(e)}getProfileMemoryDir(e){return Le(e)}getUserSettingsPath(){return Ge()}getUserSkillsDir(){return Je()}getUserPluginsDir(){return Ke()}getUserMcpConfigPath(){return ze()}getUserPluginCacheDir(){return Ve()}getUserMarketplaceConfigPath(){return Ye()}getProjectAgentDir(e=this.getActiveProjectRoot()){return H(e)}getProjectSettingsPath(e=this.getActiveProjectRoot()){return Xe(e)}getProjectInstructionsPath(e=this.getActiveProjectRoot()){return Ze(e)}getProjectPluginsDir(e=this.getActiveProjectRoot()){return Qe(e)}getProjectRulesDir(e=this.getActiveProjectRoot()){return et(e)}getProjectSessionDataRoot(e=this.getActiveProjectRoot()){return ot(e)}},vn=new ye;function ne(){return vn}function j(r){return N(ne().getProjectAgentDir(r),"workflows")}function dt(r,e){return N(j(e),r,"workflow.json")}function ke(r,e){return N(j(e),r,"revisions")}var xn=20,be=class{constructor(e){this.cwd=e;if(!e)throw new Error("WorkflowStore requires a project cwd")}cwd;async save(e){if(!e.id)throw new Error("WorkflowRecord.id is required");let t=N(j(this.cwd),e.id);await it(t,{recursive:!0}),await C(dt(e.id,this.cwd),e),await this.snapshotRevision(e)}async snapshotRevision(e){try{let t=ke(e.id,this.cwd);await it(t,{recursive:!0}),await C(N(t,`${e.rev}.json`),e);let n=await this.revisionNumbers(e.id);for(let o of n.slice(xn))await at(N(t,`${o}.json`),{force:!0})}catch{}}async revisionNumbers(e){let t;try{t=await st(ke(e,this.cwd))}catch{return[]}return t.map(n=>Number(n.replace(/\.json$/,""))).filter(n=>Number.isInteger(n)&&n>0).sort((n,o)=>o-n)}async listRevisions(e){let t=[];for(let n of await this.revisionNumbers(e)){let o=await this.loadRevision(e,n);o&&t.push({rev:n,updatedAt:o.updatedAt,name:o.name,nodeCount:o.def.nodes.length})}return t}async loadRevision(e,t){return D(N(ke(e,this.cwd),`${t}.json`))}async load(e){return D(dt(e,this.cwd))}async require(e){let t=await this.load(e);if(!t)throw new Error(`Workflow "${e}" not found`);return t}async list(){let e;try{e=await st(j(this.cwd))}catch{return[]}let t=[];for(let n of e){let o=await this.load(n);o&&t.push(o)}return t}async listActive(){return(await this.list()).filter(e=>e.active)}async delete(e){await at(N(j(this.cwd),e),{recursive:!0,force:!0})}};var q=class{nodes=new Map;edges=[];constructor(e){for(let t of e){if(this.nodes.has(t.id))throw new Error(`Duplicate node ID: ${t.id}`);this.nodes.set(t.id,{id:t.id,kind:t.kind??"agent",params:t.params??{},status:"pending",outPorts:t.outPorts??["default"],joinPolicy:t.joinPolicy??"all",runIndex:0,maxIterations:t.maxIterations})}for(let t of e)for(let n of t.dependsOn??[]){if(!this.nodes.has(n))throw new Error(`Node "${t.id}" depends on unknown node "${n}"`);this.edges.push({from:n,to:t.id,fromPort:"default"})}this.validateDag()}getNode(e){return this.nodes.get(e)}getAllNodes(){return[...this.nodes.values()]}getReadyNodes(){let e=[];for(let t of this.nodes.values()){if(t.status!=="pending"||this.isBlockedByFailed(t.id))continue;let n=this.incomingForwardEdges(t.id);if(n.length===0){e.push(t);continue}t.joinPolicy==="any"?n.some(o=>this.edgeSatisfied(o))&&e.push(t):n.every(o=>this.edgeSatisfied(o))&&e.push(t)}return e}isFinished(){for(let e of this.nodes.values())if(e.status==="running"||e.status==="paused"||e.status==="pending"&&!this.isBlockedByFailed(e.id)&&!this.isSkippable(e.id))return!1;return!0}isAllCompleted(){return[...this.nodes.values()].every(e=>e.status==="completed"||e.status==="skipped")}getBlockedNodes(){return[...this.nodes.values()].filter(e=>e.status==="pending"&&this.isBlockedByFailed(e.id))}getProgress(){let e=0,t=0,n=0,o=0,i=0,s=0;for(let a of this.nodes.values())switch(a.status){case"completed":e++;break;case"running":t++;break;case"failed":n++;break;case"pending":o++;break;case"paused":i++;break;case"skipped":s++;break}return{total:this.nodes.size,completed:e,running:t,failed:n,pending:o,paused:i,skipped:s}}markRunning(e){let t=this.requireNode(e);if(t.status!=="pending")throw new Error(`Node "${e}" is ${t.status}, cannot start`);t.status="running",t.startedAt=Date.now()}markCompleted(e,t){let n=this.requireNode(e);if(n.status!=="running")throw new Error(`Node "${e}" is ${n.status}, cannot complete`);n.status="completed",n.output=t.output,n.completedAt=Date.now(),n.firedPorts=t.firedPorts??n.outPorts,t.inputTokens!==void 0&&(n.inputTokens=t.inputTokens),t.outputTokens!==void 0&&(n.outputTokens=t.outputTokens),t.changedFiles!==void 0&&(n.changedFiles=t.changedFiles),n.acceptanceUnverified=t.acceptanceUnverified,this.propagateSkips()}markFailed(e,t){let n=this.requireNode(e);n.status="failed",n.error=t,n.completedAt=Date.now(),this.propagateSkips()}markPaused(e){let t=this.requireNode(e);t.status==="running"&&(t.status="paused")}resumePaused(e){let t=this.requireNode(e);t.status==="paused"&&(t.status="pending")}markSkipped(e){let t=this.requireNode(e);if(t.status!=="pending")throw new Error(`Node "${e}" is ${t.status}, cannot skip`);t.status="skipped",t.firedPorts=[],this.propagateSkips()}pauseAll(){for(let e of this.nodes.values())e.status==="running"&&(e.status="paused")}resumeAll(){for(let e of this.nodes.values())e.status==="paused"&&(e.status="pending")}decideLoop(e,t){let n=this.requireNode(e);if(n.kind!=="loop")throw new Error(`Node "${e}" is not a loop controller`);if(!n.maxIterations||n.maxIterations<=0)throw new Error(`Loop "${e}" requires maxIterations > 0`);let o=n.iteration??0;t&&o<n.maxIterations?(n.iteration=o+1,n.firedPorts=["loop"],this.resetLoopScope(e)):(n.firedPorts=["done"],t&&(n.error=`loop_cap_reached:${n.maxIterations}`)),this.propagateSkips()}addNode(e){if(this.nodes.has(e.id))throw new Error(`Node "${e.id}" already exists`);for(let t of e.dependsOn??[])if(!this.nodes.has(t))throw new Error(`Node "${e.id}" depends on unknown node "${t}"`);this.nodes.set(e.id,{id:e.id,kind:e.kind??"agent",params:e.params??{},status:"pending",outPorts:e.outPorts??["default"],joinPolicy:e.joinPolicy??"all",runIndex:0,maxIterations:e.maxIterations});for(let t of e.dependsOn??[])this.edges.push({from:t,to:e.id,fromPort:"default"});try{this.validateDag()}catch(t){throw this.nodes.delete(e.id),this.edges=this.edges.filter(n=>n.to!==e.id||!e.dependsOn?.includes(n.from)),t}}addNodes(e){let t=[],n=[];try{for(let o of e){if(this.nodes.has(o.id))throw new Error(`Node "${o.id}" already exists`);for(let s of o.dependsOn??[])if(!this.nodes.has(s))throw new Error(`Unknown dep "${s}" for "${o.id}"`);this.nodes.set(o.id,{id:o.id,kind:o.kind??"agent",params:o.params??{},status:"pending",outPorts:o.outPorts??["default"],joinPolicy:o.joinPolicy??"all",runIndex:0,maxIterations:o.maxIterations}),t.push(o.id);let i=(o.dependsOn??[]).map(s=>({from:s,to:o.id,fromPort:"default"}));this.edges.push(...i),n.push(...i)}this.validateDag()}catch(o){for(let i of t)this.nodes.delete(i);throw this.edges=this.edges.filter(i=>!n.includes(i)),o}}removeNode(e){let t=this.requireNode(e);if(t.status==="running")throw new Error(`Cannot remove running node "${e}"`);if(t.status==="completed")throw new Error(`Cannot remove completed node "${e}"`);this.edges=this.edges.filter(n=>n.from!==e&&n.to!==e),this.nodes.delete(e)}retryNode(e,t){let n=this.requireNode(e);if(n.status!=="failed")throw new Error(`Node "${e}" is ${n.status}, only failed nodes can be retried`);n.status="pending",n.error=void 0,n.output=void 0,n.firedPorts=void 0,n.startedAt=void 0,n.completedAt=void 0,n.inputTokens=void 0,n.outputTokens=void 0,n.changedFiles=void 0,t&&Object.assign(n.params,t)}resetForReplay(e){if(!this.nodes.has(e))throw new Error(`Node "${e}" not found`);let t=new Set([e]),n=!0;for(;n;){n=!1;for(let o of this.nodes.values()){if(t.has(o.id))continue;this.incomingForwardEdges(o.id).map(s=>s.from).some(s=>t.has(s))&&(t.add(o.id),n=!0)}}for(let o of t){let i=this.nodes.get(o);i.status="pending",i.output=void 0,i.firedPorts=void 0,i.error=void 0,i.startedAt=void 0,i.completedAt=void 0,i.inputTokens=void 0,i.outputTokens=void 0,i.changedFiles=void 0}return[...t]}updateNodeParams(e,t){let n=this.requireNode(e);if(n.status!=="pending")throw new Error(`Node "${e}" is ${n.status}, can only update pending nodes`);Object.assign(n.params,t)}addEdge(e){let{from:t,to:n,fromPort:o="default",loopBack:i=!1}=e;if(!this.nodes.has(t))throw new Error(`Unknown source node "${t}"`);if(!this.nodes.has(n))throw new Error(`Unknown target node "${n}"`);let s=this.nodes.get(t);if(!i&&!s.outPorts.includes(o))throw new Error(`Node "${t}" has no outPort "${o}"`);if(!this.edges.find(u=>u.from===t&&u.to===n&&(u.fromPort??"default")===o))if(this.edges.push({from:t,to:n,fromPort:o,loopBack:i}),i){let u=this.nodes.get(n);if(!u.maxIterations||u.maxIterations<=0)throw this.edges.pop(),new Error(`LoopBack controller "${n}" requires maxIterations > 0`)}else try{this.validateDag()}catch(u){throw this.edges=this.edges.filter(l=>!(l.from===t&&l.to===n&&(l.fromPort??"default")===o)),u}}removeEdge(e,t,n){let o=n??"default";this.edges=this.edges.filter(i=>!(i.from===e&&i.to===t&&(i.fromPort??"default")===o))}serialize(){return[...this.nodes.values()].map(e=>{let t=this.incomingForwardEdges(e.id).map(n=>n.from);return{id:e.id,kind:e.kind,params:e.params,dependsOn:t,outPorts:e.outPorts,joinPolicy:e.joinPolicy,status:e.status,firedPorts:e.firedPorts,output:e.output,error:e.error,startedAt:e.startedAt,completedAt:e.completedAt,inputTokens:e.inputTokens,outputTokens:e.outputTokens,changedFiles:e.changedFiles,acceptanceUnverified:e.acceptanceUnverified,runIndex:e.runIndex,maxIterations:e.maxIterations,iteration:e.iteration}})}restore(e){for(let t of e){let n=this.nodes.get(t.id);n&&(n.status=t.status==="running"?"pending":t.status,n.output=t.output,n.error=t.error,n.firedPorts=t.firedPorts,n.startedAt=t.startedAt,n.completedAt=t.completedAt,n.inputTokens=t.inputTokens,n.outputTokens=t.outputTokens,n.changedFiles=t.changedFiles,n.acceptanceUnverified=t.acceptanceUnverified,n.runIndex=t.runIndex??0,n.iteration=t.iteration)}}getUpstreamOutputs(e){if(!this.nodes.get(e))return[];let n=this.incomingForwardEdges(e),o=new Set,i=[];for(let s of n){let a=s.from;if(o.has(a))continue;o.add(a);let u=this.nodes.get(a);if(u&&u.status==="completed"&&u.output!=null){let l=typeof u.output=="string"?u.output:JSON.stringify(u.output);l.trim()&&i.push({taskId:a,output:l})}}return i}edgeSatisfied(e){let t=this.nodes.get(e.from);if(!t||t.status!=="completed")return!1;let n=e.fromPort??"default";return(t.firedPorts??t.outPorts).includes(n)}edgeDead(e){let t=this.nodes.get(e.from);if(!t)return!1;if(t.status==="skipped")return!0;if(t.status==="completed"){if(t.kind==="loop"&&!(t.firedPorts??[]).includes("done"))return!1;let n=e.fromPort??"default";return!(t.firedPorts??t.outPorts).includes(n)}return!1}incomingForwardEdges(e){return this.edges.filter(t=>t.to===e&&!t.loopBack)}isBlockedByFailed(e){return this.incomingForwardEdges(e).some(t=>this.nodes.get(t.from)?.status==="failed")}isSkippable(e){let t=this.incomingForwardEdges(e);return t.length===0?!1:this.nodes.get(e).joinPolicy==="any"?t.every(o=>this.edgeDead(o)):t.some(o=>this.edgeDead(o))}propagateSkips(){let e=!0;for(;e;){e=!1;for(let t of this.nodes.values())t.status==="pending"&&this.isSkippable(t.id)&&(t.status="skipped",t.firedPorts=[],e=!0)}}resetLoopScope(e){let t=this.loopBodyNodes(e);for(let n of t){let o=this.nodes.get(n);o.status="pending",o.runIndex=(o.runIndex??0)+1,o.output=void 0,o.firedPorts=void 0,o.error=void 0,o.startedAt=void 0,o.completedAt=void 0,o.inputTokens=void 0,o.outputTokens=void 0,o.changedFiles=void 0}}loopBodyNodes(e){let t=new Set,n=(o,i)=>{for(let s of this.edges)s.from!==o||s.loopBack||i&&(s.fromPort??"default")!=="loop"||s.to!==e&&(t.has(s.to)||(t.add(s.to),n(s.to,!1)))};return n(e,!0),t}validateDag(){for(let i of this.edges){if(!this.nodes.has(i.from))throw new Error(`Edge references unknown source "${i.from}"`);if(!this.nodes.has(i.to))throw new Error(`Edge references unknown target "${i.to}"`)}let e=this.edges.filter(i=>!i.loopBack),t=new Set,n=new Set,o=i=>{if(n.has(i))throw new Error(`Cycle detected involving node "${i}"`);if(!t.has(i)){n.add(i);for(let s of e)s.from===i&&o(s.to);n.delete(i),t.add(i)}};for(let i of this.nodes.keys())o(i);for(let i of this.edges){if(!i.loopBack)continue;let s=this.nodes.get(i.to);if(!s?.maxIterations||s.maxIterations<=0)throw new Error(`LoopBack controller "${i.to}" must have maxIterations > 0`)}for(let i of this.nodes.values())if(i.maxIterations!==void 0&&i.maxIterations>1e3)throw new Error(`Loop "${i.id}" maxIterations ${i.maxIterations} exceeds the hard cap of 1000`)}requireNode(e){let t=this.nodes.get(e);if(!t)throw new Error(`Unknown node: "${e}"`);return t}};function $(r,e){return e?{json:r,binary:e}:{json:r}}function ut(r){let e={};for(let t of Object.keys(r).sort())e[t]=r[t].map(n=>({json:n.json,binary:n.binary?Object.fromEntries(Object.keys(n.binary).sort().map(o=>[o,n.binary[o].ref])):void 0}));return xe(e)}function xe(r){return JSON.stringify(ve(r))}function ve(r){if(Array.isArray(r))return r.map(ve);if(r&&typeof r=="object"){let e={};for(let t of Object.keys(r).sort())e[t]=ve(r[t]);return e}return r}var gt=new Set(["__proto__","prototype","constructor"]);function ct(r,e){let t=mt(r),n=new ie(t,r),o=n.parseExpression();return n.expectEnd(),B(o,e)}function se(r){try{let e=mt(r),t=new ie(e,r),n=t.parseExpression();return t.expectEnd(),G(n),null}catch(e){return e instanceof Error?e.message:String(e)}}var Pn=new Set(["input","json","node","now","vars","trigger"]),lt=new Set(["len","upper","lower","default","jsonpath","date"]);function G(r){switch(r.type){case"root":if(!Pn.has(r.name))throw new Error(`Unknown context root "$${r.name}" (allowed: $input $json $node $now $vars $trigger)`);return;case"lit":return;case"func":if(!lt.has(r.name))throw new Error(`Unknown function "${r.name}" (whitelist: ${[...lt].join(", ")})`);r.args.forEach(G);return;case"prop":G(r.target);return;case"index":if(G(r.target),typeof r.key!="number"&&typeof r.key!="string")throw new Error("index key must be a number or string literal");return;case"call":if(!(r.target.type==="root"&&r.target.name==="node"))throw new Error("Only $node(...) is callable in this position");r.args.forEach(G);return}}function I(r,e){let t=r.match(/^\s*\{\{([\s\S]*)\}\}\s*$/);return t?ct(t[1],e):r.includes("{{")?r.replace(/\{\{([\s\S]*?)\}\}/g,(n,o)=>{let i=ct(o,e);if(i==null)throw new Error(`Expression "{{${o.trim()}}}" resolved to ${i} in string interpolation`);return typeof i=="object"?JSON.stringify(i):String(i)}):r}function pt(r,e){return Ee(r,e)}function Ee(r,e){if(typeof r=="string")return I(r,e);if(Array.isArray(r))return r.map(t=>Ee(t,e));if(r&&typeof r=="object"){let t={};for(let[n,o]of Object.entries(r))t[n]=Ee(o,e);return t}return r}function mt(r){let e=[],t=0,n=i=>/[A-Za-z_]/.test(i),o=i=>/[A-Za-z0-9_]/.test(i);for(;t<r.length;){let i=r[t];if(/\s/.test(i)){t++;continue}if(i==="$"){t++;let s="";for(;t<r.length&&o(r[t]);)s+=r[t++];if(!s)throw new Error('Bare "$" is not a valid expression');e.push({t:"dollar",v:s});continue}if(n(i)){let s="";for(;t<r.length&&o(r[t]);)s+=r[t++];e.push({t:"id",v:s});continue}if(/[0-9]/.test(i)||i==="-"&&/[0-9]/.test(r[t+1]??"")){let s=r[t++];for(;t<r.length&&/[0-9.]/.test(r[t]);)s+=r[t++];e.push({t:"num",v:s});continue}if(i==='"'||i==="'"){let s=i;t++;let a="";for(;t<r.length&&r[t]!==s;)r[t]==="\\"&&t+1<r.length?(a+=r[t+1],t+=2):a+=r[t++];if(r[t]!==s)throw new Error("Unterminated string literal in expression");t++,e.push({t:"str",v:a});continue}if(".[](),".includes(i)){e.push({t:"punc",v:i}),t++;continue}throw new Error(`Unexpected character "${i}" in expression`)}return e}var ie=class{constructor(e,t){this.toks=e;this.src=t}toks;src;pos=0;parseExpression(){return this.parseAccessors(this.parseAtom())}peek(){return this.toks[this.pos]}next(){return this.toks[this.pos++]}expectEnd(){if(this.pos!==this.toks.length)throw new Error(`Unexpected trailing tokens in expression "${this.src.trim()}"`)}parseAtom(){let e=this.peek();if(!e)throw new Error("Empty expression");if(e.t==="dollar")return this.next(),{type:"root",name:e.v};if(e.t==="num")return this.next(),{type:"lit",value:Number(e.v)};if(e.t==="str")return this.next(),{type:"lit",value:e.v};if(e.t==="id"){if(e.v==="true")return this.next(),{type:"lit",value:!0};if(e.v==="false")return this.next(),{type:"lit",value:!1};if(e.v==="null")return this.next(),{type:"lit",value:null};if(this.next(),this.peek()?.t==="punc"&&this.peek().v==="("){let t=this.parseArgs();return{type:"func",name:e.v,args:t}}throw new Error(`Bare identifier "${e.v}" is not allowed (only whitelist function calls)`)}if(e.t==="punc"&&e.v==="("){this.next();let t=this.parseExpression();return this.expectPunc(")"),t}throw new Error(`Unexpected token "${e.v}" in expression`)}parseAccessors(e){let t=e;for(;;){let n=this.peek();if(!n||n.t!=="punc")break;if(n.v==="."){this.next();let o=this.next();if(!o||o.t!=="id"&&o.t!=="num")throw new Error('Expected property name after "."');t={type:"prop",target:t,key:o.v}}else if(n.v==="["){this.next();let o=this.next(),i;if(o.t==="num")i=Number(o.v);else if(o.t==="str")i=o.v;else throw new Error("Index must be a number or string literal");this.expectPunc("]"),t={type:"index",target:t,key:i}}else if(n.v==="("){let o=this.parseArgs();t={type:"call",target:t,args:o}}else break}return t}parseArgs(){this.expectPunc("(");let e=[];if(this.peek()?.t==="punc"&&this.peek().v===")")return this.next(),e;for(;;){e.push(this.parseExpression());let t=this.next();if(!t)throw new Error("Unterminated argument list");if(t.t==="punc"&&t.v===")")break;if(!(t.t==="punc"&&t.v===","))throw new Error('Expected "," or ")" in argument list')}return e}expectPunc(e){let t=this.next();if(!t||t.t!=="punc"||t.v!==e)throw new Error(`Expected "${e}" in expression`)}},ht=Symbol("nodeAccessor");function B(r,e){switch(r.type){case"lit":return r.value;case"root":return En(r.name,e);case"func":return Rn(r.name,r.args.map(t=>B(t,e)));case"prop":return ft(B(r.target,e),r.key);case"index":return ft(B(r.target,e),r.key);case"call":{if(B(r.target,e)===ht){let n=r.args.map(i=>B(i,e));if(n.length!==1||typeof n[0]!="string")throw new Error("$node(...) takes exactly one string argument");let o=e.nodes?.[n[0]];if(!o)throw new Error(`$node("${n[0]}") not found (not completed or unknown)`);return o}throw new Error("Only $node(...) is callable in this position")}}}function En(r,e){switch(r){case"input":return e.input??{};case"json":return e.json??{};case"vars":return e.vars??{};case"trigger":return e.trigger??{};case"now":return(e.now?e.now():new Date).toISOString();case"node":return ht;default:throw new Error(`Unknown context root "$${r}" (allowed: $input $json $node $now $vars $trigger)`)}}function ft(r,e){if(typeof e=="string"&&gt.has(e))throw new Error(`Access to "${e}" is forbidden`);if(r==null)throw new Error(`Cannot read "${e}" of ${r}`);if(typeof e=="number"){if(!Array.isArray(r))throw new Error(`Cannot index non-array with [${e}]`);return r[e]}return r[e]}function Rn(r,e){switch(r){case"len":{let t=e[0];if(typeof t=="string"||Array.isArray(t))return t.length;if(t&&typeof t=="object")return Object.keys(t).length;throw new Error(`len() expects string/array/object, got ${typeof t}`)}case"upper":return String(oe(e,0,"upper")).toUpperCase();case"lower":return String(oe(e,0,"lower")).toLowerCase();case"default":return e[0]===null||e[0]===void 0?e[1]:e[0];case"jsonpath":return Sn(e[0],String(oe(e,1,"jsonpath")));case"date":return jn(e);case"eq":return Re(e[0],e[1]);case"ne":return!Re(e[0],e[1]);case"gt":return re(e[0],e[1])>0;case"gte":return re(e[0],e[1])>=0;case"lt":return re(e[0],e[1])<0;case"lte":return re(e[0],e[1])<=0;case"not":return!Pe(oe(e,0,"not"));case"and":return e.every(Pe);case"or":return e.some(Pe);case"contains":return In(e[0],e[1]);default:throw new Error(`Unknown function "${r}()" (whitelist: len upper lower default jsonpath date eq ne gt gte lt lte not and or contains)`)}}function Pe(r){return!!r}function Re(r,e){return r===e?!0:typeof r!=typeof e?!1:r&&e&&typeof r=="object"?JSON.stringify(r)===JSON.stringify(e):!1}function re(r,e){if(typeof r=="number"&&typeof e=="number")return r-e;if(typeof r=="string"&&typeof e=="string")return r<e?-1:r>e?1:0;throw new Error(`Cannot compare ${typeof r} with ${typeof e}`)}function In(r,e){if(typeof r=="string")return r.includes(String(e));if(Array.isArray(r))return r.some(t=>Re(t,e));throw new Error("contains() expects string/array as first argument")}function oe(r,e,t){if(r.length<=e||r[e]===void 0)throw new Error(`${t}() missing required argument #${e+1}`);return r[e]}function Sn(r,e){let t=e.match(/[^.[\]]+/g)??[],n=r;for(let o of t){if(gt.has(o))throw new Error(`jsonpath segment "${o}" is forbidden`);if(n==null)return;let i=/^\d+$/.test(o)?Number(o):o;n=n[i]}return n}function jn(r){let e=r.length===0?new Date:new Date(r[0]);if(Number.isNaN(e.getTime()))throw new Error(`date() received an invalid date: ${String(r[0])}`);if(r.length<2)return e.toISOString();let t=String(r[1]),n=o=>String(o).padStart(2,"0");return t.replace(/YYYY/g,String(e.getUTCFullYear())).replace(/MM/g,n(e.getUTCMonth()+1)).replace(/DD/g,n(e.getUTCDate())).replace(/HH/g,n(e.getUTCHours())).replace(/mm/g,n(e.getUTCMinutes())).replace(/ss/g,n(e.getUTCSeconds()))}import{mkdirSync as An,writeFileSync as Nn}from"node:fs";import{dirname as $n,resolve as Dn}from"node:path";var wt={filter:["condition"],transform:["mapping"],script:["*"],n8nNode:["*"],agentBinding:["*"],modelBinding:["*"],toolBinding:["*"],integration:["*"],file:["*"],form:["*"],documentLoader:["*"],parser:["*"],retriever:["*"],textSplitter:["*"],vectorStore:["*"],extract:["*"],limit:["*"],split:["*"],respond:["*"]};function ae(r,e){return{json:e.json,vars:r.vars,trigger:r.trigger,now:r.now}}var Cn=(r,e)=>{let t=e.assignments?.assignments;if(Array.isArray(t)){let o={};for(let i of t){if(!i||typeof i!="object")continue;let s=i;typeof s.name!="string"||!s.name||(o[s.name]=Kn(s.value,s.type))}return{outputs:{default:[{json:o}]}}}return{outputs:{default:[{json:e.json&&typeof e.json=="object"&&!Array.isArray(e.json)?e.json:{value:e.json??e.value??null}}]}}},Tn=r=>({outputs:{default:r.default??[]}}),Wn=r=>{let e=[];for(let t of Object.keys(r))e.push(...r[t]);return{outputs:{default:e}}},On=(r,e)=>{let n=!!e.condition?"true":"false",o=r.default??[],i={true:[],false:[]};return i[n]=o,{outputs:i,firedPorts:[n]}},Mn=(r,e,t)=>({outputs:{default:[{json:t.trigger??(e.payload&&typeof e.payload=="object"&&!Array.isArray(e.payload)?e.payload:{})}]}}),_n=(r,e,t)=>{let n=e.condition;if(typeof n!="string"||!n.trim())throw new Error('filter node requires string param "condition" (per-item {{ }} expression over $json)');return{outputs:{default:(r.default??[]).filter(s=>!!I(n,ae(t,s)))}}},Hn=(r,e)=>{let t=Array.isArray(e.cases)?e.cases:[];if(t.length===0)throw new Error('switch node requires non-empty param "cases" ([{port, condition}])');let n=r.default??[],o=typeof e.defaultPort=="string"&&e.defaultPort?e.defaultPort:"default",i=o;for(let a of t){if(typeof a.port!="string"||!a.port)throw new Error('switch case requires string "port"');if(a.condition){i=a.port;break}}let s={};for(let a of t)typeof a.port=="string"&&(s[a.port]=[]);return s[o]=s[o]??[],s[i]=n,{outputs:s,firedPorts:[i]}},qn=r=>{let e=r.default??[];return{outputs:{default:[{json:{items:e.map(t=>t.json),count:e.length}}]}}},Bn=(r,e,t)=>{let n=e.mapping;if(typeof n!="object"||n===null||Array.isArray(n))throw new Error('transform node requires object param "mapping" ({outKey: "{{ expr }}"})');let o=Object.entries(n);if(o.length===0)throw new Error('transform node: "mapping" must have at least one key');return{outputs:{default:(r.default??[]).map(a=>{let u={};for(let[l,d]of o)u[l]=typeof d=="string"?I(d,ae(t,a)):d;return{json:u}})}}},Un=async(r,e,t)=>{if(e.until==="webhook"){let o=t.host;if(!o?.waitWebhook)throw new Error("wait(until=webhook) requires an ExecutorHost with waitWebhook");let i=typeof e.path=="string"&&e.path.trim()?e.path.trim():"";if(!i)throw new Error('wait(until=webhook) requires param "path" (the webhook path to wait for)');let s=typeof e.timeoutMs=="number"&&e.timeoutMs>0?e.timeoutMs:void 0,a=await o.waitWebhook({path:i.startsWith("/")?i:`/${i}`,nodeId:t.nodeId,workflowId:t.workflowId,timeoutMs:s,signal:t.signal});return{outputs:{default:[...r.default??[],{json:{webhook:a}}]}}}let n=Number(e.ms);if(!Number.isFinite(n)||n<1||n>36e5)throw new Error('wait node requires param "ms" in 1..3600000');return await new Promise((o,i)=>{let s=setTimeout(()=>{t.signal?.removeEventListener("abort",a),o()},n),a=()=>{clearTimeout(s),i(new Error("wait node canceled"))};t.signal?.addEventListener("abort",a,{once:!0})}),{outputs:{default:r.default??[]}}},Fn=(r,e,t)=>{let n=typeof e._n8nType=="string"?`(\u6765\u81EA n8n \u8282\u70B9\u300C${e._n8nType}\u300D)`:"";throw new Error(`\u8282\u70B9\u300C${t.nodeId}\u300D${n}\u5BFC\u5165\u65F6\u672A\u80FD\u81EA\u52A8\u8F6C\u6362,\u8BF7\u6253\u5F00\u8282\u70B9\u5B8C\u6210\u4EBA\u5DE5\u8FC1\u79FB\u540E\u518D\u8FD0\u884C`)},k=(r,e,t)=>{let n=typeof e._n8nType=="string"?` (${e._n8nType})`:"",i=(Array.isArray(e._n8nOutPorts)?e._n8nOutPorts:["default"]).filter(l=>typeof l=="string"&&l.length>0),s=r.default??[],a=s.length>0?s:[{json:{imported:!0,nodeId:t.nodeId,kind:t.kind,n8nType:e._n8nType}}],u={};for(let l of i.length>0?i:["default"])u[l]=a;if(u.default||(u.default=a),e._importMode==="n8n-strict-template")throw new Error(`Imported n8n node "${t.nodeId}"${n} requires a native executor or binding before live runs.`);return{outputs:u}},Ln=(r,e,t)=>{if((typeof e.operation=="string"?e.operation:"write")!=="write")throw new Error(`Imported file node "${t.nodeId}" supports operation "write" only for live runs`);let o=r.default?.[0];if(!o)throw new Error(`Imported file node "${t.nodeId}" requires an input item`);let i=Gn(e.fileName,o,t);if(!i)throw new Error(`Imported file node "${t.nodeId}" requires fileName`);let s=Dn(i);return An($n(s),{recursive:!0}),Nn(s,Jn(o)),{outputs:{default:[{json:{...o.json,fileName:s,written:!0}}]}}},yt={set:Cn,passthrough:Tn,merge:Wn,if:On,trigger:Mn,filter:_n,switch:Hn,aggregate:qn,transform:Bn,wait:Un,manual:Fn,script:k,n8nNode:k,agentBinding:k,modelBinding:k,toolBinding:k,integration:k,file:Ln,form:k,documentLoader:k,parser:k,retriever:k,textSplitter:k,vectorStore:k,extract:k,limit:k,split:k,respond:k};function Kn(r,e){if(e==="number"){let t=Number(r);return Number.isFinite(t)?t:r}if(e==="boolean"){if(typeof r=="boolean")return r;if(r==="true")return!0;if(r==="false")return!1}return r}function Jn(r){return typeof r.json.bodyBase64=="string"?Buffer.from(r.json.bodyBase64,"base64"):typeof r.json.body=="string"?r.json.body:r.json.body!==void 0?JSON.stringify(r.json.body,null,2):typeof r.json.data=="string"?r.json.data:JSON.stringify(r.json,null,2)}function Gn(r,e,t){if(typeof r!="string")return"";let n=r.startsWith("=")?r.slice(1):r,o=n.match(/^\{\{\s*([\s\S]*?)\s*\}\}$/);return o?String(Vn(o[1],e,t)??""):n.includes("{{")?String(I(n,ae(t,e))):n}function Vn(r,e,t){let n=r.match(/^\$json\.([A-Za-z_][A-Za-z0-9_]*)$/);if(n)return e.json[n[1]];let o=r.match(/^(["'])([\s\S]*)\1\s*\+\s*\$json\.([A-Za-z_][A-Za-z0-9_]*)$/);if(o)return`${zn(o[1],o[2])}${String(e.json[o[3]]??"")}`;if(r.startsWith("$json."))return I(`{{ ${r} }}`,ae(t,e));throw new Error(`Imported n8n expression is unsupported at node "${t.nodeId}": ${r}`)}function zn(r,e){if(r==='"')try{return JSON.parse(`"${e}"`)}catch{return e}return e.replace(/\\'/g,"'").replace(/\\\\/g,"\\")}var Yn=new Set(["agentBinding","modelBinding"]),V=class{executors=new Map;constructor(e=!0){if(e)for(let[t,n]of Object.entries(yt))this.executors.set(t,n)}register(e,t){if(this.executors.has(e))throw new Error(`NodeExecutor for kind "${e}" already registered`);this.executors.set(e,t)}override(e,t){if(!this.executors.has(e))throw new Error(`Cannot override unregistered kind "${e}"`);this.executors.set(e,t)}installHostExecutors(e){for(let[t,n]of Object.entries(e))this.executors.has(t)?Yn.has(t)&&this.override(t,n):this.register(t,n)}has(e){return this.executors.has(e)}get(e){let t=this.executors.get(e);if(!t)throw new Error(`No NodeExecutor registered for kind "${e}"`);return t}kinds(){return[...this.executors.keys()]}};function kt(r,e){let t=r??"any",n=e??"any";return t==="any"||n==="any"||t===n?!0:n==="binary"&&(t==="image"||t==="video"||t==="audio")}function de(r){return r!=="manual"&&r!=="intent"&&r!=="form"}function R(r,e){if(!r)throw new Error(`Node kind "${e}" requires a host (ExecutorHost) but none was injected. Provide one via WorkflowRuntimeOptions.host.`);return r}function A(r,e,t){let n=r[e];if(typeof n!="string"||n.length===0)throw new Error(`Node kind "${t}" requires string param "${e}"`);return n}function vt(r,e){let t=r[e];if(t==null)return{};if(typeof t!="object"||Array.isArray(t))throw new Error(`Param "${e}" must be an object`);return t}var Qn=async(r,e,t)=>({outputs:{default:await R(t.host,"agent").runAgent({agentId:typeof e.agentId=="string"?e.agentId:void 0,prompt:A(e,"prompt","agent"),input:r.default??[],signal:t.signal})}}),Xn=async(r,e,t)=>{let n=R(t.host,"agentBinding"),o=Pt(e,r.default??[],t,"agentBinding");return{outputs:{default:await n.runAgent({agentId:typeof e.agentId=="string"?e.agentId:void 0,prompt:o,input:r.default??[],signal:t.signal})}}},Zn=async(r,e,t)=>{let n=R(t.host,"modelBinding");if(!n.runModel)throw new Error('Node kind "modelBinding" requires an ExecutorHost with runModel');return{outputs:{default:await n.runModel({prompt:Pt(e,r.default??[],t,"modelBinding"),modelHint:gr(e),temperature:bt(e.temperature),maxTokens:bt(e.maxTokens),input:r.default??[],signal:t.signal})}}},er=async(r,e,t)=>({outputs:{default:await R(t.host,"tool").invokeTool({tool:A(e,"tool","tool"),args:vt(e,"args"),unattended:de(t.triggerKind??"manual"),input:r.default??[],signal:t.signal})}}),tr=async(r,e,t)=>{let n=R(t.host,"http"),o=typeof e.method=="string"?e.method:"GET",i=await n.httpRequest({method:o,url:A(e,"url","http"),headers:cr(e),body:ur(e),credentialId:typeof e.credentialId=="string"&&e.credentialId?e.credentialId:void 0,signal:t.signal}),s=r.default?.[0]?.json??{};return{outputs:{default:i.map(a=>({...a,json:{...s,...a.json}}))}}},nr=async(r,e,t)=>({outputs:{default:await R(t.host,"mcp").invokeMcp({server:A(e,"server","mcp"),tool:A(e,"tool","mcp"),args:vt(e,"args"),signal:t.signal})}}),rr=async(r,e,t)=>({outputs:{default:await R(t.host,"channel").sendChannel({channel:A(e,"channel","channel"),target:typeof e.target=="string"?e.target:void 0,payload:e.payload??r.default?.[0]?.json??{},input:r.default??[],signal:t.signal})}}),or=async(r,e,t)=>{let n=R(t.host,"skill"),o=e.args;return{outputs:{default:await n.invokeTool({tool:"skill_view",args:{name:A(e,"skill","skill"),...o!=null&&o!==""?{args:o}:{}},input:r.default??[],signal:t.signal})}}},ir=async(r,e,t)=>{let n=R(t.host,"memory");if(!n.memory)throw new Error('Node kind "memory" requires an ExecutorHost with a memory backend');let o=A(e,"op","memory");if(o!=="read"&&o!=="write"&&o!=="search")throw new Error(`memory node: op must be "read"|"write"|"search", got "${o}"`);if(e.scope==="global")throw new Error('memory node: scope "global" \u9700\u7ECF\u6743\u9650\u95F8\u95E8(\u672A\u5F00\u653E);\u9ED8\u8BA4\u9879\u76EE\u7EA7\u8BF7\u79FB\u9664 scope');return{outputs:{default:await n.memory({op:o,key:typeof e.key=="string"&&e.key?e.key:void 0,value:e.value!==void 0?e.value:r.default?.[0]?.json,query:typeof e.query=="string"?e.query:void 0,input:r.default??[],signal:t.signal})}}},sr=async(r,e,t)=>{let n=R(t.host,"subworkflow");if(!n.runSubworkflow)throw new Error('Node kind "subworkflow" requires an ExecutorHost with runSubworkflow');let o=e.payload&&typeof e.payload=="object"&&!Array.isArray(e.payload)?e.payload:r.default?.[0]?.json;return{outputs:{default:await n.runSubworkflow({workflowId:A(e,"workflowId","subworkflow"),callerWorkflowId:t.workflowId,projectId:typeof e.projectId=="string"&&e.projectId?e.projectId:void 0,payload:o,input:r.default??[],signal:t.signal})}}},ar=async(r,e,t)=>{let n=R(t.host,"approval");if(!n.approval)throw new Error('Node kind "approval" requires an ExecutorHost with approval');let o=await n.approval({nodeId:t.nodeId,workflowId:t.workflowId,prompt:typeof e.prompt=="string"&&e.prompt?e.prompt:void 0,timeoutMs:typeof e.timeoutMs=="number"&&e.timeoutMs>0?e.timeoutMs:void 0,timeoutAction:e.timeoutAction==="approve"||e.timeoutAction==="reject"||e.timeoutAction==="keepPending"?e.timeoutAction:void 0,input:r.default??[],signal:t.signal});if(!o.approved)throw new Error(`approval node "${t.nodeId}" denied${o.note?`: ${o.note}`:""} (${o.decidedAt})`);return{outputs:{default:[...r.default??[],{json:{approved:!0,decidedAt:o.decidedAt,...o.note?{note:o.note}:{}}}]}}},ue={agent:Qn,agentBinding:Xn,modelBinding:Zn,tool:er,http:tr,mcp:nr,channel:rr,skill:or,memory:ir,subworkflow:sr,approval:ar},dr=Object.keys(ue);function ur(r){if(r.body!==void 0)return r.body;if(r.sendBody!==!0)return;let e=xt(r.bodyParameters);if(e.length!==0)return Object.fromEntries(e)}function cr(r){let e={};if(r.headers&&typeof r.headers=="object"&&!Array.isArray(r.headers))for(let[t,n]of Object.entries(r.headers))typeof n=="string"&&(e[t]=n);for(let[t,n]of xt(r.headerParameters))e[t]=String(n);return Object.keys(e).length>0?e:void 0}function xt(r){let e=r&&typeof r=="object"&&!Array.isArray(r)?r.parameters:void 0;if(!Array.isArray(e))return[];let t=[];for(let n of e){if(!n||typeof n!="object")continue;let o=n;typeof o.name!="string"||!o.name||t.push([o.name,o.value??""])}return t}function Pt(r,e,t,n){let o=fr(r.prompt,r.text,r.message,r.input);if(!o)throw new Error(`Node kind "${n}" requires a prompt/text parameter`);return lr(o,{json:e[0]?.json??{},input:{default:e},vars:t.vars,trigger:t.trigger,now:t.now})}function lr(r,e){let t=r.startsWith("=")?r.slice(1):r;return t.includes("{{")?String(I(t,e)):t}function fr(...r){for(let e of r)if(typeof e=="string"&&e.trim())return e}function gr(r){let e=r.model??r.modelName;if(typeof e=="string"&&e)return e;if(e&&typeof e=="object"&&!Array.isArray(e)){let t=e.value??e.cachedResultName;if(typeof t=="string"&&t)return t}}function bt(r){let e=typeof r=="number"?r:typeof r=="string"?Number(r):NaN;return Number.isFinite(e)?e:void 0}var U=class extends Error{constructor(t){super(t?`Workflow paused at "${t}"`:"Workflow paused");this.atNodeId=t;this.name="WorkflowPauseSignal"}atNodeId},b=class extends Error{constructor(e="Workflow run canceled"){super(e),this.name="WorkflowRunCanceled"}},z=class{constructor(e,t={}){this.def=e;this.registry=t.registry??new V,this.gate=t.gate,this.now=t.now??(()=>new Date),this.trigger=t.trigger,this.triggerKind=t.triggerKind,this.log=t.log,this.host=t.host,this.abortController=t.signal?void 0:new AbortController,this.signal=t.signal??this.abortController.signal,this.checkpoint=t.checkpoint,this.preserveCheckpoint=t.preserveCheckpoint===!0,this.onNodeStatus=t.onNodeStatus,this.host&&this.registry.installHostExecutors(ue);for(let n of e.nodes)this.nodeDefs.set(n.id,n);for(let n of e.edges)n.loopBack&&this.loopBackOf.set(n.from,n.to)}def;registry;gate;now;trigger;triggerKind;log;host;abortController;signal;checkpoint;preserveCheckpoint;onNodeStatus;dag;nodeDefs=new Map;nodeOutputs=new Map;cache=new Map;loopBackOf=new Map;pauseRequested=!1;nodeStats={};statsSeq=0;checkpointLoaded=!1;setNodeParams(e,t){let n=this.nodeDefs.get(e);if(!n)throw new Error(`Unknown node "${e}"`);n.params={...n.params??{},...t}}pause(){this.pauseRequested=!0}cancel(e="Workflow run canceled"){let t=new b(e);this.abortController&&!this.abortController.signal.aborted&&this.abortController.abort(t)}extendBudget(e){if(!this.gate?.extend)throw new Error("WorkflowRuntime has no extensible budget gate to raise");this.gate.extend(e)}async run(){await this.loadCheckpoint(),this.throwIfCanceled(),this.dag=this.buildDag(),this.nodeOutputs.clear(),this.pauseRequested=!1;let e=new Set,t;try{let i=0;for(;!this.dag.isFinished();){if(++i>1e5)throw new Error("WorkflowRuntime did not converge");let s=this.dag.getReadyNodes();if(s.length===0)break;for(let a of s)await this.executeNode(a,e)}}catch(i){if(i instanceof U)t=i.atNodeId;else throw i}let n={};for(let[i,s]of this.nodeOutputs)n[i]=s;let o=t?"paused":this.dag.isAllCompleted()?"completed":"failed";return o==="completed"&&this.checkpoint&&(this.preserveCheckpoint?await this.persistCheckpoint():await this.checkpoint.clear()),{status:o,outputs:n,executed:e,progress:this.dag.getProgress(),pausedAt:t,nodeStats:{...this.nodeStats}}}async loadCheckpoint(){if(!this.checkpoint||this.checkpointLoaded)return;this.checkpointLoaded=!0;let e=await this.checkpoint.load();if(e)for(let t of e.entries)this.cache.set(t.key,t.result)}async persistCheckpoint(){if(!this.checkpoint)return;let e=[...this.cache.entries()].map(([t,n])=>({key:t,result:n}));await this.checkpoint.persist(e)}async executeNode(e,t){if(this.throwIfCanceled(),this.pauseRequested)throw new U(e.id);if(e.kind==="loop"){this.enterLoop(e);return}let n=this.collectInputs(e.id),o=this.buildExprContext(n),i=this.nodeDefs.get(e.id)?.params??{},s=wt[e.kind]??[],a=s.includes("*"),u=a?{}:s.length>0?Object.fromEntries(Object.entries(i).filter(([m])=>!s.includes(m))):i,l={...pt(u,o),...a?i:Object.fromEntries(s.filter(m=>m in i).map(m=>[m,i[m]]))},d=this.cacheKey(e.kind,l,n,e.runIndex),f=Date.now(),c=0,g=(m,O)=>{let K=Date.now();this.nodeStats[e.id]={seq:++this.statsSeq,startedAt:new Date(f).toISOString(),finishedAt:new Date(K).toISOString(),durationMs:K-f,attempts:c,cacheHit:O,status:m}},p=this.cache.get(d),h=p!==void 0,w=!1;if(p)this.dag.markRunning(e.id);else{this.gate?.check(e.id,e.kind),this.dag.markRunning(e.id),this.onNodeStatus?.(e.id,"running");let m=this.nodeDefs.get(e.id),O=Math.max(1,m?.retry?.maxTries??1),K=Math.max(0,m?.retry?.backoffMs??1e3),me=m?.timeoutMs,P;for(let S=0;S<O;S++){c++,this.throwIfCanceled();let M={nodeId:e.id,kind:e.kind,workflowId:this.def.id,triggerKind:this.triggerKind,runIndex:e.runIndex,vars:this.def.vars??{},trigger:this.trigger,now:this.now,log:this.log,host:this.host,signal:me!==void 0&&me>0?AbortSignal.any([this.signal,AbortSignal.timeout(me)]):this.signal};try{p=await this.registry.get(e.kind)(n,l,M),P=void 0;break}catch(J){if(this.isCanceled())throw this.canceledError(J);P=J;let Ue=S+1<O;this.log?.warn(`node "${e.id}" attempt ${S+1}/${O} failed: ${J instanceof Error?J.message:String(J)}`+(Ue?` \u2014 retrying in ${K*2**S}ms`:"")),Ue&&await this.cancellableDelay(K*2**S)}}if(P!==void 0){let S=m?.onError??"stop",M=P instanceof Error?P.message:String(P);if(S==="errorPort")this.onNodeStatus?.(e.id,"failed",M),p={outputs:{error:[{json:{error:M,nodeId:e.id,kind:e.kind,attempts:O}}]},firedPorts:["error"]},w=!0;else if(S==="continue")this.onNodeStatus?.(e.id,"failed",M),p={outputs:{},firedPorts:[]},w=!0;else throw this.onNodeStatus?.(e.id,"failed",M),g("failed",!1),P&&typeof P=="object"&&!P.nodeId&&(P.nodeId=e.id),P}this.throwIfCanceled(),w?t.add(e.id):(this.cache.set(d,p),t.add(e.id),await this.persistCheckpoint())}this.nodeOutputs.set(e.id,p.outputs),this.dag.markCompleted(e.id,{output:p.outputs,firedPorts:p.firedPorts}),w||this.onNodeStatus?.(e.id,"completed"),g(w?"failed":"completed",h);let x=this.loopBackOf.get(e.id);x&&this.decideLoopBack(x)}enterLoop(e){this.dag.markRunning(e.id);let t={loop:[{json:{iteration:e.iteration??0}}],done:[]};this.nodeOutputs.set(e.id,t),this.dag.markCompleted(e.id,{output:t,firedPorts:["loop"]}),this.onNodeStatus?.(e.id,"completed")}decideLoopBack(e){let t=this.evalLoopCondition(e);this.dag.decideLoop(e,t);let n=this.dag.getNode(e);this.surfaceLoopCap(n);let o=n.firedPorts??[];this.nodeOutputs.set(e,{loop:o.includes("loop")?[{json:{iteration:n.iteration??0}}]:[],done:o.includes("done")?[{json:{iteration:n.iteration??0}}]:[]})}surfaceLoopCap(e){if(!e.error?.startsWith("loop_cap_reached:")||this.nodeStats[e.id]?.warning)return;let t=`loop "${e.id}" hit its maxIterations cap (${e.maxIterations}) \u2014 forced exit via "done" while the loop condition still asked to continue`;this.log?.warn(t);let n=this.nodeStats[e.id],o=new Date().toISOString();this.nodeStats[e.id]=n?{...n,warning:t}:{seq:++this.statsSeq,startedAt:o,finishedAt:o,durationMs:0,attempts:0,cacheHit:!1,status:"completed",warning:t}}evalLoopCondition(e){let n=this.nodeDefs.get(e)?.params?.condition;if(n==null||n==="")return!0;let o=this.buildExprContext({});return!!(typeof n=="string"?I(n,o):n)}collectInputs(e){let t={};for(let n of this.def.edges){if(n.to!==e||n.loopBack)continue;let o=n.fromPort??"default",i=n.toPort??"default",s=this.nodeOutputs.get(n.from);if(!s)continue;let a=s[o];a&&(t[i]??=[]).push(...a)}return t}buildExprContext(e){let t={};for(let[n,o]of this.nodeOutputs)t[n]={output:o};return{input:e,json:e.default?.[0]?.json??{},nodes:t,vars:this.def.vars??{},trigger:this.trigger,now:this.now}}cacheKey(e,t,n,o){return xe([e,t,ut(n),o])}isCanceled(){return this.signal.aborted}canceledError(e){let t=this.signal.reason;return t instanceof b?t:t instanceof Error?new b(t.message):e instanceof b?e:e instanceof Error&&this.signal.aborted?new b(e.message):new b(t===void 0?"Workflow run canceled":String(t))}throwIfCanceled(){if(this.isCanceled())throw this.canceledError()}cancellableDelay(e){return e<=0?Promise.resolve():new Promise((t,n)=>{let o=setTimeout(()=>{this.signal.removeEventListener("abort",i),t()},e),i=()=>{clearTimeout(o),n(this.canceledError())};this.signal.addEventListener("abort",i,{once:!0})})}buildDag(){let e=this.def.nodes.map(n=>{let o=n.outPorts??pr(n.kind);return n.onError==="errorPort"&&!o.includes("error")&&(o=[...o,"error"]),{id:n.id,kind:n.kind,params:n.params??{},outPorts:o,joinPolicy:n.joinPolicy??"all",maxIterations:n.maxIterations}}),t=new q(e);for(let n of this.def.edges)n.loopBack||t.addEdge({from:n.from,to:n.to,fromPort:n.fromPort??"default"});for(let n of this.def.edges)n.loopBack&&t.addEdge({from:n.from,to:n.to,loopBack:!0});return t}};function pr(r){return r==="if"?["true","false"]:r==="loop"?["loop","done"]:["default"]}var mr=new Set(["agent","tool","http","mcp","channel","im"]);var Ie=class extends Error{constructor(t,n,o){super(`Permission denied: node "${t}" (kind "${n}") may not run under unattended trigger "${o}". Authorize it by adding "${n}" to allowUnattendedKinds.`);this.nodeId=t;this.kind=n;this.trigger=o;this.name="WorkflowPermissionDenied"}nodeId;kind;trigger},ce=class extends U{constructor(t,n,o){super(t);this.reason=n;this.limit=o;this.name="WorkflowBudgetExceeded",this.message=`Budget exceeded (${n} limit ${o}) before node "${t}"`}reason;limit},le=class{trigger;maxNodeExecutions;maxDurationMs;allow;now;executions=0;startedAt=-1;constructor(e){if(!Number.isInteger(e.maxNodeExecutions)||e.maxNodeExecutions<=0)throw new Error(`BudgetPermissionGate: maxNodeExecutions must be a positive integer, got ${e.maxNodeExecutions}`);if(e.maxDurationMs!==void 0&&!(e.maxDurationMs>0))throw new Error(`BudgetPermissionGate: maxDurationMs must be greater than 0 when provided, got ${e.maxDurationMs}`);this.trigger=e.trigger,this.maxNodeExecutions=e.maxNodeExecutions,this.maxDurationMs=e.maxDurationMs,this.allow=new Set(e.allowUnattendedKinds??[]),this.now=e.now??(()=>Date.now())}get unattended(){return de(this.trigger)}check(e,t){if(this.unattended&&mr.has(t)&&!this.allow.has(t))throw new Ie(e,t,this.trigger);if(this.startedAt<0&&(this.startedAt=this.now()),this.maxDurationMs!==void 0&&this.now()-this.startedAt>=this.maxDurationMs)throw new ce(e,"duration",this.maxDurationMs);if(this.executions>=this.maxNodeExecutions)throw new ce(e,"executions",this.maxNodeExecutions);this.executions++}extend(e){if(e.executions!==void 0){if(!Number.isInteger(e.executions)||e.executions<=0)throw new Error(`BudgetPermissionGate.extend: executions delta must be a positive integer, got ${e.executions}`);this.maxNodeExecutions+=e.executions}if(e.durationMs!==void 0){if(!(e.durationMs>0))throw new Error(`BudgetPermissionGate.extend: durationMs delta must be greater than 0, got ${e.durationMs}`);if(this.maxDurationMs===void 0)throw new Error("BudgetPermissionGate.extend: cannot extend duration on a gate with no duration cap");this.maxDurationMs+=e.durationMs}}};function It(r){switch(r.type){case"manual":return[];case"schedule":return br(r.cron);case"im-message":return Pr(r.channel,r.match);case"webhook":return Er(r.path);case"intent":return wr(r.phrases,r.aliases,r.surfaces);case"form":return kr(r.fields);default:return[`unknown trigger type: ${JSON.stringify(r)}`]}}var hr=new Set(["welcome","chat"]);function wr(r,e,t){let n=[];if(!Array.isArray(r)||r.length===0)n.push("intent.phrases must be a non-empty array of trigger phrases");else for(let o of r)(typeof o!="string"||o.trim()==="")&&n.push(`intent.phrases entries must be non-empty strings, got ${JSON.stringify(o)}`);if(e!==void 0)if(!Array.isArray(e))n.push("intent.aliases must be an array when present");else for(let o of e)(typeof o!="string"||o.trim()==="")&&n.push(`intent.aliases entries must be non-empty strings, got ${JSON.stringify(o)}`);if(t!==void 0)if(!Array.isArray(t)||t.length===0)n.push("intent.surfaces must be a non-empty array when present");else for(let o of t)(typeof o!="string"||!hr.has(o))&&n.push(`intent.surfaces entries must be "welcome"|"chat", got ${JSON.stringify(o)}`);return n}var yr=new Set(["text","number","select"]);function kr(r){let e=[];if(!Array.isArray(r)||r.length===0)return["form.fields must be a non-empty array"];let t=new Set;for(let n of r){if(typeof n?.key!="string"||!/^[\w-]+$/.test(n.key)){e.push(`form field key must be a [\\w-]+ string, got ${JSON.stringify(n?.key)}`);continue}t.has(n.key)&&e.push(`duplicate form field key "${n.key}"`),t.add(n.key),n.type!==void 0&&(typeof n.type!="string"||!yr.has(n.type))&&e.push(`form field "${n.key}": type must be text|number|select`),n.type==="select"&&(!Array.isArray(n.options)||n.options.length===0)&&e.push(`form field "${n.key}": select requires non-empty options`)}return e}var Et=["JAN","FEB","MAR","APR","MAY","JUN","JUL","AUG","SEP","OCT","NOV","DEC"],Rt=["SUN","MON","TUE","WED","THU","FRI","SAT"];function br(r){if(typeof r!="string"||r.trim()==="")return["schedule.cron must be a non-empty string"];let e=r.trim().split(/\s+/);if(e.length!==5&&e.length!==6)return[`schedule.cron must have 5 or 6 fields, got ${e.length}: "${r}"`];let n=e.length===6?[{label:"second",min:0,max:59},{label:"minute",min:0,max:59},{label:"hour",min:0,max:23},{label:"day-of-month",min:1,max:31},{label:"month",min:1,max:12,names:Et},{label:"day-of-week",min:0,max:7,names:Rt}]:[{label:"minute",min:0,max:59},{label:"hour",min:0,max:23},{label:"day-of-month",min:1,max:31},{label:"month",min:1,max:12,names:Et},{label:"day-of-week",min:0,max:7,names:Rt}],o=[];for(let i=0;i<n.length;i++){let s=vr(e[i],n[i]);s&&o.push(`schedule.cron ${s}`)}return o}function vr(r,e){for(let t of r.split(",")){let n=xr(t,e);if(n)return n}}function xr(r,e){if(r==="")return`${e.label} has an empty list element`;let t=r,n,o=r.indexOf("/");if(o!==-1&&(t=r.slice(0,o),n=r.slice(o+1),!/^\d+$/.test(n)||Number(n)<=0))return`${e.label} has an invalid step "/${n}"`;if(t==="*")return;let i=t.indexOf("-");if(i!==-1){let a=Se(t.slice(0,i),e),u=Se(t.slice(i+1),e);return a===void 0||u===void 0?`${e.label} has an invalid range "${t}"`:a>u?`${e.label} range "${t}" is descending`:void 0}if(t===""&&n!==void 0)return`${e.label} step "${r}" needs a base ("*" or a range)`;if(Se(t,e)===void 0)return`${e.label} value "${t}" is out of range ${e.min}-${e.max}`}function Se(r,e){let t;if(/^\d+$/.test(r))t=Number(r);else if(e.names){let n=e.names.indexOf(r.toUpperCase());if(n===-1)return;t=e.label==="month"?n+1:n}else return;if(!(t<e.min||t>e.max))return t}function Pr(r,e){let t=[];if((typeof r!="string"||r.trim()==="")&&t.push("im-message.channel must be a non-empty string"),e!==void 0)if(typeof e!="string")t.push("im-message.match must be a string regex");else try{new RegExp(e)}catch(n){t.push(`im-message.match is not a valid regex: ${n.message}`)}return t}function Er(r){return typeof r!="string"||r===""?["webhook.path must be a non-empty string"]:r.startsWith("/")?/\s/.test(r)?[`webhook.path must not contain whitespace: "${r}"`]:r.includes("..")?[`webhook.path must not contain "..": "${r}"`]:/^\/[A-Za-z0-9\-._~/]*$/.test(r)?[]:[`webhook.path contains illegal characters: "${r}"`]:[`webhook.path must start with "/": "${r}"`]}var v=class extends Error{constructor(t){super(`Patch rejected: ${t.join("; ")}`);this.errors=t;this.name="PatchError"}errors};function je(r,e){let t=[],n=Sr(r),o=new Map(n.def.nodes.map(l=>[l.id,l])),i=e.scope?new Set(e.scope):void 0,s=new Set,a=l=>!i||i.has(l)||s.has(l),u=[];for(let[l,d]of e.patch.entries()){let f=`op[${l}] ${d.op}`;switch(d.op){case"add_node":{d.node?.id?o.has(d.node.id)?t.push(`${f}: node "${d.node.id}" already exists`):(n.def.nodes.push(d.node),o.set(d.node.id,d.node),i&&s.add(d.node.id)):t.push(`${f}: node.id is required`);break}case"remove_node":{o.has(d.nodeId)?a(d.nodeId)?(n.def.nodes=n.def.nodes.filter(c=>c.id!==d.nodeId),o.delete(d.nodeId),n.def.edges=n.def.edges.filter(c=>c.from!==d.nodeId&&c.to!==d.nodeId)):t.push(`${f}: node "${d.nodeId}" is outside the edit scope`):t.push(`${f}: node "${d.nodeId}" not found`);break}case"update_params":{let c=o.get(d.nodeId);c?a(d.nodeId)?c.params=Rr(c.params,d.params):t.push(`${f}: node "${d.nodeId}" is outside the edit scope`):t.push(`${f}: node "${d.nodeId}" not found`);break}case"rename_node":{let c=o.get(d.nodeId);c?a(d.nodeId)?c.name=d.name:t.push(`${f}: node "${d.nodeId}" is outside the edit scope`):t.push(`${f}: node "${d.nodeId}" not found`);break}case"set_node_options":{let c=o.get(d.nodeId);if(!c){t.push(`${f}: node "${d.nodeId}" not found`);break}if(!a(d.nodeId)){t.push(`${f}: node "${d.nodeId}" is outside the edit scope`);break}d.retry!==void 0&&(d.retry===null?delete c.retry:!Number.isInteger(d.retry.maxTries)||d.retry.maxTries<1||d.retry.maxTries>10?t.push(`${f}: retry.maxTries must be an integer 1..10`):d.retry.backoffMs!==void 0&&(!Number.isFinite(d.retry.backoffMs)||d.retry.backoffMs<0)?t.push(`${f}: retry.backoffMs must be a non-negative number`):c.retry={maxTries:d.retry.maxTries,...d.retry.backoffMs!==void 0?{backoffMs:d.retry.backoffMs}:{}}),d.timeoutMs!==void 0&&(d.timeoutMs===null?delete c.timeoutMs:!Number.isFinite(d.timeoutMs)||d.timeoutMs<=0?t.push(`${f}: timeoutMs must be a positive number`):c.timeoutMs=d.timeoutMs),d.onError!==void 0&&(d.onError===null?delete c.onError:d.onError!=="stop"&&d.onError!=="continue"&&d.onError!=="errorPort"?t.push(`${f}: onError must be "stop"|"continue"|"errorPort"`):c.onError=d.onError);break}case"set_node_ui":{if(!d.positions||typeof d.positions!="object"){t.push(`${f}: positions is required`);break}for(let[c,g]of Object.entries(d.positions)){let p=o.get(c);if(!p){t.push(`${f}: node "${c}" not found`);continue}if(!a(c)){t.push(`${f}: node "${c}" is outside the edit scope`);continue}if(g===null){delete p.ui;continue}if(!Number.isFinite(g?.x)||!Number.isFinite(g?.y)){t.push(`${f}: position for "${c}" must be finite {x,y}`);continue}p.ui={x:g.x,y:g.y}}break}case"add_edge":{let c=d.edge;if(!c?.from||!c?.to){t.push(`${f}: edge.from and edge.to are required`);break}if(i&&!a(c.from)&&!a(c.to)){t.push(`${f}: edge ${c.from}\u2192${c.to} has no endpoint in the edit scope`);break}let g=c.fromPort??"default";if(n.def.edges.some(m=>m.from===c.from&&m.to===c.to&&(m.fromPort??"default")===g)){t.push(`${f}: \u8FDE\u7EBF\u5DF2\u5B58\u5728(${c.from} \u2192 ${c.to})`);break}let p=o.get(c.from),h=o.get(c.to),w=p?.outPortTypes?.[g],x=h?.inPorts?.find(m=>m.name===(c.toPort??"default"))?.type;if(!kt(w,x)){t.push(`${f}: \u7AEF\u53E3\u7C7B\u578B\u4E0D\u5339\u914D:\u300C${p?.name??c.from}\u300D\u8F93\u51FA ${w??"any"},\u300C${h?.name??c.to}\u300D\u9700\u8981 ${x??"any"} \u2014\u2014 \u63A5\u4E0D\u4E0A,\u8BF7\u6362\u4E2A\u76EE\u6807\u7AEF\u53E3`);break}n.def.edges.push(c);break}case"remove_edge":{let{from:c,to:g,fromPort:p}=d.edge;if(i&&!a(c)&&!a(g))t.push(`${f}: edge ${c}\u2192${g} has no endpoint in the edit scope`);else{let h=n.def.edges.length;n.def.edges=n.def.edges.filter(w=>!(w.from===c&&w.to===g&&(w.fromPort??"default")===(p??"default"))),n.def.edges.length===h&&t.push(`${f}: edge ${c}\u2192${g} not found`)}break}case"set_trigger":{if(i)t.push(`${f}: trigger is workflow-global and cannot be changed in a scoped edit`);else if(d.trigger){let c=It(d.trigger);if(c.length>0)for(let g of c)t.push(`${f}: ${g}`);else n.meta.trigger=d.trigger}else n.meta.trigger=d.trigger;break}case"set_meta":{i?t.push(`${f}: meta is workflow-global and cannot be changed in a scoped edit`):(d.meta.name!==void 0&&(n.meta.name=d.meta.name),d.meta.active!==void 0&&(n.meta.active=d.meta.active));break}default:t.push(`${f}: unknown op`)}t.length===0&&u.push(d)}if(t.length>0)throw new v(t);if(jt(n.def,t),St(n.def,t),t.length>0)throw new v(t);return{target:n,applied:u}}function Rr(r,e){let t={...r??{}};for(let[n,o]of Object.entries(e))o===null?delete t[n]:t[n]=o;return t}function Y(r){let e=[];return jt(r,e),St(r,e),e}function St(r,e){let t=(n,o,i)=>{if(typeof n=="string"){if(n.startsWith("="))return;for(let s of n.matchAll(/\{\{([\s\S]*?)\}\}/g)){let a=se(s[1].trim());a&&e.push(`\u8282\u70B9\u300C${o}\u300D\u53C2\u6570 ${i} \u7684\u8868\u8FBE\u5F0F\u300C{{ ${s[1].trim()} }}\u300D\u8D85\u51FA\u53D7\u9650\u8BED\u8A00:${a}`)}return}if(Array.isArray(n)){n.forEach((s,a)=>t(s,o,`${i}[${a}]`));return}if(n&&typeof n=="object")for(let[s,a]of Object.entries(n))t(a,o,i?`${i}.${s}`:s)};for(let n of r.nodes)n.params?._importMode!=="n8n-strict-template"&&n.params&&t(n.params,n.id,"")}function jt(r,e){try{let t=r.nodes.map(o=>{let i=o.outPorts??Ir(o.kind);return o.onError==="errorPort"&&!i.includes("error")&&(i=[...i,"error"]),{id:o.id,kind:o.kind,params:o.params??{},outPorts:i,joinPolicy:o.joinPolicy??"all",maxIterations:o.maxIterations}}),n=new q(t);for(let o of r.edges)o.loopBack||n.addEdge({from:o.from,to:o.to,fromPort:o.fromPort??"default"});for(let o of r.edges)o.loopBack&&n.addEdge({from:o.from,to:o.to,loopBack:!0})}catch(t){e.push(`graph invalid: ${t.message}`)}}function Ir(r){return r==="if"?["true","false"]:r==="loop"?["loop","done"]:["default"]}function Sr(r){return{def:{...r.def,nodes:r.def.nodes.map(e=>({...e,params:e.params?{...e.params}:void 0})),edges:r.def.edges.map(e=>({...e})),vars:r.def.vars?{...r.def.vars}:void 0},meta:{...r.meta}}}function Ae(r,e={}){let t=e.maxNodes??50,n=e.maxValueLen??60,o=`Workflow ${JSON.stringify(r.name)} (rev ${r.rev}, trigger: ${jr(r.trigger)}, ${r.active?"active":"inactive"})`,i=r.def.nodes,a=i.slice(0,t).map(f=>" "+Ar(f,n)),u=i.length===0?"nodes: (none)":["nodes:",...a].join(`
3
+ `),l=i.length>t?`
4
+ \u2026 ${i.length-t} more node(s); call workflow.get for the full definition`:"",d=Dr(r.def.edges);return`${o}
5
+ ${u}${l}
6
+ ${d}`}function jr(r){if(!r)return"none";switch(r.type){case"manual":return"manual";case"schedule":return`schedule ${JSON.stringify(r.cron)}`;case"im-message":return r.match?`im-message ${r.channel} match=${JSON.stringify(r.match)}`:`im-message ${r.channel}`;case"webhook":return`webhook ${r.path}`;case"intent":return`intent ${r.phrases.map(e=>JSON.stringify(e)).join(" / ")}${r.semantic?" +semantic":""}`;case"form":return`form [${r.fields.map(e=>e.key).join(", ")}]`}}function Ar(r,e){let t=r.name?` "${r.name}"`:"",n=Nr(r.params,e),o=(r.outPorts??Cr(r.kind)).join(","),i=[`${r.id} [${r.kind}]${t}`];return n&&i.push(n),i.push(`out: ${o}`),i.join(" ")}function Nr(r,e){if(!r)return"";let t=Object.keys(r).sort();return t.length===0?"":t.map(n=>`${n}=${$r(r[n],e)}`).join(" ")}function $r(r,e){let t;return typeof r=="string"?t=r.includes("{{")?r:JSON.stringify(r):t=JSON.stringify(r),t.length>e&&(t=t.slice(0,e-1)+"\u2026"),t}function Dr(r){return r.length===0?"edges: (none)":`edges:
7
+ ${r.map(t=>{let n=t.fromPort??"default",o=t.toPort??"default",i=t.loopBack?" (loopBack)":"";return`${t.from}.${n}\u2192${t.to}.${o}${i}`}).join(" ; ")}`}function Cr(r){return r==="if"?["true","false"]:r==="loop"?["loop","done"]:["default"]}function Tr(r){let e=[],t=r;return t=t.replace(/\$node\[\s*(['"])([^'"\]]+)\1\s*\]\.json/g,'$node("$2").output.default[0].json'),t=t.replace(/\$\(\s*(['"])([^'")]+)\1\s*\)(?:\.item|\.first\(\))?\.json/g,'$node("$2").output.default[0].json'),t=t.replace(/\$items\(\s*(['"])([^'")]+)\1\s*\)\[(\d+)\]\.json/g,'$node("$2").output.default[$3].json'),t=t.replace(/\$input(?:\.item|\.first\(\))\.json/g,"$json"),/\$now\b/.test(t)&&e.push("$now:n8n \u4E3A Luxon DateTime,\u6B64\u5904\u4E3A Date(\u683C\u5F0F\u5316\u51FD\u6570\u7528 date(...))"),{body:t,notes:e}}function Wr(r){if(!r.startsWith("="))return null;let e=r.slice(1);if(!e.includes("{{"))return{ok:!0,converted:e,notes:[]};let t=[],n=null,o=e.replace(/\{\{([\s\S]*?)\}\}/g,(i,s)=>{if(n)return i;let{body:a,notes:u}=Tr(s.trim()),l=se(a);return l?(n=`\u8868\u8FBE\u5F0F\u300C{{ ${s.trim()} }}\u300D\u8D85\u51FA\u53D7\u9650\u8BED\u8A00(${l})`,i):(t.push(...u),`{{ ${a} }}`)});return n?{ok:!1,reason:n}:{ok:!0,converted:o,notes:t}}function At(r,e,t=""){let n=(o,i)=>{if(typeof o=="string"){let s=Wr(o);return s===null?o:s.ok?(e.converted++,e.notes.push(...s.notes),s.converted):(e.manual.push({path:i,raw:o,reason:s.reason}),o)}return Array.isArray(o)?o.map((s,a)=>n(s,`${i}[${a}]`)):o&&typeof o=="object"?Object.fromEntries(Object.entries(o).map(([s,a])=>[s,n(a,i?`${i}.${s}`:s)])):o};return n(r,t)}var Nt={"@n8n/n8n-nodes-langchain.agent":"agentBinding","@n8n/n8n-nodes-langchain.chainLlm":"agentBinding","@n8n/n8n-nodes-langchain.chainRetrievalQa":"agentBinding","@n8n/n8n-nodes-langchain.chainSummarization":"agentBinding","@n8n/n8n-nodes-langchain.chatTrigger":"trigger","@n8n/n8n-nodes-langchain.documentDefaultDataLoader":"documentLoader","@n8n/n8n-nodes-langchain.embeddingsOpenAi":"modelBinding","@n8n/n8n-nodes-langchain.informationExtractor":"agentBinding","@n8n/n8n-nodes-langchain.lmChatGoogleGemini":"modelBinding","@n8n/n8n-nodes-langchain.lmChatOpenAi":"modelBinding","@n8n/n8n-nodes-langchain.lmChatOpenRouter":"modelBinding","@n8n/n8n-nodes-langchain.lmOpenAi":"modelBinding","@n8n/n8n-nodes-langchain.memoryBufferWindow":"memory","@n8n/n8n-nodes-langchain.openAi":"modelBinding","@n8n/n8n-nodes-langchain.outputParserStructured":"parser","@n8n/n8n-nodes-langchain.retrieverVectorStore":"retriever","@n8n/n8n-nodes-langchain.textSplitterRecursiveCharacterTextSplitter":"textSplitter","@n8n/n8n-nodes-langchain.textSplitterTokenSplitter":"textSplitter","@n8n/n8n-nodes-langchain.toolCode":"script","@n8n/n8n-nodes-langchain.toolSerpApi":"toolBinding","@n8n/n8n-nodes-langchain.toolVectorStore":"toolBinding","@n8n/n8n-nodes-langchain.toolWorkflow":"subworkflow","@n8n/n8n-nodes-langchain.vectorStoreInMemory":"vectorStore","@n8n/n8n-nodes-langchain.vectorStoreQdrant":"vectorStore","n8n-nodes-base.aggregate":"aggregate","n8n-nodes-base.code":"script","n8n-nodes-base.convertToFile":"file","n8n-nodes-base.discord":"channel","n8n-nodes-base.executeWorkflow":"subworkflow","n8n-nodes-base.executeWorkflowTrigger":"trigger","n8n-nodes-base.extractFromFile":"file","n8n-nodes-base.facebookGraphApi":"channel","n8n-nodes-base.filter":"filter","n8n-nodes-base.form":"form","n8n-nodes-base.formTrigger":"trigger","n8n-nodes-base.gmail":"integration","n8n-nodes-base.gmailTool":"toolBinding","n8n-nodes-base.gmailTrigger":"trigger","n8n-nodes-base.googleDocs":"integration","n8n-nodes-base.googleDocsTool":"toolBinding","n8n-nodes-base.googleDrive":"integration","n8n-nodes-base.googleSheets":"integration","n8n-nodes-base.googleSheetsTrigger":"trigger","n8n-nodes-base.html":"transform","n8n-nodes-base.htmlExtract":"extract","n8n-nodes-base.httpRequest":"http","n8n-nodes-base.if":"if","n8n-nodes-base.limit":"limit","n8n-nodes-base.linkedIn":"channel","n8n-nodes-base.localFileTrigger":"trigger","n8n-nodes-base.manualTrigger":"trigger","n8n-nodes-base.merge":"merge","n8n-nodes-base.noOp":"passthrough","n8n-nodes-base.openAi":"modelBinding","n8n-nodes-base.postgres":"integration","n8n-nodes-base.postgresTool":"toolBinding","n8n-nodes-base.readBinaryFile":"file","n8n-nodes-base.readWriteFile":"file","n8n-nodes-base.respondToWebhook":"respond","n8n-nodes-base.s3":"integration","n8n-nodes-base.scheduleTrigger":"trigger","n8n-nodes-base.set":"set","n8n-nodes-base.splitInBatches":"split","n8n-nodes-base.splitOut":"split","n8n-nodes-base.spreadsheetFile":"file","n8n-nodes-base.supabaseTool":"toolBinding","n8n-nodes-base.switch":"switch","n8n-nodes-base.telegram":"channel","n8n-nodes-base.telegramTrigger":"trigger","n8n-nodes-base.twitter":"channel","n8n-nodes-base.wait":"wait","n8n-nodes-base.whatsApp":"channel","n8n-nodes-base.whatsAppTrigger":"trigger","n8n-nodes-base.writeBinaryFile":"file","n8n-nodes-base.writeFile":"file","n8n-nodes-base.youTube":"integration"},Or=new Set(["openAiApi","googlePalmApi","openRouterApi","mistralCloudApi","anthropicApi"]),Mr=new Set(["agentBinding"]);function $t(r){return Or.has(r)}function Dt(r){return Mr.has(r)}function Ct(r){return"workflow"}function Tt(r,e){let t=`${r} ${e}`.toLowerCase();return t.includes("gmail")?"gmail":t.includes("googlesheets")?"google-sheets":t.includes("googledrive")?"google-drive":t.includes("googledocs")?"google-docs":t.includes("telegram")?"telegram":t.includes("whatsapp")?"whatsapp":t.includes("youtube")?"youtube":t.includes("postgres")?"postgres":t.includes("supabase")?"supabase":t.includes("qdrant")?"qdrant":t.includes("s3")?"s3":t.includes("twitter")||t.includes("xapi")?"x":t.includes("facebook")?"facebook":t.includes("linkedin")?"linkedin":t.includes("discord")?"discord":t.includes("serp")?"serpapi":t.includes("firecrawl")?"firecrawl":t.includes("elevenlabs")?"elevenlabs":"custom"}var Wt={"n8n-nodes-base.set":"set","n8n-nodes-base.if":"if","n8n-nodes-base.merge":"merge","n8n-nodes-base.noOp":"passthrough","n8n-nodes-base.httpRequest":"http","n8n-nodes-base.manualTrigger":"trigger","n8n-nodes-base.scheduleTrigger":"trigger","n8n-nodes-base.cron":"trigger","n8n-nodes-base.webhook":"trigger","n8n-nodes-base.formTrigger":"trigger","n8n-nodes-base.switch":"switch","n8n-nodes-base.filter":"filter","n8n-nodes-base.wait":"wait","n8n-nodes-base.aggregate":"aggregate","n8n-nodes-base.executeWorkflow":"subworkflow"},_r={httpBasicAuth:"basic",httpBearerAuth:"bearer",httpHeaderAuth:"custom",httpQueryAuth:"custom",oAuth2Api:"oauth2",httpCustomAuth:"custom"},Hr=new Set(["n8n-nodes-base.stickyNote"]),qr=new Set(["n8n-nodes-base.code","n8n-nodes-base.function","n8n-nodes-base.functionItem","@n8n/n8n-nodes-langchain.toolCode"]),W=class extends Error{constructor(t){super(`n8n import rejected: ${t.join("; ")}`);this.errors=t;this.name="N8nImportError"}errors};function Ot(r,e,t={}){let n=Lr(r),o=t.strictTemplates===!0,i=[],s={status:"full",nodes:[],expressions:{converted:0,manual:[]},credentials:[],bindings:{models:[],agents:[],connections:[]},notes:[]},a=new Set,u=new Set,l=[];for(let[f,c]of n.nodes.entries()){if(typeof c?.name!="string"||c.name===""){i.push(`nodes[${f}] has a missing/empty name`);continue}if(a.has(c.name)){i.push(`duplicate node name "${c.name}"`);continue}if(a.add(c.name),typeof c.type!="string"||c.type===""){i.push(`node "${c.name}" has a missing/empty type`);continue}if(Hr.has(c.type)){u.add(c.name),s.nodes.push({id:c.name,n8nType:c.type,outcome:"skipped",notes:["annotation node skipped"]});continue}let g={id:c.name,n8nType:c.type,outcome:"converted",notes:[]};s.nodes.push(g);let p=Br(c.type,o);qr.has(c.type)&&!o?(p="manual",g.outcome="manual",g.notes.push("Code node contains imported script; default import keeps it as a fail-loud manual placeholder.")):p||(o?(p="n8nNode",g.outcome="unsupported",g.notes.push(`unsupported n8n node type "${c.type}" preserved as raw n8nNode`)):(p="manual",g.outcome="manual",g.notes.push(`unmapped n8n node type "${c.type}", please replace it manually`)));let h={converted:0,manual:[],notes:[]},w=At({...c.parameters??{}},h);s.expressions.converted+=h.converted;for(let m of h.manual)s.expressions.manual.push({nodeId:c.name,...m}),g.notes.push(`parameter ${m.path}: ${m.reason}`),g.outcome==="converted"&&(g.outcome="partial");for(let m of h.notes)s.notes.includes(m)||s.notes.push(m);Fr(c,p,s,o),o&&Dt(p)&&(s.bindings.agents.push({nodeId:c.name,fallback:!0,label:c.name}),g.outcome=g.outcome==="converted"?"partial":g.outcome,g.notes.push("agent capability will be resolved from the configured Agent panel, not from n8n credentials"));let x={id:c.name,kind:p,name:c.name,params:{...w,_n8nType:c.type}};o&&(x.params={...x.params,_importMode:"n8n-strict-template",_bindingKind:p}),Array.isArray(c.position)&&Number.isFinite(c.position[0])&&Number.isFinite(c.position[1])&&(x.ui={x:c.position[0],y:c.position[1]}),Ur(x,p,g,o),l.push(x)}let d=n.connections?Kr(n.connections,a,u,l,i,o):[];if(o&&Vr(d,l),Gr(l),l.length===0&&i.length===0&&i.push("workflow has no nodes"),i.length>0)throw new W(i);return s.status=s.nodes.some(f=>f.outcome==="manual"||f.outcome==="unsupported")?"manual":s.nodes.some(f=>f.outcome==="partial")||s.expressions.manual.length>0?"partial":"full",{name:typeof n.name=="string"&&n.name!==""?n.name:e,def:{id:e,nodes:l,edges:d},report:s}}function Br(r,e){return e?Nt[r]??Wt[r]??"n8nNode":Wt[r]}function Ur(r,e,t,n){let o=r.params;if(e==="if"){r.outPorts=["true","false"];return}if(e==="wait"){let i=typeof o.amount=="number"?o.amount:Number(o.amount),s=typeof o.unit=="string"?o.unit:"seconds",a=s==="hours"?36e5:s==="minutes"?6e4:1e3;Number.isFinite(i)&&i>0?o.ms=Math.min(36e5,Math.round(i*a)):n||(t.outcome=t.outcome==="manual"?"manual":"partial",t.notes.push("wait duration could not be parsed"));return}if(e==="subworkflow"){let i=typeof o.workflowId=="object"&&o.workflowId!==null?o.workflowId.value:o.workflowId;typeof i=="string"&&i?(o.workflowId=i,t.outcome=t.outcome==="converted"?"partial":t.outcome,t.notes.push("subworkflow target keeps the n8n workflow id and must be rebound to a local workflow")):n||(t.outcome=t.outcome==="manual"?"manual":"partial",t.notes.push("subworkflow target is missing"));return}(e==="switch"||e==="filter")&&!n&&(t.outcome=t.outcome==="manual"?"manual":"partial",t.notes.push(`${e} conditions preserve n8n params and may need review`))}function Fr(r,e,t,n){if(!(!r.credentials||typeof r.credentials!="object")){for(let[o,i]of Object.entries(r.credentials)){if(n&&$t(o)){t.bindings.models.push({nodeId:r.name,n8nCredentialType:o,modelPurpose:Ct(o),label:i?.name});continue}let s=Tt(r.type,o);n&&t.bindings.connections.push({nodeId:r.name,n8nCredentialType:o,connectionType:s,label:i?.name}),t.credentials.push({nodeId:r.name,n8nCredentialType:o,label:i?.name,suggestedVaultType:_r[o]??s??"custom"})}n&&e==="modelBinding"&&t.bindings.models.push({nodeId:r.name,n8nCredentialType:"model-registry",modelPurpose:"workflow"})}}function Lr(r){let e;if(typeof r=="string")try{e=JSON.parse(r)}catch(n){throw new W([`invalid JSON: ${n.message}`])}else e=r;if(!e||typeof e!="object")throw new W(["workflow must be a JSON object"]);let t=e;if(!Array.isArray(t.nodes))throw new W(["workflow.nodes must be an array"]);if(t.connections!==void 0&&(typeof t.connections!="object"||t.connections===null))throw new W(["workflow.connections must be an object"]);return{name:t.name,nodes:t.nodes,connections:t.connections??{}}}function Kr(r,e,t,n,o,i){let s=new Map(n.map(u=>[u.id,u.kind])),a=[];for(let u of Object.keys(r).sort()){if(t.has(u))continue;if(!e.has(u)){o.push(`connection source "${u}" is not a declared node`);continue}let l=r[u]??{};for(let d of Object.keys(l).sort()){let f=l[d];if(Array.isArray(f))for(let c=0;c<f.length;c++){let g=Jr(u,s.get(u),d,c,n,o,i),p=f[c];if(Array.isArray(p))for(let h of p){if(!h||typeof h.node!="string"){o.push(`connection from "${u}" has a malformed target`);continue}if(t.has(h.node))continue;if(!e.has(h.node)){o.push(`connection from "${u}" targets missing node "${h.node}"`);continue}let w={from:u,to:h.node};g!=="default"&&(w.fromPort=g),i&&typeof h.type=="string"&&h.type&&h.type!=="main"&&(w.toPort=h.type),a.push(w)}}}}return a}function Jr(r,e,t,n,o,i,s){return t!=="main"?T(o,r,n===0?t:`${t}_${n}`):e==="if"?n===0?"true":n===1?"false":(s||i.push(`if node "${r}" has an unsupported output index ${n}`),T(o,r,`out_${n}`)):e==="switch"?T(o,r,`case_${n}`):e==="filter"?n===0?T(o,r,"default"):(s||i.push(`filter node "${r}" has an unsupported discarded output`),T(o,r,n===1?"discarded":`out_${n}`)):n===0?T(o,r,"default"):(s||i.push(`node "${r}" has an unmodeled multi-output index ${n} (only single-output supported)`),T(o,r,`out_${n}`))}function T(r,e,t){let n=r.find(o=>o.id===e);return n&&(n.outPorts=n.outPorts??[],n.outPorts.includes(t)||n.outPorts.push(t)),t}function Gr(r){for(let e of r)e.outPorts&&e.outPorts.length>0&&(e.params={...e.params??{},_n8nOutPorts:e.outPorts})}function Vr(r,e){let t=[];for(let n of r)if(zr(t,n.to,n.from)){n.loopBack=!0;let o=e.find(i=>i.id===n.to);o&&(!o.maxIterations||o.maxIterations<=0)&&(o.maxIterations=100)}else t.push(n)}function zr(r,e,t){let n=[e],o=new Set;for(;n.length>0;){let i=n.pop();if(i===t)return!0;if(!o.has(i)){o.add(i);for(let s of r)s.from===i&&n.push(s.to)}}return!1}import{join as qt}from"node:path";import{mkdir as Yr}from"node:fs/promises";function fe(r,...e){let t=r.toLowerCase();return e.some(n=>t.includes(n.toLowerCase()))}function Mt(r,e){let t=(r??"").trim(),n=t.length>300?`${t.slice(0,300)}\u2026`:t||void 0;return fe(t,"credential","\u51ED\u8BC1","unauthorized","forbidden","401","403","auth")?{class:"user",message:"\u9274\u6743\u6CA1\u901A\u8FC7 \u2014\u2014 \u51ED\u8BC1\u7F3A\u5931\u6216\u5DF2\u5931\u6548\u3002",hint:"\u53BB\u51ED\u8BC1\u4FDD\u9669\u5E93\u914D\u7F6E\u540E\u91CD\u8DD1\u8FD9\u6B65\u3002",actions:["open_credentials","rerun_node","ai_fix"],detail:n}:fe(t,"\u4E0D\u5B58\u5728\u7684","\u5F15\u7528\u4E86\u4E0D\u5B58\u5728","no nodeexecutor","\u76EE\u5F55\u5916","not registered","unknown kind","\u672A\u80FD\u81EA\u52A8\u8F6C\u6362","\u4EBA\u5DE5\u8FC1\u79FB")?{class:"capability",message:"\u8FD9\u4E00\u6B65\u5F15\u7528\u4E86\u4E0D\u5B58\u5728\u7684\u80FD\u529B / \u5DE5\u5177\u3002",hint:"\u6362\u4E00\u4E2A\u771F\u5B9E\u5B58\u5728\u7684\u5DE5\u5177,\u6216\u8BA9 AI \u6539\u8FD9\u4E00\u6B65\u3002",actions:["ai_fix","swap_capability","rerun_node"],detail:n}:fe(t,"econnrefused","enotfound","etimedout","fetch failed","network","timeout","timed out","socket","getaddrinfo","invalid url","request failed","5xx","502","503","504")?{class:"network",message:"\u7F51\u7EDC\u8BF7\u6C42\u5931\u8D25 \u2014\u2014 \u5730\u5740\u4E0D\u901A\u3001\u8D85\u65F6\u6216\u5BF9\u65B9\u62A5\u9519\u3002",hint:"\u786E\u8BA4\u5730\u5740/\u7F51\u7EDC\u540E\u91CD\u8DD1;\u5730\u5740\u4E0D\u5BF9\u5C31\u8BA9 AI \u6539\u3002",actions:["rerun_node","ai_fix"],detail:n}:fe(t,"requires string param","requires param","requires object param","requires non-empty","\u7F3A\u5C11\u5FC5\u586B","required","must be","\u5FC5\u586B","in 1..","must have at least")?{class:"user",message:"\u8FD9\u4E00\u6B65\u7F3A\u5C11\u5FC5\u8981\u4FE1\u606F(\u5FC5\u586B\u53C2\u6570\u6CA1\u586B\u5168\u6216\u683C\u5F0F\u4E0D\u5BF9)\u3002",hint:"\u8BA9 AI \u8865\u5168,\u6216\u5728\u300C\u9AD8\u7EA7\u300D\u91CC\u624B\u52A8\u586B\u3002",actions:["ai_fix","rerun_node"],detail:n}:{class:"system",message:"\u8FD9\u4E00\u6B65\u6267\u884C\u51FA\u9519\u4E86\u3002",hint:"\u53EF\u4EE5\u91CD\u8DD1;\u82E5\u53CD\u590D\u5931\u8D25,\u8BA9 AI \u770B\u770B\u8FD9\u4E00\u6B65\u3002",actions:["rerun_node","ai_fix","rerun_all"],detail:n}}var Qr=20,_t=2e3;function Ht(r,e){return qt(j(r),e,"runs","history.json")}function $e(r){let e={};for(let[t,n]of Object.entries(r.outputs)){let o={};for(let[a,u]of Object.entries(n))o[a]=u.map(l=>l.json);let i=JSON.stringify(o);i.length>_t&&(i=`${i.slice(0,_t)}\u2026(truncated)`);let s=r.nodeStats?.[t];e[t]={executed:r.executed.has(t),preview:i,...s?{seq:s.seq,startedAt:s.startedAt,durationMs:s.durationMs,attempts:s.attempts,cacheHit:s.cacheHit,nodeStatus:s.status,...s.warning!==void 0?{warning:s.warning}:{}}:{}}}return e}var Ne=class{constructor(e){this.cwd=e;if(!e)throw new Error("WorkflowRunHistoryStore requires a project cwd")}cwd;async begin(e,t){let n=await this.read(e);n.unshift({...t,status:"running"}),await this.write(e,n.slice(0,Qr))}async finish(e,t,n){let o=await this.read(e),i=o.find(s=>s.runId===t);i&&(Object.assign(i,n),i.errorInfo=i.status==="failed"&&i.error?Mt(i.error):void 0,await this.write(e,o))}async list(e){return(await this.read(e)).map(({nodes:t,...n})=>n)}async get(e,t){return(await this.read(e)).find(n=>n.runId===t)}async read(e){try{let t=await D(Ht(this.cwd,e));return Array.isArray(t)?t:[]}catch{return[]}}async write(e,t){let n=Ht(this.cwd,e);await Yr(qt(j(this.cwd),e,"runs"),{recursive:!0}),await C(n,t)}};import{randomUUID as Xr}from"node:crypto";var De=class{constructor(e,t,n){this.store=e;this.runtimeFactory=t;this.runHistory=n}store;runtimeFactory;runHistory;slots=new Map;activeRuns=new Map;activeRunIdsByWorkflow=new Map;suppressedHistoryRunIds=new Set;async create(e){let t=Y(e.def);if(t.length>0)throw new v(t);let n=new Date().toISOString(),o={id:e.id,name:e.name,...e.owner?{owner:e.owner}:{},def:e.def,active:e.active??!1,concurrency:e.concurrency??"queue",rev:1,createdAt:n,updatedAt:n};return await this.store.save(o),o}async update(e,t){let o={...await this.store.require(e),...t,updatedAt:new Date().toISOString()};if(t.def!==void 0){let i=Y(o.def);if(i.length>0)throw new v(i)}return await this.store.save(o),o}async setActive(e,t){if(t){let n=await this.store.require(e);if(!n.publishedDef)throw new Error(`Workflow "${e}" has no published version \u2014 publish the draft before activating`);if(n.archived)throw new Error(`Workflow "${e}" is archived \u2014 restore it before activating`)}return this.update(e,{active:t})}async publish(e){let t=await this.store.require(e);if(t.archived)throw new Error(`Workflow "${e}" is archived \u2014 restore it before publishing`);let n=Y(t.def);if(n.length>0)throw new v(n);let o={...t,publishedDef:structuredClone(t.def),publishedRev:t.rev,updatedAt:new Date().toISOString()};return await this.store.save(o),o}async archive(e,t){let o={...await this.store.require(e),archived:t,...t?{active:!1}:{},updatedAt:new Date().toISOString()};return await this.store.save(o),o}async revertTo(e,t){let n=await this.store.require(e),o=await this.store.loadRevision(e,t);if(!o)throw new Error(`Workflow "${e}" has no stored revision ${t}`);let i=Y(o.def);if(i.length>0)throw new v(i);let s={...n,def:o.def,name:o.name,trigger:o.trigger??null,rev:n.rev+1,updatedAt:new Date().toISOString()};return await this.store.save(s),s}async importN8n(e,t,n={}){let{name:o,def:i,report:s}=Ot(t,e,{strictTemplates:!0});return{record:await this.create({id:e,name:o,def:i,concurrency:n.concurrency,owner:n.owner}),report:s}}async get(e){return this.store.require(e)}async describe(e,t){let n=await this.store.require(e);return Ae(n,t)}async patch(e,t){let n=await this.store.require(e),o=t.baseRev!==void 0&&t.baseRev<n.rev,i={def:n.def,meta:{name:n.name,active:n.active,trigger:n.trigger??null}},s,a;try{let d=je(i,t);s=d.applied,a=d.target}catch(d){if(o&&d instanceof v)return{ok:!1,conflict:{latestRev:n.rev}};throw d}if(a.meta.active===!0&&!n.active&&!n.publishedDef)throw new v([`workflow "${e}" has no published version \u2014 publish the draft before activating (set_meta.active)`]);let l={...n,def:a.def,name:a.meta.name??n.name,active:a.meta.active??n.active,trigger:a.meta.trigger??null,rev:n.rev+1,updatedAt:new Date().toISOString()};return await this.store.save(l),{ok:!0,rev:l.rev,applied:s}}async run(e,t,n={}){let o=await this.store.require(e);if(o.archived)throw new Error(`Workflow "${e}" is archived and cannot run`);let i=t?.type??"manual",s=i==="manual"||i==="intent"||i==="form",a;if(s)a=o.def;else{if(!o.publishedDef)throw new Error(`Workflow "${e}" has no published version \u2014 unattended trigger "${i}" refused`);a=o.publishedDef}let u={workflowId:e,runId:Xr(),type:i,payload:t?.payload,permissionScope:o.permissionScope,reuseCache:n.reuseCache===!0},l=this.slotFor(e),d=()=>{if(l.pending>0)switch(o.concurrency){case"skip":return Promise.resolve({workflowId:e,status:"skipped"});case"parallel":return this.startParallel(e,a,u);case"queue":return this.track(e,l,a,u,!0)}return this.track(e,l,a,u,!1)};return this.recordRun(e,u,d,n.recordHistory===!1)}async recordRun(e,t,n,o=!1){let i=Date.now();if(!this.runHistory||o)try{let a=await n();return{...a,runId:a.runId??t.runId}}catch(a){if(a instanceof b)return{workflowId:e,status:"canceled",runId:t.runId};throw a}await this.runHistory.begin(e,{runId:t.runId,triggerType:t.type,startedAt:new Date(i).toISOString()}).catch(()=>{});let s=a=>this.finishRunHistory(e,t.runId,i,a);try{let a=await n();return await s({status:a.status,...a.result?{nodes:$e(a.result)}:{}}),{...a,runId:t.runId}}catch(a){if(a instanceof b)return await s({status:"canceled",error:a.message}),{workflowId:e,status:"canceled",runId:t.runId};throw await s({status:"failed",error:a instanceof Error?a.message:String(a),failedNodeId:a?.nodeId}),a}}pause(e,t={}){this.requireActiveRun(e,t.runId).runtime.pause()}async resume(e,t={}){let n=this.requireActiveRun(e,t.runId);if(n.status!=="paused")throw new Error(`Workflow "${e}" run "${n.runId}" is not paused`);t.extraBudget&&n.runtime.extendBudget(t.extraBudget),n.status="running";let o=this.slotFor(e);o.pending++;let i=n.runtime.run().then(async s=>{let a={workflowId:e,runId:n.runId,status:s.status,result:s};return s.status==="paused"?n.status="paused":this.unregisterActiveRun(n.runId),await this.finishRunHistory(e,n.runId,n.startedAtMs,{status:a.status,nodes:$e(s)}),a}).catch(async s=>{if(this.unregisterActiveRun(n.runId),s instanceof b)return await this.finishRunHistory(e,n.runId,n.startedAtMs,{status:"canceled",error:s.message}),{workflowId:e,runId:n.runId,status:"canceled"};throw await this.finishRunHistory(e,n.runId,n.startedAtMs,{status:"failed",error:s instanceof Error?s.message:String(s),failedNodeId:s?.nodeId}),s}).finally(()=>{o.pending--});return o.tail=i.catch(()=>{}),i}async cancelRun(e,t={}){let n=this.requireActiveRun(e,t.runId),o=t.reason??`Workflow "${e}" run "${n.runId}" canceled`,i=new b(o);return n.runtime.cancel(o),n.abortController.signal.aborted||n.abortController.abort(i),this.unregisterActiveRun(n.runId),n.status==="paused"&&await this.finishRunHistory(e,n.runId,n.startedAtMs,{status:"canceled",error:o}),{workflowId:e,runId:n.runId,status:"canceled"}}async delete(e){let t=[...this.activeRunIdsByWorkflow.get(e)??[]];for(let n of t)this.suppressedHistoryRunIds.add(n),await this.cancelRun(e,{runId:n,reason:`Workflow "${e}" deleted`}).catch(()=>{});this.slots.delete(e),await this.store.delete(e)}async listActive(){return this.store.listActive()}slotFor(e){let t=this.slots.get(e);return t||(t={tail:Promise.resolve(),pending:0},this.slots.set(e,t)),t}registerActiveRun(e){this.activeRuns.set(e.runId,e);let t=this.activeRunIdsByWorkflow.get(e.workflowId);t||(t=new Set,this.activeRunIdsByWorkflow.set(e.workflowId,t)),t.add(e.runId)}unregisterActiveRun(e){let t=this.activeRuns.get(e);if(!t)return;this.activeRuns.delete(e);let n=this.activeRunIdsByWorkflow.get(t.workflowId);n&&(n.delete(e),n.size===0&&this.activeRunIdsByWorkflow.delete(t.workflowId))}requireActiveRun(e,t){if(t){let s=this.activeRuns.get(t);if(!s||s.workflowId!==e)throw new Error(`Workflow "${e}" has no active run "${t}"`);return s}let n=[...this.activeRunIdsByWorkflow.get(e)??[]],o=this.slots.get(e)?.latestRunId;if(o&&n.includes(o))return this.activeRuns.get(o);let i=n.at(-1);if(!i)throw new Error(`Workflow "${e}" has no active run`);return this.activeRuns.get(i)}async finishRunHistory(e,t,n,o){!this.runHistory||this.suppressedHistoryRunIds.has(t)||await this.runHistory.finish(e,t,{finishedAt:new Date().toISOString(),durationMs:Date.now()-n,...o}).catch(()=>{})}track(e,t,n,o,i){t.pending++;let s=()=>this.startTrackedRuntime(e,t,n,o),u=(i?t.tail.then(s):s()).finally(()=>{t.pending--});return t.tail=u.catch(()=>{}),u}async startParallel(e,t,n){return this.startTrackedRuntime(e,void 0,t,n)}async startTrackedRuntime(e,t,n,o){let i=new AbortController,s=this.runtimeFactory(n,{...o,signal:i.signal}),a={workflowId:e,runId:o.runId,startedAtMs:Date.now(),runtime:s,abortController:i,status:"running"};this.registerActiveRun(a),t&&(t.runtime=s,t.latestRunId=o.runId);try{let u=await s.run(),l={workflowId:e,runId:o.runId,status:u.status,result:u};return u.status==="paused"?a.status="paused":this.unregisterActiveRun(o.runId),l}catch(u){throw this.unregisterActiveRun(o.runId),u}}};function Zr(r){return(e,t)=>new z(e,{registry:r.registry,host:r.host,signal:t.signal,checkpoint:r.checkpoint?.(t.workflowId,t.reuseCache?"shared-cache":t.runId),preserveCheckpoint:t.reuseCache===!0,trigger:t.payload,triggerKind:t.type,now:r.now,onNodeStatus:r.emitNodeStatus?(n,o,i)=>r.emitNodeStatus(t.workflowId,n,o,i):void 0,gate:new le({trigger:t.type,maxNodeExecutions:r.budget.maxNodeExecutions,maxDurationMs:r.budget.maxDurationMs,allowUnattendedKinds:t.permissionScope?.allowUnattendedKinds??r.allowUnattendedKinds,now:r.now?()=>r.now().getTime():void 0})})}function eo(r){let e=r.content??[],t=a=>a.type==="text"&&typeof a.text=="string",n=e.filter(t).map(a=>a.text).join(`
8
+ `),o=e.filter(a=>!t(a));if(o.length===0)return n;let i=[...new Set(o.map(a=>a.type??"unknown"))].join(", "),s=`[${o.length} non-text block${o.length===1?"":"s"} omitted (${i})]`;return n?`${n}
9
+ ${s}`:s}function to(r){let e=r.findTool,t=r.fetchImpl??fetch;return{async runAgent(n){let o=await r.runAgent({agentId:n.agentId,prompt:n.prompt,signal:n.signal});return[$({text:o,output:o})]},async runModel(n){if(!r.resolveClientForPurpose)throw new Error("workflow model node: no configured model resolver is wired");let o=r.resolveClientForPurpose("textGeneration");if(!o)throw new Error("workflow model node: no textGeneration model is configured");let i="";for await(let s of o.transport.stream({model:o.model,messages:[{role:"user",content:n.prompt}],temperature:n.temperature,maxTokens:n.maxTokens,tools:[]},o.apiKey,n.signal))if(s.type==="delta"&&(i+=s.text),s.type==="error")throw new Error(s.message);return[$({text:i,output:i,model:o.model,...n.modelHint?{importedModel:n.modelHint}:{},choices:[{text:i}]})]},async invokeTool(n){let o=e(n.tool);if(!o)throw new Error(`workflow tool node: no qlogicagent tool named "${n.tool}"`);if(!o.execute)throw new Error(`workflow tool node: qlogicagent tool "${n.tool}" is not executable`);let i=n.args;if(r.workspaceCwd&&n.tool==="exec"){let u=i.workdir;(u==null||u==="")&&(i={...i,workdir:r.workspaceCwd})}n.unattended&&r.auditUnattendedTool&&r.auditUnattendedTool({...n,args:i});let s=`wf_${n.tool}_${Date.now().toString(36)}`,a=await o.execute(s,i,n.signal);return[$({result:eo(a),details:a.details??null})]},async httpRequest(n){let o=n.headers;if(n.credentialId){if(!r.resolveCredentialHeaders)throw new Error(`workflow http node: credentialId "${n.credentialId}" set but no credential vault is wired`);o={...o,...r.resolveCredentialHeaders(n.credentialId)}}let i=await t(n.url,{method:n.method||"GET",headers:o,body:n.body===void 0?void 0:typeof n.body=="string"?n.body:JSON.stringify(n.body),signal:n.signal}),s=i.headers.get("content-type")??"";if(s.includes("application/json")){let l=await i.text(),d=l;try{l.length>0&&(d=JSON.parse(l))}catch{d={__unparsedJson:l}}return[$({status:i.status,ok:i.ok,body:d})]}let a=Buffer.from(await i.arrayBuffer()),u=no(i.headers.get("content-disposition"));return[$({status:i.status,ok:i.ok,bodyBase64:a.toString("base64"),mimeType:s||"application/octet-stream",size:a.byteLength,...u?{filename:u}:{}})]},async invokeMcp(n){let o=await r.invokeMcp({server:n.server,tool:n.tool,args:n.args,signal:n.signal});return[$({result:o})]},async sendChannel(n){if(!r.sendChannel)throw new Error("workflow channel node: sendChannel requires the xiaozhiclaw gateway host, none injected (channel/IM nodes are unavailable in standalone qlogicagent \u2014 D12/D13).");let o=await r.sendChannel({channel:n.channel,target:n.target,payload:n.payload,signal:n.signal});return[$({sent:!0,result:o})]},async memory(n){if(!r.memory)throw new Error("workflow memory node: no memory backend injected (handler host wires the project memdir)");return r.memory(n)},async runSubworkflow(n){if(!r.runSubworkflow)throw new Error("workflow subworkflow node: no sub-run backend injected (handler host wires the controller)");return r.runSubworkflow(n)},async approval(n){if(!r.approval)throw new Error("workflow approval node: no approval backend injected (handler host wires the notify/await loop)");return r.approval(n)},async waitWebhook(n){if(!r.waitWebhook)throw new Error("workflow wait(until=webhook): no webhook-wait backend injected (handler host wires the wake registry)");return r.waitWebhook(n)}}}function no(r){if(!r)return;let e=r.match(/filename\*=UTF-8''([^;]+)/i);if(e)return decodeURIComponent(e[1].trim().replace(/^"|"$/g,""));let t=r.match(/filename=([^;]+)/i);return t?t[1].trim().replace(/^"|"$/g,""):void 0}var Bt=["JAN","FEB","MAR","APR","MAY","JUN","JUL","AUG","SEP","OCT","NOV","DEC"],Ut=["SUN","MON","TUE","WED","THU","FRI","SAT"];function ro(r){if(typeof r!="string"||r.trim()==="")throw new Error("cron must be a non-empty string");let e=r.trim().split(/\s+/);if(e.length!==5&&e.length!==6)throw new Error(`cron must have 5 or 6 fields, got ${e.length}: "${r}"`);let t=e.length===6,n=t?[{label:"second",min:0,max:59},{label:"minute",min:0,max:59},{label:"hour",min:0,max:23},{label:"day-of-month",min:1,max:31},{label:"month",min:1,max:12,names:Bt},{label:"day-of-week",min:0,max:7,names:Ut}]:[{label:"minute",min:0,max:59},{label:"hour",min:0,max:23},{label:"day-of-month",min:1,max:31},{label:"month",min:1,max:12,names:Bt},{label:"day-of-week",min:0,max:7,names:Ut}],o=n.map((u,l)=>({spec:u,raw:e[l],set:oo(e[l],n[l])})),i=u=>{let l=o.find(d=>d.spec.label===u);if(!l)throw new Error(`internal: missing cron field ${u}`);return l},s=i("day-of-week"),a=new Set;for(let u of s.set)a.add(u===7?0:u);return{hasSeconds:t,seconds:t?i("second").set:new Set([0]),minutes:i("minute").set,hours:i("hour").set,doms:i("day-of-month").set,months:i("month").set,dows:a,domRestricted:i("day-of-month").raw.trim()!=="*",dowRestricted:s.raw.trim()!=="*"}}function oo(r,e){let t=new Set;for(let n of r.split(","))io(n,e,t);if(t.size===0)throw new Error(`cron ${e.label} expanded to an empty set: "${r}"`);return t}function io(r,e,t){if(r==="")throw new Error(`cron ${e.label} has an empty list element`);let n=r,o=1,i=r.indexOf("/");if(i!==-1){n=r.slice(0,i);let u=r.slice(i+1);if(!/^\d+$/.test(u)||Number(u)<=0)throw new Error(`cron ${e.label} has an invalid step "/${u}"`);o=Number(u)}let s,a;if(n==="*")s=e.min,a=e.max;else{let u=n.indexOf("-");if(u!==-1){let l=Ce(n.slice(0,u),e),d=Ce(n.slice(u+1),e);if(l===void 0||d===void 0)throw new Error(`cron ${e.label} has an invalid range "${n}"`);if(l>d)throw new Error(`cron ${e.label} range "${n}" is descending`);s=l,a=d}else{let l=Ce(n,e);if(l===void 0)throw new Error(`cron ${e.label} value "${n}" is out of range ${e.min}-${e.max}`);s=l,a=o===1?l:e.max}}for(let u=s;u<=a;u+=o)t.add(u)}function Ce(r,e){let t;if(/^\d+$/.test(r))t=Number(r);else if(e.names){let n=e.names.indexOf(r.toUpperCase());if(n===-1)return;t=e.label==="month"?n+1:n}else return;if(!(t<e.min||t>e.max))return t}var so=5*366+32;function Te(r,e){let t=ro(r),n=new Date(e);t.hasSeconds?(n.setUTCMilliseconds(0),n.setUTCSeconds(n.getUTCSeconds()+1)):(n.setUTCSeconds(0,0),n.setUTCMinutes(n.getUTCMinutes()+1));for(let o=0;o<so;o++){if(!t.months.has(n.getUTCMonth()+1)){n.setUTCMonth(n.getUTCMonth()+1,1),n.setUTCHours(0,0,0,0);continue}if(!ao(t,n)){n.setUTCDate(n.getUTCDate()+1),n.setUTCHours(0,0,0,0);continue}if(!t.hours.has(n.getUTCHours())){n.setUTCHours(n.getUTCHours()+1,0,0,0);continue}if(!t.minutes.has(n.getUTCMinutes())){n.setUTCMinutes(n.getUTCMinutes()+1,0,0);continue}if(t.hasSeconds&&!t.seconds.has(n.getUTCSeconds())){n.setUTCSeconds(n.getUTCSeconds()+1,0);continue}return n.getTime()}throw new Error(`cron "${r}" has no matching time within ~5 years of ${new Date(e).toISOString()}`)}function ao(r,e){let t=r.doms.has(e.getUTCDate()),n=r.dows.has(e.getUTCDay());return r.domRestricted&&r.dowRestricted?t||n:r.domRestricted?t:r.dowRestricted?n:!0}var uo={now:()=>Date.now(),setTimer:(r,e)=>setTimeout(r,e),clearTimer:r=>clearTimeout(r)},Ft=2e9,We=class{controller;clock;onError;onRunStarted;onRunCompleted;onRunFailed;triggers=new Map;cronArms=new Map;lastFireAt=new Map;minTriggerIntervalMs;onTriggerDropped;started=!1;constructor(e){if(!e.controller)throw new Error("WorkflowScheduler requires a controller");if(typeof e.onError!="function")throw new Error("WorkflowScheduler requires an onError handler");if(this.controller=e.controller,this.clock=e.clock??uo,this.onError=e.onError,this.onRunStarted=e.onRunStarted,this.onRunCompleted=e.onRunCompleted,this.onRunFailed=e.onRunFailed,this.minTriggerIntervalMs=e.minTriggerIntervalMs??0,this.onTriggerDropped=e.onTriggerDropped,this.minTriggerIntervalMs>0&&!this.onTriggerDropped)throw new Error("WorkflowScheduler: minTriggerIntervalMs > 0 requires onTriggerDropped (drops must never be silent, \xA71.5)")}async start(){if(this.started)throw new Error("WorkflowScheduler already started");this.started=!0;let e=await this.controller.listActive();for(let t of e)this.registerTrigger(t.id,t.trigger??{type:"manual"})}stop(){for(let e of this.cronArms.values())this.clock.clearTimer(e.handle);this.cronArms.clear(),this.triggers.clear(),this.started=!1}async refresh(e){let t;try{t=await this.controller.get(e)}catch{this.unregister(e);return}if(!t.active){this.unregister(e);return}this.registerTrigger(e,t.trigger??{type:"manual"})}unregister(e){let t=this.cronArms.get(e);t&&(this.clock.clearTimer(t.handle),this.cronArms.delete(e)),this.triggers.delete(e)}registeredIds(){return[...this.triggers.keys()]}nextFireAt(e){return this.cronArms.get(e)?.fireAt}async onWebhook(e,t){let n=this.matchingIds(o=>o.type==="webhook"&&o.path===e).filter(o=>this.passesRateLimit(o,"webhook"));return Promise.all(n.map(o=>this.runWithLifecycle(o,{type:"webhook",payload:t})))}async onImMessage(e,t,n){let o=this.matchingIds(s=>s.type==="im-message"&&s.channel===e&&co(s.match,t)).filter(s=>this.passesRateLimit(s,"im-message")),i={...n,channel:e,text:t};return Promise.all(o.map(s=>this.runWithLifecycle(s,{type:"im-message",payload:i})))}async triggerManual(e,t){return this.runWithLifecycle(e,{type:"manual",payload:t})}matchingIds(e){let t=[];for(let[n,o]of this.triggers)e(o)&&t.push(n);return t}registerTrigger(e,t){if(this.unregister(e),this.triggers.set(e,t),t.type==="schedule"){let n=Te(t.cron,this.clock.now());this.armCron(e,t.cron,n)}}armCron(e,t,n){let o=Math.max(0,n-this.clock.now()),i={cron:t,fireAt:n,handle:void 0};o>Ft?i.handle=this.clock.setTimer(()=>{this.cronArms.get(e)===i&&this.armCron(e,t,n)},Ft):i.handle=this.clock.setTimer(()=>this.fireCron(e,i),o),this.cronArms.set(e,i)}fireCron(e,t){if(this.cronArms.get(e)!==t)return;let n;try{n=Te(t.cron,t.fireAt)}catch(o){this.cronArms.delete(e),this.onError(o,e);return}this.armCron(e,t.cron,n),this.passesRateLimit(e,"schedule")&&this.runWithLifecycle(e,{type:"schedule"}).catch(o=>this.onError(o,e))}passesRateLimit(e,t){if(this.minTriggerIntervalMs<=0)return!0;let n=this.clock.now(),o=this.lastFireAt.get(e);return o!==void 0&&n-o<this.minTriggerIntervalMs?(this.onTriggerDropped?.(e,t,{sinceLastMs:n-o,minIntervalMs:this.minTriggerIntervalMs}),!1):(this.lastFireAt.set(e,n),!0)}async runWithLifecycle(e,t){this.onRunStarted?.(e,t.type);try{let n=await this.controller.run(e,t);return this.onRunCompleted?.(n,t.type),n}catch(n){throw this.onRunFailed?.(e,t.type,n),n}}};function co(r,e){return r===void 0?!0:new RegExp(r).test(e)}import{createCipheriv as lo,createDecipheriv as fo,randomBytes as Lt,randomUUID as go}from"node:crypto";import{existsSync as F,mkdirSync as Kt,readFileSync as Oe,writeFileSync as Me,readdirSync as po,rmSync as mo}from"node:fs";import{join as Q}from"node:path";var Jt="aes-256-gcm",_e=class{dir;constructor(e=_()){this.dir=Q(e,"credentials")}keyPath(){return Q(this.dir,".vault-key")}ensureKey(){F(this.dir)||Kt(this.dir,{recursive:!0});let e=this.keyPath();if(!F(e)){let t=Lt(32);return Me(e,t.toString("base64"),{mode:384}),t}return Buffer.from(Oe(e,"utf-8").trim(),"base64")}encrypt(e){let t=this.ensureKey(),n=Lt(12),o=lo(Jt,t,n),i=Buffer.concat([o.update(JSON.stringify(e),"utf-8"),o.final()]);return`${n.toString("base64")}.${o.getAuthTag().toString("base64")}.${i.toString("base64")}`}decrypt(e){let t=this.ensureKey(),[n,o,i]=e.split(".");if(!n||!o||!i)throw new Error("credential vault: malformed ciphertext envelope");let s=fo(Jt,t,Buffer.from(n,"base64"));s.setAuthTag(Buffer.from(o,"base64"));let a=Buffer.concat([s.update(Buffer.from(i,"base64")),s.final()]);return JSON.parse(a.toString("utf-8"))}filePath(e){if(!/^[\w-]+$/.test(e))throw new Error(`credential vault: illegal id "${e}"`);return Q(this.dir,`${e}.json`)}list(){if(!F(this.dir))return[];let e=[];for(let t of po(this.dir))if(t.endsWith(".json"))try{let n=JSON.parse(Oe(Q(this.dir,t),"utf-8"));if(!n||typeof n!="object"||typeof n.id!="string"||typeof n.updatedAt!="string")throw new Error("malformed credential envelope");e.push({id:n.id,type:n.type,label:n.label,createdAt:n.createdAt,updatedAt:n.updatedAt,meta:n.meta})}catch(n){let o=t.replace(/\.json$/,"");console.error(`[credential-vault] credential file ${Q(this.dir,t)} is unreadable or corrupted - shown as corrupt in the list: ${n instanceof Error?n.message:String(n)}`),e.push({id:o,type:"custom",label:`${o} (corrupted credential file - delete and re-create it)`,createdAt:"",updatedAt:"",corrupt:!0})}return e.sort((t,n)=>n.updatedAt.localeCompare(t.updatedAt))}create(e){Gt(e.type,e.data);let t=e.id??`cred_${go().slice(0,8)}`,n=new Date().toISOString(),o={id:t,type:e.type,label:e.label||t,createdAt:n,updatedAt:n,...e.meta?{meta:e.meta}:{},enc:this.encrypt(e.data)};return F(this.dir)||Kt(this.dir,{recursive:!0}),Me(this.filePath(t),JSON.stringify(o,null,2),{mode:384}),{id:t,type:o.type,label:o.label,createdAt:n,updatedAt:n,meta:o.meta}}get(e){let t=this.filePath(e);if(!F(t))throw new Error(`credential "${e}" not found`);let n=JSON.parse(Oe(t,"utf-8"));return{summary:{id:n.id,type:n.type,label:n.label,createdAt:n.createdAt,updatedAt:n.updatedAt,meta:n.meta},data:this.decrypt(n.enc)}}delete(e){let t=this.filePath(e);return F(t)?(mo(t,{force:!0}),!0):!1}updateData(e,t,n){let{summary:o}=this.get(e);Gt(o.type,t);let i=new Date().toISOString(),s=o.meta;if(n){s={...o.meta??{},...n};for(let l of Object.keys(s))s[l]===void 0&&delete s[l]}let a={...o,...s!==void 0?{meta:s}:{},updatedAt:i},u={...a,enc:this.encrypt(t)};return Me(this.filePath(e),JSON.stringify(u,null,2),{mode:384}),a}};function X(r,e,t){if(typeof r[e]!="string"||!r[e])throw new Error(`credential(${t}): "${e}" is required`)}function Gt(r,e){switch(r){case"apiKey":X(e,"headerName",r),X(e,"value",r);return;case"bearer":X(e,"token",r);return;case"basic":X(e,"username",r),X(e,"password",r);return;case"oauth2":return;case"custom":if(typeof e.headers!="object"||e.headers===null||Array.isArray(e.headers))throw new Error('credential(custom): "headers" object is required');return;default:{let t=r;throw new Error(`credential: unknown type ${JSON.stringify(t)}`)}}}function ho(r,e){switch(r){case"apiKey":return{[String(e.headerName)]:String(e.value)};case"bearer":return{Authorization:`Bearer ${String(e.token)}`};case"basic":return{Authorization:`Basic ${Buffer.from(`${String(e.username)}:${String(e.password)}`).toString("base64")}`};case"oauth2":{if(typeof e.accessToken!="string"||!e.accessToken)throw new Error("credential(oauth2): no accessToken yet \u2014 complete the OAuth authorization first");return{Authorization:`Bearer ${e.accessToken}`}}case"custom":return{...e.headers};default:{let t=r;throw new Error(`credential: unknown type ${JSON.stringify(t)}`)}}}import{join as Vt}from"node:path";import{mkdir as wo,rm as yo}from"node:fs/promises";function ko(r,e,t){return Vt(ne().getProjectAgentDir(r),"workflows",e,"runs",t)}var He=class{constructor(e,t,n){this.workflowId=t;this.runId=n;if(!e)throw new Error("FileRunCheckpoint requires a project cwd");if(!t)throw new Error("FileRunCheckpoint requires a workflowId");if(!n)throw new Error("FileRunCheckpoint requires a runId");this.dir=ko(e,t,n),this.file=Vt(this.dir,"cache.json")}workflowId;runId;dir;file;async load(){return D(this.file)}async persist(e){await wo(this.dir,{recursive:!0});let t={workflowId:this.workflowId,runId:this.runId,entries:e,updatedAt:new Date().toISOString()};await C(this.file,t)}async clear(){await yo(this.dir,{recursive:!0,force:!0})}};import*as L from"node:fs";import*as ge from"node:path";var qe=class{file;constructor(e){this.file=ge.join(e,"audit.jsonl")}append(e){try{L.mkdirSync(ge.dirname(this.file),{recursive:!0}),L.appendFileSync(this.file,`${JSON.stringify(e)}
10
+ `,"utf8")}catch(t){process.stderr.write(`[workflow:audit] WRITE FAILED (${t instanceof Error?t.message:String(t)}) \u2014 entry: ${JSON.stringify(e)}
11
+ `)}}list(e,t=100){let n;try{n=L.readFileSync(this.file,"utf8")}catch{return[]}let o=[];for(let i of n.split(`
12
+ `))if(i.trim())try{let s=JSON.parse(i);(!e||s.workflowId===e)&&o.push(s)}catch{process.stderr.write(`[workflow:audit] skipping malformed line: ${i.slice(0,120)}
13
+ `)}return o.reverse().slice(0,t)}};var bo=/token|secret|authorization|api[-_]?key|apikey|password|credential|cookie|passphrase|private[-_]?key/i,vo="__CREDENTIAL_REQUIRED__";function pe(r){return typeof r=="object"&&r!==null&&!Array.isArray(r)}function Be(r,e,t,n,o){if(Array.isArray(r))return r.map((s,a)=>Be(s,`${e}[${a}]`,t,n,o));if(!pe(r))return r;let i={};for(let[s,a]of Object.entries(r)){if(bo.test(s)&&a!==void 0&&a!==null&&a!==""){o.push({type:"custom",label:`${n} ${e}.${s}`,nodeIds:[t]}),i[s]=vo;continue}i[s]=Be(a,`${e}.${s}`,t,n,o)}return i}function xo(r){let e=new Map;for(let t of r){let n=e.get(t.label);if(n)for(let o of t.nodeIds)n.nodeIds.includes(o)||n.nodeIds.push(o);else e.set(t.label,{...t,nodeIds:[...t.nodeIds]})}return[...e.values()]}function Po(r){return`\u8282\u70B9\u300C${r.name??r.id}\u300D`}function Eo(r){let e=new Map,t=(n,o)=>{let i=`${n.category}:${n.ref}`,s=e.get(i);s?s.nodeIds.includes(o)||s.nodeIds.push(o):e.set(i,{...n,nodeIds:[o]})};for(let n of r.nodes){let o=n.params??{};switch(n.kind){case"agent":{let i=typeof o.agentId=="string"&&o.agentId&&o.agentId!=="self"?o.agentId:"qlogicagent";t({category:"agent",kind:"agent",ref:i,label:`Agent: ${i}`},n.id);break}case"tool":{let i=typeof o.tool=="string"?o.tool:"";i&&t({category:"tool",kind:"tool",ref:i,label:`\u5DE5\u5177: ${i}`},n.id);break}case"skill":{let i=typeof o.skill=="string"?o.skill:"";i&&t({category:"skill",kind:"skill",ref:i,label:`\u6280\u80FD: ${i}`},n.id);break}case"mcp":{let i=typeof o.server=="string"?o.server:"",s=typeof o.tool=="string"?o.tool:"";i&&t({category:"mcp",kind:"mcp",ref:s?`${i}.${s}`:i,label:`MCP: ${i}${s?` / ${s}`:""}`},n.id);break}case"channel":{let i=typeof o.channel=="string"?o.channel:"";i&&t({category:"channel",kind:"channel",ref:i,label:`\u6E20\u9053: ${i}`},n.id);break}case"memory":{t({category:"memory",kind:"memory",ref:"memory",label:"\u8BB0\u5FC6\u8BFB\u5199"},n.id);break}default:break}}return[...e.values()]}function Ro(r){let e=[],t=r.def.nodes.map(o=>({...o,...o.params!==void 0?{params:Be(o.params,"params",o.id,Po(o),e)}:{}})),n={...r.def,nodes:t};return{schemaVersion:2,name:r.name,def:n,...r.trigger?{trigger:r.trigger}:{},concurrency:r.concurrency,requires:Eo(n),credentialsRequired:xo(e),meta:{source:"native"}}}function Io(r){let e=typeof r=="string"?JSON.parse(r):r;if(!pe(e))throw new Error("workflow bundle: payload must be an object");if(e.schemaVersion!==2)throw new Error(`workflow bundle: unsupported schemaVersion ${String(e.schemaVersion)} (expected 2)`);if(typeof e.name!="string"||!e.name)throw new Error("workflow bundle: `name` is required");let t=e.def;if(!pe(t)||!Array.isArray(t.nodes)||!Array.isArray(t.edges))throw new Error("workflow bundle: `def.nodes` and `def.edges` are required arrays");let n=e.concurrency;if(n!==void 0&&n!=="queue"&&n!=="skip"&&n!=="parallel")throw new Error(`workflow bundle: invalid concurrency "${String(n)}"`);return{name:e.name,def:t,trigger:pe(e.trigger)?e.trigger:void 0,concurrency:n,requires:Array.isArray(e.requires)?e.requires:[],credentialsRequired:Array.isArray(e.credentialsRequired)?e.credentialsRequired:[]}}export{_e as CredentialVault,He as FileRunCheckpoint,dr as HOST_BACKED_KINDS,V as NodeRegistry,v as PatchError,qe as WorkflowAuditStore,De as WorkflowController,Ne as WorkflowRunHistoryStore,z as WorkflowRuntime,We as WorkflowScheduler,be as WorkflowStore,je as applyPatch,to as createQlaExecutorHost,ho as credentialToHeaders,Zr as defaultRuntimeFactory,Io as fromWorkflowBundle,ue as hostExecutors,Ae as renderWorkflow,Ro as toWorkflowBundle,j as workflowsDir};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "qlogicagent",
3
- "version": "2.18.7",
3
+ "version": "2.18.9",
4
4
  "description": "XiaozhiClaw Agent CLI — subprocess architecture (JSON-RPC over stdio)",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -40,6 +40,14 @@
40
40
  "types": "./dist/types/pet-contracts.d.ts",
41
41
  "default": "./dist/pet-contracts.js"
42
42
  },
43
+ "./pet-host": {
44
+ "types": "./dist/types/pet-host.d.ts",
45
+ "default": "./dist/pet-host.js"
46
+ },
47
+ "./workflow-host": {
48
+ "types": "./dist/types/workflow-host.d.ts",
49
+ "default": "./dist/workflow-host.js"
50
+ },
43
51
  "./host-contract": {
44
52
  "types": "./dist/types/host-contract/index.d.ts",
45
53
  "default": "./dist/host-contract.js"
@@ -75,6 +83,12 @@
75
83
  "pet-contracts": [
76
84
  "./dist/types/pet-contracts.d.ts"
77
85
  ],
86
+ "pet-host": [
87
+ "./dist/types/pet-host.d.ts"
88
+ ],
89
+ "workflow-host": [
90
+ "./dist/types/workflow-host.d.ts"
91
+ ],
78
92
  "host-contract": [
79
93
  "./dist/types/host-contract/index.d.ts"
80
94
  ],
@@ -119,7 +133,7 @@
119
133
  "@agentclientprotocol/sdk": "^0.25.0",
120
134
  "@napi-rs/canvas": "0.1.100",
121
135
  "@xiaozhiclaw/pet-core": "0.1.3",
122
- "@xiaozhiclaw/provider-core": "^0.1.21",
136
+ "@xiaozhiclaw/provider-core": "^0.1.26",
123
137
  "better-sqlite3": "^12.10.0",
124
138
  "dotenv": "^17.3.1",
125
139
  "ioredis": "^5.11.1",
@@ -1,8 +0,0 @@
1
- import type { ToolCatalog } from "../../runtime/ports/index.js";
2
- export interface CronToolRegistrationDeps {
3
- toolCatalog: ToolCatalog;
4
- host: {
5
- getActiveProjectRoot(): string;
6
- };
7
- }
8
- export declare function registerCronTool({ host, toolCatalog }: CronToolRegistrationDeps): void;
@@ -1,7 +0,0 @@
1
- import type { CronToolDeps } from "../../skills/tools/cron-tool.js";
2
- export interface CronWorkflowServiceOptions {
3
- getProjectRoot(): string;
4
- idFactory?: () => string;
5
- }
6
- export type CronWorkflowService = CronToolDeps;
7
- export declare function createCronWorkflowService(options: CronWorkflowServiceOptions): CronWorkflowService;
@@ -1,49 +0,0 @@
1
- /**
2
- * Pet Handler — RPC methods for pet system.
3
- *
4
- * Methods:
5
- * - pet.interact: Handle user interaction (pat/feed/poke)
6
- * - pet.status: Get or initialize the shared owner pet soul + stats
7
- * - pet.forge: Generate a Petdex asset summary from image/text (P4)
8
- */
9
- import { type AgentRpcError, type AgentRpcRequest } from "../../protocol/wire/index.js";
10
- import type { PetRuntime } from "../pet-runtime.js";
11
- interface PetMemoryActivitySummary {
12
- highlights?: Array<{
13
- text?: string;
14
- }>;
15
- }
16
- interface PetMemoryProviderLike {
17
- /** B3(X7)异步化:16 面 host-state proxy 方法(host 模式经 x/host.request 跨进程)。 */
18
- getActivitySummary(userId: string, days: number): Promise<PetMemoryActivitySummary | undefined> | undefined;
19
- }
20
- interface PetSessionStateLike {
21
- turnCount?: number;
22
- }
23
- export interface PetHandlerHost {
24
- deviceId?: string;
25
- sessionState?: PetSessionStateLike | null;
26
- memoryProvider?: PetMemoryProviderLike | null;
27
- memoryUserId?: string;
28
- ownerUserId?: string;
29
- petRuntime: Pick<PetRuntime, "createPetSoulGenerator" | "createSmallLLMCall"> & Partial<Pick<PetRuntime, "forgeGeneratePetdexAtlas" | "isImageGenerationAvailable" | "isPetdexForgeAvailable">>;
30
- getActiveProjectRoot(): string;
31
- sendNotification(method: string, params: Record<string, unknown>): void;
32
- sendResponse(id: string | number, result?: unknown, error?: AgentRpcError): void;
33
- ensureModelRegistryHydrated?(): Promise<void>;
34
- configureTurnMedia?(config: Record<string, unknown> | undefined, turnId: string): void;
35
- }
36
- export declare function handlePetInteract(this: PetHandlerHost, msg: AgentRpcRequest): Promise<void>;
37
- export declare function handlePetStatus(this: PetHandlerHost, msg: AgentRpcRequest): Promise<void>;
38
- export declare function handlePetPreferencesUpdate(this: PetHandlerHost, msg: AgentRpcRequest): Promise<void>;
39
- export declare function handlePetJourneySnapshot(this: PetHandlerHost, msg: AgentRpcRequest): Promise<void>;
40
- export declare function handlePetJourneyList(this: PetHandlerHost, msg: AgentRpcRequest): Promise<void>;
41
- export declare function handlePetJourneyGet(this: PetHandlerHost, msg: AgentRpcRequest): Promise<void>;
42
- export declare function handlePetJourneyCatchUp(this: PetHandlerHost, msg: AgentRpcRequest): Promise<void>;
43
- export declare function handlePetCustomDelete(this: PetHandlerHost, msg: AgentRpcRequest): Promise<void>;
44
- export declare function handlePetAssetImport(this: PetHandlerHost, msg: AgentRpcRequest): Promise<void>;
45
- /**
46
- * Pet Forge creates the backend-owned Petdex asset record from a generated atlas.
47
- */
48
- export declare function handlePetForge(this: PetHandlerHost, msg: AgentRpcRequest): Promise<void>;
49
- export {};
@@ -1,182 +0,0 @@
1
- /**
2
- * Workflow mode handlers — ACP surface for the automation workflow engine (plan M2 接入).
3
- * Exposes workflow.create/get/describe/patch/run/setActive/list/delete over the same RPC host
4
- * as product/solo. The engine (WorkflowController) lives in qlogicagent (D12); triggers live in
5
- * the gateway (D7/B) and drive `workflow.run` over ACP.
6
- *
7
- * fail-loud throughout (plan §1.5): unknown id / illegal patch / missing capability all throw.
8
- */
9
- import { AgentProcessManager } from "../../runtime/infra/agent-process.js";
10
- import type { AcpDetector } from "../../runtime/infra/acp-detector.js";
11
- import type { DelegateBridge } from "../../orchestration/delegation-coordinator.js";
12
- import { type AgentRpcError, type AgentRpcRequest } from "../../protocol/wire/index.js";
13
- import { WorkflowController } from "../../orchestration/workflow/workflow-controller.js";
14
- import { WorkflowStore, type WorkflowRecord } from "../../orchestration/workflow/workflow-store.js";
15
- import { WorkflowRunHistoryStore } from "../../orchestration/workflow/run-history-store.js";
16
- import { WorkflowScheduler } from "../../orchestration/workflow/workflow-scheduler.js";
17
- import { WorkflowAuditStore } from "../../orchestration/workflow/workflow-audit-store.js";
18
- import type { ToolCatalog } from "../../runtime/ports/index.js";
19
- /**
20
- * One fully-wired engine root. The workflow store is project-scoped on disk
21
- * (`<project>/.qlogicagent/workflows/`), and "every automation = its own project" (spec D21)
22
- * means the engine must serve the active project root AND every type:"automation" project
23
- * root at once — so the singleton controller became this per-root bundle (multi-root,单轨).
24
- */
25
- export interface WorkflowRootBundle {
26
- cwd: string;
27
- /** The owning project id (undefined only when the active root has no registered project). */
28
- projectId?: string;
29
- store: WorkflowStore;
30
- controller: WorkflowController;
31
- scheduler: WorkflowScheduler;
32
- runHistory: WorkflowRunHistoryStore;
33
- /** D38 audit trail (config/lifecycle changes; runs live in runHistory). */
34
- audit: WorkflowAuditStore;
35
- pm: AgentProcessManager;
36
- }
37
- export interface WorkflowCoordinatorHost {
38
- acpDetector: AcpDetector;
39
- getActiveProjectRoot(): string;
40
- handleMcpToolCall(memberId: string, tool: string, args: Record<string, unknown>): Promise<unknown>;
41
- sendNotification(method: string, params: Record<string, unknown>): void;
42
- toolCatalog: ToolCatalog;
43
- resolveClientForPurpose?: (purpose: "textGeneration") => {
44
- transport: import("../provider-core-facade.js").LLMTransport;
45
- apiKey: string;
46
- model: string;
47
- } | null;
48
- /** Per-root engine bundles keyed by resolved cwd; built lazily by ensureWorkflowRoot. */
49
- workflowRoots: Map<string, WorkflowRootBundle> | null;
50
- /**
51
- * 激活层(S3c §1.6):gateway-routed delegate 桥(gateway 在 initialize 声明 delegate 能力位时
52
- * 才 isSupported;缺省/gate 关 = 旧 AgentProcessManager 本地 spawn 路径,单轨保留零回归)。
53
- */
54
- getDelegateBridge?(): DelegateBridge | undefined;
55
- }
56
- export interface WorkflowHandlerHost extends WorkflowCoordinatorHost {
57
- sendResponse(id: string | number, result?: unknown, error?: AgentRpcError): void;
58
- }
59
- /** A resolved workflow routing target: which project root an RPC operates on. */
60
- interface WorkflowTarget {
61
- cwd: string;
62
- projectId?: string;
63
- }
64
- /** Build (or fetch) the engine bundle for one project root, wired to real capabilities (§1.5). */
65
- export declare function ensureWorkflowRoot(this: WorkflowCoordinatorHost, target: WorkflowTarget): WorkflowRootBundle;
66
- /** `workflow.approvals` — 列出全部挂起审批(刷新/重连后的拉取恢复路径;推送通知是快路径)。 */
67
- export declare function handleWorkflowApprovals(this: WorkflowHandlerHost, msg: AgentRpcRequest): Promise<void>;
68
- /** `workflow.approve` — 人工审批决定(approved=false 即拒绝);未知/过期 id fail-loud。 */
69
- export declare function handleWorkflowApprove(this: WorkflowHandlerHost, msg: AgentRpcRequest): Promise<void>;
70
- /**
71
- * `workflow.onForm` — form 触发(D34):校验活跃 form 触发 + 必填字段,以表单值为 $trigger 起 run。
72
- * attended(用户亲手填表提交)。
73
- */
74
- export declare function handleWorkflowOnForm(this: WorkflowHandlerHost, msg: AgentRpcRequest): Promise<void>;
75
- export declare function handleWorkflowCreate(this: WorkflowHandlerHost, msg: AgentRpcRequest): Promise<void>;
76
- export declare function handleWorkflowGet(this: WorkflowHandlerHost, msg: AgentRpcRequest): Promise<void>;
77
- export declare function handleWorkflowDescribe(this: WorkflowHandlerHost, msg: AgentRpcRequest): Promise<void>;
78
- export declare function handleWorkflowPatch(this: WorkflowHandlerHost, msg: AgentRpcRequest): Promise<void>;
79
- export declare function handleWorkflowRun(this: WorkflowHandlerHost, msg: AgentRpcRequest): Promise<void>;
80
- /**
81
- * `workflow.update` — record-level meta/def update (rename, whole-def replacement from the
82
- * chat builder, concurrency). Graph micro-edits stay on workflow.patch; trigger stays a
83
- * set_trigger patch op (single track each).
84
- */
85
- export declare function handleWorkflowUpdate(this: WorkflowHandlerHost, msg: AgentRpcRequest): Promise<void>;
86
- export declare function handleWorkflowSetActive(this: WorkflowHandlerHost, msg: AgentRpcRequest): Promise<void>;
87
- export declare function handleWorkflowList(this: WorkflowHandlerHost, msg: AgentRpcRequest): Promise<void>;
88
- export declare function handleWorkflowDelete(this: WorkflowHandlerHost, msg: AgentRpcRequest): Promise<void>;
89
- /**
90
- * `workflow.cancelRun` — stop an in-flight run (D32; engine support landed with the teammate's
91
- * runId/AbortController work, this exposes it on the RPC face + a UI stop button). Cancels the
92
- * newest active run when runId is omitted. fail-loud when nothing is running.
93
- */
94
- export declare function handleWorkflowCancelRun(this: WorkflowHandlerHost, msg: AgentRpcRequest): Promise<void>;
95
- /**
96
- * `workflow.dryRun` — test-run the DRAFT with an optional simulated trigger payload, WITHOUT
97
- * recording into run history (D36: test runs stay out of production stats). Returns the full
98
- * outcome incl. per-node trace for inspection.
99
- */
100
- export declare function handleWorkflowDryRun(this: WorkflowHandlerHost, msg: AgentRpcRequest): Promise<void>;
101
- /** `workflow.metrics` — aggregate run history into success-rate/duration/trigger stats (D33). */
102
- export declare function handleWorkflowMetrics(this: WorkflowHandlerHost, msg: AgentRpcRequest): Promise<void>;
103
- /** `workflow.publish` — snapshot the draft as the trigger-run version (D31). */
104
- export declare function handleWorkflowPublish(this: WorkflowHandlerHost, msg: AgentRpcRequest): Promise<void>;
105
- /** `workflow.archive` — keep the data, kill the lifecycle (deactivate + refuse runs). */
106
- export declare function handleWorkflowArchive(this: WorkflowHandlerHost, msg: AgentRpcRequest): Promise<void>;
107
- export declare function handleCredentialList(this: WorkflowHandlerHost, msg: AgentRpcRequest): Promise<void>;
108
- export declare function handleCredentialCreate(this: WorkflowHandlerHost, msg: AgentRpcRequest): Promise<void>;
109
- export declare function handleCredentialDelete(this: WorkflowHandlerHost, msg: AgentRpcRequest): Promise<void>;
110
- /**
111
- * `credential.oauthStart` — create an oauth2 credential (config persisted, token pending) and
112
- * return the authorize URL the UI opens in the browser. The gateway's /api/oauth/callback lands
113
- * the code on credential.oauthComplete.
114
- */
115
- export declare function handleCredentialOauthStart(this: WorkflowHandlerHost, msg: AgentRpcRequest): Promise<void>;
116
- /** `credential.oauthComplete` — exchange the authorization code and store tokens in the vault. */
117
- export declare function handleCredentialOauthComplete(this: WorkflowHandlerHost, msg: AgentRpcRequest): Promise<void>;
118
- /**
119
- * `workflow.setPermissionScope` — the owner's explicit unattended capability grant (D30):
120
- * which sensitive kinds this workflow may run under schedule/im/webhook triggers.
121
- */
122
- export declare function handleWorkflowSetPermissionScope(this: WorkflowHandlerHost, msg: AgentRpcRequest): Promise<void>;
123
- /**
124
- * `workflow.capabilities` — enumerate the real agents/tools/skills/mcp/memory a workflow in the
125
- * target project can reference (single source of truth, five consumers: AI builder prompt,
126
- * "+" suggestions, advanced node library, config dropdowns, Hub requires checks). Channels are
127
- * gateway-owned: the gateway merges its channel registry into this response in ws-server.
128
- */
129
- export declare function handleWorkflowCapabilities(this: WorkflowHandlerHost, msg: AgentRpcRequest): Promise<void>;
130
- /** `workflow.export` — serialize one workflow as a sanitized portable bundle (no credentials). */
131
- export declare function handleWorkflowExport(this: WorkflowHandlerHost, msg: AgentRpcRequest): Promise<void>;
132
- /**
133
- * `workflow.import` — materialize a portable bundle (or raw n8n JSON, format:"n8n") into a target
134
- * project. The caller creates/owns the project (frontend: WorkspaceStep → POST /api/projects);
135
- * this RPC only lands the workflow. fail-loud on malformed payloads (§1.5).
136
- */
137
- export declare function handleWorkflowImport(this: WorkflowHandlerHost, msg: AgentRpcRequest): Promise<void>;
138
- /**
139
- * `workflow.duplicate` — copy a workflow (same graph/trigger, fresh id, inactive) into a target
140
- * project: export→import in-process (one serialization path, spec D23). 复制/另存为 both land here.
141
- */
142
- export declare function handleWorkflowDuplicate(this: WorkflowHandlerHost, msg: AgentRpcRequest): Promise<void>;
143
- export declare function handleWorkflowOnImMessage(this: WorkflowHandlerHost, msg: AgentRpcRequest): Promise<void>;
144
- export declare function handleWorkflowOnWebhook(this: WorkflowHandlerHost, msg: AgentRpcRequest): Promise<void>;
145
- /**
146
- * `workflow.onIntent` — fire an intent-triggered run (spec D22). The MATCH already happened
147
- * (deterministic phrases client-side; semantic fallback via x/workflow.matchIntent) and the user
148
- * confirmed; this entry point only verifies the workflow really has an ACTIVE intent trigger
149
- * (fail-loud otherwise — a stale client must not run a disarmed workflow) and starts the run with
150
- * the utterance as `$trigger` payload.
151
- */
152
- export declare function handleWorkflowOnIntent(this: WorkflowHandlerHost, msg: AgentRpcRequest): Promise<void>;
153
- /** All ACTIVE intent-triggered workflows across the active root + automation projects (D22 索引源). */
154
- export declare function collectActiveIntentWorkflows(this: WorkflowCoordinatorHost): Promise<Array<{
155
- workflowId: string;
156
- projectId?: string;
157
- name: string;
158
- trigger: Extract<NonNullable<WorkflowRecord["trigger"]>, {
159
- type: "intent";
160
- }>;
161
- sideEffectKinds: string[];
162
- }>>;
163
- /**
164
- * `workflow.intentIndex` — the deterministic-match index the CLIENT consumes (phrases/aliases/
165
- * confirm/surfaces per active intent workflow). The frontend matches utterances locally with zero
166
- * latency (spec D22); semantic fallback goes through x/workflow.matchIntent.
167
- */
168
- export declare function handleWorkflowIntentIndex(this: WorkflowHandlerHost, msg: AgentRpcRequest): Promise<void>;
169
- /** `workflow.revisions` — newest-first def-revision summaries for the undo/history UI. */
170
- export declare function handleWorkflowRevisions(this: WorkflowHandlerHost, msg: AgentRpcRequest): Promise<void>;
171
- /** `workflow.revert` — re-apply a stored revision as a NEW rev (git-revert semantics). */
172
- export declare function handleWorkflowRevert(this: WorkflowHandlerHost, msg: AgentRpcRequest): Promise<void>;
173
- /**
174
- * `workflow.audit` — newest-first config/lifecycle audit entries (D38: who did what when).
175
- * Runs are NOT here (runHistory is the run audit); a timeline UI merges both.
176
- */
177
- export declare function handleWorkflowAudit(this: WorkflowHandlerHost, msg: AgentRpcRequest): Promise<void>;
178
- /** `workflow.runs` — newest-first run summaries (status/trigger/timing; outputs stay behind runDetail). */
179
- export declare function handleWorkflowRuns(this: WorkflowHandlerHost, msg: AgentRpcRequest): Promise<void>;
180
- /** `workflow.runDetail` — one run incl. per-node output previews (画布点节点看产出). */
181
- export declare function handleWorkflowRunDetail(this: WorkflowHandlerHost, msg: AgentRpcRequest): Promise<void>;
182
- export {};
@@ -1,7 +0,0 @@
1
- import type { PortableTool } from "../skills/portable-tool.js";
2
- export interface LocalWorkflowToolRegistrationContext {
3
- tools: PortableTool<any>[];
4
- activeProjectRoot(): string;
5
- }
6
- export declare const localWorkflowToolRegistrationModule: import("../runtime/ports/tool-contracts.js").ToolRegistrationModule<LocalWorkflowToolRegistrationContext>;
7
- export declare function registerLocalWorkflowTools(context: LocalWorkflowToolRegistrationContext): void;