evolve-sdk 0.0.52.dev744__tar.gz → 0.0.52.dev760__tar.gz

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 (43) hide show
  1. {evolve_sdk-0.0.52.dev744 → evolve_sdk-0.0.52.dev760}/PKG-INFO +1 -1
  2. {evolve_sdk-0.0.52.dev744 → evolve_sdk-0.0.52.dev760}/bridge/dist/bridge.bundle.cjs +3 -3
  3. {evolve_sdk-0.0.52.dev744 → evolve_sdk-0.0.52.dev760}/evolve/__init__.py +19 -2
  4. {evolve_sdk-0.0.52.dev744 → evolve_sdk-0.0.52.dev760}/evolve/hosted.py +461 -27
  5. {evolve_sdk-0.0.52.dev744 → evolve_sdk-0.0.52.dev760}/evolve_sdk.egg-info/PKG-INFO +1 -1
  6. {evolve_sdk-0.0.52.dev744 → evolve_sdk-0.0.52.dev760}/pyproject.toml +1 -1
  7. {evolve_sdk-0.0.52.dev744 → evolve_sdk-0.0.52.dev760}/LICENSE +0 -0
  8. {evolve_sdk-0.0.52.dev744 → evolve_sdk-0.0.52.dev760}/MANIFEST.in +0 -0
  9. {evolve_sdk-0.0.52.dev744 → evolve_sdk-0.0.52.dev760}/README.md +0 -0
  10. {evolve_sdk-0.0.52.dev744 → evolve_sdk-0.0.52.dev760}/bridge/__init__.py +0 -0
  11. {evolve_sdk-0.0.52.dev744 → evolve_sdk-0.0.52.dev760}/evolve/_http.py +0 -0
  12. {evolve_sdk-0.0.52.dev744 → evolve_sdk-0.0.52.dev760}/evolve/agent.py +0 -0
  13. {evolve_sdk-0.0.52.dev744 → evolve_sdk-0.0.52.dev760}/evolve/bridge.py +0 -0
  14. {evolve_sdk-0.0.52.dev744 → evolve_sdk-0.0.52.dev760}/evolve/browser_credentials.py +0 -0
  15. {evolve_sdk-0.0.52.dev744 → evolve_sdk-0.0.52.dev760}/evolve/browser_profiles.py +0 -0
  16. {evolve_sdk-0.0.52.dev744 → evolve_sdk-0.0.52.dev760}/evolve/config.py +0 -0
  17. {evolve_sdk-0.0.52.dev744 → evolve_sdk-0.0.52.dev760}/evolve/integrations.py +0 -0
  18. {evolve_sdk-0.0.52.dev744 → evolve_sdk-0.0.52.dev760}/evolve/managed_secrets.py +0 -0
  19. {evolve_sdk-0.0.52.dev744 → evolve_sdk-0.0.52.dev760}/evolve/pipeline/__init__.py +0 -0
  20. {evolve_sdk-0.0.52.dev744 → evolve_sdk-0.0.52.dev760}/evolve/pipeline/pipeline.py +0 -0
  21. {evolve_sdk-0.0.52.dev744 → evolve_sdk-0.0.52.dev760}/evolve/pipeline/types.py +0 -0
  22. {evolve_sdk-0.0.52.dev744 → evolve_sdk-0.0.52.dev760}/evolve/prompts/__init__.py +0 -0
  23. {evolve_sdk-0.0.52.dev744 → evolve_sdk-0.0.52.dev760}/evolve/prompts/agent_md/judge.md +0 -0
  24. {evolve_sdk-0.0.52.dev744 → evolve_sdk-0.0.52.dev760}/evolve/prompts/agent_md/reduce.md +0 -0
  25. {evolve_sdk-0.0.52.dev744 → evolve_sdk-0.0.52.dev760}/evolve/prompts/agent_md/verify.md +0 -0
  26. {evolve_sdk-0.0.52.dev744 → evolve_sdk-0.0.52.dev760}/evolve/prompts/user/judge.md +0 -0
  27. {evolve_sdk-0.0.52.dev744 → evolve_sdk-0.0.52.dev760}/evolve/prompts/user/retry_feedback.md +0 -0
  28. {evolve_sdk-0.0.52.dev744 → evolve_sdk-0.0.52.dev760}/evolve/prompts/user/verify.md +0 -0
  29. {evolve_sdk-0.0.52.dev744 → evolve_sdk-0.0.52.dev760}/evolve/results.py +0 -0
  30. {evolve_sdk-0.0.52.dev744 → evolve_sdk-0.0.52.dev760}/evolve/retry.py +0 -0
  31. {evolve_sdk-0.0.52.dev744 → evolve_sdk-0.0.52.dev760}/evolve/schema.py +0 -0
  32. {evolve_sdk-0.0.52.dev744 → evolve_sdk-0.0.52.dev760}/evolve/sessions_client.py +0 -0
  33. {evolve_sdk-0.0.52.dev744 → evolve_sdk-0.0.52.dev760}/evolve/storage_client.py +0 -0
  34. {evolve_sdk-0.0.52.dev744 → evolve_sdk-0.0.52.dev760}/evolve/swarm/__init__.py +0 -0
  35. {evolve_sdk-0.0.52.dev744 → evolve_sdk-0.0.52.dev760}/evolve/swarm/results.py +0 -0
  36. {evolve_sdk-0.0.52.dev744 → evolve_sdk-0.0.52.dev760}/evolve/swarm/swarm.py +0 -0
  37. {evolve_sdk-0.0.52.dev744 → evolve_sdk-0.0.52.dev760}/evolve/swarm/types.py +0 -0
  38. {evolve_sdk-0.0.52.dev744 → evolve_sdk-0.0.52.dev760}/evolve/utils.py +0 -0
  39. {evolve_sdk-0.0.52.dev744 → evolve_sdk-0.0.52.dev760}/evolve_sdk.egg-info/SOURCES.txt +0 -0
  40. {evolve_sdk-0.0.52.dev744 → evolve_sdk-0.0.52.dev760}/evolve_sdk.egg-info/dependency_links.txt +0 -0
  41. {evolve_sdk-0.0.52.dev744 → evolve_sdk-0.0.52.dev760}/evolve_sdk.egg-info/requires.txt +0 -0
  42. {evolve_sdk-0.0.52.dev744 → evolve_sdk-0.0.52.dev760}/evolve_sdk.egg-info/top_level.txt +0 -0
  43. {evolve_sdk-0.0.52.dev744 → evolve_sdk-0.0.52.dev760}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: evolve-sdk
3
- Version: 0.0.52.dev744
3
+ Version: 0.0.52.dev760
4
4
  Summary: Pythonic SDK for multi-agent orchestration in E2B sandboxes
5
5
  Author-email: "Swarmlink, Inc." <brandomagnani@evolvingmachines.ai>
6
6
  License: Apache-2.0
@@ -640,8 +640,8 @@ ${C}
640
640
  ${f}
641
641
  \`\`\``:f}});else if(Array.isArray(f)){for(let m of f)if(m.type==="text"){let v=m.text;p.push({type:"content",content:{type:"text",text:d?`\`\`\`
642
642
  ${v}
643
- \`\`\``:v}})}}return{sessionUpdate:"tool_call_update",toolCallId:u,status:d?"failed":"completed",content:p}}function c(l,u){let d=q0n[l]||"other",f=[],p=[],m=l;switch(l){case"Read":case"read_file":m=`Read ${u.file_path||u.absolute_path||"file"}`,(u.file_path||u.absolute_path)&&p.push({path:u.file_path||u.absolute_path});break;case"Write":case"write_file":m=`Write ${u.file_path||"file"}`,u.file_path&&(p.push({path:u.file_path}),f.push({type:"diff",path:u.file_path,oldText:null,newText:u.content||""}));break;case"Edit":case"edit_file":m=`Edit ${u.file_path||"file"}`,u.file_path&&p.push({path:u.file_path});break;case"Bash":case"shell":case"run_shell_command":m=u.command?`\`${u.command}\``:"Run command",u.description&&f.push({type:"content",content:{type:"text",text:u.description}});break;case"WebFetch":m=u.url?`Fetch ${u.url}`:"Web fetch";break;case"WebSearch":case"brave_web_search":m=u.query?`"${u.query}"`:"Web search";break;case"Glob":m=`Find ${u.pattern||"files"}`,u.path&&p.push({path:u.path});break;case"Grep":m=`grep "${u.pattern||""}"`;break;case"LS":case"list_directory":m=`List ${u.path||"directory"}`,u.path&&p.push({path:u.path});break;case"Task":m=u.description||"Subagent task";break;case"TodoWrite":m="Update todos";break;case"ExitPlanMode":m="Exit plan mode";break;default:m=l}return{title:m,kind:d,content:f,locations:p}}}function V5t(e){switch(e){case"claude":return d0n();case"codex":return f0n();case"gemini":return T0n();case"qwen":return V0n();case"kimi":return P0n();case"opencode":return L0n();case"droid":return m0n();default:return()=>null}}var $0n=(0,DK.promisify)(rU.execFile),QS="SKILL.md",G0n=(0,Zt.join)((0,W0.homedir)(),".cache","evolve","skills"),sTe=["skills","skills/.curated","skills/.experimental","skills/.system",".claude/skills"],H0n=/^([A-Za-z0-9._-]+)\/([A-Za-z0-9._-]+)(?:@(.+))?$/,z0n=/^[0-9a-f]{40}$/,j8t=2e3,Y8t=64*1024*1024,Hw=class extends Error{constructor(e){super(e),this.name="SkillRefError"}},z0=class extends Error{constructor(e){super(e),this.name="SkillResolveError"}};function W0n(e){return e==="~"?(0,W0.homedir)():e.startsWith("~/")?(0,Zt.join)((0,W0.homedir)(),e.slice(2)):e}function J0n(e){let t=e.indexOf("@");if(t===-1)return{base:e};let r=e.slice(t+1);if(!r)throw new Hw(`Empty @ref in skill reference segment: ${JSON.stringify(e)}`);return{base:e.slice(0,t),gitRef:r}}var j0n=/^[A-Za-z0-9._-]+$/;function qxe(e,t,r){if(!j0n.test(e))throw new Hw(`Cannot parse skill reference ${JSON.stringify(r)}: ${t} ${JSON.stringify(e)} may only contain letters, digits, ".", "_" and "-".`);return e}function Y0n(e){let t=String(e??"").trim();if(!t)throw new Hw("Skill reference cannot be empty.");if(t.startsWith("upload:")){let s=t.slice(7);if(!s)throw new Hw(`Skill upload reference ${JSON.stringify(t)} names no upload id.`);return{kind:"upload",id:s,raw:t}}if(t.startsWith("./")||t.startsWith("../")||t.startsWith("/")||t.startsWith("~"))return{kind:"local",path:W0n(t),raw:t};let r=t.match(/^(?:https?:\/\/)?(?:www\.)?skills\.sh\/(.+)$/);if(r){let s=r[1].replace(/\/+$/,"").split("/").filter(Boolean);if(s.length<2||s.length>3)throw new Hw(`Cannot parse skill reference ${JSON.stringify(t)}: expected skills.sh/<owner>/<repo> or skills.sh/<owner>/<repo>/<skill>, optionally @ref.`);let{base:o,gitRef:a}=J0n(s[s.length-1]);s[s.length-1]=o;let[c,l,u]=s;return qxe(c,"owner",t),qxe(l,"repo",t),u!==void 0&&qxe(u,"skill name",t),{kind:"git",host:"github.com",org:c,repo:l,...a?{gitRef:a}:{},...u?{skillName:u}:{},viaSkillsSh:!0,raw:t}}let n=t.match(/^https?:\/\/([^/]+)\/(.+)$/);if(n){let s=n[1],o=n[2].replace(/\/+$/,"").split("/").filter(Boolean);if(o.length<2)throw new Hw(`Git URL must have at least org/name in the path: ${JSON.stringify(t)}`);let a=o[0],c=o[1].replace(/\.git$/,""),l,u;return o.length>=4&&o[2]==="tree"&&(l=o[3],o.length>4&&(u=o.slice(4).join("/"))),{kind:"git",host:s,org:a,repo:c,...l?{gitRef:l}:{},...u?{subdir:u}:{},viaSkillsSh:!1,raw:t}}let i=t.match(H0n);if(i)return{kind:"git",host:"github.com",org:i[1],repo:i[2],...i[3]?{gitRef:i[3]}:{},viaSkillsSh:!1,raw:t};throw new Hw(`Cannot parse skill reference ${JSON.stringify(t)}. Expected skills.sh/<owner>/<repo>[/<skill>], org/repo[@ref], an https git URL, or a local folder path (prefix relative paths with './').`)}function $5t(e){return`https://${e.host}/${e.org}/${e.repo}.git`}function AK(e){return`https://${e.host}/${e.org}/${e.repo}`}async function G0(e,t){try{let{stdout:r}=await $0n("git",e,{cwd:t.cwd,timeout:t.timeoutMs,env:t.gitEnv??process.env,maxBuffer:16777216});return r}catch(r){let n=r,i=(n.stderr||n.message||"").trim();throw new z0(`git ${e[0]} failed${n.killed?" (timed out)":""}: ${i}`)}}async function K0n(e,t={}){if(e.gitRef&&z0n.test(e.gitRef))return e.gitRef;let r=e.gitRef??"HEAD",n=(await G0(["ls-remote",$5t(e),r],{timeoutMs:t.lsRemoteTimeoutMs??3e4,gitEnv:t.gitEnv})).trim().split(`
644
- `)[0];if(!n)throw new z0(`No matching ref ${JSON.stringify(r)} found in ${AK(e)}`);return n.split(" ")[0]}async function K8t(e){let t=[],r=async i=>{let s=i===""?e:(0,Zt.join)(e,i),o=await(0,vr.readdir)(s,{withFileTypes:!0});for(let a of o){let c=i===""?a.name:`${i}/${a.name}`;a.isDirectory()?await r(c):a.isFile()&&t.push(c)}};await r(""),t.sort();let n=(0,Uu.createHash)("sha256");for(let i of t){let s=(0,Uu.createHash)("sha256").update(await(0,vr.readFile)((0,Zt.join)(e,i))).digest("hex");n.update(i),n.update("\0"),n.update(s),n.update("\0")}return`sha256:${n.digest("hex")}`}async function eU(e){try{return(await(0,vr.stat)(e)).isFile()}catch{return!1}}async function oTe(e){try{return(await(0,vr.stat)(e)).isDirectory()}catch{return!1}}async function Z8t(e,t){if(!await oTe(e))throw new z0(`Skill path does not exist or is not a directory: ${t}`);if(await eU((0,Zt.join)(e,QS)))return[e];let r=(await(0,vr.readdir)(e,{withFileTypes:!0})).filter(s=>s.isDirectory()&&!s.name.startsWith(".")).map(s=>s.name).sort(),n=[],i=[];for(let s of r)await eU((0,Zt.join)(e,s,QS))?i.push((0,Zt.join)(e,s)):n.push(s);if(n.length>0)throw new z0(`Skill root ${t} contains child directories without ${QS}: ${n.join(", ")}`);if(i.length===0)throw new z0(`Skill path ${t} must be a skill directory containing ${QS}, or a root whose immediate child directories each contain ${QS}.`);return i}async function Z0n(e){let t=new Map;await eU((0,Zt.join)(e,QS))&&t.set((0,Zt.basename)(e),e);for(let r of sTe){let n=(0,Zt.join)(e,r);if(!await oTe(n))continue;let i=await(0,vr.readdir)(n,{withFileTypes:!0});for(let s of i.sort((o,a)=>o.name<a.name?-1:1)){if(!s.isDirectory()||s.name.startsWith("."))continue;let o=(0,Zt.join)(n,s.name);await eU((0,Zt.join)(o,QS))&&t.set(s.name,o)}}return Array.from(t,([r,n])=>({dir:n,name:r}))}function X0n(e){return e.cacheDir??process.env.EVOLVE_SKILLS_CACHE??G0n}async function Q0n(e,t,r){let n=(0,Zt.join)(X0n(r),e.host,e.org,e.repo,t),i=(0,Zt.join)(n,e.repo),s=(0,Zt.join)(n,".evolve-complete");if(await eU(s)&&await oTe(i))return i;await(0,vr.mkdir)((0,Zt.dirname)(n),{recursive:!0});let o=await(0,vr.mkdtemp)(`${n}.tmp-`),a=(0,Zt.join)(o,e.repo),c=r.checkoutTimeoutMs??12e4,l={cwd:a,timeoutMs:c,gitEnv:r.gitEnv};try{await(0,vr.mkdir)(a),await G0(["init","--quiet"],l),await G0(["remote","add","origin",$5t(e)],l),e.subdir?(await G0(["sparse-checkout","init","--cone"],l),await G0(["sparse-checkout","set",e.subdir],l)):(await G0(["sparse-checkout","init","--cone"],l),await G0(["sparse-checkout","set",...sTe],l)),await G0(["fetch","--quiet","--depth=1","origin",t],l),await G0(["checkout","--quiet","FETCH_HEAD"],l),await(0,vr.rm)((0,Zt.join)(a,".git"),{recursive:!0,force:!0}),await(0,vr.writeFile)((0,Zt.join)(o,".evolve-complete"),""),await(0,vr.rm)(n,{recursive:!0,force:!0});try{await(0,vr.rename)(o,n)}catch{await(0,vr.rm)(o,{recursive:!0,force:!0})}return i}catch(u){throw await(0,vr.rm)(o,{recursive:!0,force:!0}),u}}async function X8t(e,t){let r=0,n=0,i=async s=>{let o=await(0,vr.readdir)(s,{withFileTypes:!0});for(let a of o){let c=(0,Zt.join)(s,a.name);if(a.isDirectory())await i(c);else if(a.isFile()&&(r+=1,n+=(await(0,vr.stat)(c)).size,r>j8t||n>Y8t))throw new z0(`Skill ${t} exceeds the size ceiling (${j8t} files / ${Y8t} bytes) \u2014 a skill is instructions, not a dataset.`)}};await i(e)}async function evn(e,t={}){let r=new Map;for(let n of e){let i=Y0n(n);if(i.kind==="upload")throw new z0(`Skill reference ${JSON.stringify(i.raw)} is a platform upload handle; only the hosted platform can resolve it. Use a skills.sh/git reference or a local folder here.`);if(i.kind==="local"){let c=await Z8t(i.path,i.raw);for(let l of c)await X8t(l,i.raw),r.set((0,Zt.basename)(l),{name:(0,Zt.basename)(l),dir:l,source:i.raw,digest:await K8t(l)});continue}let s=await K0n(i,t),o=await Q0n(i,s,t),a;if(i.subdir)a=(await Z8t((0,Zt.join)(o,i.subdir),`${i.raw} (${i.subdir})`)).map(c=>({dir:c,name:(0,Zt.basename)(c)}));else if(a=await Z0n(o),a.length===0)throw new z0(`No skills found in ${AK(i)}@${s.slice(0,12)}: expected ${QS} at the repo root or under ${sTe.join(", ")}.`);if(i.skillName){let c=a.filter(l=>l.name===i.skillName);if(c.length===0)throw new z0(`Skill ${JSON.stringify(i.skillName)} not found in ${AK(i)}@${s.slice(0,12)}. Available: ${a.map(l=>l.name).sort().join(", ")||"(none)"}`);a=c}for(let{dir:c,name:l}of a)await X8t(c,i.raw),r.set(l,{name:l,dir:c,source:i.raw,gitUrl:AK(i),gitCommit:s,digest:await K8t(c)})}return Array.from(r.values()).sort((n,i)=>n.name<i.name?-1:n.name>i.name?1:0)}function EK(e){return`'${e.replace(/'/g,"'\\''")}'`}async function tvn(e,t,r){if(t.length===0)return;let{tarGzipDirectory:n}=await Promise.resolve().then(()=>(D8t(),N8t));await e.files.makeDir(r);for(let i of t){let s=await n(i.dir),o=`${r}/.evolve-skill-${i.name}.tgz`,a=`${r}/${i.name}`;await e.files.write(o,s),await e.commands.run(`mkdir -p ${EK(a)} && tar -xzf ${EK(o)} -C ${EK(a)} && rm -f ${EK(o)}`,{timeoutMs:6e4})}}function BK(e){return e!==null&&typeof e=="object"&&"safeParse"in e&&typeof e.safeParse=="function"}function G5t(e){return JSON.stringify(Xke(e,{target:"jsonSchema7"}),null,2)}function H5t(e){return JSON.stringify(e,null,2)}var fc=class extends Error{field;constructor(e,t){super(t),this.name="EvolveConfigError",this.field=e}};function eTe(e){return typeof e=="string"&&e.trim()!==""}function pR(e){return e==null?String(e):JSON.stringify(e)}function z5t(e){if(!e)return;if(e.type!==void 0&&!Wyn(e.type))throw new fc("type",`Evolve agent config: unknown agent type ${pR(e.type)}. Valid types: ${Object.keys(J0).join(", ")}.`);let t=e.type??GK;if(e.model!==void 0&&!eTe(e.model))throw new fc("model",`Evolve agent config: "model" is empty (${pR(e.model)}). Pass a model id such as "${Jw(t).defaultModel}", or omit model entirely to use ${t}'s default.`);if(e.config!==void 0){if(!j5t(t))throw new fc("config",`Evolve agent config: agent "${t}" does not support a native config. Agents with native-config support: ${Y5t().join(", ")}.`);let r=e.config;if(typeof r=="string"){if(!eTe(r))throw new fc("config",`Evolve agent config: "config" is an empty path (${pR(r)}). Pass a local settings file path or an inline JSON object.`)}else if(!RK(r))throw new fc("config",`Evolve agent config: "config" must be a local file path or a JSON object, received ${pR(r)}.`)}e.preset!==void 0&&W5t(t,e.preset)}function W5t(e,t){if(!q8t.includes(t))throw new fc("preset",`Evolve agent config: unknown preset ${pR(t)}. Valid presets: ${q8t.join(", ")}.`);let r=nvn(t);if(!r.includes(e))throw new fc("preset",`Evolve agent config: agent "${e}" cannot guarantee preset "${t}". Agents that can: ${r.join(", ")}.`)}function rvn(e){let t=J0[e]?.presets;return t?Object.keys(t):[]}function nvn(e){return Object.keys(J0).filter(t=>rvn(t).includes(e))}function J5t(e,t){let r={...e};for(let[n,i]of Object.entries(t)){let s=r[n];if(RK(s)&&RK(i))r[n]=J5t(s,i);else if(Array.isArray(s)&&Array.isArray(i)){let o=[...s];for(let a of i)o.some(c=>mR(c)===mR(a))||o.push(a);r[n]=o}else r[n]=i}return r}function RK(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function j5t(e){return J0[e]?.nativeConfig!==void 0}function Y5t(){return Object.keys(J0).filter(j5t)}function ivn(e,t){if(t===void 0)return;let r=J0[e]?.nativeConfig;if(!r)throw new fc("config",`Evolve agent config: agent "${e}" does not support a native config. Agents with native-config support: ${Y5t().join(", ")}.`);let n;if(typeof t=="string"){let i=t.replace(/^~/,process.env.HOME||"");if(!Dg.existsSync(i))throw new fc("config",`Agent config file not found: ${i}`);let s=Dg.readFileSync(i,"utf-8");try{n=r.format==="toml"?f_(s):JSON.parse(s)}catch(o){throw new fc("config",`Invalid ${e} config file ${t}: ${o.message}`)}}else{let i;try{i=JSON.parse(JSON.stringify(t))}catch(s){throw new fc("config",`Invalid inline ${e} config: not JSON-serializable: ${s.message}`)}if(JSON.stringify(i)!==JSON.stringify(t))throw new fc("config",`Invalid inline ${e} config: expected a JSON object that can be represented without conversion`);n=i}if(!RK(n))throw new fc("config",`Invalid ${e} config: expected a ${r.format==="toml"?"TOML table":"JSON object"}.`);if(r.format==="toml"){let i;try{i=f_(dx(n))}catch(s){throw new fc("config",`Invalid ${e} config for TOML conversion: ${s.message}`)}if(mR(i)!==mR(n))throw new fc("config",`Invalid ${e} config: the document cannot be represented losslessly as TOML (TOML has no null and no mixed-type arrays)`)}return n}function mR(e){return Array.isArray(e)?`[${e.map(mR).join(",")}]`:e&&typeof e=="object"?`{${Object.entries(e).sort(([t],[r])=>t<r?-1:t>r?1:0).map(([t,r])=>`${JSON.stringify(t)}:${mR(r)}`).join(",")}}`:JSON.stringify(e)??"null"}function svn(e){if(!e||!eTe(e.prompt))throw new fc("prompt",`run() requires a non-empty "prompt" string, received ${pR(e?.prompt)}.`)}function ovn(e){if(e){for(let t of mU)if(t in e)throw new fc(`observability.${t}`,`Evolve observability metadata: "${t}" is reserved for session identity and would split this run across two dashboard sessions. Reserved keys: ${mU.join(", ")}. Use a different key, or set the session tag with .withSessionTagPrefix().`)}}function K5t(e){if(e.externalGateway){if(e.providerApiKey||e.providerBaseUrl||e.oauthToken)throw new Error("externalGateway cannot be combined with providerApiKey/providerBaseUrl/oauthToken (direct mode)");if(e.apiKey)throw new Error("externalGateway cannot be combined with apiKey (Evolve gateway mode)")}}function avn(e){let t=e.replace(/^~/,process.env.HOME||"");if(!Dg.existsSync(t))throw new Error(`OAuth file not found: ${t}`);return Dg.readFileSync(t,"utf-8")}function Q8t(e){let t=e?.type??GK,r=Jw(t),n=ivn(t,e?.config);e?.preset!==void 0&&W5t(t,e.preset);let i={...n!==void 0?{config:n}:{},...e?.preset!==void 0?{preset:e.preset}:{}};if(e?.externalGateway){K5t(e);let{apiKey:c,baseUrl:l,revoke:u}=e.externalGateway;if(!c||!l||typeof u!="function")throw new Error("externalGateway requires apiKey, baseUrl, and a revoke() function");return{type:t,apiKey:c,baseUrl:l,isDirectMode:!0,externalGateway:{revoke:u},model:e.model,reasoningEffort:e.reasoningEffort,maxContextSize:e.maxContextSize,...i}}if(e?.oauthToken){if(t!=="claude")throw new Error(`oauthToken is only supported for claude agent (Claude Max subscription), not ${t}. Use providerApiKey for ${t} instead.`);return{type:t,apiKey:e.oauthToken,isDirectMode:!0,isOAuth:!0,model:e.model,reasoningEffort:e.reasoningEffort,maxContextSize:e.maxContextSize,...i}}if(e?.providerApiKey){let c=r.baseUrlEnv?process.env[r.baseUrlEnv]:void 0,l=e.providerBaseUrl??c??r.defaultBaseUrl;return{type:t,apiKey:e.providerApiKey,baseUrl:l,isDirectMode:!0,model:e.model,reasoningEffort:e.reasoningEffort,maxContextSize:e.maxContextSize,...i}}if(e?.apiKey)return{type:t,apiKey:e.apiKey,isDirectMode:!1,model:e.model,reasoningEffort:e.reasoningEffort,maxContextSize:e.maxContextSize,...i};let s=process.env[Dd];if(s)return{type:t,apiKey:s,isDirectMode:!1,model:e?.model,reasoningEffort:e?.reasoningEffort,maxContextSize:e?.maxContextSize,...i};if(r.providerEnvMap){let c=(e?.model??r.defaultModel)?.split("/")[0],l=c?r.providerEnvMap[c]:void 0,u=l?process.env[l.keyEnv]:void 0;if(u){let d=(r.baseUrlEnv?process.env[r.baseUrlEnv]:void 0)??r.defaultBaseUrl;return{type:t,apiKey:u,baseUrl:d,isDirectMode:!0,model:e?.model,reasoningEffort:e?.reasoningEffort,maxContextSize:e?.maxContextSize,...i}}}let o=process.env[r.apiKeyEnv];if(o){let c=(r.baseUrlEnv?process.env[r.baseUrlEnv]:void 0)??r.defaultBaseUrl;return{type:t,apiKey:o,baseUrl:c,isDirectMode:!0,model:e?.model,reasoningEffort:e?.reasoningEffort,maxContextSize:e?.maxContextSize,...i}}if(r.oauthEnv){let c=process.env[r.oauthEnv];if(c){if(r.oauthFileName){let l=avn(c);return{type:t,apiKey:"__oauth_file__",isDirectMode:!0,isOAuth:!0,oauthFileContent:l,model:e?.model,reasoningEffort:e?.reasoningEffort,maxContextSize:e?.maxContextSize,...i}}return{type:t,apiKey:c,isDirectMode:!0,isOAuth:!0,model:e?.model,reasoningEffort:e?.reasoningEffort,maxContextSize:e?.maxContextSize,...i}}}let a=r.oauthEnv?r.oauthFileName?`, or ${r.oauthEnv}`:`, oauthToken, or ${r.oauthEnv}`:"";throw new Error(`No API key found for ${t}. Set apiKey (gateway), providerApiKey (direct)${a}, or ${Dd} / ${r.apiKeyEnv} env var.`)}function cvn(e){return`e2b_${Buffer.from(e,"utf8").toString("hex")}`}var Z5t=new WeakSet;function Vxe(e){return Z5t.add(e),e}function X5t(e){return Z5t.has(e)}function e5t(e,t){return new Error(`${Dd} is set but ${e} failed to load.
643
+ \`\`\``:v}})}}return{sessionUpdate:"tool_call_update",toolCallId:u,status:d?"failed":"completed",content:p}}function c(l,u){let d=q0n[l]||"other",f=[],p=[],m=l;switch(l){case"Read":case"read_file":m=`Read ${u.file_path||u.absolute_path||"file"}`,(u.file_path||u.absolute_path)&&p.push({path:u.file_path||u.absolute_path});break;case"Write":case"write_file":m=`Write ${u.file_path||"file"}`,u.file_path&&(p.push({path:u.file_path}),f.push({type:"diff",path:u.file_path,oldText:null,newText:u.content||""}));break;case"Edit":case"edit_file":m=`Edit ${u.file_path||"file"}`,u.file_path&&p.push({path:u.file_path});break;case"Bash":case"shell":case"run_shell_command":m=u.command?`\`${u.command}\``:"Run command",u.description&&f.push({type:"content",content:{type:"text",text:u.description}});break;case"WebFetch":m=u.url?`Fetch ${u.url}`:"Web fetch";break;case"WebSearch":case"brave_web_search":m=u.query?`"${u.query}"`:"Web search";break;case"Glob":m=`Find ${u.pattern||"files"}`,u.path&&p.push({path:u.path});break;case"Grep":m=`grep "${u.pattern||""}"`;break;case"LS":case"list_directory":m=`List ${u.path||"directory"}`,u.path&&p.push({path:u.path});break;case"Task":m=u.description||"Subagent task";break;case"TodoWrite":m="Update todos";break;case"ExitPlanMode":m="Exit plan mode";break;default:m=l}return{title:m,kind:d,content:f,locations:p}}}function V5t(e){switch(e){case"claude":return d0n();case"codex":return f0n();case"gemini":return T0n();case"qwen":return V0n();case"kimi":return P0n();case"opencode":return L0n();case"droid":return m0n();default:return()=>null}}var $0n=(0,DK.promisify)(rU.execFile),QS="SKILL.md",G0n=(0,Zt.join)((0,W0.homedir)(),".cache","evolve","skills"),sTe=["skills","skills/.curated","skills/.experimental","skills/.system",".claude/skills"],H0n=/^([A-Za-z0-9._-]+)\/([A-Za-z0-9._-]+)(?:@(.+))?$/,z0n=/^[0-9a-f]{40}$/,j8t=2e3,Y8t=64*1024*1024,Hw=class extends Error{constructor(e){super(e),this.name="SkillRefError"}},z0=class extends Error{constructor(e){super(e),this.name="SkillResolveError"}};function W0n(e){return e==="~"?(0,W0.homedir)():e.startsWith("~/")?(0,Zt.join)((0,W0.homedir)(),e.slice(2)):e}function J0n(e){let t=e.indexOf("@");if(t===-1)return{base:e};let r=e.slice(t+1);if(!r)throw new Hw(`Empty @ref in skill reference segment: ${JSON.stringify(e)}`);return{base:e.slice(0,t),gitRef:r}}var j0n=/^[A-Za-z0-9._-]+$/;function qxe(e,t,r){if(!j0n.test(e))throw new Hw(`Cannot parse skill reference ${JSON.stringify(r)}: ${t} ${JSON.stringify(e)} may only contain letters, digits, ".", "_" and "-".`);return e}function Y0n(e){let t=String(e??"").trim();if(!t)throw new Hw("Skill reference cannot be empty.");if(t.startsWith("upload:")){let s=t.slice(7);if(!s)throw new Hw(`Skill upload reference ${JSON.stringify(t)} names no upload id.`);return{kind:"upload",id:s,raw:t}}if(t.startsWith("./")||t.startsWith("../")||t.startsWith("/")||t.startsWith("~"))return{kind:"local",path:W0n(t),raw:t};let r=t.match(/^(?:https?:\/\/)?(?:www\.)?skills\.sh\/(.+)$/);if(r){let s=r[1].replace(/\/+$/,"").split("/").filter(Boolean);if(s.length<2||s.length>3)throw new Hw(`Cannot parse skill reference ${JSON.stringify(t)}: expected skills.sh/<owner>/<repo> or skills.sh/<owner>/<repo>/<skill>, optionally @ref.`);let{base:o,gitRef:a}=J0n(s[s.length-1]);s[s.length-1]=o;let[c,l,u]=s;return qxe(c,"owner",t),qxe(l,"repo",t),u!==void 0&&qxe(u,"skill name",t),{kind:"git",host:"github.com",org:c,repo:l,...a?{gitRef:a}:{},...u?{skillName:u}:{},viaSkillsSh:!0,raw:t}}let n=t.match(/^https?:\/\/([^/]+)\/(.+)$/);if(n){let s=n[1],o=n[2].replace(/\/+$/,"").split("/").filter(Boolean);if(o.length<2)throw new Hw(`Git URL must have at least org/name in the path: ${JSON.stringify(t)}`);let a=o[0],c=o[1].replace(/\.git$/,""),l,u;return o.length>=4&&o[2]==="tree"&&(l=o[3],o.length>4&&(u=o.slice(4).join("/"))),{kind:"git",host:s,org:a,repo:c,...l?{gitRef:l}:{},...u?{subdir:u}:{},viaSkillsSh:!1,raw:t}}let i=t.match(H0n);if(i)return{kind:"git",host:"github.com",org:i[1],repo:i[2],...i[3]?{gitRef:i[3]}:{},viaSkillsSh:!1,raw:t};throw new Hw(`Cannot parse skill reference ${JSON.stringify(t)}. Expected skills.sh/<owner>/<repo>[/<skill>], org/repo[@ref], an https git URL, or a local folder path (prefix relative paths with './').`)}function $5t(e){return`https://${e.host}/${e.org}/${e.repo}.git`}function AK(e){return`https://${e.host}/${e.org}/${e.repo}`}async function G0(e,t){try{let{stdout:r}=await $0n("git",e,{cwd:t.cwd,timeout:t.timeoutMs,env:t.gitEnv??process.env,maxBuffer:16777216});return r}catch(r){let n=r,i=(n.stderr||n.message||"").trim();throw new z0(`git ${e[0]} failed${n.killed?" (timed out)":""}: ${i}`)}}async function K0n(e,t={}){if(e.gitRef&&z0n.test(e.gitRef))return e.gitRef;let r=e.gitRef??"HEAD",n=(await G0(["ls-remote",$5t(e),r,`${r}^{}`],{timeoutMs:t.lsRemoteTimeoutMs??3e4,gitEnv:t.gitEnv})).trim().split(`
644
+ `).filter(s=>s.length>0).map(s=>{let[o,a]=s.split(" ");return{sha:o,name:a}});if(n.length===0||!n[0].sha)throw new z0(`No matching ref ${JSON.stringify(r)} found in ${AK(e)}`);let i=n[0];return(n.find(s=>s.name===`${i.name}^{}`)??i).sha}async function K8t(e){let t=[],r=async i=>{let s=i===""?e:(0,Zt.join)(e,i),o=await(0,vr.readdir)(s,{withFileTypes:!0});for(let a of o){let c=i===""?a.name:`${i}/${a.name}`;a.isDirectory()?await r(c):a.isFile()&&t.push(c)}};await r(""),t.sort();let n=(0,Uu.createHash)("sha256");for(let i of t){let s=(0,Uu.createHash)("sha256").update(await(0,vr.readFile)((0,Zt.join)(e,i))).digest("hex");n.update(i),n.update("\0"),n.update(s),n.update("\0")}return`sha256:${n.digest("hex")}`}async function eU(e){try{return(await(0,vr.stat)(e)).isFile()}catch{return!1}}async function oTe(e){try{return(await(0,vr.stat)(e)).isDirectory()}catch{return!1}}async function Z8t(e,t){if(!await oTe(e))throw new z0(`Skill path does not exist or is not a directory: ${t}`);if(await eU((0,Zt.join)(e,QS)))return[e];let r=(await(0,vr.readdir)(e,{withFileTypes:!0})).filter(s=>s.isDirectory()&&!s.name.startsWith(".")).map(s=>s.name).sort(),n=[],i=[];for(let s of r)await eU((0,Zt.join)(e,s,QS))?i.push((0,Zt.join)(e,s)):n.push(s);if(n.length>0)throw new z0(`Skill root ${t} contains child directories without ${QS}: ${n.join(", ")}`);if(i.length===0)throw new z0(`Skill path ${t} must be a skill directory containing ${QS}, or a root whose immediate child directories each contain ${QS}.`);return i}async function Z0n(e){let t=new Map;await eU((0,Zt.join)(e,QS))&&t.set((0,Zt.basename)(e),e);for(let r of sTe){let n=(0,Zt.join)(e,r);if(!await oTe(n))continue;let i=await(0,vr.readdir)(n,{withFileTypes:!0});for(let s of i.sort((o,a)=>o.name<a.name?-1:1)){if(!s.isDirectory()||s.name.startsWith("."))continue;let o=(0,Zt.join)(n,s.name);await eU((0,Zt.join)(o,QS))&&t.set(s.name,o)}}return Array.from(t,([r,n])=>({dir:n,name:r}))}function X0n(e){return e.cacheDir??process.env.EVOLVE_SKILLS_CACHE??G0n}async function Q0n(e,t,r){let n=(0,Zt.join)(X0n(r),e.host,e.org,e.repo,t),i=(0,Zt.join)(n,e.repo),s=(0,Zt.join)(n,".evolve-complete");if(await eU(s)&&await oTe(i))return i;await(0,vr.mkdir)((0,Zt.dirname)(n),{recursive:!0});let o=await(0,vr.mkdtemp)(`${n}.tmp-`),a=(0,Zt.join)(o,e.repo),c=r.checkoutTimeoutMs??12e4,l={cwd:a,timeoutMs:c,gitEnv:r.gitEnv};try{await(0,vr.mkdir)(a),await G0(["init","--quiet"],l),await G0(["remote","add","origin",$5t(e)],l),e.subdir?(await G0(["sparse-checkout","init","--cone"],l),await G0(["sparse-checkout","set",e.subdir],l)):(await G0(["sparse-checkout","init","--cone"],l),await G0(["sparse-checkout","set",...sTe],l)),await G0(["fetch","--quiet","--depth=1","origin",t],l),await G0(["checkout","--quiet","FETCH_HEAD"],l),await(0,vr.rm)((0,Zt.join)(a,".git"),{recursive:!0,force:!0}),await(0,vr.writeFile)((0,Zt.join)(o,".evolve-complete"),""),await(0,vr.rm)(n,{recursive:!0,force:!0});try{await(0,vr.rename)(o,n)}catch{await(0,vr.rm)(o,{recursive:!0,force:!0})}return i}catch(u){throw await(0,vr.rm)(o,{recursive:!0,force:!0}),u}}async function X8t(e,t){let r=0,n=0,i=async s=>{let o=await(0,vr.readdir)(s,{withFileTypes:!0});for(let a of o){let c=(0,Zt.join)(s,a.name);if(a.isDirectory())await i(c);else if(a.isFile()&&(r+=1,n+=(await(0,vr.stat)(c)).size,r>j8t||n>Y8t))throw new z0(`Skill ${t} exceeds the size ceiling (${j8t} files / ${Y8t} bytes) \u2014 a skill is instructions, not a dataset.`)}};await i(e)}async function evn(e,t={}){let r=new Map;for(let n of e){let i=Y0n(n);if(i.kind==="upload")throw new z0(`Skill reference ${JSON.stringify(i.raw)} is a platform upload handle; only the hosted platform can resolve it. Use a skills.sh/git reference or a local folder here.`);if(i.kind==="local"){let c=await Z8t(i.path,i.raw);for(let l of c)await X8t(l,i.raw),r.set((0,Zt.basename)(l),{name:(0,Zt.basename)(l),dir:l,source:i.raw,digest:await K8t(l)});continue}let s=await K0n(i,t),o=await Q0n(i,s,t),a;if(i.subdir)a=(await Z8t((0,Zt.join)(o,i.subdir),`${i.raw} (${i.subdir})`)).map(c=>({dir:c,name:(0,Zt.basename)(c)}));else if(a=await Z0n(o),a.length===0)throw new z0(`No skills found in ${AK(i)}@${s.slice(0,12)}: expected ${QS} at the repo root or under ${sTe.join(", ")}.`);if(i.skillName){let c=a.filter(l=>l.name===i.skillName);if(c.length===0)throw new z0(`Skill ${JSON.stringify(i.skillName)} not found in ${AK(i)}@${s.slice(0,12)}. Available: ${a.map(l=>l.name).sort().join(", ")||"(none)"}`);a=c}for(let{dir:c,name:l}of a)await X8t(c,i.raw),r.set(l,{name:l,dir:c,source:i.raw,gitUrl:AK(i),gitCommit:s,digest:await K8t(c)})}return Array.from(r.values()).sort((n,i)=>n.name<i.name?-1:n.name>i.name?1:0)}function EK(e){return`'${e.replace(/'/g,"'\\''")}'`}async function tvn(e,t,r){if(t.length===0)return;let{tarGzipDirectory:n}=await Promise.resolve().then(()=>(D8t(),N8t));await e.files.makeDir(r);for(let i of t){let s=await n(i.dir),o=`${r}/.evolve-skill-${i.name}.tgz`,a=`${r}/${i.name}`;await e.files.write(o,s),await e.commands.run(`mkdir -p ${EK(a)} && tar -xzf ${EK(o)} -C ${EK(a)} && rm -f ${EK(o)}`,{timeoutMs:6e4})}}function BK(e){return e!==null&&typeof e=="object"&&"safeParse"in e&&typeof e.safeParse=="function"}function G5t(e){return JSON.stringify(Xke(e,{target:"jsonSchema7"}),null,2)}function H5t(e){return JSON.stringify(e,null,2)}var fc=class extends Error{field;constructor(e,t){super(t),this.name="EvolveConfigError",this.field=e}};function eTe(e){return typeof e=="string"&&e.trim()!==""}function pR(e){return e==null?String(e):JSON.stringify(e)}function z5t(e){if(!e)return;if(e.type!==void 0&&!Wyn(e.type))throw new fc("type",`Evolve agent config: unknown agent type ${pR(e.type)}. Valid types: ${Object.keys(J0).join(", ")}.`);let t=e.type??GK;if(e.model!==void 0&&!eTe(e.model))throw new fc("model",`Evolve agent config: "model" is empty (${pR(e.model)}). Pass a model id such as "${Jw(t).defaultModel}", or omit model entirely to use ${t}'s default.`);if(e.config!==void 0){if(!j5t(t))throw new fc("config",`Evolve agent config: agent "${t}" does not support a native config. Agents with native-config support: ${Y5t().join(", ")}.`);let r=e.config;if(typeof r=="string"){if(!eTe(r))throw new fc("config",`Evolve agent config: "config" is an empty path (${pR(r)}). Pass a local settings file path or an inline JSON object.`)}else if(!RK(r))throw new fc("config",`Evolve agent config: "config" must be a local file path or a JSON object, received ${pR(r)}.`)}e.preset!==void 0&&W5t(t,e.preset)}function W5t(e,t){if(!q8t.includes(t))throw new fc("preset",`Evolve agent config: unknown preset ${pR(t)}. Valid presets: ${q8t.join(", ")}.`);let r=nvn(t);if(!r.includes(e))throw new fc("preset",`Evolve agent config: agent "${e}" cannot guarantee preset "${t}". Agents that can: ${r.join(", ")}.`)}function rvn(e){let t=J0[e]?.presets;return t?Object.keys(t):[]}function nvn(e){return Object.keys(J0).filter(t=>rvn(t).includes(e))}function J5t(e,t){let r={...e};for(let[n,i]of Object.entries(t)){let s=r[n];if(RK(s)&&RK(i))r[n]=J5t(s,i);else if(Array.isArray(s)&&Array.isArray(i)){let o=[...s];for(let a of i)o.some(c=>mR(c)===mR(a))||o.push(a);r[n]=o}else r[n]=i}return r}function RK(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function j5t(e){return J0[e]?.nativeConfig!==void 0}function Y5t(){return Object.keys(J0).filter(j5t)}function ivn(e,t){if(t===void 0)return;let r=J0[e]?.nativeConfig;if(!r)throw new fc("config",`Evolve agent config: agent "${e}" does not support a native config. Agents with native-config support: ${Y5t().join(", ")}.`);let n;if(typeof t=="string"){let i=t.replace(/^~/,process.env.HOME||"");if(!Dg.existsSync(i))throw new fc("config",`Agent config file not found: ${i}`);let s=Dg.readFileSync(i,"utf-8");try{n=r.format==="toml"?f_(s):JSON.parse(s)}catch(o){throw new fc("config",`Invalid ${e} config file ${t}: ${o.message}`)}}else{let i;try{i=JSON.parse(JSON.stringify(t))}catch(s){throw new fc("config",`Invalid inline ${e} config: not JSON-serializable: ${s.message}`)}if(JSON.stringify(i)!==JSON.stringify(t))throw new fc("config",`Invalid inline ${e} config: expected a JSON object that can be represented without conversion`);n=i}if(!RK(n))throw new fc("config",`Invalid ${e} config: expected a ${r.format==="toml"?"TOML table":"JSON object"}.`);if(r.format==="toml"){let i;try{i=f_(dx(n))}catch(s){throw new fc("config",`Invalid ${e} config for TOML conversion: ${s.message}`)}if(mR(i)!==mR(n))throw new fc("config",`Invalid ${e} config: the document cannot be represented losslessly as TOML (TOML has no null and no mixed-type arrays)`)}return n}function mR(e){return Array.isArray(e)?`[${e.map(mR).join(",")}]`:e&&typeof e=="object"?`{${Object.entries(e).sort(([t],[r])=>t<r?-1:t>r?1:0).map(([t,r])=>`${JSON.stringify(t)}:${mR(r)}`).join(",")}}`:JSON.stringify(e)??"null"}function svn(e){if(!e||!eTe(e.prompt))throw new fc("prompt",`run() requires a non-empty "prompt" string, received ${pR(e?.prompt)}.`)}function ovn(e){if(e){for(let t of mU)if(t in e)throw new fc(`observability.${t}`,`Evolve observability metadata: "${t}" is reserved for session identity and would split this run across two dashboard sessions. Reserved keys: ${mU.join(", ")}. Use a different key, or set the session tag with .withSessionTagPrefix().`)}}function K5t(e){if(e.externalGateway){if(e.providerApiKey||e.providerBaseUrl||e.oauthToken)throw new Error("externalGateway cannot be combined with providerApiKey/providerBaseUrl/oauthToken (direct mode)");if(e.apiKey)throw new Error("externalGateway cannot be combined with apiKey (Evolve gateway mode)")}}function avn(e){let t=e.replace(/^~/,process.env.HOME||"");if(!Dg.existsSync(t))throw new Error(`OAuth file not found: ${t}`);return Dg.readFileSync(t,"utf-8")}function Q8t(e){let t=e?.type??GK,r=Jw(t),n=ivn(t,e?.config);e?.preset!==void 0&&W5t(t,e.preset);let i={...n!==void 0?{config:n}:{},...e?.preset!==void 0?{preset:e.preset}:{}};if(e?.externalGateway){K5t(e);let{apiKey:c,baseUrl:l,revoke:u}=e.externalGateway;if(!c||!l||typeof u!="function")throw new Error("externalGateway requires apiKey, baseUrl, and a revoke() function");return{type:t,apiKey:c,baseUrl:l,isDirectMode:!0,externalGateway:{revoke:u},model:e.model,reasoningEffort:e.reasoningEffort,maxContextSize:e.maxContextSize,...i}}if(e?.oauthToken){if(t!=="claude")throw new Error(`oauthToken is only supported for claude agent (Claude Max subscription), not ${t}. Use providerApiKey for ${t} instead.`);return{type:t,apiKey:e.oauthToken,isDirectMode:!0,isOAuth:!0,model:e.model,reasoningEffort:e.reasoningEffort,maxContextSize:e.maxContextSize,...i}}if(e?.providerApiKey){let c=r.baseUrlEnv?process.env[r.baseUrlEnv]:void 0,l=e.providerBaseUrl??c??r.defaultBaseUrl;return{type:t,apiKey:e.providerApiKey,baseUrl:l,isDirectMode:!0,model:e.model,reasoningEffort:e.reasoningEffort,maxContextSize:e.maxContextSize,...i}}if(e?.apiKey)return{type:t,apiKey:e.apiKey,isDirectMode:!1,model:e.model,reasoningEffort:e.reasoningEffort,maxContextSize:e.maxContextSize,...i};let s=process.env[Dd];if(s)return{type:t,apiKey:s,isDirectMode:!1,model:e?.model,reasoningEffort:e?.reasoningEffort,maxContextSize:e?.maxContextSize,...i};if(r.providerEnvMap){let c=(e?.model??r.defaultModel)?.split("/")[0],l=c?r.providerEnvMap[c]:void 0,u=l?process.env[l.keyEnv]:void 0;if(u){let d=(r.baseUrlEnv?process.env[r.baseUrlEnv]:void 0)??r.defaultBaseUrl;return{type:t,apiKey:u,baseUrl:d,isDirectMode:!0,model:e?.model,reasoningEffort:e?.reasoningEffort,maxContextSize:e?.maxContextSize,...i}}}let o=process.env[r.apiKeyEnv];if(o){let c=(r.baseUrlEnv?process.env[r.baseUrlEnv]:void 0)??r.defaultBaseUrl;return{type:t,apiKey:o,baseUrl:c,isDirectMode:!0,model:e?.model,reasoningEffort:e?.reasoningEffort,maxContextSize:e?.maxContextSize,...i}}if(r.oauthEnv){let c=process.env[r.oauthEnv];if(c){if(r.oauthFileName){let l=avn(c);return{type:t,apiKey:"__oauth_file__",isDirectMode:!0,isOAuth:!0,oauthFileContent:l,model:e?.model,reasoningEffort:e?.reasoningEffort,maxContextSize:e?.maxContextSize,...i}}return{type:t,apiKey:c,isDirectMode:!0,isOAuth:!0,model:e?.model,reasoningEffort:e?.reasoningEffort,maxContextSize:e?.maxContextSize,...i}}}let a=r.oauthEnv?r.oauthFileName?`, or ${r.oauthEnv}`:`, oauthToken, or ${r.oauthEnv}`:"";throw new Error(`No API key found for ${t}. Set apiKey (gateway), providerApiKey (direct)${a}, or ${Dd} / ${r.apiKeyEnv} env var.`)}function cvn(e){return`e2b_${Buffer.from(e,"utf8").toString("hex")}`}var Z5t=new WeakSet;function Vxe(e){return Z5t.add(e),e}function X5t(e){return Z5t.has(e)}function e5t(e,t){return new Error(`${Dd} is set but ${e} failed to load.
645
645
  Try installing: ${t}`)}function t5t(e){return e.message?.includes("Cannot find module")||e.message?.includes("MODULE_NOT_FOUND")}function $xe(e,t){if(!t||t.timeoutMs===void 0&&t.resources===void 0)return e;let r=e.create.bind(e);return e.create=(n={})=>r({...t.timeoutMs!==void 0?{timeoutMs:t.timeoutMs}:{},...t.resources!==void 0?{resources:t.resources}:{},...n}),e}async function aTe(e,t="e2b",r){let n=e||process.env[Dd];if(!n)throw new Error(`${Dd} is required for Evolve-managed sandbox features`);if(!uU.includes(t))throw new Error(`Unknown managed sandbox provider "${t}". Supported: ${uU.join(", ")}`);if(t==="daytona")try{let{createDaytonaProvider:i}=await Promise.resolve().then(()=>(dB(),j0e));return $xe(Vxe(i({apiKey:n,apiUrl:bR("daytona"),managedToolboxUrl:STe()})),r)}catch(i){let s=i;throw t5t(s)?e5t("@evolvingmachines/daytona","npm install @evolvingmachines/daytona"):s}if(t==="modal"){let{ManagedModalProvider:i}=await Promise.resolve().then(()=>(L8t(),F8t));return $xe(Vxe(new i({apiKey:n,baseUrl:bR("modal")})),r)}try{let{createE2BProvider:i}=await Promise.resolve().then(()=>(E1(),yne));return $xe(Vxe(i({apiKey:cvn(n),apiUrl:VK()})),r)}catch(i){let s=i;throw t5t(s)?e5t("@evolvingmachines/e2b","npm install @evolvingmachines/sdk"):s}}function Q5t(e="e2b",t){let r=typeof t=="string"?{apiKey:t}:t??{},{apiKey:n,...i}=r;return aTe(n,e,i)}async function lvn(){let e=process.env[dU];if(e)try{let{createE2BProvider:s}=await Promise.resolve().then(()=>(E1(),yne));return process.env.E2B_API_URL===VK()&&delete process.env.E2B_API_URL,s({apiKey:e})}catch(s){let o=s;throw o.message?.includes("Cannot find module")||o.message?.includes("MODULE_NOT_FOUND")?new Error(`${dU} is set but @evolvingmachines/e2b failed to load.
646
646
  Try reinstalling: npm install @evolvingmachines/sdk`):o}let t=process.env[fU];if(t)try{let{createDaytonaProvider:s}=await Promise.resolve().then(()=>(dB(),j0e));return s({apiKey:t})}catch(s){let o=s;throw o.message?.includes("Cannot find module")||o.message?.includes("MODULE_NOT_FOUND")?new Error(`${fU} is set but @evolvingmachines/daytona failed to load.
647
647
  Try installing: npm install @evolvingmachines/daytona`):o}let r=process.env[pU],n=process.env[$K];if(r&&n)try{let{createModalProvider:s}=await Promise.resolve().then(()=>(SK(),R8t));return s({tokenId:r,tokenSecret:n})}catch(s){let o=s;throw o.message?.includes("Cannot find module")||o.message?.includes("MODULE_NOT_FOUND")?new Error(`${pU} is set but @evolvingmachines/modal failed to load.
@@ -1224,7 +1224,7 @@ PY`,{timeoutMs:1e4})).exitCode!==0)throw new Error("Managed secret egress proxy
1224
1224
  `);d=P.pop()??"";for(let F of P){if(!F.trim())continue;let H=f(F);if(this.captureDroidSession(F,H),this.sessionLogger?.writeEventParsed(F,H),t?.onStdout?.(F+`
1225
1225
  `),H&&t?.onContent)for(let Y of H)t.onContent(Y)}},m=C=>{t?.onStderr?.(C)},v=await a.commands.spawn(c,{cwd:this.workingDir,timeoutMs:n,envs:u,onStdout:p,onStderr:m}),b=this.beginOperation("run",v,t,"run_start");if(this.hasRun=!0,i)return this.watchBackgroundOperation(b,"run",v,t,a),{sandboxId:a.sandboxId,sessionId:this.managedBrowserSession?.sessionId,browser:this.browserResponseInfo(),runId:l,exitCode:0,stdout:`Background process started with ID ${v.processId}`,stderr:""};let S;try{S=await v.wait()}catch(C){throw this.interruptedOperations.delete(b),this.finalizeOperation(b,t,"run_failed","error"),C}if(this.interruptedOperations.delete(b)||S.exitCode===130?this.finalizeOperation(b,t,"run_interrupted","interrupted"):S.exitCode===0?this.finalizeOperation(b,t,"run_complete","idle"):this.finalizeOperation(b,t,"run_failed","error"),d.trim()){let C=f(d);if(this.captureDroidSession(d,C),this.sessionLogger?.writeEventParsed(d,C),t?.onStdout?.(d+`
1226
1226
  `),C&&t?.onContent)for(let P of C)t.onContent(P)}await this.writeDroidSessionState(a),this.sessionLogger&&!i&&await this.flushSessionLoggerWithTimeout();let T;if(this.storage&&!i&&S.exitCode===0)try{T=await o5t(a,this.storage,this.agentConfig.type,this.workingDir,{tag:this.sessionTag,model:this.agentConfig.model||this.registry.defaultModel,workspaceMode:this.options.workspaceMode||"knowledge",comment:s,parentId:this.lastCheckpointId}),this.lastCheckpointId=T.id}catch(C){console.warn(`[Evolve] Auto-checkpoint failed: ${C.message}`)}return{sandboxId:a.sandboxId,sessionId:this.managedBrowserSession?.sessionId,browser:this.browserResponseInfo(),runId:l,exitCode:S.exitCode,stdout:S.stdout,stderr:S.stderr,checkpoint:T}}async executeCommand(e,t={},r){let{timeoutMs:n=hU,background:i=!1}=t;if(this.activeCommand)throw new Error("Agent is already running. Call interrupt(), wait for the active/background command to finish, or create a new Evolve instance.");let s=await this.getSandbox(r);this.credentialsSealed||await this.ensureProviderRuntimeToken(),this.lastRunTimestamp=Date.now(),this.requiresPreRunDashboardIngest()&&(this.ensureSessionLogger(s),this.sessionLogger?.writePrompt(e),await this.flushSessionLoggerWithTimeout());let o="",a="",c=m=>{o+=m,r?.onStdout?.(m)},l=m=>{a+=m,r?.onStderr?.(m)},u=this.credentialsSealed?{}:this.buildProviderRuntimeProcessEnvs(),d=await s.commands.spawn(e,{cwd:this.workingDir,timeoutMs:n,envs:Object.keys(u).length>0?u:void 0,onStdout:c,onStderr:l}),f=this.beginOperation("command",d,r,"command_start");if(i)return this.watchBackgroundOperation(f,"command",d,r),{sandboxId:s.sandboxId,sessionId:this.managedBrowserSession?.sessionId,browser:this.browserResponseInfo(),exitCode:0,stdout:`Background process started with ID ${d.processId}`,stderr:""};let p;try{p=await d.wait()}catch(m){throw this.interruptedOperations.delete(f),this.finalizeOperation(f,r,"command_failed","error"),m}return this.interruptedOperations.delete(f)||p.exitCode===130?this.finalizeOperation(f,r,"command_interrupted","interrupted"):p.exitCode===0?this.finalizeOperation(f,r,"command_complete","idle"):this.finalizeOperation(f,r,"command_failed","error"),{sandboxId:s.sandboxId,sessionId:this.managedBrowserSession?.sessionId,browser:this.browserResponseInfo(),exitCode:p.exitCode,stdout:o||p.stdout||"",stderr:a||p.stderr||""}}async sealCredentials(){if(!this.credentialsSealed){if(!this.sandbox)throw new Error("No active sandbox. Call run() or executeCommand() first.");if(this.activeCommand)throw new Error("Cannot seal credentials while a process is running.");if(this.agentConfig.isDirectMode&&!this.agentConfig.externalGateway)throw new Error("Credential sealing requires gateway mode; direct provider credentials cannot be revoked by Evolve");if([this.options.secrets&&Object.keys(this.options.secrets).length>0,this.options.sandboxCreateOptions?.envs&&Object.keys(this.options.sandboxCreateOptions.envs).length>0,this.options.managedSecrets,this.options.integrations,this.options.mcpServers&&Object.keys(this.options.mcpServers).length>0,this.options.managedBrowser,this.options.browserCredentials].some(Boolean))throw new Error("Credential sealing requires a credential-minimal sandbox: omit secrets, managed secrets, integrations, MCP servers, and browser credentials");if(this.agentConfig.externalGateway){await this.agentConfig.externalGateway.revoke(),this.credentialsSealed=!0;return}if(!this.providerRuntimeToken||!this.options.providerRouting)throw new Error("Cannot seal credentials: no active provider runtime token to revoke. Without a gateway-issued runtime token the sandbox may hold credentials Evolve cannot revoke, so sealing would be a false guarantee.");await this.closeProviderRuntimeToken(!0),this.credentialsSealed=!0}}isSealed(){return this.credentialsSealed}async collectArtifacts(e){if(!this.credentialsSealed)throw new Error("Call sealCredentials() before collecting artifacts.");if(!this.sandbox)throw new Error("No active sandbox.");if(this.activeCommand)throw new Error("Cannot collect artifacts while a process is running.");return Ybn(this.sandbox,this.workingDir,e)}async uploadContext(e){let t=await this.getSandbox();await this.uploadContextFiles(t,e)}async uploadFiles(e){let t=await this.getSandbox();await this.uploadWorkspaceFiles(t,e)}async uploadFileFromPath(e,t){let r=await this.getSandbox(),n=e.startsWith("/")?e:`${this.workingDir}/${e}`,i=n.substring(0,n.lastIndexOf("/"));if(i&&await r.commands.run(`mkdir -p ${i}`,{timeoutMs:3e4}),r.files.writeFromPath){await r.files.writeFromPath(n,t);return}let{readFile:s}=await import("fs/promises");await r.files.write(n,await s(t))}async getOutputFiles(e=!1){let t=await this.getSandbox(),r=`${this.workingDir}/output`,n=e?"":"-maxdepth 1",i=(await t.commands.run(`find ${r} ${n} -type f -exec stat -c '%n|%Z' {} \\; 2>/dev/null || true`,{timeoutMs:3e4})).stdout.split(`
1227
- `).filter(Boolean),s=this.lastRunTimestamp?Math.floor(this.lastRunTimestamp/1e3)-2:0,o=[],a=`${r}/`;for(let f of i){let[p,m]=f.split("|");if(!p||!m)continue;let v=parseInt(m,10);s>0&&v<s||o.push(p)}let c={},l=await Promise.all(o.map(async f=>{try{let p=await t.files.read(f);return{relativePath:f.startsWith(a)?f.slice(a.length):f.split("/").pop()||f,content:p}}catch{return null}}));for(let f of l)f&&(c[f.relativePath]=f.content);if(!this.zodSchema&&!this.jsonSchema)return{files:c,data:null};let u=c["result.json"];if(!u)return{files:c,data:null,error:"Schema provided but agent did not create output/result.json"};let d=typeof u=="string"?u:new TextDecoder().decode(u);try{let f=JSON.parse(d);if(this.zodSchema){let p=this.zodSchema.safeParse(f);return p.success?{files:c,data:p.data}:{files:c,data:null,error:`Schema validation failed: ${p.error.message}`,rawData:d}}if(this.compiledValidator){if(this.compiledValidator(f))return{files:c,data:f};{let p=this.compiledValidator.errors?.map(m=>`${m.instancePath} ${m.message}`).join(", ")||"Unknown validation error";return{files:c,data:null,error:`Schema validation failed: ${p}`,rawData:d}}}return{files:c,data:null}}catch(f){return{files:c,data:null,error:`Failed to parse result.json: ${f.message}`,rawData:d}}}async checkpoint(e){if(!this.storage)throw new Error("Storage not configured. Call .withStorage().");if(!this.sandbox)throw new Error("No active sandbox. Call run() first.");let t=await o5t(this.sandbox,this.storage,this.agentConfig.type,this.workingDir,{tag:this.sessionTag,model:this.agentConfig.model||this.registry.defaultModel,workspaceMode:this.options.workspaceMode||"knowledge",comment:e?.comment,parentId:this.lastCheckpointId});return this.lastCheckpointId=t.id,t}getSession(){return this.sandbox?.sandboxId||this.options.sandboxId||null}async setSession(e){if(this.credentialsSealed)throw new Error("Agent credentials are sealed and this Evolve instance cannot switch sandboxes");if(this.options.managedSecrets)throw new Error("setSession() cannot be used with managed secrets; managed secret grants are sandbox-scoped.");if(this.options.sandboxCreateOptions?.user)throw new Error("setSession() cannot be used with a configured sandbox user; the user cannot be enforced on an existing sandbox.");if(this.activeCommand&&!await this.interrupt())throw new Error("Cannot switch session while an active process is running and could not be interrupted.");await this.rotateSession(),await this.closeProviderRuntimeToken(),await this.closeManagedSecretRuntimeToken(),await this.closeManagedBrowserSession(),this.options.sandboxId=e,this.sandbox=void 0,this.interruptedOperations.clear(),this.invalidateActiveOperation(),this.sandboxState="ready",this.agentState="idle",this.hasRun=!0,this.lastCheckpointId=void 0}async pause(e){this.sandbox&&(this.activeCommand&&await this.interrupt(e),await this.sandbox.pause(),this.sandboxState="paused",this.agentState="idle",this.emitLifecycle(e,"sandbox_pause"))}async resume(e){this.sandbox&&this.options.sandboxProvider&&(this.sandbox=await this.options.sandboxProvider.connect(this.sandbox.sandboxId),this.sandboxState="ready",this.agentState="idle",this.emitLifecycle(e,"sandbox_resume"))}async interrupt(e){if(!this.activeCommand&&!this.activeProcessId)return!1;let t=this.activeOperationId,r=this.activeOperationKind,n=!1;try{this.activeCommand?n=await this.activeCommand.kill():this.sandbox&&this.activeProcessId&&(n=await this.sandbox.commands.kill(this.activeProcessId))}catch{n=!1}if(!n)return this.sandboxState="running",this.agentState="running",!1;t!==null&&this.interruptedOperations.add(t),this.invalidateActiveOperation(),this.sandboxState="ready",this.agentState="interrupted";let i=r==="run"?"run_interrupted":"command_interrupted";return this.emitLifecycle(e,i),n}status(){let e=this.browserRuntimeInfo();return{sandboxId:this.getSession(),sandbox:this.sandboxState,agent:this.agentState,activeProcessId:this.activeProcessId,hasRun:this.hasRun,timestamp:new Date().toISOString(),...e?{browser:e}:{}}}async kill(e){await this.rotateSession();let t;try{this.activeCommand&&await this.interrupt(e),this.sandbox&&(await this.sandbox.kill(),this.sandbox=void 0)}catch(r){t=r}finally{await this.closeProviderRuntimeToken(),await this.closeManagedSecretRuntimeToken(),await this.closeManagedBrowserSession()}if(t)throw t;this.options.sandboxId=void 0,this.interruptedOperations.clear(),this.invalidateActiveOperation(),this.sandboxState="stopped",this.agentState="idle",this.hasRun=!1,this.lastCheckpointId=void 0,this.emitLifecycle(e,"sandbox_killed")}async getHost(e){return(await this.getSandbox()).getHost(e)}getAgentType(){return this.agentConfig.type}getSessionTag(){return!this.sandbox&&!this.sessionLogger?null:this.sessionTag}getSessionTimestamp(){return this.sessionLogger?.getTimestamp()||null}async flushObservability(){await this.sessionLogger?.flush()}async rotateSession(){let e=!!this.sessionLogger;this.sessionLogger&&(await this.sessionLogger.close(),this.sessionLogger=void 0),e&&(this.previousSessionTag=this.sessionTag),this.sessionTag=I5t(this.options.sessionTagPrefix||"evolve")}async fetchSpend(e){if(this.agentConfig.isDirectMode)throw new Error("Cost tracking requires gateway mode (set EVOLVE_API_KEY).");let t=this.agentConfig.apiKey;if(!t)throw new Error("Cost tracking requires an API key.");let r=process.env.EVOLVE_DASHBOARD_URL||oa,n=await fetch(`${r}/api/sessions/spend?${e}`,{headers:{Authorization:`Bearer ${t}`},signal:AbortSignal.timeout(1e4)});if(!n.ok){let i=await n.text().catch(()=>"");throw new Error(`Spend query failed (${n.status}): ${i}`)}return n}resolveSpendTag(){if(this.sandbox||this.sessionLogger)return this.sessionTag;if(this.previousSessionTag)return this.previousSessionTag;throw new Error("No session to query. Call run() first.")}normalizeRunCost(e,t){return{...e,asOf:e.asOf??t.asOf,isComplete:e.isComplete??t.isComplete,truncated:e.truncated??t.truncated}}normalizeSessionCost(e){let t={asOf:e.asOf,isComplete:e.isComplete,truncated:e.truncated};return{...e,runs:e.runs.map(r=>this.normalizeRunCost(r,t))}}async getSessionCost(){let e=this.resolveSpendTag(),t=new URLSearchParams({tag:e}),r=await(await this.fetchSpend(t)).json();return this.normalizeSessionCost(r)}async getRunCost(e){let t=this.resolveSpendTag();if("runId"in e){let s=new URLSearchParams({tag:t,runId:e.runId}),o=await(await this.fetchSpend(s)).json();return this.normalizeRunCost(o,{asOf:new Date().toISOString(),isComplete:!1,truncated:!1})}let r=await this.getSessionCost(),n=e.index>0?e.index-1:r.runs.length+e.index,i=r.runs[n];if(!i)throw new Error(`Run index ${e.index} out of range. Session has ${r.runs.length} run(s).`);return i}};function tSn(e){return(e||process.env.EVOLVE_DASHBOARD_URL||oa).replace(/\/$/,"")}function rSn(e){let t=e||process.env.EVOLVE_API_KEY;if(!t)throw new Error("Browser profiles require EVOLVE_API_KEY or an explicit apiKey");return t}async function nSn(e){return await e.text().catch(()=>"")}async function x5t(e,t,r={}){let n=await fetch(`${tSn(e?.dashboardUrl)}${t}`,{...r,headers:{Authorization:`Bearer ${rSn(e?.apiKey)}`,accept:"application/json",...r.body?{"content-type":"application/json"}:{},...r.headers||{}}});if(!n.ok)throw new Error(`Browser profiles request failed (${n.status}): ${await nSn(n)}`);return n.status===204?{}:await n.json()}var iSn=class{constructor(e={}){this.config=e}toMetadata(e){return{id:e.id,profile:e.profile,createdAt:e.createdAt||e.created_at||"",updatedAt:e.updatedAt||e.updated_at||"",lastUsedAt:e.lastUsedAt??e.last_used_at??null}}async list(){return{profiles:(await x5t(this.config,"/api/browser-profiles")).profiles.map(e=>this.toMetadata(e))}}async delete(e){return await x5t(this.config,"/api/browser-profiles",{method:"DELETE",body:JSON.stringify(e)})}};function sSn(e={}){return new iSn(e)}var Yw=class extends A5t.EventEmitter{config={};agent;fallbackSandboxState="stopped";fallbackAgentState="idle";fallbackHasRun=!1;constructor(){super()}on(e,t){return super.on(e,t)}off(e,t){return super.off(e,t)}emit(e,...t){return super.emit(e,...t)}withAgent(e){return e&&(z5t(e),K5t(e),this.config.agent=e,this._cachedGatewayOverrides=null),this}withSandbox(e){return this.config.sandbox=e,this}withSandboxCreateOptions(e){return this.config.sandboxCreateOptions={...e,envs:e.envs?{...e.envs}:void 0,metadata:e.metadata?{...e.metadata}:void 0},this}withWorkingDirectory(e){return this.config.workingDirectory=e,this}withWorkspaceMode(e){return this.config.workspaceMode=e,this}withSecrets(e){return this.config.secrets={...this.config.secrets,...e},this}withManagedSecrets(e){return this.config.managedSecrets=e,this}withSession(e){return this.config.sandboxId=e,this.agent||(this.fallbackSandboxState="ready",this.fallbackAgentState="idle",this.fallbackHasRun=!0),this}withSystemPrompt(e){return this.config.systemPrompt=e,this}withContext(e){return this.config.context={...this.config.context,...e},this}withFiles(e){return this.config.files={...this.config.files,...e},this}withMcpServers(e){return this.config.mcpServers={...this.config.mcpServers,...e},this}withBrowser(e={provider:"agent-browser",remote:!0}){return e===!1?delete this.config.browser:this.config.browser=e,this}withBrowserCredentials(e={}){return this.config.browserCredentials=e,this}withPlugins(e){let t=Array.isArray(e)?e:[e];return this.config.plugins=[...this.config.plugins??[],...t],this}withSkills(e){return this.config.skills=e,this}withSchema(e,t){return this.config.schema=e,t&&(BK(e)?console.warn("[Evolve] schemaOptions ignored for Zod schemas - use .passthrough(), .strip(), z.coerce instead"):this.config.schemaOptions=t),this}withSessionTagPrefix(e){return this.config.sessionTagPrefix=e,this}withObservability(e){return this.config.observability={...this.config.observability,...e},this}withIntegrations(e){return this.config.integrations=e,this}withStorage(e){return this.config.storage=e||{},this}static integrations=Hvn;static browserCredentials=bbn;static browserProfiles=sSn;static managedSecrets=Dbn;async initializeAgent(){let e=Q8t(this.config.agent),t=Jw(e.type);if(this.config.integrations&&e.isDirectMode)throw new Error("withIntegrations() is available only in gateway mode with EVOLVE_API_KEY");if(this.config.managedSecrets&&e.isDirectMode)throw new Error("withManagedSecrets() is available only in gateway mode with EVOLVE_API_KEY");if(this.config.managedSecrets&&this.config.sandboxId)throw new Error("withManagedSecrets() cannot be used with withSession(); managed secret grants are sandbox-scoped.");let r=$bn(this.config.managedSecrets,t);if(r&&this.config.sandbox&&!X5t(this.config.sandbox))throw new Error("withManagedSecrets() requires an Evolve-managed sandbox; remove withSandbox() or pass a managed sandbox provider.");let n=this.config.sandbox??(r?await aTe(e.apiKey):await lvn()),i={},s,o,a=this.config.skills,c;if(this.config.browser){let d=lbn(this.config.browser);if(c=d,d.provider==="browser-use"){if(e.isDirectMode)throw new Error('withBrowser("browser-use") requires gateway mode. Use apiKey/EVOLVE_API_KEY instead of providerApiKey/direct mode.');i=_Te(e.apiKey)}if((d.provider==="actionbook"||d.provider==="agent-browser")&&d.managed){if(e.isDirectMode)throw new Error(`Managed browser provider "${d.provider}" requires gateway mode. Use apiKey/EVOLVE_API_KEY instead of providerApiKey/direct mode.`);s=d.provider==="actionbook"?Avn:kvn,o={provider:d.provider,apiKey:e.apiKey,dashboardUrl:process.env.EVOLVE_DASHBOARD_URL||oa,...d.profile?{profile:d.profile}:{}}}if(d.profile&&!d.managed)throw new Error('withBrowser({ profile }) requires managed remote browser mode. Use .withBrowser({ profile }) or .withBrowser({ provider: "agent-browser", remote: true, profile }).')}if(this.config.browserCredentials!==void 0){if(this.config.sandboxId)throw new Error("withBrowserCredentials() cannot be used with withSession(); browser login tokens are run-scoped.");if(e.isDirectMode)throw new Error("withBrowserCredentials() requires gateway mode. Use apiKey/EVOLVE_API_KEY instead of providerApiKey/direct mode.");if(!c||c.provider!=="agent-browser"||!c.managed)throw new Error('withBrowserCredentials() requires .withBrowser() or .withBrowser({ provider: "agent-browser", remote: true }).');if(this.config.mcpServers?.["browser-login"])throw new Error('withBrowserCredentials() reserves the "browser-login" MCP server name.')}let l=this.config.storage!==void 0?e7t(this.config.storage,!e.isDirectMode,oa,e.isDirectMode?void 0:e.apiKey):void 0,u={sandboxProvider:n,sandboxCreateOptions:this.config.sandboxCreateOptions,secrets:this.config.secrets,managedSecrets:r?{secrets:r,apiKey:e.apiKey,dashboardUrl:process.env.EVOLVE_DASHBOARD_URL||oa}:void 0,sandboxId:this.config.sandboxId,workingDirectory:this.config.workingDirectory,workspaceMode:this.config.workspaceMode,systemPrompt:this.config.systemPrompt,context:this.config.context,files:this.config.files,mcpServers:{...i,...this.config.mcpServers},browserPrompt:s,managedBrowser:o,browserCredentials:this.config.browserCredentials!==void 0?{apiKey:e.apiKey,dashboardUrl:process.env.EVOLVE_DASHBOARD_URL||oa,config:this.config.browserCredentials}:void 0,plugins:this.config.plugins,skills:a,schema:this.config.schema,schemaOptions:this.config.schemaOptions,sessionTagPrefix:this.config.sessionTagPrefix,observability:this.config.observability,integrations:this.config.integrations?{...this.config.integrations,apiKey:e.apiKey,dashboardUrl:process.env.EVOLVE_DASHBOARD_URL||oa}:void 0,providerRouting:e.isDirectMode?void 0:{apiKey:e.apiKey,dashboardUrl:process.env.EVOLVE_DASHBOARD_URL||oa},storage:l};this.agent=new eSn(e,u)}createStreamCallbacks(){let e=this.listenerCount("stdout")>0,t=this.listenerCount("stderr")>0,r=this.listenerCount("content")>0,n=this.listenerCount("lifecycle")>0;return{onStdout:e?i=>this.emit("stdout",i):void 0,onStderr:t?i=>this.emit("stderr",i):void 0,onContent:r?i=>this.emit("content",i):void 0,onLifecycle:n?i=>this.emit("lifecycle",i):void 0}}emitLifecycleFromStatus(e){if(this.listenerCount("lifecycle")===0)return;let t=this.status();this.emit("lifecycle",{sandboxId:t.sandboxId,sandbox:t.sandbox,agent:t.agent,timestamp:new Date().toISOString(),reason:e,...t.browser?{browser:t.browser}:{}})}async run({prompt:e,timeoutMs:t,background:r,from:n,checkpointComment:i}){if(n&&this.config.sandboxId)throw new Error("Cannot use 'from' with 'withSession()' \u2014 restore requires a fresh sandbox.");this.agent||await this.initializeAgent();let s=this.createStreamCallbacks();return this.agent.run({prompt:e,timeoutMs:t,background:r,from:n,checkpointComment:i},s)}async executeCommand(e,t={}){this.agent||await this.initializeAgent();let r=this.createStreamCallbacks();return this.agent.executeCommand(e,t,r)}async prepareSandbox(){this.agent||await this.initializeAgent();let e=this.createStreamCallbacks();return(await this.agent.getSandbox(e)).sandboxId}async sealCredentials(){if(!this.agent)throw new Error("Agent not initialized. Call run() or executeCommand() first.");await this.agent.sealCredentials()}isSealed(){return this.agent?.isSealed()??!1}resolvedSkills(){return this.agent?.resolvedSkills()??[]}async collectArtifacts(e){if(!this.agent)throw new Error("Agent not initialized. Call run() or executeCommand() first.");return this.agent.collectArtifacts(e)}async interrupt(){if(!this.agent)return!1;let e=this.createStreamCallbacks();return this.agent.interrupt(e)}async uploadContext(e){return this.agent||await this.initializeAgent(),this.agent.uploadContext(e)}async uploadFiles(e){return this.agent||await this.initializeAgent(),this.agent.uploadFiles(e)}async uploadFileFromPath(e,t){return this.agent||await this.initializeAgent(),this.agent.uploadFileFromPath(e,t)}async getOutputFiles(e=!1){if(!this.agent)throw new Error("Agent not initialized. Call run() first.");return this.agent.getOutputFiles(e)}async checkpoint(e){if(!this.agent)throw new Error("Agent not initialized. Call run() first.");return this.agent.checkpoint(e)}_cachedGatewayOverrides=null;resolveGatewayOverrides(){if(this._cachedGatewayOverrides!==null)return this._cachedGatewayOverrides||void 0;try{let e=Q8t(this.config.agent);if(!e.isDirectMode)return this._cachedGatewayOverrides={gatewayUrl:oa,gatewayApiKey:e.apiKey},this._cachedGatewayOverrides}catch{}this._cachedGatewayOverrides=void 0}async listCheckpoints(e){if(this.config.storage===void 0)throw new Error("Storage not configured. Call .withStorage().");return f5t(this.config.storage,this.resolveGatewayOverrides()||{}).listCheckpoints(e)}storage(){if(this.config.storage===void 0)throw new Error("Storage not configured. Call .withStorage().");return f5t(this.config.storage,this.resolveGatewayOverrides()||{})}getSession(){return this.agent?this.agent.getSession():this.config.sandboxId??null}async setSession(e){if(this.config.managedSecrets)throw new Error("setSession() cannot be used with withManagedSecrets(); managed secret grants are sandbox-scoped.");this.agent?await this.agent.setSession(e):(this.fallbackSandboxState="ready",this.fallbackAgentState="idle",this.fallbackHasRun=!0),this.config.sandboxId=e}status(){return this.agent?this.agent.status():{sandboxId:this.config.sandboxId??null,sandbox:this.fallbackSandboxState,agent:this.fallbackAgentState,activeProcessId:null,hasRun:this.fallbackHasRun,timestamp:new Date().toISOString()}}async pause(){if(this.agent){let e=this.createStreamCallbacks();await this.agent.pause(e);return}this.config.sandboxId&&this.config.sandbox&&(await(await this.config.sandbox.connect(this.config.sandboxId)).pause(),this.fallbackSandboxState="paused",this.fallbackAgentState="idle",this.emitLifecycleFromStatus("sandbox_pause"))}async resume(){if(this.agent){let e=this.createStreamCallbacks();await this.agent.resume(e);return}this.config.sandboxId&&this.config.sandbox&&(await this.config.sandbox.connect(this.config.sandboxId),this.fallbackSandboxState="ready",this.fallbackAgentState="idle",this.emitLifecycleFromStatus("sandbox_resume"))}async kill(){if(this.agent){let e=this.createStreamCallbacks();await this.agent.kill(e),this.config.sandboxId=void 0,this.fallbackSandboxState="stopped",this.fallbackAgentState="idle",this.fallbackHasRun=!1;return}this.config.sandboxId&&this.config.sandbox&&(await(await this.config.sandbox.connect(this.config.sandboxId)).kill(),this.fallbackSandboxState="stopped",this.fallbackAgentState="idle",this.fallbackHasRun=!1,this.emitLifecycleFromStatus("sandbox_killed"),this.config.sandboxId=void 0)}async getHost(e){return this.agent||await this.initializeAgent(),this.agent.getHost(e)}getSessionTag(){return this.agent?.getSessionTag()||null}getSessionTimestamp(){return this.agent?.getSessionTimestamp()||null}async flushObservability(){await this.agent?.flushObservability()}async getSessionCost(){if(!this.agent)throw new Error("No agent initialized. Call run() first.");return this.agent.getSessionCost()}async getRunCost(e){if(!this.agent)throw new Error("No agent initialized. Call run() first.");return this.agent.getRunCost(e)}},oSn=class{permits;queue=[];constructor(e){if(e<1)throw new Error("Semaphore max must be >= 1");this.permits=e}async use(e){await this.acquire();try{return await e()}finally{this.release()}}acquire(){return this.permits>0?(this.permits--,Promise.resolve()):new Promise(e=>this.queue.push(e))}release(){this.queue.length>0?this.queue.shift()():this.permits++}},Z3=Symbol.for("evolve.SwarmResult"),T5t=class _7t extends Array{get success(){return this.filter(t=>t.status==="success")}get filtered(){return this.filter(t=>t.status==="filtered")}get error(){return this.filter(t=>t.status==="error")}static from(t){let r=new _7t;return r.push(...t),r}},wZn=class PK{config;semaphore;constructor(t={}){let r=t.concurrency??ITe;if(r>HK)throw new Error(`concurrency=${r} exceeds max ${HK}. For higher parallelism, scale horizontally with multiple processes.`);this.config={agent:t.agent,sandbox:t.sandbox,tag:t.tag??"swarm",concurrency:r,timeoutMs:t.timeoutMs??hU,workspaceMode:t.workspaceMode??"knowledge",retry:t.retry,mcpServers:t.mcpServers,skills:t.skills,integrations:t.integrations},this.semaphore=new oSn(this.config.concurrency)}async map(t){let{items:r,prompt:n,bestOf:i,verify:s}=t,o=t.retry??this.config.retry,a=this.generateOperationId(),c=t.timeoutMs??this.config.timeoutMs;if(i&&s)throw new Error("map() cannot use both bestOf and verify options simultaneously");let l=await Promise.all(r.map((u,d)=>i?this.executeMapItemWithBestOf(u,n,d,a,t,c,o):s?this.executeMapItemWithVerify(u,n,d,a,t,c,o):o?V0(f=>this.executeMapItem(u,n,d,a,t,c,f),o,d):this.executeMapItem(u,n,d,a,t,c)));return T5t.from(l)}async filter(t){let{items:r,prompt:n,condition:i,verify:s}=t,o=t.retry??this.config.retry,a=this.generateOperationId(),c=t.timeoutMs??this.config.timeoutMs,l=await Promise.all(r.map((d,f)=>s?this.executeFilterItemWithVerify(d,n,f,a,t,c,o):o?V0(p=>this.executeFilterItem(d,n,f,a,t,c,p),o,f):this.executeFilterItem(d,n,f,a,t,c))),u=[];for(let d of l)if(d.status==="error")u.push(d);else if(d.data!==null)try{i(d.data)?u.push(d):u.push({...d,status:"filtered"})}catch(f){u.push({...d,status:"error",data:null,error:`Condition function threw: ${f.message}`})}return T5t.from(u)}async reduce(t){let{items:r,prompt:n,verify:i}=t,s=t.retry??this.config.retry,o=this.generateOperationId(),a=t.timeoutMs??this.config.timeoutMs,c=[],l=[];r.forEach((P,F)=>{c.push(this.getFiles(P)),l.push(this.getIndex(P,F))});let u={};c.forEach((P,F)=>{Object.entries(P).forEach(([H,Y])=>{u[`item_${l[F]}/${H}`]=Y})});let d=Gxe(u),f=Ww(Dvn,{fileTree:d}),p=t.systemPrompt?`${f}
1227
+ `).filter(Boolean),s=this.lastRunTimestamp?Math.floor(this.lastRunTimestamp/1e3)-2:0,o=[],a=`${r}/`;for(let f of i){let[p,m]=f.split("|");if(!p||!m)continue;let v=parseInt(m,10);s>0&&v<s||o.push(p)}let c={},l=await Promise.all(o.map(async f=>{try{let p=await t.files.read(f);return{relativePath:f.startsWith(a)?f.slice(a.length):f.split("/").pop()||f,content:p}}catch{return null}}));for(let f of l)f&&(c[f.relativePath]=f.content);if(!this.zodSchema&&!this.jsonSchema)return{files:c,data:null};let u=c["result.json"];if(!u)return{files:c,data:null,error:"Schema provided but agent did not create output/result.json"};let d=typeof u=="string"?u:new TextDecoder().decode(u);try{let f=JSON.parse(d);if(this.zodSchema){let p=this.zodSchema.safeParse(f);return p.success?{files:c,data:p.data}:{files:c,data:null,error:`Schema validation failed: ${p.error.message}`,rawData:d}}if(this.compiledValidator){if(this.compiledValidator(f))return{files:c,data:f};{let p=this.compiledValidator.errors?.map(m=>`${m.instancePath} ${m.message}`).join(", ")||"Unknown validation error";return{files:c,data:null,error:`Schema validation failed: ${p}`,rawData:d}}}return{files:c,data:null}}catch(f){return{files:c,data:null,error:`Failed to parse result.json: ${f.message}`,rawData:d}}}async checkpoint(e){if(!this.storage)throw new Error("Storage not configured. Call .withStorage().");if(!this.sandbox)throw new Error("No active sandbox. Call run() first.");let t=await o5t(this.sandbox,this.storage,this.agentConfig.type,this.workingDir,{tag:this.sessionTag,model:this.agentConfig.model||this.registry.defaultModel,workspaceMode:this.options.workspaceMode||"knowledge",comment:e?.comment,parentId:this.lastCheckpointId});return this.lastCheckpointId=t.id,t}getSession(){return this.sandbox?.sandboxId||this.options.sandboxId||null}async setSession(e){if(this.credentialsSealed)throw new Error("Agent credentials are sealed and this Evolve instance cannot switch sandboxes");if(this.options.managedSecrets)throw new Error("setSession() cannot be used with managed secrets; managed secret grants are sandbox-scoped.");if(this.options.sandboxCreateOptions?.user)throw new Error("setSession() cannot be used with a configured sandbox user; the user cannot be enforced on an existing sandbox.");if(this.activeCommand&&!await this.interrupt())throw new Error("Cannot switch session while an active process is running and could not be interrupted.");await this.rotateSession(),await this.closeProviderRuntimeToken(),await this.closeManagedSecretRuntimeToken(),await this.closeManagedBrowserSession(),this.options.sandboxId=e,this.sandbox=void 0,this.interruptedOperations.clear(),this.invalidateActiveOperation(),this.sandboxState="ready",this.agentState="idle",this.hasRun=!0,this.lastCheckpointId=void 0}async pause(e){this.sandbox&&(this.activeCommand&&await this.interrupt(e),await this.sandbox.pause(),this.sandboxState="paused",this.agentState="idle",this.emitLifecycle(e,"sandbox_pause"))}async resume(e){this.sandbox&&this.options.sandboxProvider&&(this.sandbox=await this.options.sandboxProvider.connect(this.sandbox.sandboxId),this.sandboxState="ready",this.agentState="idle",this.emitLifecycle(e,"sandbox_resume"))}async interrupt(e){if(!this.activeCommand&&!this.activeProcessId)return!1;let t=this.activeOperationId,r=this.activeOperationKind,n=!1;try{this.activeCommand?n=await this.activeCommand.kill():this.sandbox&&this.activeProcessId&&(n=await this.sandbox.commands.kill(this.activeProcessId))}catch{n=!1}if(!n)return this.sandboxState="running",this.agentState="running",!1;t!==null&&this.interruptedOperations.add(t),this.invalidateActiveOperation(),this.sandboxState="ready",this.agentState="interrupted";let i=r==="run"?"run_interrupted":"command_interrupted";return this.emitLifecycle(e,i),n}status(){let e=this.browserRuntimeInfo();return{sandboxId:this.getSession(),sandbox:this.sandboxState,agent:this.agentState,activeProcessId:this.activeProcessId,hasRun:this.hasRun,timestamp:new Date().toISOString(),...e?{browser:e}:{}}}async kill(e){await this.rotateSession();let t;try{this.activeCommand&&await this.interrupt(e),this.sandbox&&(await this.sandbox.kill(),this.sandbox=void 0)}catch(r){t=r}finally{await this.closeProviderRuntimeToken(),await this.closeManagedSecretRuntimeToken(),await this.closeManagedBrowserSession()}if(t)throw t;this.options.sandboxId=void 0,this.interruptedOperations.clear(),this.invalidateActiveOperation(),this.sandboxState="stopped",this.agentState="idle",this.hasRun=!1,this.lastCheckpointId=void 0,this.emitLifecycle(e,"sandbox_killed")}async getHost(e){return(await this.getSandbox()).getHost(e)}getAgentType(){return this.agentConfig.type}getSessionTag(){return!this.sandbox&&!this.sessionLogger?null:this.sessionTag}getSessionTimestamp(){return this.sessionLogger?.getTimestamp()||null}async flushObservability(){await this.sessionLogger?.flush()}async rotateSession(){let e=!!this.sessionLogger;this.sessionLogger&&(await this.sessionLogger.close(),this.sessionLogger=void 0),e&&(this.previousSessionTag=this.sessionTag),this.sessionTag=I5t(this.options.sessionTagPrefix||"evolve")}async fetchSpend(e){if(this.agentConfig.isDirectMode)throw new Error("Cost tracking requires gateway mode (set EVOLVE_API_KEY).");let t=this.agentConfig.apiKey;if(!t)throw new Error("Cost tracking requires an API key.");let r=process.env.EVOLVE_DASHBOARD_URL||oa,n=await fetch(`${r}/api/sessions/spend?${e}`,{headers:{Authorization:`Bearer ${t}`},signal:AbortSignal.timeout(1e4)});if(!n.ok){let i=await n.text().catch(()=>"");throw new Error(`Spend query failed (${n.status}): ${i}`)}return n}resolveSpendTag(){if(this.sandbox||this.sessionLogger)return this.sessionTag;if(this.previousSessionTag)return this.previousSessionTag;throw new Error("No session to query. Call run() first.")}normalizeRunCost(e,t){return{...e,asOf:e.asOf??t.asOf,isComplete:e.isComplete??t.isComplete,truncated:e.truncated??t.truncated}}normalizeSessionCost(e){let t={asOf:e.asOf,isComplete:e.isComplete,truncated:e.truncated};return{...e,runs:e.runs.map(r=>this.normalizeRunCost(r,t))}}async getSessionCost(){let e=this.resolveSpendTag(),t=new URLSearchParams({tag:e}),r=await(await this.fetchSpend(t)).json();return this.normalizeSessionCost(r)}async getRunCost(e){let t=this.resolveSpendTag();if("runId"in e){let s=new URLSearchParams({tag:t,runId:e.runId}),o=await(await this.fetchSpend(s)).json();return this.normalizeRunCost(o,{asOf:new Date().toISOString(),isComplete:!1,truncated:!1})}let r=await this.getSessionCost(),n=e.index>0?e.index-1:r.runs.length+e.index,i=r.runs[n];if(!i)throw new Error(`Run index ${e.index} out of range. Session has ${r.runs.length} run(s).`);return i}};function tSn(e){return(e||process.env.EVOLVE_DASHBOARD_URL||oa).replace(/\/$/,"")}function rSn(e){let t=e||process.env.EVOLVE_API_KEY;if(!t)throw new Error("Browser profiles require EVOLVE_API_KEY or an explicit apiKey");return t}async function nSn(e){return await e.text().catch(()=>"")}async function x5t(e,t,r={}){let n=await fetch(`${tSn(e?.dashboardUrl)}${t}`,{...r,headers:{Authorization:`Bearer ${rSn(e?.apiKey)}`,accept:"application/json",...r.body?{"content-type":"application/json"}:{},...r.headers||{}}});if(!n.ok)throw new Error(`Browser profiles request failed (${n.status}): ${await nSn(n)}`);return n.status===204?{}:await n.json()}var iSn=class{constructor(e={}){this.config=e}toMetadata(e){return{id:e.id,profile:e.profile,createdAt:e.createdAt||e.created_at||"",updatedAt:e.updatedAt||e.updated_at||"",lastUsedAt:e.lastUsedAt??e.last_used_at??null}}async list(){return{profiles:(await x5t(this.config,"/api/browser-profiles")).profiles.map(e=>this.toMetadata(e))}}async delete(e){return await x5t(this.config,"/api/browser-profiles",{method:"DELETE",body:JSON.stringify(e)})}};function sSn(e={}){return new iSn(e)}var Yw=class extends A5t.EventEmitter{config={};agent;fallbackSandboxState="stopped";fallbackAgentState="idle";fallbackHasRun=!1;constructor(){super()}on(e,t){return super.on(e,t)}off(e,t){return super.off(e,t)}emit(e,...t){return super.emit(e,...t)}withAgent(e){return e&&(z5t(e),K5t(e),this.config.agent=e,this._cachedGatewayOverrides=null),this}withSandbox(e){return this.config.sandbox=e,this}withSandboxCreateOptions(e){return this.config.sandboxCreateOptions={...e,envs:e.envs?{...e.envs}:void 0,metadata:e.metadata?{...e.metadata}:void 0},this}withWorkingDirectory(e){return this.config.workingDirectory=e,this}withWorkspaceMode(e){return this.config.workspaceMode=e,this}withSecrets(e){return this.config.secrets={...this.config.secrets,...e},this}withManagedSecrets(e){return this.config.managedSecrets=e,this}withSession(e){return this.config.sandboxId=e,this.agent||(this.fallbackSandboxState="ready",this.fallbackAgentState="idle",this.fallbackHasRun=!0),this}withSystemPrompt(e){return this.config.systemPrompt=e,this}withContext(e){return this.config.context={...this.config.context,...e},this}withFiles(e){return this.config.files={...this.config.files,...e},this}withMcpServers(e){return this.config.mcpServers={...this.config.mcpServers,...e},this}withBrowser(e={provider:"agent-browser",remote:!0}){return e===!1?delete this.config.browser:this.config.browser=e,this}withBrowserCredentials(e={}){return this.config.browserCredentials=e,this}withPlugins(e){let t=Array.isArray(e)?e:[e];return this.config.plugins=[...this.config.plugins??[],...t],this}withSkills(e){return this.config.skills=e,this}withSchema(e,t){return this.config.schema=e,t&&(BK(e)?console.warn("[Evolve] schemaOptions ignored for Zod schemas - use .passthrough(), .strip(), z.coerce instead"):this.config.schemaOptions=t),this}withSessionTagPrefix(e){return this.config.sessionTagPrefix=e,this}withObservability(e){return this.config.observability={...this.config.observability,...e},this}withIntegrations(e){return this.config.integrations=e,this}withStorage(e){return this.config.storage=e||{},this}static integrations=Hvn;static browserCredentials=bbn;static browserProfiles=sSn;static managedSecrets=Dbn;async initializeAgent(){let e=Q8t(this.config.agent),t=Jw(e.type);if(this.config.integrations&&e.isDirectMode)throw new Error("withIntegrations() is available only in gateway mode with EVOLVE_API_KEY");if(this.config.managedSecrets&&e.isDirectMode)throw new Error("withManagedSecrets() is available only in gateway mode with EVOLVE_API_KEY");if(this.config.managedSecrets&&this.config.sandboxId)throw new Error("withManagedSecrets() cannot be used with withSession(); managed secret grants are sandbox-scoped.");let r=$bn(this.config.managedSecrets,t);if(r&&this.config.sandbox&&!X5t(this.config.sandbox))throw new Error("withManagedSecrets() requires an Evolve-managed sandbox; remove withSandbox() or pass a managed sandbox provider.");let n=this.config.sandbox??(r?await aTe(e.apiKey):await lvn()),i={},s,o,a=this.config.skills,c;if(this.config.browser){let d=lbn(this.config.browser);if(c=d,d.provider==="browser-use"){if(e.isDirectMode)throw new Error('withBrowser("browser-use") requires gateway mode. Use apiKey/EVOLVE_API_KEY instead of providerApiKey/direct mode.');i=_Te(e.apiKey)}if((d.provider==="actionbook"||d.provider==="agent-browser")&&d.managed){if(e.isDirectMode)throw new Error(`Managed browser provider "${d.provider}" requires gateway mode. Use apiKey/EVOLVE_API_KEY instead of providerApiKey/direct mode.`);s=d.provider==="actionbook"?Avn:kvn,o={provider:d.provider,apiKey:e.apiKey,dashboardUrl:process.env.EVOLVE_DASHBOARD_URL||oa,...d.profile?{profile:d.profile}:{}}}if(d.profile&&!d.managed)throw new Error('withBrowser({ profile }) requires managed remote browser mode. Use .withBrowser({ profile }) or .withBrowser({ provider: "agent-browser", remote: true, profile }).')}if(this.config.browserCredentials!==void 0){if(this.config.sandboxId)throw new Error("withBrowserCredentials() cannot be used with withSession(); browser login tokens are run-scoped.");if(e.isDirectMode)throw new Error("withBrowserCredentials() requires gateway mode. Use apiKey/EVOLVE_API_KEY instead of providerApiKey/direct mode.");if(!c||c.provider!=="agent-browser"||!c.managed)throw new Error('withBrowserCredentials() requires .withBrowser() or .withBrowser({ provider: "agent-browser", remote: true }).');if(this.config.mcpServers?.["browser-login"])throw new Error('withBrowserCredentials() reserves the "browser-login" MCP server name.')}let l=this.config.storage!==void 0?e7t(this.config.storage,!e.isDirectMode,oa,e.isDirectMode?void 0:e.apiKey):void 0,u={sandboxProvider:n,sandboxCreateOptions:this.config.sandboxCreateOptions,secrets:this.config.secrets,managedSecrets:r?{secrets:r,apiKey:e.apiKey,dashboardUrl:process.env.EVOLVE_DASHBOARD_URL||oa}:void 0,sandboxId:this.config.sandboxId,workingDirectory:this.config.workingDirectory,workspaceMode:this.config.workspaceMode,systemPrompt:this.config.systemPrompt,context:this.config.context,files:this.config.files,mcpServers:{...i,...this.config.mcpServers},browserPrompt:s,managedBrowser:o,browserCredentials:this.config.browserCredentials!==void 0?{apiKey:e.apiKey,dashboardUrl:process.env.EVOLVE_DASHBOARD_URL||oa,config:this.config.browserCredentials}:void 0,plugins:this.config.plugins,skills:a,schema:this.config.schema,schemaOptions:this.config.schemaOptions,sessionTagPrefix:this.config.sessionTagPrefix,observability:this.config.observability,integrations:this.config.integrations?{...this.config.integrations,apiKey:e.apiKey,dashboardUrl:process.env.EVOLVE_DASHBOARD_URL||oa}:void 0,providerRouting:e.isDirectMode?void 0:{apiKey:e.apiKey,dashboardUrl:process.env.EVOLVE_DASHBOARD_URL||oa},storage:l};this.agent=new eSn(e,u)}createStreamCallbacks(){let e=this.listenerCount("stdout")>0,t=this.listenerCount("stderr")>0,r=this.listenerCount("content")>0,n=this.listenerCount("lifecycle")>0;return{onStdout:e?i=>this.emit("stdout",i):void 0,onStderr:t?i=>this.emit("stderr",i):void 0,onContent:r?i=>this.emit("content",i):void 0,onLifecycle:n?i=>this.emit("lifecycle",i):void 0}}emitLifecycleFromStatus(e){if(this.listenerCount("lifecycle")===0)return;let t=this.status();this.emit("lifecycle",{sandboxId:t.sandboxId,sandbox:t.sandbox,agent:t.agent,timestamp:new Date().toISOString(),reason:e,...t.browser?{browser:t.browser}:{}})}async run({prompt:e,timeoutMs:t,background:r,from:n,checkpointComment:i}){if(n&&this.config.sandboxId)throw new Error("Cannot use 'from' with 'withSession()' \u2014 restore requires a fresh sandbox.");this.agent||await this.initializeAgent();let s=this.createStreamCallbacks();return this.agent.run({prompt:e,timeoutMs:t,background:r,from:n,checkpointComment:i},s)}async executeCommand(e,t={}){this.agent||await this.initializeAgent();let r=this.createStreamCallbacks();return this.agent.executeCommand(e,t,r)}async prepareSandbox(){this.agent||await this.initializeAgent();let e=this.createStreamCallbacks();return(await this.agent.getSandbox(e)).sandboxId}async sealCredentials(){if(!this.agent)throw new Error("Agent not initialized. Call run() or executeCommand() first.");await this.agent.sealCredentials()}isSealed(){return this.agent?.isSealed()??!1}resolvedSkills(){return this.agent?.resolvedSkills()??[]}async collectArtifacts(e){if(!this.agent)throw new Error("Agent not initialized. Call run() or executeCommand() first.");return this.agent.collectArtifacts(e)}async interrupt(){if(!this.agent)return!1;let e=this.createStreamCallbacks();return this.agent.interrupt(e)}async uploadContext(e){return this.agent||await this.initializeAgent(),this.agent.uploadContext(e)}async uploadFiles(e){return this.agent||await this.initializeAgent(),this.agent.uploadFiles(e)}async uploadFileFromPath(e,t){return this.agent||await this.initializeAgent(),this.agent.uploadFileFromPath(e,t)}async getOutputFiles(e=!1){if(!this.agent)throw new Error("Agent not initialized. Call run() first.");return this.agent.getOutputFiles(e)}async checkpoint(e){if(!this.agent)throw new Error("Agent not initialized. Call run() first.");return this.agent.checkpoint(e)}_cachedGatewayOverrides=null;resolveGatewayOverrides(){if(this._cachedGatewayOverrides!==null)return this._cachedGatewayOverrides||void 0;try{let e=Q8t(this.config.agent);if(!e.isDirectMode)return this._cachedGatewayOverrides={gatewayUrl:oa,gatewayApiKey:e.apiKey},this._cachedGatewayOverrides}catch{}this._cachedGatewayOverrides=void 0}async listCheckpoints(e){if(this.config.storage===void 0)throw new Error("Storage not configured. Call .withStorage().");return f5t(this.config.storage,this.resolveGatewayOverrides()||{}).listCheckpoints(e)}storage(){if(this.config.storage===void 0)throw new Error("Storage not configured. Call .withStorage().");return f5t(this.config.storage,this.resolveGatewayOverrides()||{})}getSession(){return this.agent?this.agent.getSession():this.config.sandboxId??null}async setSession(e){if(this.config.managedSecrets)throw new Error("setSession() cannot be used with withManagedSecrets(); managed secret grants are sandbox-scoped.");this.agent?await this.agent.setSession(e):(this.fallbackSandboxState="ready",this.fallbackAgentState="idle",this.fallbackHasRun=!0),this.config.sandboxId=e}status(){return this.agent?this.agent.status():{sandboxId:this.config.sandboxId??null,sandbox:this.fallbackSandboxState,agent:this.fallbackAgentState,activeProcessId:null,hasRun:this.fallbackHasRun,timestamp:new Date().toISOString()}}async pause(){if(this.agent){let e=this.createStreamCallbacks();await this.agent.pause(e);return}this.config.sandboxId&&this.config.sandbox&&(await(await this.config.sandbox.connect(this.config.sandboxId)).pause(),this.fallbackSandboxState="paused",this.fallbackAgentState="idle",this.emitLifecycleFromStatus("sandbox_pause"))}async resume(){if(this.agent){let e=this.createStreamCallbacks();await this.agent.resume(e);return}this.config.sandboxId&&this.config.sandbox&&(await this.config.sandbox.connect(this.config.sandboxId),this.fallbackSandboxState="ready",this.fallbackAgentState="idle",this.emitLifecycleFromStatus("sandbox_resume"))}async kill(){if(this.agent){let e=this.createStreamCallbacks();await this.agent.kill(e),this.config.sandboxId=void 0,this.fallbackSandboxState="stopped",this.fallbackAgentState="idle",this.fallbackHasRun=!1;return}this.config.sandboxId&&this.config.sandbox&&(await(await this.config.sandbox.connect(this.config.sandboxId)).kill(),this.fallbackSandboxState="stopped",this.fallbackAgentState="idle",this.fallbackHasRun=!1,this.emitLifecycleFromStatus("sandbox_killed"),this.config.sandboxId=void 0)}async getHost(e){return this.agent||await this.initializeAgent(),this.agent.getHost(e)}getSessionTag(){return this.agent?.getSessionTag()||null}getSessionTimestamp(){return this.agent?.getSessionTimestamp()||null}async flushObservability(){await this.agent?.flushObservability()}async getSessionCost(){if(!this.agent)throw new Error("No agent initialized. Call run() first.");return this.agent.getSessionCost()}async getRunCost(e){if(!this.agent)throw new Error("No agent initialized. Call run() first.");return this.agent.getRunCost(e)}},oSn=class{permits;queue=[];constructor(e){if(e<1)throw new Error("Semaphore max must be >= 1");this.permits=e}async use(e){await this.acquire();try{return await e()}finally{this.release()}}acquire(){return this.permits>0?(this.permits--,Promise.resolve()):new Promise(e=>this.queue.push(e))}release(){this.queue.length>0?this.queue.shift()():this.permits++}},Z3=Symbol.for("evolve.SwarmResult"),T5t=class _7t extends Array{get success(){return this.filter(t=>t.status==="success")}get filtered(){return this.filter(t=>t.status==="filtered")}get error(){return this.filter(t=>t.status==="error")}static from(t){let r=new _7t;return r.push(...t),r}},xZn=class PK{config;semaphore;constructor(t={}){let r=t.concurrency??ITe;if(r>HK)throw new Error(`concurrency=${r} exceeds max ${HK}. For higher parallelism, scale horizontally with multiple processes.`);this.config={agent:t.agent,sandbox:t.sandbox,tag:t.tag??"swarm",concurrency:r,timeoutMs:t.timeoutMs??hU,workspaceMode:t.workspaceMode??"knowledge",retry:t.retry,mcpServers:t.mcpServers,skills:t.skills,integrations:t.integrations},this.semaphore=new oSn(this.config.concurrency)}async map(t){let{items:r,prompt:n,bestOf:i,verify:s}=t,o=t.retry??this.config.retry,a=this.generateOperationId(),c=t.timeoutMs??this.config.timeoutMs;if(i&&s)throw new Error("map() cannot use both bestOf and verify options simultaneously");let l=await Promise.all(r.map((u,d)=>i?this.executeMapItemWithBestOf(u,n,d,a,t,c,o):s?this.executeMapItemWithVerify(u,n,d,a,t,c,o):o?V0(f=>this.executeMapItem(u,n,d,a,t,c,f),o,d):this.executeMapItem(u,n,d,a,t,c)));return T5t.from(l)}async filter(t){let{items:r,prompt:n,condition:i,verify:s}=t,o=t.retry??this.config.retry,a=this.generateOperationId(),c=t.timeoutMs??this.config.timeoutMs,l=await Promise.all(r.map((d,f)=>s?this.executeFilterItemWithVerify(d,n,f,a,t,c,o):o?V0(p=>this.executeFilterItem(d,n,f,a,t,c,p),o,f):this.executeFilterItem(d,n,f,a,t,c))),u=[];for(let d of l)if(d.status==="error")u.push(d);else if(d.data!==null)try{i(d.data)?u.push(d):u.push({...d,status:"filtered"})}catch(f){u.push({...d,status:"error",data:null,error:`Condition function threw: ${f.message}`})}return T5t.from(u)}async reduce(t){let{items:r,prompt:n,verify:i}=t,s=t.retry??this.config.retry,o=this.generateOperationId(),a=t.timeoutMs??this.config.timeoutMs,c=[],l=[];r.forEach((P,F)=>{c.push(this.getFiles(P)),l.push(this.getIndex(P,F))});let u={};c.forEach((P,F)=>{Object.entries(P).forEach(([H,Y])=>{u[`item_${l[F]}/${H}`]=Y})});let d=Gxe(u),f=Ww(Dvn,{fileTree:d}),p=t.systemPrompt?`${f}
1228
1228
 
1229
1229
  ${t.systemPrompt}`:f,m=(P,F,H)=>({operationId:o,operation:"reduce",tag:P.tag,sandboxId:P.sandboxId,swarmName:this.config.tag,operationName:t.name,inputCount:r.length,inputIndices:l,errorRetry:F,verifyRetry:H,...this.pipelineContextToMeta(t._pipelineContext)}),v=t.mcpServers??this.config.mcpServers,b=t.skills??this.config.skills,S=t.integrations??this.config.integrations,T=async(P,F,H,Y)=>{let B=await this.semaphore.use(()=>this.execute(u,P,{systemPrompt:p,schema:t.schema,schemaOptions:t.schemaOptions,agent:t.agent,mcpServers:v,skills:b,integrations:S,tagPrefix:F,timeoutMs:a,observability:{swarmName:this.config.tag,operationName:t.name,operationId:o,operation:"reduce",role:"worker",errorRetry:H,verifyRetry:Y&&Y>1?Y-1:void 0,...this.pipelineContextToObservability(t._pipelineContext)}})),X=m(B,H,Y&&Y>1?Y-1:void 0);return B.error?{status:"error",data:null,files:B.files,meta:X,error:B.error,rawData:B.rawData}:{status:"success",data:B.data,files:B.files,meta:X}},C=`${this.config.tag}-reduce`;return i?this.runWithVerification((P,F,H)=>T(P,F,void 0,H),{originalPrompt:n,inputFiles:u,verifyConfig:i,timeoutMs:a,systemPrompt:p,schema:t.schema,mcpServers:v,skills:b,integrations:S,operationId:o,baseTag:C,retry:s,operation:"reduce",_pipelineContext:t._pipelineContext}):s?V0(P=>{let F=P>1?P-1:void 0,H=F?`${C}-er${F}`:C;return T(n,H,F)},s):T(n,C)}async bestOf(t){let{item:r,prompt:n,config:i}=t,s=t.retry??this.config.retry,o=i.n??i.taskAgents?.length;if(o===void 0)throw new Error("bestOf requires n or taskAgents");if(o<2)throw new Error("bestOf requires n >= 2");let a=this.generateOperationId(),c=t.timeoutMs??this.config.timeoutMs,l=this.getFiles(r),u=i.mcpServers??this.config.mcpServers,d=i.judgeMcpServers??i.mcpServers??this.config.mcpServers,f=i.skills??this.config.skills,p=i.judgeSkills??i.skills??this.config.skills,m=i.integrations??this.config.integrations,v=i.judgeIntegrations??i.integrations??this.config.integrations,b=await Promise.all(Array.from({length:o},async(F,H)=>{let Y=s?await V0(B=>this.executeBestOfCandidate({inputFiles:l,prompt:n,candidateIndex:H,operationId:a,config:i,systemPrompt:t.systemPrompt,schema:t.schema,schemaOptions:t.schemaOptions,mcpServers:u,skills:f,integrations:m,timeoutMs:c,attempt:B}),s,H):await this.executeBestOfCandidate({inputFiles:l,prompt:n,candidateIndex:H,operationId:a,config:i,systemPrompt:t.systemPrompt,schema:t.schema,schemaOptions:t.schemaOptions,mcpServers:u,skills:f,integrations:m,timeoutMs:c});return i.onCandidateComplete?.(0,H,Y.status==="success"?"success":"error"),Y})),S=s?await V0(F=>this.executeBestOfJudge({inputFiles:l,taskPrompt:n,candidates:b,config:i,timeoutMs:c,operationId:a,systemPrompt:t.systemPrompt,schema:t.schema,schemaOptions:t.schemaOptions,mcpServers:d,skills:p,integrations:v,attempt:F}),{...s,retryOn:void 0},0):await this.executeBestOfJudge({inputFiles:l,taskPrompt:n,candidates:b,config:i,timeoutMs:c,operationId:a,systemPrompt:t.systemPrompt,schema:t.schema,schemaOptions:t.schemaOptions,mcpServers:d,skills:p,integrations:v}),T=b.findIndex(F=>F.status==="success"),C=S.decision?.winner??(T>=0?T:0);i.onJudgeComplete?.(0,C,S.decision?.reasoning??"Judge failed to provide reasoning");let P={operationId:a,operation:"bestof-judge",tag:S.tag,sandboxId:S.sandboxId,swarmName:this.config.tag,operationName:t.name,candidateCount:o};return{winner:b[C]??b[0],winnerIndex:C,judgeReasoning:S.decision?.reasoning??"Judge failed to provide reasoning",judgeMeta:P,candidates:b}}async execute(t,r,n){let i=null,s="",o=n.tagPrefix,a={},c=null,l,u,d={...this.config.agent,...n.agent};try{i=new Yw().withAgent(d).withSandbox(this.config.sandbox).withWorkspaceMode(this.config.workspaceMode).withSessionTagPrefix(n.tagPrefix),n.schema&&i.withSchema(n.schema,n.schemaOptions),n.systemPrompt&&i.withSystemPrompt(n.systemPrompt),n.mcpServers&&i.withMcpServers(n.mcpServers),n.skills?.length&&i.withSkills(n.skills),n.integrations&&i.withIntegrations(n.integrations),n.observability&&i.withObservability(n.observability),Object.keys(t).length>0&&i.withContext(t);let f=await i.run({prompt:r,timeoutMs:n.timeoutMs});s=f.sandboxId,o=i.getSessionTag()??n.tagPrefix;let p=null;try{p=await i.getOutputFiles(!0),a=p.files}catch{}f.exitCode!==0?l=`Agent exited with code ${f.exitCode}`:n.schema?p?(c=p.data,p.error&&(l=p.error),p.rawData&&(u=p.rawData)):l="Failed to read output files from sandbox":c=a}catch(f){if(l=f.message,i){o=i.getSessionTag()??n.tagPrefix;try{a=(await i.getOutputFiles(!0)).files}catch{}}}finally{i&&await i.kill().catch(()=>{})}return{files:a,data:c,tag:o,sandboxId:s,error:l,rawData:u}}async executeMapItem(t,r,n,i,s,o,a=1){let c=this.getFiles(t),l=a>1?`${this.config.tag}-map-${n}-er${a-1}`:`${this.config.tag}-map-${n}`,u=this.evaluatePrompt(r,c,n);if(u instanceof Error)return this.buildErrorResult(`Prompt function threw: ${u.message}`,{operationId:i,operation:"map",tag:l,sandboxId:"",itemIndex:n});let d=s.mcpServers??this.config.mcpServers,f=s.skills??this.config.skills,p=s.integrations??this.config.integrations,m=await this.semaphore.use(()=>this.execute(c,u,{systemPrompt:s.systemPrompt,schema:s.schema,schemaOptions:s.schemaOptions,agent:s.agent,mcpServers:d,skills:f,integrations:p,tagPrefix:l,timeoutMs:o,observability:{swarmName:this.config.tag,operationName:s.name,operationId:i,operation:"map",itemIndex:n,role:"worker",errorRetry:a>1?a-1:void 0,...this.pipelineContextToObservability(s._pipelineContext)}})),v={operationId:i,operation:"map",tag:m.tag,sandboxId:m.sandboxId,swarmName:this.config.tag,operationName:s.name,itemIndex:n,errorRetry:a>1?a-1:void 0,...this.pipelineContextToMeta(s._pipelineContext)};return this.buildResult(m,v)}async executeMapItemWithVerify(t,r,n,i,s,o,a){let c=this.getFiles(t),l=`${this.config.tag}-map-${n}`,u=s.verify,d=s.mcpServers??this.config.mcpServers,f=s.skills??this.config.skills,p=s.integrations??this.config.integrations,m=this.evaluatePrompt(r,c,n);if(m instanceof Error)return this.buildErrorResult(`Prompt function threw: ${m.message}`,{operationId:i,operation:"map",tag:l,sandboxId:"",itemIndex:n});let v=async(b,S,T)=>{let C=await this.semaphore.use(()=>this.execute(c,b,{systemPrompt:s.systemPrompt,schema:s.schema,schemaOptions:s.schemaOptions,agent:s.agent,mcpServers:d,skills:f,integrations:p,tagPrefix:S,timeoutMs:o,observability:{swarmName:this.config.tag,operationName:s.name,operationId:i,operation:"map",itemIndex:n,role:"worker",verifyRetry:T&&T>1?T-1:void 0,...this.pipelineContextToObservability(s._pipelineContext)}})),P={operationId:i,operation:"map",tag:C.tag,sandboxId:C.sandboxId,swarmName:this.config.tag,operationName:s.name,itemIndex:n,verifyRetry:T&&T>1?T-1:void 0,...this.pipelineContextToMeta(s._pipelineContext)};return this.buildResult(C,P)};return this.runWithVerification(v,{originalPrompt:m,inputFiles:c,verifyConfig:u,timeoutMs:o,systemPrompt:s.systemPrompt,schema:s.schema,mcpServers:d,skills:f,integrations:p,operationId:i,baseTag:l,retry:a,itemIndex:n,operation:"map",_pipelineContext:s._pipelineContext})}async executeMapItemWithBestOf(t,r,n,i,s,o,a){let c=this.getFiles(t),l=`${this.config.tag}-map-${n}`,u=this.evaluatePrompt(r,c,n);if(u instanceof Error)return this.buildErrorResult(`Prompt function threw: ${u.message}`,{operationId:i,operation:"map",tag:l,sandboxId:"",itemIndex:n});let d=s.bestOf,f=d.n??d.taskAgents?.length;if(f===void 0||f<2)return this.buildErrorResult("bestOf requires n >= 2 or taskAgents with at least 2 elements",{operationId:i,operation:"map",tag:l,sandboxId:"",itemIndex:n});let p=s.mcpServers??this.config.mcpServers,m=d.mcpServers??p,v=d.judgeMcpServers??d.mcpServers??p,b=s.skills??this.config.skills,S=d.skills??b,T=d.judgeSkills??d.skills??b,C=s.integrations??this.config.integrations,P=d.integrations??C,F=d.judgeIntegrations??d.integrations??C,H=await Promise.all(Array.from({length:f},async(We,de)=>{let O=a?await V0($=>this.executeBestOfCandidate({inputFiles:c,prompt:u,candidateIndex:de,operationId:i,config:d,systemPrompt:s.systemPrompt,schema:s.schema,schemaOptions:s.schemaOptions,mcpServers:m,skills:S,integrations:P,timeoutMs:o,parentIndex:n,attempt:$,_pipelineContext:s._pipelineContext}),a,de):await this.executeBestOfCandidate({inputFiles:c,prompt:u,candidateIndex:de,operationId:i,config:d,systemPrompt:s.systemPrompt,schema:s.schema,schemaOptions:s.schemaOptions,mcpServers:m,skills:S,integrations:P,timeoutMs:o,parentIndex:n,_pipelineContext:s._pipelineContext});return d.onCandidateComplete?.(n,de,O.status==="success"?"success":"error"),O})),Y=a?await V0(We=>this.executeBestOfJudge({inputFiles:c,taskPrompt:u,candidates:H,config:d,timeoutMs:o,operationId:i,systemPrompt:s.systemPrompt,schema:s.schema,schemaOptions:s.schemaOptions,mcpServers:v,skills:T,integrations:F,parentIndex:n,attempt:We,_pipelineContext:s._pipelineContext}),{...a,retryOn:void 0},0):await this.executeBestOfJudge({inputFiles:c,taskPrompt:u,candidates:H,config:d,timeoutMs:o,operationId:i,systemPrompt:s.systemPrompt,schema:s.schema,schemaOptions:s.schemaOptions,mcpServers:v,skills:T,integrations:F,parentIndex:n,_pipelineContext:s._pipelineContext}),B=H.findIndex(We=>We.status==="success"),X=Y.decision?.winner??(B>=0?B:0),pe=H[X]??H[0];d.onJudgeComplete?.(n,X,Y.decision?.reasoning??"Judge failed to provide reasoning");let V={operationId:i,operation:"bestof-judge",tag:Y.tag,sandboxId:Y.sandboxId,swarmName:this.config.tag,operationName:s.name,candidateCount:f,...this.pipelineContextToMeta(s._pipelineContext)};return{...pe,meta:{...pe.meta,operation:"map",swarmName:this.config.tag,operationName:s.name,itemIndex:n,...this.pipelineContextToMeta(s._pipelineContext)},bestOf:{winnerIndex:X,judgeReasoning:Y.decision?.reasoning??"Judge failed to provide reasoning",judgeMeta:V,candidates:H}}}async executeFilterItem(t,r,n,i,s,o,a=1){let c=this.getFiles(t),l=a>1?`${this.config.tag}-filter-${n}-er${a-1}`:`${this.config.tag}-filter-${n}`,u=s.mcpServers??this.config.mcpServers,d=s.skills??this.config.skills,f=s.integrations??this.config.integrations,p=await this.semaphore.use(()=>this.execute(c,r,{systemPrompt:s.systemPrompt,schema:s.schema,schemaOptions:s.schemaOptions,agent:s.agent,mcpServers:u,skills:d,integrations:f,tagPrefix:l,timeoutMs:o,observability:{swarmName:this.config.tag,operationName:s.name,operationId:i,operation:"filter",itemIndex:n,role:"worker",errorRetry:a>1?a-1:void 0,...this.pipelineContextToObservability(s._pipelineContext)}})),m={operationId:i,operation:"filter",tag:p.tag,sandboxId:p.sandboxId,swarmName:this.config.tag,operationName:s.name,itemIndex:n,errorRetry:a>1?a-1:void 0,...this.pipelineContextToMeta(s._pipelineContext)};return this.buildResult(p,m,c)}async executeFilterItemWithVerify(t,r,n,i,s,o,a){let c=this.getFiles(t),l=`${this.config.tag}-filter-${n}`,u=s.verify,d=s.mcpServers??this.config.mcpServers,f=s.skills??this.config.skills,p=s.integrations??this.config.integrations,m=async(v,b,S)=>{let T=await this.semaphore.use(()=>this.execute(c,v,{systemPrompt:s.systemPrompt,schema:s.schema,schemaOptions:s.schemaOptions,agent:s.agent,mcpServers:d,skills:f,integrations:p,tagPrefix:b,timeoutMs:o,observability:{swarmName:this.config.tag,operationName:s.name,operationId:i,operation:"filter",itemIndex:n,role:"worker",verifyRetry:S&&S>1?S-1:void 0,...this.pipelineContextToObservability(s._pipelineContext)}})),C={operationId:i,operation:"filter",tag:T.tag,sandboxId:T.sandboxId,swarmName:this.config.tag,operationName:s.name,itemIndex:n,verifyRetry:S&&S>1?S-1:void 0,...this.pipelineContextToMeta(s._pipelineContext)};return this.buildResult(T,C,c)};return this.runWithVerification(m,{originalPrompt:r,inputFiles:c,verifyConfig:u,timeoutMs:o,systemPrompt:s.systemPrompt,schema:s.schema,mcpServers:d,skills:f,integrations:p,operationId:i,baseTag:l,retry:a,itemIndex:n,operation:"filter",_pipelineContext:s._pipelineContext})}async executeBestOfCandidate(t){let{inputFiles:r,prompt:n,candidateIndex:i,operationId:s,config:o,timeoutMs:a,parentIndex:c,attempt:l=1,_pipelineContext:u}=t,d=c!==void 0?`${this.config.tag}-map-${c}-bestof-cand-${i}`:`${this.config.tag}-bestof-cand-${i}`,f=l>1?`${d}-er${l-1}`:d,p=await this.semaphore.use(()=>this.execute(r,n,{systemPrompt:t.systemPrompt,schema:t.schema,schemaOptions:t.schemaOptions,agent:o.taskAgents?.[i],mcpServers:t.mcpServers,skills:t.skills,integrations:t.integrations,tagPrefix:f,timeoutMs:a,observability:{swarmName:this.config.tag,operationId:s,operation:"map",itemIndex:c,role:"candidate",candidateIndex:i,errorRetry:l>1?l-1:void 0,...this.pipelineContextToObservability(u)}})),m={operationId:s,operation:"bestof-cand",tag:p.tag,sandboxId:p.sandboxId,swarmName:this.config.tag,itemIndex:i,errorRetry:l>1?l-1:void 0,candidateIndex:i,...this.pipelineContextToMeta(u)};return this.buildResult(p,m)}buildJudgeContext(t){let r=this.buildEvaluatorContext({inputFiles:t.inputFiles,taskPrompt:t.taskPrompt,systemPrompt:t.systemPrompt,schema:t.schema});return t.candidates.forEach((n,i)=>{n.status==="error"&&(r[`candidate_${i}/_failed.txt`]=`STATUS: FAILED
1230
1230
 
@@ -38,6 +38,7 @@ from .hosted import (
38
38
  Agent,
39
39
  AgentArm,
40
40
  AgentCapability,
41
+ AgentDatasetStats,
41
42
  AgentInfo,
42
43
  AgentPage,
43
44
  AgentResult,
@@ -70,6 +71,8 @@ from .hosted import (
70
71
  EvolveDigestMismatchError,
71
72
  EvolveIncompleteDownloadError,
72
73
  ExceptionInfo,
74
+ GateRunningError,
75
+ GateRunningProgress,
73
76
  HostedEvolve,
74
77
  HOSTED_ERROR_CODES,
75
78
  HostedErrorCode,
@@ -80,6 +83,9 @@ from .hosted import (
80
83
  JobEvent,
81
84
  JobFailure,
82
85
  JobPage,
86
+ JobRetryConfig,
87
+ JobRetryConfigInput,
88
+ JobStats,
83
89
  JobStatus,
84
90
  JobTaskRollup,
85
91
  JobTaskRollupPage,
@@ -100,6 +106,7 @@ from .hosted import (
100
106
  StatusVocabulary,
101
107
  StopResponse,
102
108
  Task,
109
+ TaskGate,
103
110
  TaskPage,
104
111
  TaskProviderVerdict,
105
112
  TimingInfo,
@@ -385,7 +392,7 @@ async def list_checkpoints(
385
392
  await store.close()
386
393
 
387
394
 
388
- __version__ = '0.0.52.dev744'
395
+ __version__ = '0.0.52.dev760'
389
396
 
390
397
  __all__ = [
391
398
  # Main classes
@@ -464,6 +471,8 @@ __all__ = [
464
471
  'EvolveDigestMismatchError',
465
472
  'EvolveIncompleteDownloadError',
466
473
  'NoActiveVersionError',
474
+ 'GateRunningError',
475
+ 'GateRunningProgress',
467
476
  'Dataset',
468
477
  'ActiveDataset',
469
478
  'DatasetManifestAuthor',
@@ -478,11 +487,16 @@ __all__ = [
478
487
  'ImportTaskFailure',
479
488
  'ImportWarning',
480
489
  'Task',
490
+ 'TaskGate',
481
491
  'TaskProviderVerdict',
482
492
  'AgentArm',
493
+ 'AgentDatasetStats',
483
494
  'Job',
484
495
  'JobCounts',
485
496
  'JobFailure',
497
+ 'JobRetryConfig',
498
+ 'JobRetryConfigInput',
499
+ 'JobStats',
486
500
  'JobStatus',
487
501
  'TrialStatus',
488
502
  'EvalSandboxProvider',
@@ -601,7 +615,10 @@ __all__ = [
601
615
  'JudgeCompleteEvent',
602
616
  'EmitOption',
603
617
 
604
- # Retry
618
+ # Retry — the SWARM client-side retry helper. The hosted job auto-retry
619
+ # policy is a different shape with its own names: JobRetryConfig /
620
+ # JobRetryConfigInput above (the spec calls that pair RetryConfig /
621
+ # RetryConfigInput; the Python export is prefixed so the two never shadow).
605
622
  'RetryConfig',
606
623
  'OnItemRetryCallback',
607
624
  'execute_with_retry',
@@ -46,6 +46,7 @@ from typing import (
46
46
  Literal,
47
47
  NoReturn,
48
48
  Optional,
49
+ TypedDict,
49
50
  Union,
50
51
  get_args,
51
52
  )
@@ -161,6 +162,7 @@ HostedErrorCode = Literal[
161
162
  'import_not_found',
162
163
  'import_too_large',
163
164
  'invalid_archive',
165
+ 'unpinned_git_ref',
164
166
  'package_not_retained',
165
167
  'package_corrupt',
166
168
  'package_missing',
@@ -279,6 +281,36 @@ class NoActiveVersionError(Exception):
279
281
  self.dataset = name
280
282
 
281
283
 
284
+ class GateRunningError(Exception):
285
+ """Raised by ``datasets().activate()`` when the activation gate is still
286
+ scheduled or running — the API's 202 ``gate_running`` answer.
287
+
288
+ NOT an :class:`EvolveAPIError`: the wire body is deliberately not the
289
+ error envelope, because an in-progress gate is a healthy state — nothing
290
+ is wrong and nothing is asked of the caller. Poll the dataset (each
291
+ version carries ``gate``); a gate that PASSES activates the version
292
+ itself, so there is normally nothing left to call. Its own type, like
293
+ :class:`NoActiveVersionError`, because ``activate()`` promised a Dataset
294
+ it cannot return yet.
295
+
296
+ ``gate`` is a :class:`GateRunningProgress` — the gate's progress at the
297
+ moment of the call.
298
+ """
299
+
300
+ def __init__(
301
+ self, dataset: str, version: str, message: str, gate: 'GateRunningProgress'
302
+ ):
303
+ super().__init__(message)
304
+ #: The stable machine word for this state.
305
+ self.code = 'gate_running'
306
+ #: The dataset whose version is still being proven.
307
+ self.dataset = dataset
308
+ #: The version the gate is proving.
309
+ self.version = version
310
+ #: Gate progress at the moment of the call.
311
+ self.gate = gate
312
+
313
+
282
314
  # =============================================================================
283
315
  # PUBLIC TYPES
284
316
  # =============================================================================
@@ -339,13 +371,34 @@ class DatasetVersionGate:
339
371
  ``failed_tasks`` names each ineligible task with the gate's own reasons
340
372
  (the server sends the first 25); it is empty while the gate is healthy and
341
373
  empty on servers that predate the field — absence is "nothing to report",
342
- never a crash.
374
+ never a crash. ``failed_task_count`` is the TRUE total of ineligible
375
+ tasks: the list is capped at 25, so a gate that failed more tasks than
376
+ that is under-counted by ``len(failed_tasks)`` — this number never is (it
377
+ falls back to the length on servers that predate the field, which never
378
+ truncated without it).
343
379
  """
344
380
  status: str
345
381
  attempts: int
346
382
  code: Optional[str] = None
347
383
  message: Optional[str] = None
348
384
  failed_tasks: List[DatasetVersionGateFailedTask] = field(default_factory=list)
385
+ failed_task_count: int = 0
386
+
387
+
388
+ @dataclass
389
+ class GateRunningProgress:
390
+ """Gate progress at the moment of an ``activate()`` call that answered
391
+ 202 — carried on :class:`GateRunningError`.
392
+
393
+ ``status`` is the gate's own lifecycle (PENDING or RUNNING here),
394
+ ``tasks`` the version's task count, ``unverified`` the tasks the gate has
395
+ not yet produced a verdict for, and ``ineligible`` the tasks whose
396
+ verdict so far is not activation-eligible.
397
+ """
398
+ status: str
399
+ tasks: int = 0
400
+ unverified: int = 0
401
+ ineligible: int = 0
349
402
 
350
403
 
351
404
  @dataclass
@@ -405,6 +458,25 @@ class TaskProviderVerdict:
405
458
  degrades_to: Optional[str] = None
406
459
 
407
460
 
461
+ @dataclass
462
+ class TaskGate:
463
+ """One task's activation-gate verdict — the public subset.
464
+
465
+ The per-task half of the version's ``gate``: while the gate is RUNNING,
466
+ verdicts appear on tasks as they land. ``outcome`` is PASS; FLAKY (gold
467
+ passed only on a retry — still eligible under the operator default); FAIL
468
+ (definitive: gold never scored 1.0, or a do-nothing agent did); or ERROR
469
+ (inconclusive — no usable score, e.g. no archived solution to run).
470
+ ``reasons`` are human-readable and empty on PASS. The full stored verdict
471
+ carries oracle diagnostics that stay internal, like the environment specs
472
+ beside it.
473
+ """
474
+ outcome: str
475
+ flaky: bool = False
476
+ reasons: List[str] = field(default_factory=list)
477
+ ran_at: Optional[str] = None
478
+
479
+
408
480
  @dataclass
409
481
  class Task:
410
482
  """Public task fields only — instructions/environments/tests never leave the server.
@@ -417,6 +489,10 @@ class Task:
417
489
  ``gpus``/``gpu_types`` are the task's declared GPU requirement (Harbor's
418
490
  task fields honored verbatim): 0 = a CPU task; ``gpu_types`` None = any
419
491
  type is acceptable (always None when ``gpus`` is 0).
492
+
493
+ ``gate`` is this task's activation-gate verdict — ``None`` until the gate
494
+ has run it, and ``None`` on servers that predate the field: absence is
495
+ "nothing to report", never "passed".
420
496
  """
421
497
  task_name: str
422
498
  agent_timeout_sec: float
@@ -424,6 +500,7 @@ class Task:
424
500
  providers: Dict[str, TaskProviderVerdict]
425
501
  gpus: int = 0
426
502
  gpu_types: Optional[List[str]] = None
503
+ gate: Optional[TaskGate] = None
427
504
 
428
505
 
429
506
  @dataclass
@@ -437,15 +514,22 @@ class TaskPage:
437
514
 
438
515
  @dataclass
439
516
  class UpstreamStatus:
440
- """Where a dataset's git source points now, versus what its active version
441
- was built from — the data behind a "new version available" badge.
517
+ """The active version's git provenance, plus the watch on a ref that can
518
+ move.
519
+
520
+ The provenance half — ``git_url`` + the requested ``ref`` + the resolved
521
+ commit (``current_commit``) + the repository subfolder (``path``) — says
522
+ what the active version was built from. The watch half (``latest_commit``,
523
+ ``moved``, ``checked_at``, …) is the data behind a "new version available"
524
+ badge; on a version pinned to a commit sha it stays at rest (None / False),
525
+ because a pin cannot move and nothing checks one.
442
526
 
443
527
  Nothing here imports anything by itself — a new version is always a row you
444
528
  create, or ``auto_import`` creates.
445
529
  """
446
- #: The ref the active version was imported from.
530
+ #: The ref the active version was imported from, exactly as requested.
447
531
  ref: str
448
- #: The commit the active version was built from.
532
+ #: The commit the active version was built from (the resolved sha).
449
533
  current_commit: str
450
534
  #: Where the ref points upstream now; None when the last check failed.
451
535
  latest_commit: Optional[str]
@@ -459,6 +543,16 @@ class UpstreamStatus:
459
543
  error: Optional[str]
460
544
  #: Whether a moved upstream automatically imports a new version.
461
545
  auto_import: bool = False
546
+ #: The repository the active version was imported from, userinfo (an
547
+ #: embedded token) stripped. None on an older server or an unparseable url.
548
+ git_url: Optional[str] = None
549
+ #: The repository subfolder the corpus was read from; None = the
550
+ #: repository root (or an older server).
551
+ path: Optional[str] = None
552
+ #: The newest commit a local version already exists for, whether or not it
553
+ #: is the active one; None before any import recorded one (or an older
554
+ #: server).
555
+ acked_commit: Optional[str] = None
462
556
 
463
557
 
464
558
  @dataclass
@@ -781,6 +875,149 @@ class JobFailure:
781
875
  message: str
782
876
 
783
877
 
878
+ class AgentDatasetStats(TypedDict, total=False):
879
+ """Per-(agent, model, dataset) statistics — one ``stats['evals']`` group.
880
+
881
+ The evals key format is ``{agent}__{model}__{dataset}`` — the dataset ref
882
+ is always the LAST ``__`` segment, which is where Harbor-compatible
883
+ readers recover it — with the platform extension of an ``__{effort}``
884
+ segment inserted BEFORE the dataset when a declared reasoning effort is
885
+ part of the arm identity: ``{agent}__{model}__{effort}__{dataset}``.
886
+
887
+ A ``TypedDict``: at runtime this IS the plain wire dict, read by key like
888
+ always — the class only teaches type checkers the keys. Every key is
889
+ optional, like the TypeScript interface's ``?`` fields.
890
+ """
891
+ #: Trials that produced a rewards map — rewarded, not merely settled.
892
+ n_trials: int
893
+ #: Trials carrying ``exception_info`` — indeterminate and cancelled included.
894
+ n_errors: int
895
+ #: Metric results (a mean entry per arm today: the primary reward averaged
896
+ #: over EVERY trial of the group, unrewarded trials counting 0); open objects.
897
+ metrics: List[Dict[str, Any]]
898
+ #: pass@k for this group, k (as a string — JSON object keys always are) to
899
+ #: a value in [0, 1]; ``{}`` when the group cannot answer. Read it with
900
+ #: :func:`pass_at_k`, which returns sorted numeric points.
901
+ pass_at_k: Dict[str, float]
902
+ #: reward key -> reward value -> trial identifiers.
903
+ reward_stats: Dict[str, Dict[str, List[str]]]
904
+ #: exception type -> trial identifiers.
905
+ exception_stats: Dict[str, List[str]]
906
+
907
+
908
+ class JobStats(TypedDict, total=False):
909
+ """Aggregate statistics of a job. Progress counters, token totals, and
910
+ measured cost. The ``n_*`` counters are CUMULATIVE, Harbor-style: errored
911
+ trials are a subset of completed, cancelled a subset of errored — a
912
+ cancelled trial counts in all three. The disjoint per-status breakdown
913
+ rides ``Job.trials.by_status``. ``cost_usd`` is what the trials actually
914
+ spent so far — reporting, never a gate (enforcement is the per-trial cap).
915
+
916
+ A ``TypedDict``: at runtime this IS the plain wire dict, read by key like
917
+ always (``stats.get('cost_usd')``, ``stats['evals']``) — the class only
918
+ teaches type checkers the keys. Every key is optional, like the
919
+ TypeScript interface's ``?`` fields.
920
+ """
921
+ #: Cumulative: every trial that produced a result — errored and cancelled included.
922
+ n_completed_trials: int
923
+ #: Cumulative: every completed trial carrying ``exception_info``, cancelled included.
924
+ n_errored_trials: int
925
+ n_running_trials: int
926
+ n_pending_trials: int
927
+ #: A subset of ``n_errored_trials``.
928
+ n_cancelled_trials: int
929
+ n_retries: int
930
+ #: Keyed ``{agent}__{model}__{dataset}`` — dataset ref last, optional
931
+ #: effort segment before it.
932
+ evals: Dict[str, AgentDatasetStats]
933
+ #: Total input tokens (cache included); None until recorded.
934
+ n_input_tokens: Optional[int]
935
+ n_cache_tokens: Optional[int]
936
+ n_output_tokens: Optional[int]
937
+ #: Measured spend across settled trials — the WHOLE model bill, agent and
938
+ #: judge together; None before any settled.
939
+ cost_usd: Optional[float]
940
+ #: Sum of the job's per-trial GPU compute ESTIMATES (each trial's
941
+ #: ``gpu_cost['estimate_usd']``) — a SEPARATE labeled figure, never merged
942
+ #: into ``cost_usd`` (metered model spend). None when no trial of the job
943
+ #: carries an estimate; a real $0 (a GPU trial that provably never booted
944
+ #: a sandbox) keeps the sum non-None.
945
+ gpu_cost_usd: Optional[float]
946
+ #: The judge share of ``cost_usd``, itemized: what the trials'
947
+ #: verifier-phase judge keys spent. 0 for a job with no judge-enabled
948
+ #: tasks; None before anything settled, like ``cost_usd``.
949
+ judge_cost_usd: Optional[float]
950
+
951
+
952
+ class JobRetryConfigInput(TypedDict, total=False):
953
+ """Auto-retry policy INPUT — ``jobs().start(retry=...)``, the spec's
954
+ ``RetryConfigInput`` schema, Harbor's RetryConfig vocabulary verbatim.
955
+
956
+ ONE NAMING NOTE: Harbor, the spec, and the TypeScript SDK call this pair
957
+ ``RetryConfig`` / ``RetryConfigInput``. The Python SDK exports them as
958
+ ``JobRetryConfig`` / ``JobRetryConfigInput`` because ``evolve.RetryConfig``
959
+ already names the Swarm client-side retry helper (``max_attempts``,
960
+ ``backoff_ms``, ...) — two unrelated shapes never share one exported name.
961
+
962
+ A ``TypedDict``: pass the plain dict you always passed — the class only
963
+ teaches type checkers the keys. Every key is optional, and an omitted key
964
+ takes Harbor's own default with ONE named deviation: ``max_retries``
965
+ omitted takes the PLATFORM fleet default (published as
966
+ ``limits['job']['default_max_retries']`` on ``meta()``; 2 unless the
967
+ operator tuned it) rather than Harbor's 0 — infrastructure errors on a
968
+ hosted fleet retry automatically. Send ``{'max_retries': 0}`` to turn
969
+ retries off.
970
+
971
+ Inside the policy, an EXPLICIT ``'exclude_exceptions': None`` is not the
972
+ same as leaving the key out: None turns exclusions off entirely (Harbor's
973
+ own None semantics), while an omitted key keeps Harbor's default
974
+ non-retryable set. ``include_exceptions`` has no such split: None, an
975
+ omitted key, and ``[]`` all mean no filter.
976
+ """
977
+ #: Maximum automatic retries per trial (0-10). Omitted = fleet default; 0 = off.
978
+ max_retries: int
979
+ #: Exception types to retry on. None, omitted, or ``[]`` = no filter.
980
+ include_exceptions: Optional[List[str]]
981
+ #: Exception types to NOT retry on; wins over ``include_exceptions``.
982
+ #: Omitted = Harbor's default non-retryable set; an EXPLICIT None turns
983
+ #: exclusions off entirely.
984
+ exclude_exceptions: Optional[List[str]]
985
+ #: Multiplier for exponential backoff wait time (default 1.0).
986
+ wait_multiplier: float
987
+ #: Minimum wait in seconds between retries (default 1.0).
988
+ min_wait_sec: float
989
+ #: Maximum wait in seconds between retries (default 60.0; platform cap 3600).
990
+ max_wait_sec: float
991
+
992
+
993
+ class JobRetryConfig(TypedDict):
994
+ """The RESOLVED auto-retry policy a job runs under — the spec's
995
+ ``RetryConfig`` schema, echoed on every job body as ``Job.retry``: the
996
+ caller's values or the defaults of the day, resolved at create and
997
+ stored, so the row always states the policy it executes. Backoff between
998
+ attempts is Harbor's formula:
999
+ min(min_wait_sec x wait_multiplier^attempt, max_wait_sec).
1000
+
1001
+ A ``TypedDict``: at runtime this IS the plain wire dict, read by key like
1002
+ always (``job.retry['max_retries']``) — the class only teaches type
1003
+ checkers the keys. Every key is REQUIRED, like the spec's own required
1004
+ list: the mapper reads an older server that sends no policy as the
1005
+ retries-off policy with Harbor's defaults — exactly how such a server
1006
+ behaves — so every field is always present.
1007
+
1008
+ Named ``JobRetryConfig`` rather than the spec's ``RetryConfig`` because
1009
+ ``evolve.RetryConfig`` is the (unrelated) Swarm retry helper — see
1010
+ :class:`JobRetryConfigInput` for the input half and the naming note.
1011
+ """
1012
+ max_retries: int
1013
+ #: None = no include filter (everything the exclude set admits).
1014
+ include_exceptions: Optional[List[str]]
1015
+ exclude_exceptions: List[str]
1016
+ wait_multiplier: float
1017
+ min_wait_sec: float
1018
+ max_wait_sec: float
1019
+
1020
+
784
1021
  @dataclass
785
1022
  class Job:
786
1023
  """THE job body — the same shape from start, get, list rows, cancel,
@@ -807,8 +1044,21 @@ class Job:
807
1044
  #: The RESOLVED auto-retry policy this job runs under — Harbor's
808
1045
  #: RetryConfig field names (``max_retries``, ``include_exceptions``,
809
1046
  #: ``exclude_exceptions``, ``wait_multiplier``, ``min_wait_sec``,
810
- #: ``max_wait_sec``). A plain dict with the wire's own keys, read by key.
811
- retry: Dict[str, Any]
1047
+ #: ``max_wait_sec``). Still the plain wire dict at runtime, read by key
1048
+ #: :class:`JobRetryConfig` types the keys, and every field is ALWAYS
1049
+ #: present: an older server that sends no policy reads as the retries-off
1050
+ #: policy with Harbor's defaults, exactly how such a server behaves.
1051
+ retry: JobRetryConfig
1052
+ #: The RESOLVED timeout multipliers this job's phases arm under —
1053
+ #: Harbor's five flat JobConfig fields, echoed on every job body. The
1054
+ #: global one is always a number (1.0 when the create request named
1055
+ #: none); each phase field below is None when not overridden, meaning the
1056
+ #: global one applies to that phase.
1057
+ timeout_multiplier: float
1058
+ agent_timeout_multiplier: Optional[float]
1059
+ verifier_timeout_multiplier: Optional[float]
1060
+ agent_setup_timeout_multiplier: Optional[float]
1061
+ environment_build_timeout_multiplier: Optional[float]
812
1062
  sandbox_provider: EvalSandboxProvider
813
1063
  counts: JobCounts
814
1064
  n_total_trials: int
@@ -820,8 +1070,10 @@ class Job:
820
1070
  #: GPU compute estimate, never merged into ``cost_usd``; ``evals`` keyed
821
1071
  #: ``agent__model__dataset``, each group carrying its mean and its
822
1072
  #: ``pass_at_k`` — read the latter with :func:`pass_at_k`).
823
- #: A plain dict with the wire's own keys, read by key, never constructed.
824
- stats: Dict[str, Any]
1073
+ #: Still the plain wire dict at runtime, read by key, never constructed
1074
+ #: :class:`JobStats` types the keys so ``stats['evals']`` and friends
1075
+ #: check instead of being ``Any``.
1076
+ stats: JobStats
825
1077
  #: Why the job FAILED, or None.
826
1078
  failure: Optional[JobFailure]
827
1079
  #: Provenance of a derived job; empty for an original one.
@@ -1477,6 +1729,9 @@ def _map_upstream(data: Any) -> Optional[UpstreamStatus]:
1477
1729
  checked_at=data.get('checked_at'),
1478
1730
  error=data.get('error'),
1479
1731
  auto_import=data.get('auto_import') is True,
1732
+ git_url=data.get('git_url'),
1733
+ path=data.get('path'),
1734
+ acked_commit=data.get('acked_commit'),
1480
1735
  )
1481
1736
 
1482
1737
 
@@ -1559,12 +1814,24 @@ def _map_version_gate(data: Any) -> Optional[DatasetVersionGate]:
1559
1814
  raw_failed = data.get('failed_tasks')
1560
1815
  if not isinstance(raw_failed, list):
1561
1816
  raw_failed = failure.get('failed_tasks')
1817
+ failed_tasks = _map_gate_failed_tasks(raw_failed)
1818
+ raw_count = data.get('failed_task_count')
1819
+ if not isinstance(raw_count, int) or isinstance(raw_count, bool):
1820
+ raw_count = failure.get('failed_task_count')
1562
1821
  return DatasetVersionGate(
1563
1822
  status=data['status'],
1564
1823
  attempts=attempts if isinstance(attempts, int) and not isinstance(attempts, bool) else 0,
1565
1824
  code=code if isinstance(code, str) else None,
1566
1825
  message=message if isinstance(message, str) else None,
1567
- failed_tasks=_map_gate_failed_tasks(raw_failed),
1826
+ failed_tasks=failed_tasks,
1827
+ # The TRUE total behind the 25-task cap on failed_tasks. An older
1828
+ # server never truncated without the count, so absence reads as the
1829
+ # length.
1830
+ failed_task_count=(
1831
+ raw_count
1832
+ if isinstance(raw_count, int) and not isinstance(raw_count, bool)
1833
+ else len(failed_tasks)
1834
+ ),
1568
1835
  )
1569
1836
 
1570
1837
 
@@ -1653,6 +1920,46 @@ def _map_dataset_summary(data: Dict[str, Any]) -> Dataset:
1653
1920
  )
1654
1921
 
1655
1922
 
1923
+ def _map_gate_running_progress(data: Any) -> GateRunningProgress:
1924
+ """The 202 body's ``gate`` progress block, defensively.
1925
+
1926
+ A count that is not a number reads as 0 and a missing status as PENDING
1927
+ (scheduled is the least a 202 can mean) — a misbehaving server must never
1928
+ crash the refusal path.
1929
+ """
1930
+ raw = data if isinstance(data, dict) else {}
1931
+
1932
+ def _count(value: Any) -> int:
1933
+ return value if isinstance(value, int) and not isinstance(value, bool) else 0
1934
+
1935
+ status = raw.get('status')
1936
+ return GateRunningProgress(
1937
+ status=status if isinstance(status, str) else 'PENDING',
1938
+ tasks=_count(raw.get('tasks')),
1939
+ unverified=_count(raw.get('unverified')),
1940
+ ineligible=_count(raw.get('ineligible')),
1941
+ )
1942
+
1943
+
1944
+ def _map_task_gate(data: Any) -> Optional[TaskGate]:
1945
+ """A task's own activation-gate verdict, with the gate mappers' tolerance.
1946
+
1947
+ Absent (the gate has not run it, or an older server) or unreadable input
1948
+ is ``None`` — "nothing to report", never "passed" and never a crash. An
1949
+ entry without an outcome word is no verdict at all.
1950
+ """
1951
+ if not isinstance(data, dict) or not isinstance(data.get('outcome'), str):
1952
+ return None
1953
+ reasons = data.get('reasons')
1954
+ ran_at = data.get('ran_at')
1955
+ return TaskGate(
1956
+ outcome=data['outcome'],
1957
+ flaky=data.get('flaky') is True,
1958
+ reasons=[r for r in reasons if isinstance(r, str)] if isinstance(reasons, list) else [],
1959
+ ran_at=ran_at if isinstance(ran_at, str) else None,
1960
+ )
1961
+
1962
+
1656
1963
  def _map_task(data: Dict[str, Any]) -> Task:
1657
1964
  providers_raw = data.get('providers') or {}
1658
1965
  gpus_raw = data.get('gpus')
@@ -1677,6 +1984,9 @@ def _map_task(data: Dict[str, Any]) -> Task:
1677
1984
  if isinstance(gpu_types_raw, list) and gpu_types_raw
1678
1985
  else None
1679
1986
  ),
1987
+ # The per-task half of the version's gate — verdicts appear here as
1988
+ # they land while the gate runs.
1989
+ gate=_map_task_gate(data.get('gate')),
1680
1990
  )
1681
1991
 
1682
1992
 
@@ -1734,6 +2044,34 @@ def _map_source_job(data: Dict[str, Any]) -> SourceJob:
1734
2044
  )
1735
2045
 
1736
2046
 
2047
+ def _optional_float(value: Any) -> Optional[float]:
2048
+ """A wire number or None — anything else (an older server, garbage) is None."""
2049
+ return float(value) if isinstance(value, (int, float)) else None
2050
+
2051
+
2052
+ def _map_retry_config(data: Any) -> JobRetryConfig:
2053
+ """The resolved retry policy off a job body. Tolerant of an OLDER server
2054
+ that does not send one yet: the absent-field reading is the retries-off
2055
+ policy with Harbor's defaults — exactly how such a server behaves.
2056
+ """
2057
+ raw = data if isinstance(data, dict) else {}
2058
+
2059
+ def _number(value: Any, default: float) -> float:
2060
+ # bool is an int in Python; a boolean here is malformed, not a number.
2061
+ return value if isinstance(value, (int, float)) and not isinstance(value, bool) else default
2062
+
2063
+ include = raw.get('include_exceptions')
2064
+ exclude = raw.get('exclude_exceptions')
2065
+ return {
2066
+ 'max_retries': int(_number(raw.get('max_retries'), 0)),
2067
+ 'include_exceptions': include if isinstance(include, list) else None,
2068
+ 'exclude_exceptions': exclude if isinstance(exclude, list) else [],
2069
+ 'wait_multiplier': _number(raw.get('wait_multiplier'), 1.0),
2070
+ 'min_wait_sec': _number(raw.get('min_wait_sec'), 1.0),
2071
+ 'max_wait_sec': _number(raw.get('max_wait_sec'), 60.0),
2072
+ }
2073
+
2074
+
1737
2075
  def _map_job(data: Dict[str, Any]) -> Job:
1738
2076
  """The ONE job mapper — nothing conditional, because nothing is optional."""
1739
2077
  agents = data.get('agents')
@@ -1753,9 +2091,23 @@ def _map_job(data: Dict[str, Any]) -> Job:
1753
2091
  n_concurrent_trials=int(data.get('n_concurrent_trials', 0)),
1754
2092
  max_trial_spend_usd=float(data.get('max_trial_spend_usd', 0)),
1755
2093
  worst_case_spend_usd=float(data.get('worst_case_spend_usd', 0)),
1756
- # An older server sends no policy; {} reads as "no auto-retry", which
1757
- # is exactly how such a server behaves.
1758
- retry=data.get('retry') if isinstance(data.get('retry'), dict) else {},
2094
+ # Resolved with Harbor's defaults for anything absent an older
2095
+ # server that sends no policy reads as the retries-off policy, which
2096
+ # is exactly how such a server behaves; every field always present.
2097
+ retry=_map_retry_config(data.get('retry')),
2098
+ # Timeout multipliers: an older server sends none — 1.0 / None reads
2099
+ # as "every phase at 1.0", exactly how such a server behaves.
2100
+ timeout_multiplier=(
2101
+ float(data['timeout_multiplier'])
2102
+ if isinstance(data.get('timeout_multiplier'), (int, float))
2103
+ else 1.0
2104
+ ),
2105
+ agent_timeout_multiplier=_optional_float(data.get('agent_timeout_multiplier')),
2106
+ verifier_timeout_multiplier=_optional_float(data.get('verifier_timeout_multiplier')),
2107
+ agent_setup_timeout_multiplier=_optional_float(data.get('agent_setup_timeout_multiplier')),
2108
+ environment_build_timeout_multiplier=_optional_float(
2109
+ data.get('environment_build_timeout_multiplier')
2110
+ ),
1759
2111
  sandbox_provider=data.get('sandbox_provider', ''),
1760
2112
  counts=_map_counts(data.get('counts')),
1761
2113
  n_total_trials=int(data.get('n_total_trials', 0)),
@@ -1907,6 +2259,23 @@ def _map_trial_retry(data: Dict[str, Any]) -> TrialRetry:
1907
2259
  )
1908
2260
 
1909
2261
 
2262
+ def _map_provider_degrade(data: Any) -> Optional[Dict[str, str]]:
2263
+ """The wire degrade object, defensively: anything malformed answers None,
2264
+ never a crash and never a partial row; extra keys never ride through."""
2265
+ if not isinstance(data, dict):
2266
+ return None
2267
+ from_provider = data.get('from')
2268
+ to_provider = data.get('to')
2269
+ reason = data.get('reason')
2270
+ if not (
2271
+ isinstance(from_provider, str)
2272
+ and isinstance(to_provider, str)
2273
+ and isinstance(reason, str)
2274
+ ):
2275
+ return None
2276
+ return {'from': from_provider, 'to': to_provider, 'reason': reason}
2277
+
2278
+
1910
2279
  def _map_trial(data: Dict[str, Any]) -> Trial:
1911
2280
  retries = data.get('retries')
1912
2281
  return Trial(
@@ -1938,11 +2307,7 @@ def _map_trial(data: Dict[str, Any]) -> Trial:
1938
2307
  max_trial_spend_usd=data.get('max_trial_spend_usd'),
1939
2308
  sandbox_provider=data.get('sandbox_provider'),
1940
2309
  # Defensive: a malformed degrade object reads as None, never a crash.
1941
- sandbox_provider_degrade=(
1942
- data['sandbox_provider_degrade']
1943
- if isinstance(data.get('sandbox_provider_degrade'), dict)
1944
- else None
1945
- ),
2310
+ sandbox_provider_degrade=_map_provider_degrade(data.get('sandbox_provider_degrade')),
1946
2311
  # Same defensive rule; absent (an older server) reads as None too.
1947
2312
  gpu_cost=(
1948
2313
  data['gpu_cost'] if isinstance(data.get('gpu_cost'), dict) else None
@@ -2199,6 +2564,25 @@ class _HostedHttp:
2199
2564
  ) -> Dict[str, Any]:
2200
2565
  return await asyncio.to_thread(self._request_sync, path, method, body, headers, False)
2201
2566
 
2567
+ async def request_json_status(
2568
+ self,
2569
+ path: str,
2570
+ method: str = 'GET',
2571
+ body: Optional[Dict[str, Any]] = None,
2572
+ headers: Optional[Dict[str, str]] = None,
2573
+ ) -> 'tuple[Dict[str, Any], int]':
2574
+ """Like :meth:`request_json`, plus the HTTP status code.
2575
+
2576
+ For the one verb whose 2xx statuses mean different bodies — activate
2577
+ answers 200 with the Dataset and 202 with a GateRunning progress
2578
+ report — where parsing every 2xx as the success shape returned a
2579
+ garbage object.
2580
+ """
2581
+ return await asyncio.to_thread(
2582
+ self._request_sync, path, method, body, headers, False,
2583
+ REQUEST_TIMEOUT_SEC, True,
2584
+ )
2585
+
2202
2586
  async def request_bytes(
2203
2587
  self, path: str, *, timeout: int = DOWNLOAD_TIMEOUT_SEC
2204
2588
  ) -> 'tuple[bytes, Dict[str, str]]':
@@ -2258,6 +2642,7 @@ class _HostedHttp:
2258
2642
  headers: Optional[Dict[str, str]],
2259
2643
  raw: bool,
2260
2644
  timeout: int = REQUEST_TIMEOUT_SEC,
2645
+ with_status: bool = False,
2261
2646
  ):
2262
2647
  data = json.dumps(body).encode('utf-8') if body is not None else None
2263
2648
  request_headers = {
@@ -2277,13 +2662,13 @@ class _HostedHttp:
2277
2662
  try:
2278
2663
  with _http.urlopen(request, timeout=timeout) as response:
2279
2664
  payload = response.read()
2665
+ status = response.status
2280
2666
  if raw:
2281
2667
  return payload, dict(response.headers.items())
2282
2668
  except urllib.error.HTTPError as exc:
2283
2669
  _raise_api_error(exc)
2284
- if not payload:
2285
- return {}
2286
- return json.loads(payload.decode('utf-8'))
2670
+ parsed = json.loads(payload.decode('utf-8')) if payload else {}
2671
+ return (parsed, status) if with_status else parsed
2287
2672
 
2288
2673
  def _download_sync(self, path: str, to_dir: str, default_filename: str) -> str:
2289
2674
  """Stream a download straight to disk — never buffers the archive in memory."""
@@ -2981,13 +3366,33 @@ class DatasetsClient:
2981
3366
  async def activate(self, name: str, version: str) -> Dataset:
2982
3367
  """Make a READY version the dataset's active version.
2983
3368
 
2984
- Returns the full detail shape, exactly like :meth:`get`.
3369
+ Returns the full detail shape, exactly like :meth:`get`. While the
3370
+ version's activation gate is still scheduled or running the API
3371
+ answers 202 ``gate_running`` — a healthy in-progress state, raised
3372
+ here as the typed :class:`GateRunningError` (its ``gate`` carries the
3373
+ gate's progress). A gate that passes activates the version itself, so
3374
+ there is normally nothing left to call.
2985
3375
  """
2986
- raw = await self._http.request_json(
3376
+ raw, status = await self._http.request_json_status(
2987
3377
  f'/api/datasets/{urllib.parse.quote(name)}'
2988
3378
  f'/versions/{urllib.parse.quote(version)}/activate',
2989
3379
  method='POST',
2990
3380
  )
3381
+ # 202 is "not yet", not "here is the dataset": the body is a
3382
+ # GateRunning progress report — parsing it as a Dataset returned a
3383
+ # garbage object. Typed, like NoActiveVersionError, so a caller can
3384
+ # branch and poll.
3385
+ if status == 202:
3386
+ message = raw.get('message')
3387
+ raise GateRunningError(
3388
+ name,
3389
+ version,
3390
+ message if isinstance(message, str) else (
3391
+ f'Dataset {name!r} version {version!r} is still being '
3392
+ 'proven by its activation gate'
3393
+ ),
3394
+ _map_gate_running_progress(raw.get('gate')),
3395
+ )
2991
3396
  return _map_dataset_detail(raw)
2992
3397
 
2993
3398
  async def update(self, name: str, *, upstream_auto_import: bool) -> Dataset:
@@ -3387,7 +3792,12 @@ class JobsClient:
3387
3792
  n_concurrent_trials: Optional[int] = None,
3388
3793
  max_trial_spend_usd: Optional[float] = None,
3389
3794
  sandbox_provider: Optional[str] = None,
3390
- retry: Optional[Dict[str, Any]] = None,
3795
+ retry: Optional[JobRetryConfigInput] = None,
3796
+ timeout_multiplier: Optional[float] = None,
3797
+ agent_timeout_multiplier: Optional[float] = None,
3798
+ verifier_timeout_multiplier: Optional[float] = None,
3799
+ agent_setup_timeout_multiplier: Optional[float] = None,
3800
+ environment_build_timeout_multiplier: Optional[float] = None,
3391
3801
  agent_env: Optional[Dict[str, str]] = None,
3392
3802
  verifier_env: Optional[Dict[str, str]] = None,
3393
3803
  idempotency_key: Optional[str] = None,
@@ -3408,10 +3818,12 @@ class JobsClient:
3408
3818
  case for the whole job. ``retry`` is the auto-retry policy in
3409
3819
  Harbor's RetryConfig vocabulary (``max_retries``,
3410
3820
  ``include_exceptions``, ``exclude_exceptions``, ``wait_multiplier``,
3411
- ``min_wait_sec``, ``max_wait_sec``); omitted, the server applies its
3821
+ ``min_wait_sec``, ``max_wait_sec``) a plain dict, typed
3822
+ :class:`JobRetryConfigInput`; omitted, the server applies its
3412
3823
  fleet defaults (infrastructure errors retry automatically — send
3413
3824
  ``{'max_retries': 0}`` to turn retries off), and the response echoes
3414
- the RESOLVED policy either way. Inside the policy, an EXPLICIT
3825
+ the RESOLVED policy either way as ``Job.retry``
3826
+ (:class:`JobRetryConfig`, every field present). Inside the policy, an EXPLICIT
3415
3827
  ``'exclude_exceptions': None`` is not the same as leaving the key
3416
3828
  out: None turns exclusions off entirely (everything the include set
3417
3829
  admits is retried — Harbor's own None semantics), while an omitted
@@ -3419,7 +3831,19 @@ class JobsClient:
3419
3831
  ``'include_exceptions'`` has no such split: None, an omitted key,
3420
3832
  and the empty list ``[]`` all mean no filter — Harbor's include
3421
3833
  check treats the empty set exactly like None, so ``[]`` never means
3422
- "retry nothing". ``agent_env`` / ``verifier_env`` are
3834
+ "retry nothing". The five ``*timeout_multiplier`` arguments are
3835
+ Harbor's timeout knobs verbatim: ``timeout_multiplier`` multiplies
3836
+ every TASK-DECLARED timeout for this job's runs (default 1.0;
3837
+ values below 1 shrink), and each phase-specific one —
3838
+ ``agent_timeout_multiplier``, ``verifier_timeout_multiplier``,
3839
+ ``agent_setup_timeout_multiplier``,
3840
+ ``environment_build_timeout_multiplier`` — overrides it for that
3841
+ phase. The task itself is never rewritten. Every multiplier must be
3842
+ greater than 0 and at most the published ceiling
3843
+ (``limits['job']['max_timeout_multiplier']`` on the capability
3844
+ document; 10 unless the fleet changes it) — an absurd value is
3845
+ refused at create with a typed message naming the bound.
3846
+ ``agent_env`` / ``verifier_env`` are
3423
3847
  pass-through slots injected into every agent / verifier run — sent
3424
3848
  verbatim; the server owns acceptance (refused where unsupported,
3425
3849
  never silently dropped). The hosted platform honors exactly two
@@ -3452,6 +3876,16 @@ class JobsClient:
3452
3876
  body['sandbox_provider'] = sandbox_provider
3453
3877
  if retry is not None:
3454
3878
  body['retry'] = retry
3879
+ if timeout_multiplier is not None:
3880
+ body['timeout_multiplier'] = timeout_multiplier
3881
+ if agent_timeout_multiplier is not None:
3882
+ body['agent_timeout_multiplier'] = agent_timeout_multiplier
3883
+ if verifier_timeout_multiplier is not None:
3884
+ body['verifier_timeout_multiplier'] = verifier_timeout_multiplier
3885
+ if agent_setup_timeout_multiplier is not None:
3886
+ body['agent_setup_timeout_multiplier'] = agent_setup_timeout_multiplier
3887
+ if environment_build_timeout_multiplier is not None:
3888
+ body['environment_build_timeout_multiplier'] = environment_build_timeout_multiplier
3455
3889
  if agent_env is not None:
3456
3890
  body['agent_env'] = agent_env
3457
3891
  if verifier_env is not None:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: evolve-sdk
3
- Version: 0.0.52.dev744
3
+ Version: 0.0.52.dev760
4
4
  Summary: Pythonic SDK for multi-agent orchestration in E2B sandboxes
5
5
  Author-email: "Swarmlink, Inc." <brandomagnani@evolvingmachines.ai>
6
6
  License: Apache-2.0
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "evolve-sdk"
7
- version = "0.0.52.dev744"
7
+ version = "0.0.52.dev760"
8
8
  description = "Pythonic SDK for multi-agent orchestration in E2B sandboxes"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"