@task-handoff/node-agent 0.0.22-alpha.1 → 0.0.22-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -1 +1 @@
1
- "use strict";var e=require("commander"),t=require("node:fs"),n=require("node:path"),i=require("node:http"),r=require("node:url"),o=require("fastify"),s=require("@fastify/websocket"),a=require("zod"),c=require("node:os"),d=require("node:crypto"),l=require("node:child_process"),u=require("node-pty"),m=require("ws"),p=require("node:net"),h=require("node:stream"),g=require("node:fs/promises"),f=require("node:stream/promises"),y=require("tar"),I=require("write-file-atomic"),A=require("semver"),b="undefined"!=typeof document?document.currentScript:null;function w(e,n){try{const i=JSON.parse(t.readFileSync(e,"utf8"));if(n&&i.name!==n)return;return"string"==typeof i.version&&i.version.trim()?i.version.trim():void 0}catch{return}}function v(e){if(e)try{return n.dirname(t.realpathSync(e))}catch{return}}function E(e,t=process.env,i=e){const r=t.TASK_HANDOFF_VERSION?.trim();if(r)return r;const o=i.split("/").at(-1),s=process.argv[1]?n.resolve(process.argv[1]):void 0,a=s?n.dirname(s):void 0,c=[v(s),a,process.cwd()].filter(e=>Boolean(e));for(const t of new Set(c)){let i=t;for(;;){const t=w(n.join(i,"package.json"),e);if(t)return t;const r=n.dirname(i);if(r===i)break;i=r}}let d;for(const e of new Set(c)){let t=e;for(;;){if(o){const e=w(n.join(t,"packages",o,"package.json"),i);if(e)return e}d||=w(n.join(t,"package.json"));const e=n.dirname(t);if(e===t)break;t=e}}return d||"unknown"}class N extends Error{code;lockPath;owner;constructor(e,t,n={}){const i=t?.pid?` pid ${t.pid}`:"";super(`${n.label||"Process"} is already running${i}. Lock: ${e}`),this.name="ProcessSingletonError",this.code=n.code||"PROCESS_ALREADY_RUNNING",this.lockPath=e,this.owner=t}}function S(e){return n.join(e,"owner.json")}function T(e){return n.join(e,"initializing.json")}function z(e){return n.join(e,"recovering.json")}function _(e){return Number.isInteger(e)&&Number(e)>0}function C(e,n=process.platform){if(_(e)){if("linux"===n)try{const n=t.readFileSync(`/proc/${e}/stat`,"utf8"),i=n.lastIndexOf(")");if(i<0)return;const r=n.slice(i+2).trim().split(/\s+/)[19];return r?`linux:${r}`:void 0}catch{return}if(["darwin","freebsd","openbsd","aix","sunos"].includes(n)){const t=l.spawnSync("ps",["-o","lstart=","-p",String(e)],{encoding:"utf8",timeout:1e3}),i=0===t.status?t.stdout.trim().replace(/\s+/g," "):"";return i?`${n}:${i}`:void 0}if("win32"===n){const t=`(Get-Process -Id ${e} -ErrorAction Stop).StartTime.ToUniversalTime().Ticks`,n=l.spawnSync("powershell.exe",["-NoProfile","-NonInteractive","-Command",t],{encoding:"utf8",timeout:2e3}),i=0===n.status?n.stdout.trim():"";return/^\d+$/.test(i)?`win32:${i}`:void 0}}}function k(e){try{const n=JSON.parse(t.readFileSync(S(e),"utf8"));if(_(n.pid)&&"string"==typeof n.startTime){const e=n;return{pid:e.pid,hostname:"string"==typeof e.hostname&&e.hostname?e.hostname:c.hostname(),component:e.component||"server-update",command:"string"==typeof e.command?e.command:"",acquiredAt:"string"==typeof e.createdAt&&Number.isFinite(Date.parse(e.createdAt))?e.createdAt:new Date(0).toISOString(),token:"string"==typeof e.token&&e.token?e.token:`legacy:${e.pid}:${e.startTime}`,startIdentity:e.startTime.startsWith("linux:")?e.startTime:`linux:${e.startTime}`}}if(!(_(n.pid)&&"string"==typeof n.hostname&&n.hostname&&"string"==typeof n.command&&"string"==typeof n.acquiredAt&&Number.isFinite(Date.parse(n.acquiredAt))&&"string"==typeof n.token&&n.token))return;return n}catch{return}}const O=k;function R(e){if(!_(e))return!1;try{return process.kill(Number(e),0),!0}catch(e){return"EPERM"===e.code}}function x(e){if(!e||!R(e.pid))return!1;if(!e.startIdentity)return!0;const t=C(e.pid);return void 0===t||t===e.startIdentity}function D(e,i){const r=n.join(e,`.owner-${i.token}.tmp`);t.writeFileSync(r,`${JSON.stringify(i,null,2)}\n`,{encoding:"utf8",mode:384,flag:"wx"});const o=M(e);if(o?.token!==i.token)throw j(r),new Error(`Process lock initialization was superseded: ${e}`);t.renameSync(r,S(e)),j(T(e))}function P(e,i,r){const o=O(e);if(o?.token!==i.token)return!1;const s={...i};for(const[e,t]of Object.entries(r))void 0===t?delete s[e]:Object.assign(s,{[e]:t});const a=n.join(e,`.owner-update-${i.token}-${d.randomUUID()}.tmp`);try{if(t.writeFileSync(a,`${JSON.stringify(s,null,2)}\n`,{encoding:"utf8",mode:384,flag:"wx"}),O(e)?.token!==i.token)return!1;t.renameSync(a,S(e));for(const e of Object.keys(i))delete i[e];return Object.assign(i,s),!0}catch(e){if("ENOENT"===e.code)return!1;throw e}finally{j(a)}}function M(e){try{return JSON.parse(t.readFileSync(T(e),"utf8"))}catch{return}}function L(e){const t=M(e);return _(t?.pid)&&x({pid:t.pid,startIdentity:t.startIdentity})}function j(e){try{t.unlinkSync(e)}catch(e){if("ENOENT"!==e.code)throw e}}function $(){Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,20)}function F(e){try{const n=M(e),i=Date.parse(n?.startedAt||"");return Number.isFinite(i)?Math.max(0,Date.now()-i):Math.max(0,Date.now()-t.statSync(e).mtimeMs)}catch{return 0}}function U(e,i){try{return t.writeFileSync(z(e),`${JSON.stringify({token:i,pid:process.pid,startedAt:(new Date).toISOString()})}\n`,{encoding:"utf8",mode:384,flag:"wx"}),!0}catch(r){if("EEXIST"===r.code)return!!function(e){const i=z(e),r=V(i),o=Date.parse(r?.startedAt||"");if(R(r?.pid)||Number.isFinite(o)&&Date.now()-o<2e3)return!1;const s=n.join(e,`.recovering-${d.randomUUID()}.stale`);try{t.renameSync(i,s)}catch(e){if(["ENOENT","EEXIST"].includes(e.code||""))return!1;throw e}const a=V(s);if(a?.token===r?.token)return j(s),!0;try{t.linkSync(s,i)}catch(e){if("EEXIST"!==e.code)throw e}finally{j(s)}return!1}(e)&&U(e,i);if("ENOENT"===r.code)return!1;throw r}}function V(e){try{return JSON.parse(t.readFileSync(e,"utf8"))}catch{return}}function q(e,t){return V(z(e))?.token===t}const H=6048e5;function B(e,t){const i=n.resolve(e),r=n.resolve(i,t);if(n.dirname(r)!==i||n.basename(r)!==t)throw new Error(`Retention entry is not a direct child of its managed root: ${t}`);return r}function K(e){if(t.existsSync(e)){const n=t.lstatSync(e);if(!n.isDirectory()||n.isSymbolicLink())throw new Error(`Managed persistence path must be a real directory: ${e}`)}t.mkdirSync(e,{recursive:!0,mode:448}),t.chmodSync(e,448)}const G=41943040,J="ai.sessions",W=a.z.string().trim().min(1).max(80),Y=a.z.enum(["app-session","ai-session"]),X=a.z.enum(["running","waiting","idle","failed"]);a.z.object({instanceId:a.z.string().trim().min(1).max(160),sessionId:a.z.string().trim().min(1).max(120),unread:a.z.boolean(),sessionUpdatedAt:a.z.string().datetime(),updatedAt:a.z.string().datetime()}).strict();const Q=a.z.enum(["thinking","tool","editing","approval","responding","unknown"]),Z=a.z.object({id:a.z.string().trim().min(1).max(240).optional(),kind:a.z.string().trim().min(1).max(80).optional(),name:a.z.string().trim().min(1).max(120),inputPreview:a.z.string().trim().max(500).optional(),startedAt:a.z.string().datetime().optional()}).strict(),ee=a.z.enum(["pending-init","running","interrupted","completed","errored","shutdown","not-found"]),te=a.z.enum(["started","interacted","interrupted"]),ne=a.z.object({threadId:a.z.string().trim().min(1).max(240),path:a.z.string().trim().max(4096).optional(),status:ee,activity:te.optional(),message:a.z.string().trim().max(1e3).optional(),updatedAt:a.z.string().datetime()}).strict(),ie=a.z.object({toolCalls:a.z.number().int().min(0).default(0),edits:a.z.number().int().min(0).default(0),approvals:a.z.number().int().min(0).default(0)}).strict().default({toolCalls:0,edits:0,approvals:0}),re=a.z.object({send:a.z.boolean().optional(),interrupt:a.z.boolean().optional(),approval:a.z.boolean().optional(),fork:a.z.boolean().optional(),openApp:a.z.boolean().optional(),close:a.z.boolean().optional()}).strict(),oe=a.z.object({kind:a.z.literal("fork"),parentProviderSessionId:a.z.string().trim().min(1).max(240),throughTurnId:a.z.string().trim().min(1).max(240).optional()}).strict(),se=a.z.enum(["image","file"]),ae=a.z.object({id:a.z.string().trim().min(1).max(120),kind:se,name:a.z.string().trim().min(1).max(240),mime:a.z.string().trim().min(1).max(120),size:a.z.number().int().min(0).max(Number.MAX_SAFE_INTEGER)}),ce=a.z.union([ae.extend({source:a.z.object({type:a.z.literal("inline"),encoding:a.z.literal("base64"),data:a.z.string().min(1).max(31457280)}).strict()}).strict().superRefine((e,t)=>{const n="image"===e.kind?20971520:512e3;(e.size<=0||("file"===e.kind?e.size>=n:e.size>n))&&t.addIssue({code:a.z.ZodIssueCode.custom,path:["size"],message:`Inline ${e.kind} must be between 1 byte and ${n} bytes.`})}),ae.extend({source:a.z.object({type:a.z.literal("runtime-path"),path:a.z.string().trim().min(1).max(4096)}).strict()}).strict()]),de=ae.extend({sourceType:a.z.enum(["inline","runtime-path"])}).strict(),le=a.z.union([a.z.object({id:a.z.string().trim().min(1).max(120),kind:se.optional(),source:a.z.object({type:a.z.literal("upload-ref")}).strict().default({type:"upload-ref"})}).strict(),a.z.object({id:a.z.string().trim().min(1).max(120),kind:se,name:a.z.string().trim().min(1).max(240),mime:a.z.string().trim().min(1).max(120),size:a.z.number().int().min(0).max(Number.MAX_SAFE_INTEGER),source:a.z.object({type:a.z.literal("runtime-path"),path:a.z.string().trim().min(1).max(4096)}).strict()}).strict()]),ue=a.z.enum(["auto","queue","steer","immediate"]),me=a.z.enum(["ask","auto-review","full-access"]),pe=a.z.enum(["review","rename","goal","compact"]);a.z.object({command:pe,argument:a.z.string().trim().max(4e3).optional()}).strict().superRefine((e,t)=>{"rename"!==e.command||e.argument||t.addIssue({code:"custom",path:["argument"],message:"Rename requires a thread name."}),"review"!==e.command&&"compact"!==e.command||!e.argument||t.addIssue({code:"custom",path:["argument"],message:`${e.command} does not accept an argument.`})}),a.z.object({command:pe,value:a.z.string().max(4e3).optional(),turnId:a.z.string().trim().min(1).max(240).optional()}).strict(),a.z.enum(["skill","app","plugin"]);const he=a.z.object({name:a.z.string().trim().min(1).max(240),path:a.z.string().trim().min(1).max(4096)}),ge=a.z.discriminatedUnion("kind",[he.extend({kind:a.z.literal("skill"),path:a.z.string().trim().min(1).max(4096).refine(e=>e.startsWith("/"),"Skill paths must be absolute.")}).strict(),he.extend({kind:a.z.literal("app"),path:a.z.string().trim().min(7).max(4096).regex(/^app:\/\/[^\s/]+$/,"App paths must use app://<id>.")}).strict(),he.extend({kind:a.z.literal("plugin"),path:a.z.string().trim().min(10).max(4096).regex(/^plugin:\/\/[^\s/]+$/,"Plugin paths must use plugin://<id>.")}).strict()]),fe=a.z.array(ge).max(20).default([]),ye=a.z.enum(["plugin","skill","file","directory","app"]),Ie=a.z.object({kind:ye,name:a.z.string().trim().min(1).max(240),description:a.z.string().trim().max(1e3).optional(),path:a.z.string().trim().min(1).max(4096),icon:a.z.string().trim().max(4096).optional()}).strict().superRefine((e,t)=>{"skill"!==e.kind||e.path.startsWith("/")||t.addIssue({code:"custom",path:["path"],message:"Skill paths must be absolute."}),"app"!==e.kind||/^app:\/\/[^\s/]+$/.test(e.path)||t.addIssue({code:"custom",path:["path"],message:"App paths must use app://<id>."}),"plugin"!==e.kind||/^plugin:\/\/[^\s/]+$/.test(e.path)||t.addIssue({code:"custom",path:["path"],message:"Plugin paths must use plugin://<id>."}),"file"!==e.kind&&"directory"!==e.kind||!e.path.startsWith("/")&&!e.path.split(/[\\/]+/).includes("..")||t.addIssue({code:"custom",path:["path"],message:"File and directory paths must be relative to the session cwd."})}),Ae=a.z.object({category:a.z.enum(["skills","plugins","apps","files"]),code:a.z.string().trim().min(1).max(160),message:a.z.string().trim().min(1).max(2e3)}).strict();a.z.object({sessionId:a.z.string().trim().min(1).max(120),providerSessionId:a.z.string().trim().min(1).max(240),cwd:a.z.string().trim().min(1).max(4096),candidates:a.z.array(Ie).max(1e3).default([]),diagnostics:a.z.array(Ae).max(20).default([])}).strict(),a.z.object({query:a.z.string().trim().max(240).default("")}).strict(),a.z.object({sessionId:a.z.string().trim().min(1).max(120),cwd:a.z.string().trim().min(1).max(4096),query:a.z.string().trim().max(240),requestId:a.z.string().trim().min(1).max(160),candidates:a.z.array(Ie.refine(e=>"file"===e.kind||"directory"===e.kind,"File search only returns files and directories.")).max(200).default([]),complete:a.z.boolean().default(!1)}).strict();const be=a.z.object({message:a.z.string().trim().min(1).max(2e4),mode:ue.optional(),permissionMode:me.optional()}),we=be.extend({attachments:a.z.array(ce).max(6).default([]),references:fe}).strict().superRefine((e,t)=>{e.attachments.reduce((e,t)=>e+("inline"===t.source.type?t.size:0),0)>G&&t.addIssue({code:a.z.ZodIssueCode.custom,path:["attachments"],message:"Inline attachments must be 41943040 bytes or less in total."})}),ve=be.extend({attachments:a.z.array(le).max(6).default([]),references:fe}).strict(),Ee=a.z.object({type:a.z.literal("runtime-path"),path:a.z.string().trim().min(1).max(4096).refine(e=>e.startsWith("/")||/^[A-Za-z]:[\\/]/.test(e),"Runtime paths must be absolute in the target controlled instance.")}).strict();we.extend({agent:W,cwd:Ee,cwdFolderId:a.z.string().trim().min(1).max(120).optional(),clientRequestId:a.z.string().trim().min(1).max(160)}).strict();const Ne=a.z.object({mode:a.z.enum(["current-folder","worktree"]),branch:a.z.string().trim().min(1).max(1024)}).strict();ve.extend({agent:W,cwdFolderId:a.z.string().trim().min(1).max(120).optional(),gitSelection:Ne.optional(),clientRequestId:a.z.string().trim().min(1).max(160)}).strict(),a.z.object({disposition:a.z.enum(["created","already-created"]),aiSessionId:a.z.string().trim().min(1).max(120),providerSessionId:a.z.string().trim().min(1).max(240),creationSource:a.z.literal("ai-session")}).strict();const Se=a.z.object({mode:a.z.enum(["current","managed-worktree"]).default("current")}).strict().default({mode:"current"});a.z.object({clientRequestId:a.z.string().trim().min(1).max(160),throughTurnId:a.z.string().trim().min(1).max(240).optional(),workspace:Se.optional().default({mode:"current"})}).strict(),a.z.object({disposition:a.z.enum(["created","already-created"]),aiSessionId:a.z.string().trim().min(1).max(120),providerSessionId:a.z.string().trim().min(1).max(240),creationSource:a.z.literal("ai-session")}).strict(),a.z.object({clientRequestId:a.z.string().trim().min(1).max(160)}).strict(),a.z.object({disposition:a.z.enum(["opened","already-open"]),aiSessionId:a.z.string().trim().min(1).max(120),providerSessionId:a.z.string().trim().min(1).max(240),appSessionId:a.z.string().trim().min(1).max(120),creationSource:Y}).strict(),a.z.object({clientRequestId:a.z.string().trim().min(1).max(160)}).strict(),a.z.object({disposition:a.z.enum(["closed","already-closed"]),aiSessionId:a.z.string().trim().min(1).max(120),providerSessionId:a.z.string().trim().min(1).max(240),creationSource:Y}).strict(),a.z.object({code:a.z.enum(["invalid-request","not-found","unsupported","provider-unavailable","materialization-failed","open-app-failed","close-failed","conflict"]),message:a.z.string().trim().min(1).max(4e3),retryable:a.z.boolean().default(!1),aiSessionId:a.z.string().trim().min(1).max(120).optional(),providerSessionId:a.z.string().trim().min(1).max(240).optional()}).strict(),a.z.object({decision:a.z.enum(["allow","deny","skip"])}).strict(),a.z.object({expectedRevision:a.z.number().int().min(0),queueIds:a.z.array(a.z.string().trim().min(1).max(120)).max(100)}).strict(),a.z.object({expectedRevision:a.z.number().int().min(0),message:a.z.string().trim().min(1).max(2e4)}).strict(),a.z.object({code:a.z.string().trim().min(1).max(160),message:a.z.string(),instanceId:a.z.string().trim().min(1).max(160).optional(),nodeId:a.z.string().trim().min(1).max(160).optional(),route:a.z.string().trim().min(1).max(4096).optional()}).strict();const Te=a.z.object({id:a.z.string().trim().min(1).max(120),message:a.z.string().trim().min(1).max(2e4),attachments:a.z.array(de).max(6).default([]),references:fe,permissionMode:me.optional(),status:a.z.enum(["queued","sending","failed"]).default("queued"),createdAt:a.z.string().datetime(),updatedAt:a.z.string().datetime(),error:a.z.string().trim().max(4e3).optional()}).strict(),ze=a.z.object({revision:a.z.number().int().min(0).default(0),pendingCount:a.z.number().int().min(0).default(0),items:a.z.array(Te).max(100).default([])}).strict().default({revision:0,pendingCount:0,items:[]}),_e=a.z.enum(["control","realtime","adapter-snapshot","transcript-tail","transcript-scan","process-scan","app-session"]),Ce=a.z.object({id:a.z.string().trim().min(1).max(240),status:a.z.enum(["running","completed"]),startedAt:a.z.string().datetime().optional(),completedAt:a.z.string().datetime().optional()}).strict(),ke=a.z.object({id:a.z.string().trim().min(1).max(240),providerTurnId:a.z.string().trim().max(240).optional(),source:_e.optional(),userPrompt:a.z.string().trim().optional(),status:a.z.enum(["queued","running","waiting","completed","failed"]).default("running"),phase:Q.optional(),summary:a.z.string().trim().max(1e3).optional(),lastMessage:a.z.string().trim().optional(),lastMessageItemId:a.z.string().trim().max(240).optional(),contextCompactions:a.z.array(Ce).max(20).optional(),revision:a.z.number().int().min(0).default(0),sourcePriority:a.z.number().int().min(0).max(100).optional(),snapshotVersion:a.z.number().int().min(0).optional(),observedAt:a.z.string().datetime().optional(),startedAt:a.z.string().datetime().optional(),updatedAt:a.z.string().datetime().optional(),completedAt:a.z.string().datetime().optional()}).strict(),Oe=ke.pick({id:!0,providerTurnId:!0,userPrompt:!0,status:!0,phase:!0,summary:!0,lastMessage:!0,contextCompactions:!0,startedAt:!0,updatedAt:!0,completedAt:!0}).strict(),Re=a.z.object({id:a.z.string().trim().min(1).max(120),agent:W,creationSource:Y.default("app-session"),appSessionId:a.z.string().trim().max(120).optional(),appId:a.z.string().trim().max(120).optional(),providerSessionId:a.z.string().trim().max(240).optional(),lineage:oe.optional(),providerMeta:a.z.record(a.z.string(),a.z.unknown()).optional(),appBindingKeys:a.z.array(a.z.string().trim().min(1).max(240)).max(20).optional(),actions:re.optional(),activeTurnId:a.z.string().trim().max(240).optional(),title:a.z.string().trim().max(240).optional(),cwd:a.z.string().trim().max(4096).optional(),cwdFolderId:a.z.string().trim().min(1).max(120).optional(),userPrompt:a.z.string().trim().optional(),turns:a.z.array(ke).max(50).optional(),status:X.default("running"),phase:Q.default("unknown"),summary:a.z.string().trim().max(1e3).optional(),lastMessage:a.z.string().trim().optional(),lastMessageItemId:a.z.string().trim().max(240).optional(),currentTool:Z.optional(),toolCallsSinceLastMessage:a.z.number().int().min(0).default(0),subAgents:a.z.array(ne).max(50).default([]),transcriptPath:a.z.string().trim().max(4096).optional(),transcriptSize:a.z.number().int().min(0).optional(),startedAt:a.z.string().datetime(),updatedAt:a.z.string().datetime(),completedAt:a.z.string().datetime().optional(),error:a.z.string().trim().max(4e3).optional(),counters:ie,queue:ze}).strict();a.z.object({session:Re,provider:a.z.string().trim().min(1).max(80),action:a.z.enum(["send","queue","steer","interrupt","approval"]),decision:a.z.enum(["allow","deny","skip"]).optional(),turnId:a.z.string().trim().min(1).max(240).optional(),providerTurnId:a.z.string().trim().min(1).max(240).optional(),queueId:a.z.string().trim().min(1).max(120).optional()}).strict();const xe=a.z.object({id:a.z.string().trim().min(1).max(120),agent:a.z.enum(["codex","claude"]),creationSource:Y,providerSessionId:a.z.string().trim().min(1).max(240),lineage:oe.optional(),title:a.z.string().trim().max(240).optional(),userPrompt:a.z.string().trim().optional(),lastMessage:a.z.string().trim().optional(),cwd:a.z.string().trim().min(1).max(4096),cwdFolderId:a.z.string().trim().min(1).max(120).optional(),lastActiveAt:a.z.string().datetime(),archivedAt:a.z.string().datetime()}).strict();a.z.object({schemaVersion:a.z.literal(1).default(1),items:a.z.array(xe).max(50).default([])}).strict(),a.z.object({items:a.z.array(xe).max(50).default([])}).strict(),a.z.object({item:xe,turns:a.z.array(Oe).max(50).default([])}).strict(),a.z.object({disposition:a.z.enum(["resumed","already-open"]),aiSessionId:a.z.string().trim().min(1).max(120),providerSessionId:a.z.string().trim().min(1).max(240),appSessionId:a.z.string().trim().min(1).max(120).optional(),creationSource:Y}).strict();const De=Re.pick({id:!0,agent:!0,creationSource:!0,appSessionId:!0,appId:!0,providerSessionId:!0,lineage:!0,providerMeta:!0,appBindingKeys:!0,actions:!0,activeTurnId:!0,title:!0,cwd:!0,cwdFolderId:!0,userPrompt:!0,turns:!0,status:!0,phase:!0,summary:!0,lastMessage:!0,lastMessageItemId:!0,currentTool:!0,toolCallsSinceLastMessage:!0,subAgents:!0,queue:!0,startedAt:!0,updatedAt:!0,error:!0}),Pe=a.z.object({runningCount:a.z.number().int().min(0).default(0),waitingCount:a.z.number().int().min(0).default(0),staleCount:a.z.number().int().min(0).default(0),sessions:a.z.array(De).default([]),updatedAt:a.z.string().datetime()}).strict();a.z.object({streamId:a.z.string().trim().min(1).max(240),revision:a.z.number().int().min(0),lastEventAt:a.z.string().datetime(),snapshot:Pe}).strict(),Pe.pick({runningCount:!0,waitingCount:!0,staleCount:!0,updatedAt:!0}).extend({idleCount:a.z.number().int().min(0).default(0),problemCount:a.z.number().int().min(0).default(0),revision:a.z.number().int().min(0).optional()});const Me=a.z.enum(["provider-event","app-session-created","app-session-updated","app-session-deleted","discovery-scan","control-action","heartbeat-sync","startup"]),Le=a.z.object({streamId:a.z.string().trim().min(1).max(240),instanceId:a.z.string().trim().min(1).max(160),nodeId:a.z.string().trim().min(1).max(160).optional(),revision:a.z.number().int().min(0),previousRevision:a.z.number().int().min(0).optional(),traceId:a.z.string().trim().min(1).max(160),generatedAt:a.z.string().datetime(),reason:Me}).strict(),je=a.z.object({meta:Le,snapshot:Pe}).strict(),$e=a.z.object({meta:Le,upserted:a.z.array(De).default([]),removed:a.z.array(a.z.string().trim().min(1).max(120)).default([])}).strict(),Fe=a.z.object({meta:Le,sessionIds:a.z.array(a.z.string().trim().min(1).max(120)).default([]),expiresAt:a.z.string().datetime()}).strict();a.z.object({instanceId:a.z.string().trim().min(1).max(160),nodeId:a.z.string().trim().min(1).max(160).optional(),sessionId:a.z.string().trim().min(1).max(120),providerSessionId:a.z.string().trim().min(1).max(240),turnId:a.z.string().trim().min(1).max(240),itemId:a.z.string().trim().min(1).max(240),delta:a.z.string().min(1),generatedAt:a.z.string().datetime()}).strict(),a.z.object({streamId:a.z.string().trim().min(1).max(240),instanceId:a.z.string().trim().min(1).max(160),sinceRevision:a.z.number().int().min(0),latestRevision:a.z.number().int().min(0),earliestRetainedRevision:a.z.number().int().min(0),syncRequired:a.z.boolean().default(!1),events:a.z.array(a.z.discriminatedUnion("type",[a.z.object({type:a.z.literal("ai-session.snapshot"),payload:je}).strict(),a.z.object({type:a.z.literal("ai-session.patch"),payload:$e}).strict(),a.z.object({type:a.z.literal("ai-session.removed"),payload:Fe}).strict()])).default([])}).strict();const Ue=a.z.object({source:_e,sourcePriority:a.z.number().int().min(0).max(100).optional(),observedAt:a.z.string().datetime().optional(),snapshotVersion:a.z.number().int().min(0).optional()}).strict(),Ve=Ue.extend({type:a.z.literal("snapshot"),agent:a.z.string().trim().min(1).max(80),creationSource:Y.optional(),appSessionId:a.z.string().trim().max(120).optional(),appId:a.z.string().trim().max(120).optional(),providerSessionId:a.z.string().trim().max(240).optional(),lineage:oe.optional(),providerMeta:a.z.record(a.z.string(),a.z.unknown()).optional(),appBindingKeys:a.z.array(a.z.string().trim().min(1).max(240)).max(20).optional(),actions:re.optional(),title:a.z.string().trim().max(240).optional(),cwd:a.z.string().trim().max(4096).optional(),cwdFolderId:a.z.string().trim().min(1).max(120).optional(),activeTurnId:a.z.string().trim().max(240).optional(),userPrompt:a.z.string().trim().optional(),turns:a.z.array(ke).max(50).optional(),status:X.optional(),phase:Q.optional(),summary:a.z.string().trim().max(1e3).optional(),lastMessage:a.z.string().trim().optional(),lastMessageItemId:a.z.string().trim().max(240).optional(),error:a.z.string().trim().max(4e3).optional(),currentTool:Z.optional(),toolCallsSinceLastMessage:a.z.number().int().min(0).optional(),subAgents:a.z.array(ne).max(50).optional(),transcriptPath:a.z.string().trim().max(4096).optional(),transcriptSize:a.z.number().int().min(0).optional(),replaceActivity:a.z.boolean().optional()}).strict(),qe=Ue.extend({type:a.z.literal("event"),sessionId:a.z.string().trim().min(1).max(120),kind:a.z.enum(["lifecycle","send-ack","turn-started","user-message","assistant-message","approval-requested","turn-completed","session-error","tool-activity","sub-agent-activity","context-compaction"]),activeTurnId:a.z.string().trim().max(240).optional(),providerTurnId:a.z.string().trim().max(240).optional(),userPrompt:a.z.string().trim().optional(),text:a.z.string().optional(),itemId:a.z.string().trim().max(240).optional(),status:X.optional(),phase:Q.optional(),summary:a.z.string().trim().max(1e3).optional(),error:a.z.string().trim().max(4e3).optional(),currentTool:Z.nullable().optional(),toolCallsSinceLastMessage:a.z.number().int().min(0).optional(),subAgents:a.z.array(ne).max(50).optional(),contextCompaction:Ce.optional(),counters:a.z.object({toolCalls:a.z.number().int().min(0).optional(),edits:a.z.number().int().min(0).optional(),approvals:a.z.number().int().min(0).optional()}).strict().optional()}).strict().superRefine((e,t)=>{if("session-error"!==e.kind||e.error||t.addIssue({code:"custom",path:["error"],message:"session-error events require error"}),"context-compaction"===e.kind?e.contextCompaction||t.addIssue({code:"custom",path:["contextCompaction"],message:"context-compaction events require contextCompaction"}):void 0!==e.contextCompaction&&t.addIssue({code:"custom",path:["contextCompaction"],message:"contextCompaction is only valid for context-compaction events"}),"sub-agent-activity"===e.kind?e.subAgents||t.addIssue({code:"custom",path:["subAgents"],message:"sub-agent-activity events require subAgents"}):void 0!==e.subAgents&&t.addIssue({code:"custom",path:["subAgents"],message:"subAgents is only valid for sub-agent-activity events"}),"tool-activity"!==e.kind)return void 0!==e.currentTool&&t.addIssue({code:"custom",path:["currentTool"],message:"currentTool is only valid for tool-activity events"}),void(void 0!==e.toolCallsSinceLastMessage&&t.addIssue({code:"custom",path:["toolCallsSinceLastMessage"],message:"toolCallsSinceLastMessage is only valid for tool-activity events"}));"currentTool"in e||t.addIssue({code:"custom",path:["currentTool"],message:"tool-activity events require currentTool"}),void 0===e.toolCallsSinceLastMessage&&t.addIssue({code:"custom",path:["toolCallsSinceLastMessage"],message:"tool-activity events require toolCallsSinceLastMessage"})});a.z.discriminatedUnion("type",[Ve,qe]);const He=a.z.union([a.z.object({type:a.z.literal("schedule"),scheduleKind:a.z.literal("interval").default("interval"),intervalMs:a.z.number().int().min(1e3)}).strict(),a.z.object({type:a.z.literal("schedule"),scheduleKind:a.z.literal("daily"),timeOfDay:a.z.string().regex(/^([01]\d|2[0-3]):[0-5]\d$/),timezone:a.z.string().trim().min(1).max(120)}).strict(),a.z.object({type:a.z.literal("schedule"),scheduleKind:a.z.literal("weekly"),weekdays:a.z.array(a.z.number().int().min(0).max(6)).min(1).max(7),timeOfDay:a.z.string().regex(/^([01]\d|2[0-3]):[0-5]\d$/),timezone:a.z.string().trim().min(1).max(120)}).strict()]),Be=a.z.union([He,a.z.object({type:a.z.literal("file-change"),roots:a.z.array(a.z.string().trim().min(1).max(4096)).min(1).max(50),globs:a.z.array(a.z.string().trim().min(1).max(500)).min(1).max(100),ignore:a.z.array(a.z.string().trim().min(1).max(500)).max(100).optional(),debounceMs:a.z.number().int().min(100).max(6e4).default(1500)}).strict(),a.z.object({type:a.z.literal("ai-session"),agent:a.z.string().trim().min(1).max(80).optional(),statuses:a.z.array(a.z.enum(["running","waiting","idle","failed"])).max(20).optional(),phases:a.z.array(a.z.enum(["thinking","tool","editing","approval","responding","unknown"])).max(20).optional()}).strict()]),Ke=a.z.object({promptTemplate:a.z.string().trim().min(1).max(2e4)}).strict(),Ge=a.z.object({cooldownMs:a.z.number().int().min(0).max(864e5).optional(),maxConcurrentRuns:a.z.number().int().min(1).max(20).default(1),whenBusy:a.z.enum(["skip","queue"]).default("skip")}).strict(),Je=a.z.object({configHash:a.z.string().trim().min(8).max(80),name:a.z.string().trim().min(1).max(160),description:a.z.string().trim().max(1e3).optional(),source:Be,action:Ke,policy:Ge.default({maxConcurrentRuns:1,whenBusy:"skip"}),createdAt:a.z.string().datetime(),updatedAt:a.z.string().datetime()}).strict(),We=a.z.object({type:a.z.literal("ai-session"),aiSessionId:a.z.string().trim().min(1).max(160)}).strict(),Ye=a.z.object({configHash:a.z.string().trim().min(8).max(80),deploymentId:a.z.string().trim().min(1).max(240).optional(),instanceId:a.z.string().trim().min(1).max(160),origin:a.z.enum(["control-plane","controlled-instance"]).default("controlled-instance"),enabled:a.z.boolean().default(!0),target:We,localName:a.z.string().trim().min(1).max(160).optional(),createdAt:a.z.string().datetime(),updatedAt:a.z.string().datetime()}).strict(),Xe=a.z.object({configHash:a.z.string().trim().min(8).max(80),deploymentId:a.z.string().trim().min(1).max(240).optional(),instanceId:a.z.string().trim().min(1).max(160),status:a.z.enum(["idle","running","disabled","error"]).default("idle"),lastTriggeredAt:a.z.string().datetime().optional(),lastCompletedAt:a.z.string().datetime().optional(),lastSkippedAt:a.z.string().datetime().optional(),lastError:a.z.string().trim().max(4e3).optional(),runCount:a.z.number().int().min(0).default(0),skippedCount:a.z.number().int().min(0).default(0)}).strict(),Qe=a.z.object({id:a.z.string().trim().min(1).max(160),configHash:a.z.string().trim().min(8).max(80),deploymentId:a.z.string().trim().min(1).max(240).optional(),instanceId:a.z.string().trim().min(1).max(160),eventType:a.z.enum(["manual","schedule","file-change","ai-session"]),status:a.z.enum(["started","completed","failed","skipped"]),target:We,promptPreview:a.z.string().trim().max(500),eventSummary:a.z.string().trim().max(1e3).optional(),error:a.z.string().trim().max(4e3).optional(),startedAt:a.z.string().datetime(),completedAt:a.z.string().datetime().optional()}).strict();a.z.object({schemaVersion:a.z.literal(1).default(1),configs:a.z.array(Je).default([]),deployments:a.z.array(Ye).default([]),runtime:a.z.array(Xe).default([]),recentRuns:a.z.array(Qe).default([])}).strict();const Ze=a.z.object({instanceId:a.z.string().trim().min(1).max(160),instanceName:a.z.string().trim().min(1).max(160),deployment:Ye,runtime:Xe.optional()}).strip(),et=Qe.extend({instanceName:a.z.string().trim().min(1).max(160).optional()}).strip(),tt=a.z.object({configHash:a.z.string().trim().min(8).max(80),config:Je,deploymentCount:a.z.number().int().min(0),enabledCount:a.z.number().int().min(0),runningCount:a.z.number().int().min(0),errorCount:a.z.number().int().min(0),ownedByControlPlane:a.z.boolean(),controlPlaneDeploymentCount:a.z.number().int().min(0),deployments:a.z.array(Ze),recentRuns:a.z.array(et)}).strip();a.z.object({updatedAt:a.z.string().datetime(),triggers:a.z.array(tt)}).strip(),a.z.object({name:Je.shape.name,description:Je.shape.description,source:Be,action:Ke,policy:Ge.partial().optional()}).strict();const nt=a.z.string().regex(/^\d{4}-\d{2}-\d{2}$/,"Proxy protocol version must use YYYY-MM-DD format."),it=a.z.string().trim().min(1).max(160).regex(/^[a-zA-Z0-9][a-zA-Z0-9_.:-]*$/),rt=a.z.string().datetime(),ot=a.z.string().trim().min(32).max(4096),st=a.z.string().trim().max(2048).transform((e,t)=>{try{return function(e){const t=new URL(e.trim());if("https:"!==t.protocol||t.username||t.password||"/"!==t.pathname||t.search||t.hash)throw new Error("Proxy origin must be an HTTPS origin without credentials, path, query, or fragment.");return t.origin}(e)}catch(e){return t.addIssue({code:"custom",message:e instanceof Error?e.message:String(e)}),a.z.NEVER}});a.z.string().trim().min(1).max(4096).transform((e,t)=>{try{return function(e){const t=e.trim();if(!t.startsWith("/")||t.startsWith("//")||t.includes("\\")||/%25/i.test(t))throw new Error("Proxy route must be a single-encoded node-agent relative route.");const n=t.split("?",1)[0];let i,r;try{i=n.split("/").map(e=>decodeURIComponent(e))}catch{throw new Error("Proxy route contains invalid percent encoding.")}if(i.some(e=>".."===e||"."===e))throw new Error("Proxy route cannot traverse outside the node-agent API.");try{r=new URL(t,"https://node-agent.invalid")}catch{throw new Error("Proxy route is invalid.")}if("https://node-agent.invalid"!==r.origin||r.username||r.password)throw new Error("Proxy route cannot select an absolute upstream URL.");return`${r.pathname}${r.search}`}(e)}catch(e){return t.addIssue({code:"custom",message:e instanceof Error?e.message:String(e)}),a.z.NEVER}});const at=a.z.enum(Object.values({ProtocolUnsupported:"CONTROL_PLANE_PROXY_PROTOCOL_UNSUPPORTED",InviteInvalid:"CONTROL_PLANE_PROXY_INVITE_INVALID",InviteExpired:"CONTROL_PLANE_PROXY_INVITE_EXPIRED",InviteConsumed:"CONTROL_PLANE_PROXY_INVITE_CONSUMED",InviteRevoked:"CONTROL_PLANE_PROXY_INVITE_REVOKED",TargetUnavailable:"CONTROL_PLANE_PROXY_TARGET_UNAVAILABLE",TargetMismatch:"CONTROL_PLANE_PROXY_TARGET_MISMATCH",BindingUnknown:"CONTROL_PLANE_PROXY_BINDING_UNKNOWN",BindingRevoked:"CONTROL_PLANE_PROXY_BINDING_REVOKED",BindingIdentityConflict:"CONTROL_PLANE_PROXY_BINDING_IDENTITY_CONFLICT",AuthenticationFailed:"CONTROL_PLANE_PROXY_AUTHENTICATION_FAILED",RouteInvalid:"CONTROL_PLANE_PROXY_ROUTE_INVALID",HeaderInvalid:"CONTROL_PLANE_PROXY_HEADER_INVALID",ResourceLimit:"CONTROL_PLANE_PROXY_RESOURCE_LIMIT",SnapshotRequired:"CONTROL_PLANE_PROXY_SNAPSHOT_REQUIRED",Unavailable:"CONTROL_PLANE_PROXY_UNAVAILABLE",TransportFailed:"CONTROL_PLANE_PROXY_TRANSPORT_FAILED"})),ct=a.z.object({code:at,message:a.z.string().trim().min(1).max(2048),retryable:a.z.boolean(),details:a.z.record(a.z.string(),a.z.unknown()).optional()}).strict(),dt=a.z.enum(["active","consumed","revoked","expired"]),lt=a.z.object({id:it,targetNodeId:it,tokenHash:a.z.string().trim().min(32).max(256),status:dt,createdBy:it,expiresAt:rt,consumedByClaimId:it.optional(),consumedAt:rt.optional(),revokedAt:rt.optional(),createdAt:rt,updatedAt:rt}).strict().omit({tokenHash:!0});a.z.object({targetNodeId:it,expiresInSeconds:a.z.number().int().min(60).max(3600).default(600)}).strict(),a.z.object({invite:lt,token:a.z.string().trim().min(24).max(512),proxyOrigin:st,protocolVersion:nt}).strict();const ut=a.z.enum(["active","revoked"]),mt=a.z.object({id:it,claimId:it,sourceControlPlaneId:it,targetNodeId:it,bindingKeyId:it,credentialHash:a.z.string().trim().min(32).max(256),status:ut,revision:a.z.number().int().positive(),lastError:ct.optional(),revokedAt:rt.optional(),createdAt:rt,updatedAt:rt}).strict().omit({credentialHash:!0});a.z.object({protocolVersion:nt,inviteToken:a.z.string().trim().min(24).max(512).optional(),claimId:it,sourceControlPlaneId:it,targetNodeId:it.optional(),bindingKeyId:it,credential:ot}).strict(),a.z.object({sourceControlPlaneId:it,bindingKeyId:it,credential:ot}).strict();const pt=a.z.object({id:it,name:a.z.string().trim().min(1).max(160),status:a.z.enum(["unknown","online","offline","degraded"]),health:a.z.enum(["unknown","ok","degraded","failed"]),lastSeenAt:rt.optional(),capabilities:a.z.record(a.z.string(),a.z.unknown()).default({})}).strict(),ht=a.z.object({protocolVersion:nt,binding:mt,streamId:it,revision:a.z.number().int().nonnegative(),observedAt:rt,target:pt}).strict(),gt=a.z.object({type:a.z.literal("control-plane-proxy.event"),protocolVersion:nt,streamId:it,bindingId:it,sourceControlPlaneId:it,targetNodeId:it,revision:a.z.number().int().positive(),source:a.z.object({id:a.z.string().trim().min(1).max(512),seq:a.z.number().int().nonnegative()}).strict(),target:pt,event:a.z.object({type:a.z.string().trim().min(1).max(240),topic:a.z.string().trim().min(1).max(240),createdAt:rt}).strict()}).strict(),ft=a.z.object({type:a.z.literal("control-plane-proxy.events.ready"),protocolVersion:nt,streamId:it,bindingId:it,sourceControlPlaneId:it,targetNodeId:it,latestRevision:a.z.number().int().nonnegative(),earliestRetainedRevision:a.z.number().int().nonnegative()}).strict(),yt=a.z.object({type:a.z.literal("control-plane-proxy.snapshot-required"),protocolVersion:nt,streamId:it,bindingId:it,sourceControlPlaneId:it,targetNodeId:it,sinceRevision:a.z.number().int().nonnegative(),latestRevision:a.z.number().int().nonnegative(),earliestRetainedRevision:a.z.number().int().nonnegative(),error:ct}).strict();a.z.discriminatedUnion("type",[gt,ft,yt]),a.z.object({protocolVersion:nt,binding:mt,target:ht.shape.target}).strict(),a.z.object({id:it,claimId:it,proxyOrigin:st,requestedName:a.z.string().trim().min(1).max(160).optional(),sourceControlPlaneId:it,targetNodeId:it.optional(),bindingKeyId:it,credential:ot,status:a.z.enum(["pending","compensation-required"]),createdAt:rt,updatedAt:rt,expiresAt:rt}).strict().omit({credential:!0}),a.z.object({id:it,nodeId:it,proxyOrigin:st,proxyBindingId:it,targetNodeId:it,sourceControlPlaneId:it,bindingKeyId:it,credential:ot,createdAt:rt,updatedAt:rt}).strict();const It="2026-08-01",At=a.z.string(),bt=a.z.string().trim().min(1).max(120).regex(/^[a-zA-Z0-9][a-zA-Z0-9_.:-]*$/),wt=a.z.string().datetime(),vt=a.z.record(a.z.string(),a.z.string()).default({}),Et=a.z.record(a.z.string(),a.z.string()).default({}),Nt=a.z.string().regex(/^\d{4}-\d{2}-\d{2}$/,"Protocol version must use YYYY-MM-DD format."),St=a.z.object({encoding:a.z.enum(["utf8","base64"]),data:a.z.string()}).strict().superRefine((e,t)=>{"base64"===e.encoding&&Buffer.from(e.data,"base64").toString("base64")!==e.data&&t.addIssue({code:"custom",path:["data"],message:"Node tunnel binary body must use canonical base64 encoding."})});function Tt(e){if(null==e)return;const t=St.parse(e);return"utf8"===t.encoding?t.data:Buffer.from(t.data,"base64")}const zt=/^[A-Za-z0-9_][A-Za-z0-9_.-]{0,127}$/,_t=/^sha256:([a-fA-F0-9]{64})$/,Ct=/^(?:localhost|[a-z0-9](?:[a-z0-9.-]*[a-z0-9])?)(?::[1-9][0-9]{0,4})?$/,kt=/^[a-z0-9]+(?:(?:[._]|__|-+)[a-z0-9]+)*$/;function Ot(e){const t=e.trim();if(!t||t.length>512||t.includes("://")||/\s/.test(t))throw new Error("Docker image reference must not contain a URL scheme or whitespace.");const n=t.indexOf("@");if(-1!==n&&n!==t.lastIndexOf("@"))throw new Error("Docker image reference contains more than one digest separator.");const i=-1===n?void 0:t.slice(n+1),r=-1===n?t:t.slice(0,n),o=i?_t.exec(i):void 0;if(i&&!o)throw new Error("Docker image digest must use sha256 followed by 64 hexadecimal characters.");const s=r.lastIndexOf("/"),a=r.lastIndexOf(":"),c=a>s,d=c?r.slice(a+1):void 0,l=c?r.slice(0,a):r;if(d&&!zt.test(d))throw new Error("Docker image tag is invalid.");if(!d&&!o)throw new Error("Docker image reference must include an explicit tag or sha256 digest.");const u=l.split("/");if(!u.length||u.some(e=>!e))throw new Error("Docker image repository path is invalid.");const m=u.length>1&&(u[0].includes(".")||u[0].includes(":")||"localhost"===u[0]),p=m?u.slice(1):u;if(m&&!Ct.test(u[0].toLowerCase()))throw new Error("Docker image registry host or port is invalid.");if(!p.length||p.some(e=>!kt.test(e)))throw new Error("Docker image repository names must be lowercase and use valid separators.");const h=u.map((e,t)=>m&&0===t?e.toLowerCase():e).join("/"),g=o?`sha256:${o[1].toLowerCase()}`:void 0;return`${h}${d?`:${d}`:""}${g?`@${g}`:""}`}function Rt(e){const t=Ot(e),n=t.indexOf("@"),i=-1===n?void 0:t.slice(n+1),r=-1===n?t:t.slice(0,n),o=r.lastIndexOf("/"),s=r.lastIndexOf(":"),a=s>o;return{reference:t,repository:a?r.slice(0,s):r,tag:a?r.slice(s+1):void 0,digest:i}}const xt=a.z.string().trim().min(1).max(512).transform((e,t)=>{try{return Ot(e)}catch(e){return t.addIssue({code:"custom",message:e instanceof Error?e.message:String(e)}),a.z.NEVER}}),Dt=a.z.string().trim().transform((e,t)=>{const n=_t.exec(e);return n?`sha256:${n[1].toLowerCase()}`:(t.addIssue({code:"custom",message:"Docker image digest must use sha256 followed by 64 hexadecimal characters."}),a.z.NEVER)}),Pt=a.z.object({codexModelHash:bt.nullable().optional(),claudeModelHash:bt.nullable().optional()}).strict().default({}),Mt=a.z.object({imageId:bt,tag:a.z.string().trim().min(1).max(128).regex(zt).optional()}).strict(),Lt=a.z.discriminatedUnion("type",[a.z.object({type:a.z.literal("image"),imageSelection:Mt}).strict(),a.z.object({type:a.z.literal("template"),environmentTemplateId:bt}).strict()]),jt=a.z.enum(["creating","ready","failed","deleting"]),$t=a.z.enum(["linux","darwin","win32","freebsd","openbsd","aix","sunos","unknown"]),Ft=a.z.enum(["x64","arm64","arm","ia32","ppc64","s390x","riscv64","unknown"]),Ut=a.z.object({code:a.z.string().trim().min(1).max(120),message:a.z.string().trim().min(1).max(2048),phase:a.z.enum(["validate","commit","inspect","security-check","persist","delete","recovery"]).optional()}).strict(),Vt=a.z.object({templateId:bt,nodeId:bt,imageId:Dt,name:a.z.string().trim().min(1).max(160),platform:$t,architecture:Ft}).strict(),qt=a.z.enum(["data","agent-home","workspace"]),Ht=a.z.object({deleteVolumes:a.z.boolean()}).strict(),Bt=a.z.object({role:qt,name:a.z.string().trim().min(1).max(255),mountPath:a.z.string().trim().startsWith("/").max(4096),status:a.z.enum(["deleted","retained","missing","failed"]),error:a.z.object({code:a.z.string().trim().min(1).max(120),message:a.z.string().trim().min(1).max(2048)}).strict().optional()}).strict(),Kt=a.z.object({instanceId:bt,containerDeleted:a.z.boolean(),completed:a.z.boolean(),deletedVolumes:a.z.array(Bt),retainedVolumes:a.z.array(Bt),volumeResults:a.z.array(Bt)}).strict(),Gt={img_default:"market_taskhandoff_browser",img_codex:"market_taskhandoff_codex",img_ai:"market_taskhandoff_ai"};function Jt(e,t){if(e&&"object"==typeof e&&!Array.isArray(e)){const t=e;return{imageId:"string"==typeof t.imageId&&Gt[t.imageId]||t.imageId,..."string"==typeof t.tag?{tag:t.tag}:{}}}if("string"==typeof t)return{imageId:Gt[t]||t}}function Wt(e){if(!e||"object"!=typeof e||Array.isArray(e))return e;const t=e,{defaultImageId:n,...i}=t;return{...i,defaultImageSelection:Jt(t.defaultImageSelection,n)}}const Yt=a.z.object({id:bt,name:a.z.string().trim().min(1).max(120),kind:a.z.enum(["tty","gui","web"]),source:a.z.enum(["builtin","custom"]),availability:a.z.enum(["available","missing-dependency"]),capabilities:a.z.object({automation:a.z.enum(["cdp"]).optional(),supportsCwdSelection:a.z.boolean().default(!1)}).strict().default({supportsCwdSelection:!1}),diagnosticCode:a.z.enum(["APP_EXECUTABLE_NOT_FOUND"]).optional()}).strict(),Xt=a.z.object({code:a.z.enum(["APP_CATALOG_INVALID"]),message:a.z.string().trim().min(1).max(500)}).strict(),Qt=a.z.object({items:a.z.array(Yt).max(256),observedAt:wt,issues:a.z.array(Xt).max(32).default([])}).strict(),Zt=a.z.object({id:bt,name:a.z.string().trim().min(1).max(160),sourceInstanceId:bt,nodeId:bt,imageId:Dt.optional(),internalTag:a.z.string().trim().min(1).max(512).optional(),platform:$t.optional(),architecture:Ft.optional(),sizeBytes:a.z.number().int().nonnegative().optional(),status:jt,error:Ut.optional(),createdAt:wt,updatedAt:wt}).strict().superRefine((e,t)=>{if("ready"===e.status)for(const n of["imageId","internalTag","platform","architecture","sizeBytes"])void 0===e[n]&&t.addIssue({code:"custom",path:[n],message:`Ready environment template requires ${n}.`});"failed"!==e.status||e.error||t.addIssue({code:"custom",path:["error"],message:"Failed environment template requires an error diagnostic."})}),en=a.z.enum(["apt","dnf","brew","npm"]),tn=a.z.enum(["user","passwordless-sudo","root"]),nn=a.z.object({platform:$t,arch:Ft,installers:a.z.array(en).max(8),privilege:tn,installerAccess:a.z.object({npmGlobalWritable:a.z.boolean().optional()}).strict().optional()}).strict(),rn=a.z.enum(["installed","not-installed","broken","unsupported"]),on=a.z.enum(["recipe","bundled","external","none"]),sn=a.z.object({code:a.z.enum(["BUNDLED","EXTERNALLY_MANAGED","ALREADY_INSTALLED","NOT_INSTALLED","UNSUPPORTED_PLATFORM","INSTALLER_UNAVAILABLE","INSTALLER_NOT_WRITABLE","INSUFFICIENT_PRIVILEGE","OPERATION_IN_PROGRESS"]),message:a.z.string().trim().min(1).max(500)}).strict(),an=a.z.object({id:bt,name:a.z.string().trim().min(1).max(120),kind:a.z.enum(["tty","gui","web"]),description:a.z.string().trim().max(500).optional(),state:rn,managementSource:on,version:a.z.string().trim().max(120).optional(),canInstall:a.z.boolean(),canUninstall:a.z.boolean(),installReason:sn.optional(),uninstallReason:sn.optional(),activeJobId:bt.optional()}).strict(),cn=a.z.enum(["install","uninstall"]),dn=a.z.enum(["queued","running","succeeded","failed","cancelled","interrupted"]),ln=a.z.object({current:a.z.number().finite().nonnegative().optional(),total:a.z.number().finite().positive().optional(),unit:a.z.string().trim().min(1).max(40).optional()}).strict().refine(e=>void 0===e.total||void 0===e.current||e.current<=e.total,{message:"Progress current must not exceed total.",path:["current"]}),un=a.z.object({executable:a.z.string().trim().min(1).max(4096),args:a.z.array(a.z.string().max(4096)).max(128)}).strict(),mn=a.z.object({code:a.z.string().trim().min(1).max(120).regex(/^[a-z0-9][a-z0-9._-]*$/),message:a.z.string().trim().min(1).max(4096),retryable:a.z.boolean(),sessionIds:a.z.array(bt).max(64).optional()}).strict(),pn=a.z.object({id:bt,requestId:bt.optional(),appId:bt,operation:cn,state:dn,phase:a.z.string().trim().min(1).max(120).optional(),progress:ln.optional(),command:un.optional(),logTail:a.z.string().max(32768).optional(),logTruncated:a.z.boolean().optional(),error:mn.optional(),requestedAt:wt,startedAt:wt.optional(),finishedAt:wt.optional(),updatedAt:wt}).strict(),hn=a.z.object({streamId:bt,sequence:a.z.number().int().nonnegative(),capabilities:nn,apps:a.z.array(an).max(256),activeJobs:a.z.array(pn).max(256),recentJobs:a.z.array(pn).max(256),observedAt:wt}).strict();a.z.object({requestId:bt.optional()}).strict(),a.z.object({job:pn}).strict(),a.z.object({type:a.z.literal("app-management"),streamId:bt,sequence:a.z.number().int().nonnegative(),observedAt:wt,job:pn.optional(),snapshot:hn.optional()}).strict().refine(e=>void 0!==e.job||void 0!==e.snapshot,{message:"An app management event requires a job or snapshot."});const gn=a.z.object({component:a.z.enum(["control-plane","node-agent","controlled-instance"]),packageName:a.z.string().trim().max(160).optional(),packageVersion:a.z.string().trim().max(80).optional(),protocolVersion:At.optional(),buildId:a.z.string().trim().max(160).optional(),builtAt:a.z.string().trim().max(120).optional(),gitCommit:a.z.string().trim().max(120).optional(),imageRef:a.z.string().trim().max(512).optional(),imageDigest:a.z.string().trim().max(240).optional()}).strict();a.z.object({data:a.z.object({ok:a.z.literal(!0),role:a.z.literal("control-plane"),protocolVersion:At,build:gn.extend({component:a.z.literal("control-plane"),packageVersion:a.z.string().trim().min(1).max(80)}).loose(),dataDir:a.z.string().min(1),serverTime:wt}).loose()}).loose();const fn=a.z.enum(["stable","beta","alpha"]),yn=a.z.object({packageName:a.z.literal("@task-handoff/controlled-instance"),version:a.z.string().trim().min(1).max(80),platform:a.z.string().trim().min(1).max(40),arch:a.z.string().trim().min(1).max(40),formatVersion:a.z.number().int().positive(),launcherAbi:a.z.number().int().positive(),entrypoint:a.z.string().trim().min(1).max(512),sha256:a.z.string().regex(/^[a-f0-9]{64}$/)}).strict(),In=a.z.object({code:a.z.enum(["INSTANCE_RUNTIME_VERSION_MISMATCH","INSTANCE_RUNTIME_ARTIFACT_UNAVAILABLE","INSTANCE_RUNTIME_ARTIFACT_INVALID","INSTANCE_RUNTIME_INSTALL_FAILED","INSTANCE_RUNTIME_RESTART_FAILED","INSTANCE_RUNTIME_VERIFICATION_FAILED","INSTANCE_BASE_RUNTIME_INCOMPATIBLE","NODE_UPDATE_PREFLIGHT_FAILED","NODE_UPDATE_FAILED","LEGACY_INSTANCE_UPDATE_RETIRED"]),message:a.z.string().trim().min(1).max(4096),expectedVersion:a.z.string().trim().min(1).max(80).optional(),actualVersion:a.z.string().trim().min(1).max(80).optional(),retryable:a.z.boolean().default(!1)}).strict(),An=a.z.object({desiredVersion:a.z.string().trim().min(1).max(80),actualVersion:a.z.string().trim().min(1).max(80).optional(),phase:a.z.enum(["pending","draining","installing","restarting","verifying","matched","failed"]),attempt:a.z.number().int().nonnegative().default(0),lastAttemptAt:wt.optional(),matchedAt:wt.optional(),error:In.optional()}).strict(),bn=a.z.object({runningInstanceCount:a.z.number().int().nonnegative(),stoppedInstanceCount:a.z.number().int().nonnegative(),activeInstanceCount:a.z.number().int().nonnegative(),restartInstanceCount:a.z.number().int().nonnegative(),runningInstanceIds:a.z.array(bt).max(1024).default([]),stoppedInstanceIds:a.z.array(bt).max(1024).default([]),activeInstanceIds:a.z.array(bt).max(1024).default([])}).strict(),wn=a.z.object({phase:a.z.enum(["queued","updating-node","restarting-node","converging-instances","succeeded","degraded","failed"]),desiredVersion:a.z.string().trim().min(1).max(80),nodeVersion:a.z.string().trim().min(1).max(80).optional(),expectedInstanceIds:a.z.array(bt).max(1024).default([]),expectedInstanceCount:a.z.number().int().nonnegative(),matchedInstanceCount:a.z.number().int().nonnegative(),pendingInstanceCount:a.z.number().int().nonnegative(),failedInstanceCount:a.z.number().int().nonnegative(),deferredInstanceCount:a.z.number().int().nonnegative().default(0)}).strict(),vn=a.z.object({channel:fn.default("stable")}).strict(),En=a.z.object({source:a.z.literal("npm"),channel:fn,currentVersion:a.z.string().trim().max(240).optional(),availableVersion:a.z.string().trim().min(1).max(240),artifactRef:a.z.string().trim().min(1).max(512).optional(),runtimeArtifacts:a.z.array(yn).default([]),impact:bn,updateAvailable:a.z.boolean(),supported:a.z.boolean().default(!0),reason:a.z.string().trim().max(2048).optional(),checkedAt:wt,preflightToken:a.z.string().trim().min(16).max(240).optional()}).strict(),Nn=a.z.object({id:bt,nodeId:bt,source:a.z.literal("npm"),channel:fn,fromVersion:a.z.string().trim().max(240).optional(),toVersion:a.z.string().trim().min(1).max(240),artifactRef:a.z.string().trim().min(1).max(512).optional(),runtimeArtifacts:a.z.array(yn).default([]),impact:bn,rollout:wn,status:a.z.enum(["queued","updating-node","restarting-node","converging-instances","succeeded","degraded","failed"]),error:In.optional(),startedAt:wt.optional(),completedAt:wt.optional(),createdAt:wt,updatedAt:wt}).strict(),Sn=a.z.object({channel:fn,targetVersion:a.z.string().trim().min(1).max(240),preflightToken:a.z.string().trim().min(16).max(240)}).strict(),Tn=a.z.object({type:a.z.enum(["branch","tag","commit"]),name:a.z.string().trim().min(1).max(240).optional(),commit:a.z.string().trim().max(80).optional()}).strict(),zn=a.z.object({type:a.z.enum(["none","ssh-key","https-token"]).default("none"),secretId:a.z.string().trim().min(1).max(120).optional()}).strict(),_n=a.z.object({depth:a.z.number().int().positive().max(1e5).optional(),submodules:a.z.boolean().default(!1),lfs:a.z.boolean().default(!1),subdirectory:a.z.string().trim().max(240).default("")}).strict();a.z.object({id:bt,name:a.z.string().trim().min(1).max(160),url:a.z.string().trim().min(1).max(2048),provider:a.z.string().trim().max(80).optional(),ref:Tn.default({type:"branch",name:"main"}),auth:zn.default({type:"none"}),clone:_n.default({submodules:!1,lfs:!1,subdirectory:""}),defaultImageSelection:Mt.optional(),labels:vt,createdAt:wt,updatedAt:wt}).strict();const Cn=a.z.object({id:bt,nodeId:bt,name:a.z.string().trim().min(1).max(160),path:a.z.string().trim().min(1).max(4096),defaultImageSelection:Mt.optional(),labels:vt,createdAt:wt,updatedAt:wt}).strict(),kn=a.z.discriminatedUnion("type",[a.z.object({type:a.z.literal("git-repository"),repositoryId:bt.optional(),url:a.z.string().trim().min(1).max(2048),provider:a.z.string().trim().max(80).optional(),ref:Tn.default({type:"branch",name:"main"}),auth:zn.default({type:"none"}),clone:_n.default({submodules:!1,lfs:!1,subdirectory:""})}).strict(),a.z.object({type:a.z.literal("git-template"),url:a.z.string().trim().min(1).max(2048),templateId:a.z.string().trim().min(1).max(120).optional(),ref:Tn.default({type:"branch",name:"main"}),auth:zn.default({type:"none"}),clone:_n.default({submodules:!1,lfs:!1,subdirectory:""})}).strict(),a.z.object({type:a.z.literal("local-folder"),localFolderId:bt.optional(),path:a.z.string().trim().min(1).max(4096),ownerNodeId:bt.optional()}).strict()]),On=a.z.object({mode:a.z.enum(["local-bind","git-clone","empty-volume","persistent-volume"]),path:a.z.string().trim().min(1).max(4096).default("/workspace"),volumeName:a.z.string().trim().max(240).optional(),readOnly:a.z.boolean().default(!1)}).strict(),Rn=a.z.enum(["codex","claude"]),xn=a.z.object({id:bt,name:a.z.string().trim().min(1).max(160),source:kn,defaultImageSelection:Mt.optional(),defaultNodeId:bt.optional(),defaultRuntimeId:bt.optional(),workspacePolicy:On,labels:vt,createdAt:wt,updatedAt:wt}).strict(),Dn=a.z.object({id:bt,name:a.z.string().trim().min(1).max(160),endpoint:a.z.string().trim().min(1).max(2048),key:a.z.string().trim().min(1).max(4096),model:a.z.string().trim().min(1).max(240),app:Rn,enabled:a.z.boolean().default(!0),order:a.z.number().int().min(0).max(1e6).default(0),labels:vt,createdAt:wt,updatedAt:wt}).strict(),Pn=Dn,Mn=Dn.omit({key:!0}).extend({keyPreview:a.z.string().trim().min(1).max(160),keySet:a.z.boolean()}).strict(),Ln=Mn.extend({referenceCount:a.z.number().int().min(0)}).strict(),jn=a.z.object({instanceId:bt,codexModelHash:bt.optional(),claudeModelHash:bt.optional(),updatedAt:wt}).strict(),$n=a.z.discriminatedUnion("type",[a.z.object({type:a.z.literal("control-plane"),name:Dn.shape.name,enabled:Dn.shape.enabled,order:Dn.shape.order}).strict(),a.z.object({type:a.z.literal("node"),nodeId:bt,name:Dn.shape.name,enabled:Dn.shape.enabled,order:Dn.shape.order,referenceCount:a.z.number().int().min(0)}).strict()]),Fn=a.z.object({id:bt,model:Mn,locations:a.z.array($n).min(1),referenceCount:a.z.number().int().min(0).default(0)}).strict(),Un=a.z.object({nodeId:bt,code:a.z.string().trim().min(1).max(120),message:a.z.string().trim().min(1).max(2e3)}).strict();a.z.object({models:a.z.array(Fn),nodeDiagnostics:a.z.array(Un).default([]),updatedAt:wt}).strict();const Vn=Dn.omit({id:!0,createdAt:!0,updatedAt:!0}).strict(),qn=Vn.partial().strict(),Hn=Dn,Bn=a.z.object({modelSelection:Pt,codexModelHash:bt.optional(),claudeModelHash:bt.optional()}).strict();function Kn(e){const t={app:Rn.parse(e.app),endpoint:Dn.shape.endpoint.parse(e.endpoint),key:Dn.shape.key.parse(e.key),model:Dn.shape.model.parse(e.model)};return`mdl_${d.createHash("sha256").update(JSON.stringify(t)).digest("hex")}`}const Gn=a.z.enum(["market","custom"]),Jn=a.z.enum(["active","deprecated","yanked"]),Wn=a.z.discriminatedUnion("kind",[a.z.object({kind:a.z.literal("builtin"),key:a.z.string().trim().min(1).max(120)}).strict(),a.z.object({kind:a.z.literal("remote"),url:a.z.string().trim().url().max(2048),mediaType:a.z.enum(["image/png","image/jpeg","image/webp"]).optional(),digest:Dt.optional()}).strict()]),Yn=a.z.array(a.z.string().trim().min(1).max(80)).default([]),Xn=a.z.array(a.z.string().trim().min(1).max(120)).default([]),Qn=a.z.record(a.z.string().trim().min(2).max(35),a.z.string().trim().min(1).max(4096)),Zn=a.z.object({os:a.z.string().trim().min(1).max(40),architecture:a.z.string().trim().min(1).max(40),digest:Dt.optional(),downloadSizeBytes:a.z.number().int().positive().optional(),unpackedSizeBytes:a.z.number().int().positive().optional()}).strict(),ei=a.z.object({name:a.z.string().trim().min(1).max(128).regex(zt),version:a.z.string().trim().min(1).max(160).optional(),reference:xt,manifestDigest:Dt.optional(),publishedAt:wt.optional(),platforms:a.z.array(Zn).default([]),status:Jn.default("active")}).strict(),ti=a.z.object({id:bt,publisher:a.z.string().trim().min(1).max(160),slug:a.z.string().trim().min(1).max(160),name:a.z.string().trim().min(1).max(160),description:a.z.string().trim().min(1).max(4096),localizedDescriptions:Qn.optional(),cover:Wn.optional(),repository:a.z.string().trim().min(1).max(512),defaultTag:a.z.string().trim().min(1).max(128).regex(zt),tags:a.z.array(ei).min(1),capabilities:Yn,optionalApps:Xn,defaultEnv:Et,labels:vt,status:Jn.default("active")}).strict().superRefine((e,t)=>{e.tags.some(t=>t.name===e.defaultTag)||t.addIssue({code:"custom",path:["defaultTag"],message:"Market defaultTag must identify one of the image tags."})});a.z.object({protocolVersion:Nt,catalogId:bt,revision:a.z.string().trim().min(1).max(240),source:a.z.enum(["embedded","remote","cache"]),generatedAt:wt,expiresAt:wt.optional(),items:a.z.array(ti)}).strict(),a.z.object({source:a.z.enum(["embedded","remote","cache"]),state:a.z.enum(["ready","refreshing","stale","failed"]),revision:a.z.string().trim().min(1).max(240),updatedAt:wt,error:a.z.string().trim().max(4096).optional()}).strict(),a.z.object({id:bt,origin:a.z.literal("custom"),name:a.z.string().trim().min(1).max(160),description:a.z.string().trim().max(4096).optional(),localizedDescriptions:Qn.optional(),cover:Wn.optional(),reference:xt,repository:a.z.string().trim().min(1).max(512),tag:a.z.string().trim().min(1).max(128).regex(zt).optional(),pullPolicy:a.z.literal("if-not-present").default("if-not-present"),capabilities:Yn,optionalApps:Xn,defaultEnv:Et,labels:vt,createdAt:wt,updatedAt:wt}).strict();const ni=a.z.object({name:a.z.string().trim().min(1).max(128).regex(zt),version:a.z.string().trim().min(1).max(160).optional(),reference:xt,manifestDigest:Dt.optional(),status:Jn}).strict(),ii=a.z.object({id:bt,origin:Gn,name:a.z.string().trim().min(1).max(160),description:a.z.string().trim().max(4096).optional(),localizedDescriptions:Qn.optional(),cover:Wn,repository:a.z.string().trim().min(1).max(512),tag:a.z.string().trim().min(1).max(128).regex(zt).optional(),availableTags:a.z.array(ni),reference:xt,digest:Dt.optional(),downloadSizeBytes:a.z.number().int().positive().optional(),unpackedSizeBytes:a.z.number().int().positive().optional(),capabilities:Yn,optionalApps:Xn,defaultEnv:Et,labels:vt,readOnly:a.z.boolean(),lifecycleStatus:Jn.optional(),market:a.z.object({catalogId:bt,catalogRevision:a.z.string().trim().min(1).max(240),publisher:a.z.string().trim().min(1).max(160),version:a.z.string().trim().min(1).max(160).optional()}).strict().optional()}).strict(),ri=a.z.object({id:bt,origin:Gn,name:a.z.string().trim().min(1).max(160),description:a.z.string().trim().max(4096).optional(),localizedDescriptions:Qn.optional(),cover:Wn.optional(),repository:a.z.string().trim().min(1).max(512),tag:a.z.string().trim().min(1).max(128).regex(zt).optional(),requestedReference:xt,resolvedDigest:Dt.optional(),resolvedReference:xt.optional(),downloadSizeBytes:a.z.number().int().positive().optional(),pullPolicy:a.z.literal("if-not-present").default("if-not-present"),capabilities:Yn,optionalApps:Xn,defaultEnv:Et,labels:vt,market:a.z.object({catalogId:bt,catalogRevision:a.z.string().trim().min(1).max(240),publisher:a.z.string().trim().min(1).max(160),version:a.z.string().trim().min(1).max(160).optional()}).strict().optional(),createdAt:wt,updatedAt:wt}).strict(),oi=a.z.object({phase:a.z.enum(["checking-image","pulling-image","resolving-image","ready","failed"]),requestedReference:xt,generation:a.z.number().int().nonnegative().default(0),error:a.z.string().trim().max(4096).optional(),startedAt:wt,updatedAt:wt}).strict(),si="image.pull.terminal.output",ai="image.pull.terminal.finished",ci=a.z.object({instanceId:bt,generation:a.z.number().int().nonnegative(),requestedReference:xt,sequence:a.z.number().int().nonnegative(),observedAt:wt}).strict(),di=ci.extend({data:a.z.string().min(1).max(65536),replay:a.z.boolean().optional()}).strict(),li=ci.extend({outcome:a.z.enum(["succeeded","failed"])}).strict();ci.extend({status:a.z.enum(["connecting","pulling","extracting","complete","failed"]),layers:a.z.object({total:a.z.number().int().nonnegative(),completed:a.z.number().int().nonnegative(),downloaded:a.z.number().int().nonnegative(),downloading:a.z.number().int().nonnegative(),extracting:a.z.number().int().nonnegative()}).strict(),bytes:a.z.object({current:a.z.number().finite().nonnegative(),total:a.z.number().finite().positive()}).strict().optional(),percent:a.z.number().finite().min(0).max(100).optional(),message:a.z.string().trim().min(1).max(500),terminalTail:a.z.string().max(262144).optional(),terminalTruncated:a.z.boolean().optional()}).strict();const ui=a.z.discriminatedUnion("kind",[a.z.object({kind:a.z.literal("direct")}).strict(),a.z.object({kind:a.z.literal("control-plane-proxy"),proxyId:bt,proxyBindingId:bt,targetNodeId:bt}).strict()]),mi=a.z.object({reachability:a.z.enum(["unknown","reachable","unreachable"]),bindingStatus:a.z.enum(["unknown","active","revoked"]),bindingRevision:a.z.number().int().positive().optional(),streamId:a.z.string().trim().min(1).max(160).optional(),revision:a.z.number().int().nonnegative().optional(),observedAt:wt.optional(),target:pt.optional(),lastError:ct.optional(),updatedAt:wt}).strict(),pi=a.z.object({id:bt,name:a.z.string().trim().min(1).max(160),connectionMode:a.z.enum(["local-ipc","local-loopback","direct-http","reverse-wss","control-plane-proxy"]).default("direct-http"),connectionPath:ui.default({kind:"direct"}),connectionEnabled:a.z.boolean().default(!0),auth:a.z.object({mode:a.z.enum(["local-static-key","paired-hmac","proxy-binding"]).default("local-static-key"),keyId:bt.optional(),secret:a.z.string().trim().max(4096).optional(),pairedAt:wt.optional(),pairing:a.z.object({status:a.z.enum(["pending","paired","expired"]).default("pending"),joinToken:a.z.string().trim().max(4096).optional(),expiresAt:wt.optional()}).strict().optional()}).strict().default({mode:"local-static-key"}),endpoint:a.z.string().trim().max(2048).optional(),controlEndpoint:a.z.string().trim().max(2048).optional(),containerEndpoint:a.z.string().trim().max(2048).optional(),publicWebBase:a.z.string().trim().max(2048).optional(),status:a.z.enum(["unknown","online","offline","degraded"]).default("unknown"),health:a.z.enum(["unknown","ok","degraded","failed"]).default("unknown"),capabilities:a.z.record(a.z.string(),a.z.unknown()).default({}),proxyState:mi.optional(),appInventory:Qt.optional(),labels:vt,lastSeenAt:wt.optional(),createdAt:wt,updatedAt:wt}).strict().superRefine((e,t)=>{"control-plane-proxy"===e.connectionPath.kind&&"control-plane-proxy"!==e.connectionMode&&t.addIssue({code:"custom",path:["connectionPath"],message:"Control-plane proxy paths require control-plane-proxy connection mode."}),"control-plane-proxy"===e.connectionMode&&"control-plane-proxy"!==e.connectionPath.kind&&t.addIssue({code:"custom",path:["connectionPath"],message:"Control-plane proxy nodes require a control-plane-proxy connection path."})}),hi=a.z.object({id:bt,nodeId:bt,name:a.z.string().trim().min(1).max(160),type:a.z.enum(["docker","kubernetes","local"]),status:a.z.enum(["unknown","online","offline","degraded"]).default("unknown"),accessStrategy:a.z.enum(["node-proxy","direct-port","kubernetes-ingress","kubernetes-port-forward"]).default("node-proxy"),capabilities:a.z.record(a.z.string(),a.z.unknown()).default({}),labels:vt,createdAt:wt,updatedAt:wt}).strict(),gi=a.z.object({instanceId:bt,runtimeKind:a.z.literal("docker"),state:a.z.enum(["pending","available","stopped","unavailable"]),sampledAt:wt,cpu:a.z.object({usagePercent:a.z.number().nonnegative()}).strict().optional(),memory:a.z.object({usageBytes:a.z.number().nonnegative(),limitBytes:a.z.number().nonnegative().optional(),usagePercent:a.z.number().nonnegative().optional()}).strict().optional(),network:a.z.object({rxBytes:a.z.number().nonnegative(),txBytes:a.z.number().nonnegative()}).strict().optional(),blockIo:a.z.object({readBytes:a.z.number().nonnegative(),writeBytes:a.z.number().nonnegative()}).strict().optional(),pids:a.z.number().int().nonnegative().optional(),error:a.z.string().trim().max(2048).optional()}).strict();a.z.object({ok:a.z.boolean().optional(),role:a.z.string().optional(),nodeId:bt.optional(),platform:$t.optional(),arch:Ft.optional(),protocolVersion:At.optional(),build:gn.strip().optional(),process:a.z.object({pid:a.z.number().int().positive(),startIdentity:a.z.string().trim().min(1).optional()}).strip().optional(),listener:a.z.object({host:a.z.string().trim().min(1),port:a.z.number().int().min(1).max(65535)}).strip().optional(),instanceProxy:a.z.object({requests:a.z.number().int().nonnegative(),active:a.z.number().int().nonnegative(),completed:a.z.number().int().nonnegative(),aborted:a.z.number().int().nonnegative(),limitRejected:a.z.number().int().nonnegative(),responseBytes:a.z.number().nonnegative(),totalDurationMs:a.z.number().nonnegative(),maxResponseBytes:a.z.number().int().nonnegative()}).partial().strip().optional(),serverTime:wt.optional()}).strip();const fi=a.z.object({bindScope:a.z.enum(["loopback","all-ipv4"]),port:a.z.number().int().min(1).max(65535)}).strict(),yi=fi.extend({host:a.z.enum(["127.0.0.1","0.0.0.0"]),status:a.z.enum(["listening","error"]),source:a.z.enum(["bootstrap","persisted"]),error:a.z.string().trim().max(2048).optional()}).strict(),Ii=fi;a.z.object({nodeId:bt,joinToken:a.z.string().trim().min(1),expiresAt:wt}).passthrough(),a.z.object({nodeId:bt,keyId:bt,secret:a.z.string().regex(/^[A-Za-z0-9_-]{32,128}$/),pairedAt:wt}).strict();const Ai=a.z.object({id:bt,keyId:bt,name:a.z.string().trim().min(1).max(160).optional(),pairedAt:wt,updatedAt:wt,current:a.z.boolean()}).passthrough();a.z.object({keyId:bt,revoked:a.z.literal(!0),revokedAt:wt}).strict(),a.z.object({id:bt,pairingKeyId:bt,url:a.z.string().trim().min(1).max(2048),name:a.z.string().trim().min(1).max(160).optional(),enabled:a.z.boolean(),createdAt:wt,updatedAt:wt,status:a.z.enum(["disabled","connecting","connected","reconnecting","failed"]),lastConnectedAt:wt.optional(),lastDisconnectedAt:wt.optional(),error:a.z.string().optional()}).passthrough(),a.z.object({pairing:Ai,connection:a.z.object({id:bt,pairingKeyId:bt,url:a.z.string().trim().min(1).max(2048),name:a.z.string().trim().min(1).max(160).optional(),enabled:a.z.boolean(),createdAt:wt,updatedAt:wt}).passthrough(),tunnel:a.z.object({status:a.z.enum(["disabled","saved","connecting","connected","failed"]),error:a.z.string().trim().max(2048).optional()}).passthrough()}).passthrough(),a.z.object({deleted:a.z.boolean().optional()}).passthrough();const bi=a.z.object({repository:a.z.string().trim().optional(),tag:a.z.string().trim().optional(),id:a.z.string().trim(),createdSince:a.z.string().trim().optional(),size:a.z.string().trim().optional(),sizeBytes:a.z.number().int().nonnegative().optional(),reference:a.z.string().trim().min(1),repoDigests:a.z.array(a.z.string().trim().min(1).max(512)).default([])}).passthrough();a.z.object({image:ii,status:a.z.enum(["available","pull-required","unknown"]),localImage:bi.optional(),localSizeBytes:a.z.number().int().nonnegative().optional(),downloadSizeBytes:a.z.number().int().positive().optional(),unpackedSizeBytes:a.z.number().int().positive().optional(),error:a.z.string().trim().max(2048).optional()}).strict();const wi=a.z.lazy(()=>a.z.object({name:a.z.string().trim().min(1),path:a.z.string().trim().min(1).max(4096),children:a.z.array(wi)}).passthrough());a.z.object({status:a.z.number().int().min(100).max(599).optional(),headers:a.z.record(a.z.string(),a.z.string()).optional(),bodyBase64:a.z.string().optional()}).passthrough();const vi=a.z.object({strategy:a.z.enum(["node-proxy","direct-port","kubernetes-ingress","kubernetes-port-forward"]).default("node-proxy"),web:a.z.string().trim().max(2048).optional(),api:a.z.string().trim().max(2048).optional(),vnc:a.z.string().trim().max(2048).optional(),tty:a.z.string().trim().max(2048).optional(),logs:a.z.string().trim().max(2048).optional(),status:a.z.enum(["unknown","reachable","endpoint-unreachable"]).default("unknown")}).strict(),Ei=a.z.object({strategy:a.z.enum(["control-plane-proxy","direct-port","node-proxy","kubernetes-ingress","kubernetes-port-forward"]).default("control-plane-proxy"),web:a.z.string().trim().max(2048).optional(),api:a.z.string().trim().max(2048).optional(),ws:a.z.string().trim().max(2048).optional(),status:a.z.enum(["unknown","reachable","endpoint-unreachable"]).default("unknown")}).strict().default({strategy:"control-plane-proxy",status:"unknown"}),Ni=a.z.object({mode:a.z.enum(["local-bind","git-clone","empty-volume","persistent-volume"]).optional(),status:a.z.enum(["unknown","pending","ready","failed"]).default("unknown"),path:a.z.string().trim().max(4096).optional(),resolvedCommit:a.z.string().trim().max(120).optional(),error:a.z.string().trim().max(2048).optional()}).passthrough(),Si=a.z.object({id:bt,name:a.z.string().trim().min(1).max(160),projectId:bt.optional(),source:kn,sourceSnapshot:a.z.record(a.z.string(),a.z.unknown()).default({}),modelSelection:Pt,nodeId:bt,runtimeId:bt,imageSelection:Mt.optional(),environmentSource:Lt.optional(),environmentTemplateOrigin:Vt.optional(),imageSnapshot:ri.optional(),imageProvisioning:oi.optional(),stateRevision:a.z.number().int().min(0).default(0),processIncarnationId:a.z.string().trim().min(1).max(120).optional(),status:a.z.enum(["created","provisioning","starting","registering","registered","running","stopping","stopped","deleting","failed","unhealthy"]).default("created"),health:a.z.enum(["unknown","ok","degraded","failed"]).default("unknown"),connectionStatus:a.z.enum(["unknown","online","offline","endpoint-unreachable"]).default("unknown"),agentStatus:a.z.enum(["unknown","online","offline"]).default("unknown"),targetStatus:a.z.enum(["unknown","reachable","endpoint-unreachable"]).default("unknown"),uiAccessStatus:a.z.enum(["unknown","reachable","endpoint-unreachable"]).default("unknown"),controlMode:a.z.enum(["standalone","controlled"]).default("controlled"),protocolVersion:At.optional(),instanceVersion:a.z.string().trim().max(80).optional(),build:gn.optional(),runtimeVersion:An.optional(),ready:a.z.boolean().default(!1),capabilities:a.z.record(a.z.string(),a.z.unknown()).default({}),appInventory:Qt.optional(),config:a.z.object({autoImportAgentConfigs:a.z.boolean().default(!0),defaultCodexPermissionMode:me.default("ask")}).strict().default({autoImportAgentConfigs:!0,defaultCodexPermissionMode:"ask"}),workspace:Ni.default({status:"unknown"}),target:vi.default({strategy:"direct-port",status:"unknown"}),access:Ei,apps:a.z.object({runningCount:a.z.number().int().min(0).default(0),problemCount:a.z.number().int().min(0).default(0),updatedAt:wt.optional(),revision:a.z.number().int().min(0).optional()}).strict().default({runningCount:0,problemCount:0}),aiSessions:Pe.default(()=>({runningCount:0,waitingCount:0,staleCount:0,sessions:[],updatedAt:(new Date).toISOString()})),triggers:a.z.object({enabledCount:a.z.number().int().min(0).default(0),runningCount:a.z.number().int().min(0).default(0),errorCount:a.z.number().int().min(0).default(0),configs:a.z.array(a.z.object({configHash:a.z.string().trim().min(1),config:Je,deployments:a.z.array(Ye).default([]),runtime:a.z.array(Xe).default([])}).strict()).default([]),recentRuns:a.z.array(Qe).default([])}).strict().optional(),runtime:a.z.object({kind:a.z.string().trim().max(80).optional(),containerName:a.z.string().trim().max(240).optional(),containerId:a.z.string().trim().max(240).optional(),workspacePath:a.z.string().trim().max(4096).optional(),pid:a.z.number().int().positive().optional(),port:a.z.number().int().positive().max(65535).optional(),labels:a.z.record(a.z.string(),a.z.string()).default({})}).strict().default({labels:{}}),registrationToken:a.z.string().trim().min(1).max(240).optional(),lastHeartbeatAt:wt.optional(),createdAt:wt,updatedAt:wt}).strict(),Ti="instance.lifecycle.snapshot",zi=a.z.object({instanceId:Si.shape.id,revision:a.z.number().int().min(0),updatedAt:wt,status:Si.shape.status.unwrap(),health:Si.shape.health.unwrap(),connectionStatus:Si.shape.connectionStatus.unwrap(),accessStatus:a.z.enum(["reachable","endpoint-unreachable"]),imageProvisioning:oi.optional(),workspace:Ni,runtime:Si.shape.runtime.unwrap(),runtimeVersion:An.optional(),ready:a.z.boolean(),lastHeartbeatAt:wt.optional()}).strict();function _i(e,t){return Si.safeParse(Ci(e,t))}function Ci(e,t){if(!e||"object"!=typeof e||Array.isArray(e))return e;const n=e,i=new Set(Object.keys(Si.shape)),r={};for(const[e,o]of Object.entries(n))i.has(e)?r[e]=o:t?.({instanceId:"string"==typeof n.id?n.id:void 0,field:e});if(n.capabilities&&"object"==typeof n.capabilities&&!Array.isArray(n.capabilities)){const e={...n.capabilities};Object.prototype.hasOwnProperty.call(e,"apps")&&(t?.({instanceId:"string"==typeof n.id?n.id:void 0,field:"capabilities.apps"}),delete e.apps),r.capabilities=e}else r.capabilities={};r.appInventory=function(e,t,n){if(!e||"object"!=typeof e||Array.isArray(e))return;const i=e;Object.keys(i).some(e=>!["observedAt","items","issues"].includes(e))&&t?.({instanceId:n,field:"appInventory"});const r={observedAt:i.observedAt,items:Array.isArray(i.items)?i.items.map(e=>{e&&"object"==typeof e&&!Array.isArray(e)&&Object.keys(e).some(e=>!["id","name","kind","source","availability","capabilities","diagnosticCode"].includes(e))&&t?.({instanceId:n,field:"appInventory.items"});const i=Ri(e,["id","name","kind","source","availability","diagnosticCode"]);return!i||"object"!=typeof i||Array.isArray(i)?i:{...i,capabilities:Ri(e.capabilities,["automation","supportsCwdSelection"])}}):i.items,issues:Array.isArray(i.issues)?i.issues.map(e=>Ri(e,["code","message"])):i.issues},o=Qt.safeParse(r);return o.success?o.data:void 0}(n.appInventory,t,"string"==typeof n.id?n.id:void 0),r.source=function(e,t,n){if(!e||"object"!=typeof e||Array.isArray(e))return e;const i=e,r=i.type,o=kn.options.find(e=>e.shape.type.value===r);if(!o)return e;const s="local-folder"===r?["type","localFolderId","path","ownerNodeId"]:"git-template"===r?["type","url","templateId","ref","auth","clone"]:["type","repositoryId","url","provider","ref","auth","clone"],a=Ri(i,s);if("local-folder"!==r){const e=ki(Tn,Ri(i.ref,["type","name","commit"]),"source.ref",t,n),r=ki(zn,Ri(i.auth,["type","secretId"]),"source.auth",t,n),o=ki(_n,Ri(i.clone,["depth","submodules","lfs","subdirectory"]),"source.clone",t,n);e?a.ref=e:delete a.ref,r?a.auth=r:delete a.auth,o?a.clone=o:delete a.clone}const c=ki(o,a,"source",t,n);return c?(Object.keys(i).some(e=>!s.includes(e))&&t?.({instanceId:n,field:"source"}),c):a}(n.source,t,"string"==typeof n.id?n.id:void 0),r.sourceSnapshot=n.sourceSnapshot&&"object"==typeof n.sourceSnapshot&&!Array.isArray(n.sourceSnapshot)?n.sourceSnapshot:{},r.build=ki(gn,n.build,"build",t,"string"==typeof n.id?n.id:void 0),r.aiSessions=function(e,t,n){if(!e||"object"!=typeof e||Array.isArray(e))return;const i=e,r=Array.isArray(i.sessions)?i.sessions.flatMap((e,i)=>{const r=ki(De,e,`aiSessions.sessions.${i}`,t,n);return r?[r]:[]}):[],o={runningCount:"number"==typeof i.runningCount&&Number.isInteger(i.runningCount)&&i.runningCount>=0?i.runningCount:0,waitingCount:"number"==typeof i.waitingCount&&Number.isInteger(i.waitingCount)&&i.waitingCount>=0?i.waitingCount:0,staleCount:"number"==typeof i.staleCount&&Number.isInteger(i.staleCount)&&i.staleCount>=0?i.staleCount:0,sessions:r,updatedAt:wt.safeParse(i.updatedAt).success?i.updatedAt:(new Date).toISOString()};return Object.keys(i).some(e=>!["runningCount","waitingCount","staleCount","sessions","updatedAt"].includes(e))&&t?.({instanceId:n,field:"aiSessions"}),Pe.parse(o)}(n.aiSessions,t,"string"==typeof n.id?n.id:void 0),r.triggers=function(e,t,n){if(!e||"object"!=typeof e||Array.isArray(e))return;const i=e;Object.keys(i).some(e=>!["enabledCount","runningCount","errorCount","configs","recentRuns"].includes(e))&&t?.({instanceId:n,field:"triggers"});const r=(e,i,r)=>Array.isArray(e)?e.flatMap((e,o)=>{const s=ki(i,e,`${r}.${o}`,t,n);return s?[s]:[]}):[],o=Array.isArray(i.configs)?i.configs.flatMap((e,i)=>{if(!e||"object"!=typeof e||Array.isArray(e))return[];const o=e;Object.keys(o).some(e=>!["configHash","config","deployments","runtime"].includes(e))&&t?.({instanceId:n,field:`triggers.configs.${i}`});const s=function(e,t,n,i){if(!e||"object"!=typeof e||Array.isArray(e))return;const r=e,o=Ri(r,["configHash","name","description","createdAt","updatedAt"]);if(r.source&&"object"==typeof r.source&&!Array.isArray(r.source)){const e=r.source,t="schedule"===e.type?"interval"===e.scheduleKind?["type","scheduleKind","intervalMs"]:"daily"===e.scheduleKind?["type","scheduleKind","timeOfDay","timezone"]:["type","scheduleKind","weekdays","timeOfDay","timezone"]:"file-change"===e.type?["type","roots","globs","ignore","debounceMs"]:["type","agent","statuses","phases"];o.source=Ri(e,t)}return o.action=Ri(r.action,["promptTemplate"]),o.policy=Ri(r.policy,["cooldownMs","maxConcurrentRuns","whenBusy"]),ki(Je,o,t,n,i)}(o.config,`triggers.configs.${i}.config`,t,n);return"string"==typeof o.configHash&&s?[{configHash:o.configHash,config:s,deployments:r(o.deployments,Ye,`triggers.configs.${i}.deployments`),runtime:r(o.runtime,Xe,`triggers.configs.${i}.runtime`)}]:[]}):[];return{enabledCount:"number"==typeof i.enabledCount&&Number.isInteger(i.enabledCount)&&i.enabledCount>=0?i.enabledCount:0,runningCount:"number"==typeof i.runningCount&&Number.isInteger(i.runningCount)&&i.runningCount>=0?i.runningCount:0,errorCount:"number"==typeof i.errorCount&&Number.isInteger(i.errorCount)&&i.errorCount>=0?i.errorCount:0,configs:o,recentRuns:r(i.recentRuns,Qe,"triggers.recentRuns")}}(n.triggers,t,"string"==typeof n.id?n.id:void 0),r.apps=ki(Si.shape.apps.unwrap(),Ri(n.apps,["runningCount","problemCount","updatedAt","revision"]),"apps",t,"string"==typeof n.id?n.id:void 0)||{runningCount:0,problemCount:0},r.config=ki(Si.shape.config.unwrap(),Ri(n.config,["autoImportAgentConfigs","defaultCodexPermissionMode"]),"config",t,"string"==typeof n.id?n.id:void 0)||{autoImportAgentConfigs:!0,defaultCodexPermissionMode:"ask"},r.modelSelection=ki(Pt.unwrap(),Ri(n.modelSelection,["codexModelHash","claudeModelHash"]),"modelSelection",t,"string"==typeof n.id?n.id:void 0)||{},r.imageSnapshot=function(e,t,n,i){if(!e||"object"!=typeof e||Array.isArray(e))return e;const r=e,o=function(e){if(!e||"object"!=typeof e||Array.isArray(e))return e;const t=e,n=new Set(["id","origin","name","description","localizedDescriptions","cover","reference","repository","tag","image","registry","pullPolicy","capabilities","optionalApps","defaultEnv","labels","createdAt","updatedAt"]);for(const e of Object.keys(t))n.has(e);"string"==typeof t.id&&t.id;const i="string"==typeof t.image?t.image:void 0;Object.prototype.hasOwnProperty.call(t,"registry");let r,o="string"==typeof t.reference?t.reference:i;if(o)try{o=Ot(o)}catch{if(!o.includes("@")&&o.lastIndexOf(":")<=o.lastIndexOf("/"))try{o=Ot(`${o}:latest`)}catch{}}try{r=o?Rt(o):void 0}catch{}return{id:t.id,origin:"custom",name:t.name,description:t.description,localizedDescriptions:t.localizedDescriptions,cover:Ri(t.cover,["kind","key","url","mediaType","digest"]),reference:r?.reference??o,repository:r?.repository??t.repository,tag:r?.tag??t.tag,pullPolicy:t.pullPolicy??"if-not-present",capabilities:t.capabilities,optionalApps:t.optionalApps,defaultEnv:t.defaultEnv,labels:t.labels,createdAt:t.createdAt,updatedAt:t.updatedAt}}(r),{reference:s,...a}=o,c=r.requestedReference??s;let d;try{d="string"==typeof c?Rt(c):void 0}catch{}const l={img_default:"market_taskhandoff_browser",img_codex:"market_taskhandoff_codex",img_ai:"market_taskhandoff_ai"},u="string"==typeof r.id?r.id:"string"==typeof t?t:void 0,m="market"===r.origin||u&&l[u]?"market":"custom";return void 0===r.image&&void 0===r.reference||n?.({instanceId:i,field:"imageSnapshot.reference"}),{...a,id:u&&l[u]?l[u]:u,origin:m,repository:d?.repository??r.repository,tag:d?.tag??r.tag,requestedReference:d?.reference??c,resolvedDigest:r.resolvedDigest,resolvedReference:r.resolvedReference,downloadSizeBytes:r.downloadSizeBytes,market:"market"===m?Ri(r.market,["catalogId","catalogRevision","publisher","version"])??{catalogId:"task_handoff_embedded",catalogRevision:"legacy",publisher:"task-handoff"}:void 0}}(n.imageSnapshot,n.imageId,t,"string"==typeof n.id?n.id:void 0);const o="string"==typeof n.imageId?{img_default:"market_taskhandoff_browser",img_codex:"market_taskhandoff_codex",img_ai:"market_taskhandoff_ai"}[n.imageId]||n.imageId:void 0,s=Ri(n.imageSelection,["imageId","tag"]);r.imageSelection=s||(o?{imageId:o,tag:r.imageSnapshot?.tag}:void 0),r.imageProvisioning=ki(oi,Ri(n.imageProvisioning,["phase","requestedReference","generation","error","startedAt","updatedAt"]),"imageProvisioning",t,"string"==typeof n.id?n.id:void 0),r.runtimeVersion=function(e,t,n){if(!e||"object"!=typeof e||Array.isArray(e))return;const i=e,r=e=>{if("string"!=typeof e)return;const t=e.trim();return t&&t.length<=80?t:void 0},o=r(i.desiredVersion);if(!o)return void t?.({instanceId:n,field:"runtimeVersion.desiredVersion"});const s=new Set(An.shape.phase.options),a="string"==typeof i.phase?i.phase:"pending",c=s.has(a)?a:{idle:"pending",queued:"pending",checking:"pending",downloading:"installing",updating:"installing",completed:"matched",succeeded:"matched",ready:"matched",error:"failed"}[a]||"pending";let d;if(c!==a&&t?.({instanceId:n,field:"runtimeVersion.phase"}),i.error&&"object"==typeof i.error&&!Array.isArray(i.error)){const e=i.error,o="string"==typeof e.message?e.message.trim().slice(0,4096):"";if(o){const i=new Set(In.shape.code.options),s="string"==typeof e.code&&i.has(e.code)?e.code:"INSTANCE_RUNTIME_INSTALL_FAILED";s!==e.code&&t?.({instanceId:n,field:"runtimeVersion.error.code"});const a=r(e.expectedVersion),c=r(e.actualVersion);d={code:s,message:o,...a?{expectedVersion:a}:{},...c?{actualVersion:c}:{},retryable:!0===e.retryable}}else t?.({instanceId:n,field:"runtimeVersion.error"})}"string"==typeof i.error&&i.error.trim()&&(d={code:"INSTANCE_RUNTIME_INSTALL_FAILED",message:i.error.trim().slice(0,4096),expectedVersion:o,...r(i.actualVersion)?{actualVersion:r(i.actualVersion)}:{},retryable:!1});const l=r(i.actualVersion),u=wt.safeParse(i.lastAttemptAt),m=wt.safeParse(i.matchedAt);return void 0===i.lastAttemptAt||u.success||t?.({instanceId:n,field:"runtimeVersion.lastAttemptAt"}),void 0===i.matchedAt||m.success||t?.({instanceId:n,field:"runtimeVersion.matchedAt"}),{desiredVersion:o,...l?{actualVersion:l}:{},phase:c,attempt:"number"==typeof i.attempt&&Number.isInteger(i.attempt)&&i.attempt>=0?i.attempt:0,...u.success?{lastAttemptAt:u.data}:{},...m.success?{matchedAt:m.data}:{},...d?{error:d}:{}}}(n.runtimeVersion,t,"string"==typeof n.id?n.id:void 0),r.workspace=ki(Ni,n.workspace,"workspace",t,"string"==typeof n.id?n.id:void 0)||{status:"unknown"},r.environmentSource=ki(Lt,n.environmentSource,"environmentSource",t,"string"==typeof n.id?n.id:void 0),r.environmentTemplateOrigin=ki(Vt,n.environmentTemplateOrigin,"environmentTemplateOrigin",t,"string"==typeof n.id?n.id:void 0),r.runtime=ki(Si.shape.runtime.unwrap(),n.runtime,"runtime",t,"string"==typeof n.id?n.id:void 0)||{labels:{}},r.target=ki(vi,Ri(n.target??n.endpoints,["strategy","web","api","vnc","tty","logs","status"]),"target",t,"string"==typeof n.id?n.id:void 0)||{strategy:"direct-port",status:"unknown"},r.access=ki(Ei,Ri(n.access,["strategy","web","api","ws","status"]),"access",t,"string"==typeof n.id?n.id:void 0)||{strategy:"control-plane-proxy",status:"unknown"};for(const[e,i]of Object.entries(Si.shape))Object.prototype.hasOwnProperty.call(r,e)&&!i.safeParse(r[e]).success&&i.safeParse(void 0).success&&(delete r[e],t?.({instanceId:"string"==typeof n.id?n.id:void 0,field:e}));return r}function ki(e,t,n,i,r){if(!t||"object"!=typeof t||Array.isArray(t))return;let o=structuredClone(t),s=!1;for(let t=0;t<20;t+=1){const t=e.safeParse(o);if(t.success)return s&&i?.({instanceId:r,field:n}),t.data;let a=!1;for(const e of t.error.issues){if("unrecognized_keys"!==e.code)continue;const t=Oi(o,e.path);if(t&&"object"==typeof t&&!Array.isArray(t))for(const n of e.keys)Object.prototype.hasOwnProperty.call(t,n)&&(delete t[n],a=!0,s=!0)}if(!a){const s=structuredClone(o);let a=!1;for(const e of t.error.issues){if(!e.path.length||"string"!=typeof e.path.at(-1))continue;const t=Oi(s,e.path.slice(0,-1)),n=e.path.at(-1);t&&"object"==typeof t&&!Array.isArray(t)&&Object.prototype.hasOwnProperty.call(t,n)&&(delete t[n],a=!0)}if(a){const t=e.safeParse(s);if(t.success)return i?.({instanceId:r,field:n}),t.data}break}}i?.({instanceId:r,field:n})}function Oi(e,t){let n=e;for(const e of t){if(!n||"object"!=typeof n)return;n=n[e]}return n}function Ri(e,t){if(!e||"object"!=typeof e||Array.isArray(e))return e;const n=e;return Object.fromEntries(t.filter(e=>Object.prototype.hasOwnProperty.call(n,e)).map(e=>[e,n[e]]))}const xi=a.z.object({instanceId:bt.optional(),projectId:bt.optional(),source:kn.optional(),nodeId:bt.optional(),runtimeId:bt.optional(),imageSelection:Mt.optional(),instanceVersion:a.z.string().trim().max(80).optional(),protocolVersion:At,build:gn.optional(),controlMode:a.z.enum(["standalone","controlled"]).default("controlled"),capabilities:a.z.record(a.z.string(),a.z.unknown()).default({}),appInventory:Qt.optional(),target:vi.default({strategy:"direct-port",status:"unknown"}),workspace:Ni.default({status:"unknown"}),registrationToken:a.z.string().trim().max(240).optional(),processIncarnationId:a.z.string().trim().min(1).max(120).optional()}).strict().superRefine((e,t)=>{e.protocolVersion!==It||e.appInventory||t.addIssue({code:"custom",path:["appInventory"],message:"Current protocol register payload requires appInventory."})}),Di=a.z.object({status:Si.shape.status.optional(),health:Si.shape.health.optional(),protocolVersion:At,build:gn.optional(),capabilities:Si.shape.capabilities.optional(),appInventory:Qt.optional(),apps:Si.shape.apps.optional(),aiSessions:Si.shape.aiSessions.optional(),triggers:Si.shape.triggers.optional(),workspace:Ni.optional(),target:vi.partial().optional(),processIncarnationId:a.z.string().trim().min(1).max(120).optional()}).strict().superRefine((e,t)=>{e.protocolVersion!==It||e.appInventory||t.addIssue({code:"custom",path:["appInventory"],message:"Current protocol heartbeat payload requires appInventory."})}),Pi=a.z.enum(["web","telegram","wechat","dingding","lark"]);function Mi(e,t){let n=Fi(t);for(let t=0;t<100;t+=1){const t=e.safeParse(n);if(t.success)return t;const i=Li(t.error.issues);let r=!1;for(const e of i){const t=$i(n,e.path);if(t&&"object"==typeof t&&!Array.isArray(t))for(const n of e.keys)Object.prototype.hasOwnProperty.call(t,n)&&(delete t[n],r=!0)}if(!r)return t}return e.safeParse(n)}function Li(e,t=[]){const n=[];for(const i of e){if("unrecognized_keys"===i.code){n.push({code:"unrecognized_keys",keys:i.keys,path:[...t,...i.path]});continue}if("invalid_union"!==i.code||!Array.isArray(i.errors))continue;const e=i.errors.filter(e=>Array.isArray(e));if(!e.length)continue;const r=e.reduce((e,t)=>ji(t)<ji(e)?t:e);n.push(...Li(r,[...t,...i.path]))}return n}function ji(e){return e.reduce((e,t)=>{if("unrecognized_keys"===t.code)return e;if("invalid_union"!==t.code||!Array.isArray(t.errors))return e+1;const n=t.errors.filter(e=>Array.isArray(e));return e+(n.length?Math.min(...n.map(ji)):1)},0)}function $i(e,t){let n=e;for(const e of t){if(!n||"object"!=typeof n)return;n=n[e]}return n}function Fi(e){return Array.isArray(e)?e.map(Fi):e&&"object"==typeof e?Object.getPrototypeOf(e)!==Object.prototype&&null!==Object.getPrototypeOf(e)?e:Object.fromEntries(Object.entries(e).map(([e,t])=>[e,Fi(t)])):e}function Ui(e,t,n={}){return new Promise((i,r)=>{if(n.signal?.aborted)return void r(Object.assign(new Error(`${e} was aborted.`),{code:"RUNTIME_COMMAND_ABORTED"}));const o=l.spawn(e,t,{stdio:["ignore","pipe","pipe"]}),s=[],a=[];let c=!1;const d=n.timeoutMs?setTimeout(()=>{c=!0,o.kill("SIGKILL")},n.timeoutMs):void 0;let u=!1;const m=()=>{u=!0,o.kill("SIGKILL")},p=()=>{d&&clearTimeout(d),n.signal?.removeEventListener("abort",m)};n.signal?.addEventListener("abort",m,{once:!0}),d?.unref?.(),o.stdout.on("data",e=>s.push(Buffer.from(e))),o.stderr.on("data",e=>a.push(Buffer.from(e))),o.on("error",e=>{p(),r(e)}),o.on("close",t=>{p();const o={stdout:Buffer.concat(s).toString("utf8").trim(),stderr:Buffer.concat(a).toString("utf8").trim()};if(c){const t=new Error(`${e} timed out after ${n.timeoutMs}ms`);return Object.assign(t,{statusCode:504,code:"RUNTIME_COMMAND_TIMEOUT",details:o}),void r(t)}if(u)return void r(Object.assign(new Error(`${e} was aborted.`),{code:"RUNTIME_COMMAND_ABORTED",details:o}));if(0===t)return void i(o);const d=new Error(o.stderr||`${e} exited with code ${t}`);Object.assign(d,{statusCode:502,code:"RUNTIME_EXECUTOR_FAILED",details:o}),r(d)})})}a.z.object({id:bt,channel:Pi,name:a.z.string().trim().min(1).max(160),enabled:a.z.boolean().default(!1),token:a.z.string().trim().max(4096).optional(),defaultChatId:a.z.string().trim().max(240).optional(),allowedUserIds:a.z.array(a.z.string().trim().min(1).max(240)).default([]),pollIntervalMs:a.z.number().int().positive().max(6e4).default(3e3),settings:a.z.record(a.z.string(),a.z.unknown()).default({}),createdAt:wt,updatedAt:wt}).strict(),a.z.object({id:bt,channel:Pi,bridgeId:bt.optional(),chatSessionId:a.z.string().trim().min(1).max(240),userId:a.z.string().trim().max(240).optional(),activeProjectId:bt.optional(),activeInstanceId:bt.optional(),activeAiSessionId:a.z.string().trim().min(1).max(120).optional(),lastUsedAt:wt,createdAt:wt,updatedAt:wt}).strict(),a.z.object({source:a.z.object({type:a.z.literal("chat-gateway").default("chat-gateway"),channel:Pi,bridgeId:bt.optional(),chatSessionId:a.z.string().trim().min(1).max(240),userId:a.z.string().trim().max(240).optional()}).strict(),message:a.z.object({text:a.z.string().trim().max(2e4).default(""),attachments:a.z.array(ce).max(6).default([])}).strict().superRefine((e,t)=>{e.attachments.reduce((e,t)=>e+("inline"===t.source.type?t.size:0),0)>G&&t.addIssue({code:a.z.ZodIssueCode.custom,path:["attachments"],message:"Inline attachments must be 41943040 bytes or less in total."})}),target:a.z.object({instanceId:bt,aiSessionId:a.z.string().trim().min(1).max(120)}).strict().optional()}).strict(),a.z.object({id:bt,instanceId:bt,projectId:bt.optional(),aiSessionId:a.z.string().trim().min(1).max(120),providerSessionId:a.z.string().trim().max(240).optional(),result:a.z.string().default(""),timeoutMs:a.z.number().positive().optional(),source:a.z.string().trim().max(120).optional(),kind:a.z.enum(["task","approval"]).default("task"),status:a.z.enum(["pending","unreachable"]).default("pending"),error:a.z.string().trim().max(2048).optional(),lastSeenAt:wt}).strict();const Vi=(e,t,n={})=>new Promise((i,r)=>{if(n.signal?.aborted)return void r(Object.assign(new Error(`${e} was aborted.`),{code:"RUNTIME_COMMAND_ABORTED"}));const o=[];let s,a=!1,c=!1;try{s=u.spawn(e,t,{name:"xterm-256color",cols:n.cols||120,rows:n.rows||40,cwd:process.cwd(),env:process.env})}catch(e){return void r(e)}const d=n.timeoutMs?setTimeout(()=>{a=!0,s.kill("SIGKILL")},n.timeoutMs):void 0,l=()=>{c=!0;try{s.kill("SIGKILL")}catch{}};n.signal?.addEventListener("abort",l,{once:!0}),d?.unref?.(),s.onData(e=>{o.push(e),n.onData?.(e)}),s.onExit(({exitCode:t})=>{d&&clearTimeout(d),n.signal?.removeEventListener("abort",l);const s={stdout:o.join(""),stderr:""};a?r(Object.assign(new Error(`${e} timed out after ${n.timeoutMs}ms`),{statusCode:504,code:"RUNTIME_COMMAND_TIMEOUT",details:s})):c?r(Object.assign(new Error(`${e} was aborted.`),{code:"RUNTIME_COMMAND_ABORTED",details:s})):0!==t?r(Object.assign(new Error(s.stdout.replace(/\u001b\[[0-?]*[ -/]*[@-~]/g,"").split(/\r?\n/).map(e=>e.trim()).filter(Boolean).at(-1)||`${e} exited with code ${t}`),{statusCode:502,code:"RUNTIME_EXECUTOR_FAILED",details:s})):i(s)})});class qi{inFlight=new Map;runCommand;runTerminalCommand;constructor(e=Ui,t){this.runCommand=e,this.runTerminalCommand=t||function(e){return e===Ui?Vi:async(t,n,i={})=>{const r=await e(t,n,{timeoutMs:i.timeoutMs,signal:i.signal});return r.stdout&&i.onData?.(r.stdout),r.stderr&&i.onData?.(r.stderr),r}}(e)}ensure(e,t,n,i){const r=Ot(e),o=this.inFlight.get(r);if(o)return t&&(o.phaseListeners.add(t),o.phase&&t(o.phase)),n&&(o.terminalListeners.add(n),o.terminalTail&&n({sequence:o.terminalSequence,data:o.terminalTail,replay:!0})),this.bindAbort(o,i),o.promise;const s=new Set,a=new Set;t&&s.add(t),n&&a.add(n);const c={promise:Promise.resolve(void 0),controller:new AbortController,abortDisposers:new Set,phaseListeners:s,terminalListeners:a,terminalSequence:0,terminalTail:""};return this.bindAbort(c,i),c.promise=this.ensureOnce(r,e=>{c.phase=e,s.forEach(t=>t(e))},e=>{c.terminalSequence+=1,c.terminalTail=`${c.terminalTail}${e}`.slice(-262144);const t={sequence:c.terminalSequence,data:e};a.forEach(e=>e(t))},c.controller.signal).finally(()=>{this.inFlight.delete(r);for(const e of c.abortDisposers)e();c.abortDisposers.clear()}),this.inFlight.set(r,c),c.promise}bindAbort(e,t){if(!t)return;if(t.aborted)return void e.controller.abort();const n=()=>e.controller.abort();t.addEventListener("abort",n,{once:!0}),e.abortDisposers.add(()=>t.removeEventListener("abort",n))}async ensureOnce(e,t,n,i){t("checking-image");let r=await this.inspect(e,i).catch(e=>{if(i.aborted)throw e}),o=!1;r||(t("pulling-image"),await this.runTerminalCommand("docker",["pull",e],{cols:120,rows:40,signal:i,onData:n}),o=!0,r=await this.inspect(e,i)),t("resolving-image");const s=(a=r,Array.isArray(a.RepoDigests)?a.RepoDigests.filter(e=>"string"==typeof e):[]).find(e=>/@sha256:[a-fA-F0-9]{64}$/.test(e));var a;const c=s?.split("@").at(-1)?.toLowerCase();return{requestedReference:e,...c?{resolvedDigest:c}:{},resolvedReference:s||e,pulled:o}}async inspect(e,t){const n=await this.runCommand("docker",["image","inspect",e,"--format","{{json .}}"],{signal:t});return JSON.parse(n.stdout.trim()||"{}")}}function Hi(e){if(!e)return;const t=/^([0-9]+(?:\.[0-9]+)?)\s*(B|kB|MB|GB|TB)$/i.exec(e.trim());if(!t)return;const n=Number(t[1])*{b:1,kb:1e3,mb:1e6,gb:1e9,tb:1e12}[t[2].toLowerCase()];return Number.isSafeInteger(Math.round(n))?Math.round(n):void 0}const Bi="/run/task-handoff/bootstrap",Ki=`${Bi}/entrypoint.sh`,Gi="/bin/bash",Ji=`${Bi}/runtime-installer.mjs`;function Wi(e,t){return{role:"runtime",name:`${mr(e)}-runtime`,mountPath:"/opt/task-handoff/instance-runtime",labels:{"task-handoff.owner":"task-handoff","task-handoff.instance-id":e,"task-handoff.node-id":t,"task-handoff.volume-role":"runtime"}}}function Yi(e){return function(e,t,n){const i=mr(e);return[{role:"data",suffix:"data",mountPath:"/data"},{role:"agent-home",suffix:"agent-home",mountPath:"/home/agent"},..."local-folder"===n.type?[]:[{role:"workspace",suffix:"workspace",mountPath:"/workspace"}]].map(({role:n,suffix:r,mountPath:o})=>({role:n,name:`${i}-${r}`,mountPath:o,labels:{"task-handoff.owner":"task-handoff","task-handoff.instance-id":e,"task-handoff.node-id":t,"task-handoff.volume-role":n}}))}(e.instance.id,e.node?.id||"node_unset",e.project.source)}const Xi=new Set(["TASK_HANDOFF_REGISTRATION_TOKEN","OPENAI_API_KEY","OPENAI_BASE_URL","CODEX_MODEL","TASK_HANDOFF_CODEX_BASE_URL","TASK_HANDOFF_CODEX_MODEL","TASK_HANDOFF_CODEX_MODEL_ID","ANTHROPIC_API_KEY","ANTHROPIC_BASE_URL","CLAUDE_MODEL","TASK_HANDOFF_CLAUDE_MODEL","TASK_HANDOFF_CLAUDE_MODEL_ID"]);function Qi(e,t=[]){const n=e&&"object"==typeof e&&!Array.isArray(e)?e:{},i=n.Config&&"object"==typeof n.Config&&!Array.isArray(n.Config)?n.Config:n,r=new Set;for(const e of Array.isArray(i.Env)?i.Env:[]){if("string"!=typeof e)continue;const n=e.indexOf("="),i=-1===n?e:e.slice(0,n),o=-1===n?"":e.slice(n+1);Xi.has(i)&&r.add(`Config.Env.${i}`),t.some(e=>e&&o.includes(e))&&r.add(`Config.Env.${i||"unknown"}`)}if(i.Labels&&"object"==typeof i.Labels&&!Array.isArray(i.Labels))for(const[e,n]of Object.entries(i.Labels))(Xi.has(e)||"string"==typeof n&&t.some(e=>e&&n.includes(e)))&&r.add(`Config.Labels.${e}`);if(r.size)throw Object.assign(new Error(`Docker configuration contains instance-private values in ${[...r].sort().join(", ")}.`),{statusCode:409,code:"ENVIRONMENT_TEMPLATE_SECRET_IN_DOCKER_CONFIG",findings:[...r].sort()})}class Zi{runCommand;publishHost;images;launcherAssetsDir;portResolutionRetryDelaysMs;constructor(e=Ui,t={}){this.runCommand=e,this.images=t.imageService||new qi(e),this.publishHost=t.publishHost||"127.0.0.1",this.launcherAssetsDir=t.launcherAssetsDir||or(),this.portResolutionRetryDelaysMs=t.portResolutionRetryDelaysMs?.length?t.portResolutionRetryDelaysMs:[0,100,250,500,1e3]}async start(e){gr(e);const t=e.instance.runtime.containerName||mr(e.instance.id),i=await this.inspectContainerForStart(t);if(i){lr(t,i.id,e.instance.runtime.containerId,"before start","RUNTIME_EXECUTOR_FAILED");const r=i.labels["task-handoff.instance-id"];if(r!==e.instance.id)throw ar("RUNTIME_EXECUTOR_FAILED",`Docker container ${t} belongs to ${r||"an unknown instance"}, not ${e.instance.id}.`);const o=i.mounts.find(e=>"bind"===e.type&&e.destination===Bi);if("1"!==i.labels["task-handoff.bootstrap-abi"]||i.entrypoint[0]!==Gi||i.command[0]!==Ki||!o?.source||n.resolve(o.source)!==n.resolve(this.launcherAssetsDir)){const n=new Set(Yi(e).flatMap(e=>i.mounts.some(t=>"volume"===t.type&&t.name===e.name&&t.destination===e.mountPath)?[e.name]:[]));return await this.createPersistentVolumes(e,n),this.recreateWithAuthoritativeBootstrap(e,t,i)}await this.createRuntimeVolume(e),await this.validatePersistentVolumes(e,i.mounts);try{await this.runCommand("docker",["start",t])}catch(e){throw ar("RUNTIME_EXECUTOR_FAILED",`Could not start Docker container ${t}.`,e)}return this.bootstrapResult(e,t,i.id)}if(e.instance.environmentTemplateOrigin){const t=await this.inspectEnvironmentTemplateImage(e.instance.environmentTemplateOrigin.imageId);if(t.imageId!==e.instance.environmentTemplateOrigin.imageId||t.platform!==e.instance.environmentTemplateOrigin.platform||t.architecture!==e.instance.environmentTemplateOrigin.architecture)throw Object.assign(new Error(`Environment template image identity or platform changed for instance ${e.instance.id}.`),{statusCode:409,code:"ENVIRONMENT_TEMPLATE_IMAGE_IDENTITY_MISMATCH"})}else await this.images.ensure(e.image.resolvedReference||e.image.requestedReference);let r;await this.createPersistentVolumes(e);try{r=await this.runCommand("docker",hr(e,t,{publishHost:this.publishHost,launcherAssetsDir:this.launcherAssetsDir}))}catch(e){throw ar("RUNTIME_EXECUTOR_FAILED",`Could not create Docker container ${t}.`,e)}return this.bootstrapResult(e,t,r.stdout||void 0)}async recreateWithAuthoritativeBootstrap(e,t,n){const i=`${t}-pre-bootstrap-${n.id.slice(0,12)}`;n.running&&await this.runCommand("docker",["stop",t]);try{await this.runCommand("docker",["rename",t,i])}catch(e){throw n.running&&await this.runCommand("docker",["start",t]).catch(()=>({stdout:"",stderr:""})),ar("RUNTIME_EXECUTOR_FAILED",`Could not preserve Docker container ${t} before bootstrap migration.`,e)}try{const r=await this.runCommand("docker",hr(e,t,{publishHost:this.publishHost,launcherAssetsDir:this.launcherAssetsDir,imageReference:n.image}));return this.bootstrapResult(e,t,r.stdout||void 0,i)}catch(e){throw await this.runCommand("docker",["rm","-f",t]).catch(()=>({stdout:"",stderr:""})),await this.runCommand("docker",["rename",i,t]).catch(()=>({stdout:"",stderr:""})),n.running&&await this.runCommand("docker",["start",t]).catch(()=>({stdout:"",stderr:""})),ar("RUNTIME_EXECUTOR_FAILED",`Could not recreate Docker container ${t} with the node-agent bootstrap.`,e)}}async inspectContainerConfigSecurity(e,t){Qi(await this.runCommand("docker",["inspect","--format","{{json .}}",e]).then(e=>JSON.parse(e.stdout||"{}")).catch(t=>{throw ar("ENVIRONMENT_TEMPLATE_CONTAINER_INSPECT_FAILED",`Could not inspect Docker container ${e}.`,t)}),t)}async inspectImageConfigSecurity(e,t){Qi(await this.runCommand("docker",["image","inspect","--format","{{json .}}",e]).then(e=>JSON.parse(e.stdout||"{}")).catch(e=>{throw ar("ENVIRONMENT_TEMPLATE_IMAGE_INSPECT_FAILED","Could not inspect Docker image configuration.",e)}),t)}async commitEnvironmentTemplate(e,t,n){const i=await this.inspectContainerId(e);if(!i)throw ar("ENVIRONMENT_TEMPLATE_CONTAINER_NOT_FOUND",`Docker container ${e} does not exist.`);lr(e,i,t,"before environment template commit","ENVIRONMENT_TEMPLATE_CONTAINER_IDENTITY_MISMATCH");try{const t=(await this.runCommand("docker",["commit",e,n])).stdout.trim();if(!t)throw new Error("Docker commit did not return an image id.");return t}catch(t){throw ar("ENVIRONMENT_TEMPLATE_COMMIT_FAILED",`Could not save Docker container ${e} as an environment template.`,t)}}async inspectEnvironmentTemplateImage(e){try{const t=await this.runCommand("docker",["image","inspect","--format","{{json .}}",e]),n=JSON.parse(t.stdout||"{}"),i="string"==typeof n.Id?n.Id:"",r=ir(n.Os),o=rr(n.Architecture),s="number"==typeof n.Size?n.Size:Number.NaN;if(!/^sha256:[a-f0-9]{64}$/.test(i)||!r||!o||!Number.isSafeInteger(s)||s<0)throw new Error("Docker image inspection did not return a valid immutable identity.");return{imageId:i,platform:r,architecture:o,sizeBytes:s}}catch(e){throw ar("ENVIRONMENT_TEMPLATE_IMAGE_INSPECT_FAILED","Could not inspect the committed environment template image.",e)}}async untagEnvironmentTemplate(e,t){try{const n=t||(await this.inspectEnvironmentTemplateImage(e)).imageId;return await this.runCommand("docker",["tag",n,sr(n)]),await this.runCommand("docker",["image","rm",e]),n}catch(e){const t=cr(e)?.toLowerCase()||"";if(t.includes("no such image")||t.includes("no such object"))return;throw ar("ENVIRONMENT_TEMPLATE_UNTAG_FAILED","Could not remove the environment template tag.",e)}}async garbageCollectEnvironmentTemplateImage(e){try{try{await this.runCommand("docker",["image","rm",sr(e)])}catch(e){const t=cr(e)?.toLowerCase()||"";if(t.includes("being used by")||t.includes("is referenced")||t.includes("conflict"))return!1;if(!t.includes("no such image")&&!t.includes("no such object"))throw e}return await this.runCommand("docker",["image","rm",e]),!0}catch(e){const t=cr(e)?.toLowerCase()||"";if(t.includes("being used by")||t.includes("is referenced")||t.includes("conflict"))return!1;if(t.includes("no such image")||t.includes("no such object"))return!0;throw ar("ENVIRONMENT_TEMPLATE_GC_FAILED","Could not garbage collect the environment template image.",e)}}async createPersistentVolumes(e,t=new Set){const n=Wi(e.instance.id,e.node?.id||"node_unset");for(const i of[...Yi(e),n])await this.createVolume(i),await this.validateOwnedVolume(e.instance.id,i,t.has(i.name))}async createRuntimeVolume(e){await this.createVolume(Wi(e.instance.id,e.node?.id||"node_unset"))}async createVolume(e){const t=["volume","create"];for(const[n,i]of Object.entries(e.labels).sort(([e],[t])=>e.localeCompare(t)))t.push("--label",`${n}=${i}`);t.push(e.name);try{await this.runCommand("docker",t)}catch(t){throw ar("INSTANCE_VOLUME_CREATE_FAILED",`Could not create managed volume ${e.name}.`,t)}}async validatePersistentVolumes(e,t){for(const n of Yi(e)){await this.validateOwnedVolume(e.instance.id,n);const i=t.find(e=>"volume"===e.type&&e.destination===n.mountPath);if(!i||i.name!==n.name)throw Object.assign(new Error(`Docker container mount for ${n.role} does not match managed volume ${n.name}.`),{statusCode:409,code:"INSTANCE_VOLUME_MOUNT_IDENTITY_MISMATCH"})}const i=Wi(e.instance.id,e.node?.id||"node_unset");await this.validateOwnedVolume(e.instance.id,i);const r=t.find(e=>"volume"===e.type&&e.destination===i.mountPath);if(!r||r.name!==i.name)throw Object.assign(new Error(`Docker container runtime mount does not match ${i.name}.`),{statusCode:409,code:"INSTANCE_VOLUME_MOUNT_IDENTITY_MISMATCH"});if("local-folder"===e.project.source.type){const i=t.find(t=>t.destination===(e.project.workspacePolicy.path||"/workspace"));if(!i||"bind"!==i.type||n.resolve(i.source||"")!==n.resolve(e.project.source.path))throw Object.assign(new Error(`Docker container workspace bind does not match local folder ${e.project.source.path}.`),{statusCode:409,code:"INSTANCE_WORKSPACE_MOUNT_IDENTITY_MISMATCH"})}}async validateOwnedVolume(e,t,n=!1){let i;try{i=await this.runCommand("docker",["volume","inspect","--format","{{json .}}",t.name])}catch(e){throw ar("INSTANCE_VOLUME_INSPECT_FAILED",`Could not inspect managed volume ${t.name}.`,e)}try{const r=JSON.parse(i.stdout||"{}"),o=r.Labels&&"object"==typeof r.Labels&&!Array.isArray(r.Labels)?r.Labels:{},s=r.Name===t.name&&"task-handoff"===o["task-handoff.owner"]&&o["task-handoff.instance-id"]===e&&o["task-handoff.volume-role"]===t.role,a=n&&r.Name===t.name&&0===Object.keys(o).length;if(!s&&!a)throw new Error("volume name or ownership labels do not match")}catch(n){throw Object.assign(new Error(`Managed volume ${t.name} identity does not match instance ${e}.`,{cause:n}),{statusCode:409,code:"INSTANCE_VOLUME_IDENTITY_MISMATCH"})}}async runningResult(e,t,n){const i=await this.containerPort(t,"8080/tcp"),r=i?`http://127.0.0.1:${i}`:void 0,o=e.node?.id||"node_unset",s=e.runtime?.id||"runtime_local_docker";return{status:"registering",health:"unknown",connectionStatus:r?"online":"unknown",agentStatus:"unknown",targetStatus:"unknown",uiAccessStatus:"unknown",target:{strategy:"direct-port",status:r?"reachable":"unknown",...r?{web:r,api:`${r}/api`}:{}},workspace:{mode:e.project.workspacePolicy.mode,status:"pending",path:e.project.workspacePolicy.path},runtime:{...e.instance.runtime,kind:"docker",containerName:t,...n?{containerId:n}:{},labels:{...e.instance.runtime.labels,"task-handoff.instance-id":e.instance.id,"task-handoff.project-id":e.project.id,"task-handoff.node-id":o,"task-handoff.runtime-id":s,"task-handoff.image-id":e.image.id}}}}bootstrapResult(e,t,n,i){return{status:"starting",health:"unknown",connectionStatus:"unknown",agentStatus:"unknown",targetStatus:"unknown",uiAccessStatus:"unknown",target:{strategy:"direct-port",status:"unknown"},workspace:{mode:e.project.workspacePolicy.mode,status:"pending",path:e.project.workspacePolicy.path},runtime:{...e.instance.runtime,kind:"docker",containerName:t,...n?{containerId:n}:{},labels:{...e.instance.runtime.labels,"task-handoff.bootstrap-abi":"1",...i?{"task-handoff.bootstrap-backup":i}:{}}}}}async stop(e){const t=e.instance.runtime.containerName||mr(e.instance.id);try{await this.runCommand("docker",["stop",t])}catch(e){if(!dr(e))throw ar("RUNTIME_EXECUTOR_FAILED",`Could not stop Docker container ${t}.`,e)}return{status:"stopped",health:"unknown",connectionStatus:"offline",target:{...e.instance.target,status:"unknown"},runtime:e.instance.runtime}}async restart(e,t){gr(e);const n=e.instance.runtime.containerName||mr(e.instance.id),i=await this.inspectContainerId(n);if(!i)throw ar("INSTANCE_RUNTIME_RESTART_FAILED",`Docker container ${n} does not exist.`);lr(n,i,t,"before restart","INSTANCE_RUNTIME_RESTART_FAILED"),await this.runCommand("docker",["restart",n]);const r=await this.inspectContainerId(n);if(!r||r!==i)throw ar("INSTANCE_RUNTIME_RESTART_FAILED",`Docker container identity changed while restarting ${n}.`);return lr(n,r,t,"after restart","INSTANCE_RUNTIME_RESTART_FAILED"),this.runningResult(e,n,r)}async delete(e,t){const n=e.instance.runtime.containerName||mr(e.instance.id),i=await this.inspectContainerForStart(n),r=new Set;if(i){lr(n,i.id,e.instance.runtime.containerId,"before delete","RUNTIME_EXECUTOR_FAILED");const t=i.labels["task-handoff.instance-id"];if(t!==e.instance.id)throw ar("RUNTIME_EXECUTOR_FAILED",`Docker container ${n} belongs to ${t||"an unknown instance"}, not ${e.instance.id}.`);for(const t of Yi(e))i.mounts.some(e=>"volume"===e.type&&e.name===t.name&&e.destination===t.mountPath)&&r.add(t.name);try{await this.runCommand("docker",["rm","-f",i.id])}catch(e){if(!dr(e))throw ar("RUNTIME_EXECUTOR_FAILED",`Could not delete Docker container ${n}.`,e)}}const o=[];for(const n of Yi(e))if(t.deleteVolumes)try{const t=await this.inspectVolumeForDelete(n.name);if(!t){o.push({role:n.role,name:n.name,mountPath:n.mountPath,status:"missing"});continue}const i=t.name===n.name&&"task-handoff"===t.labels["task-handoff.owner"]&&t.labels["task-handoff.instance-id"]===e.instance.id&&t.labels["task-handoff.volume-role"]===n.role,s=r.has(n.name)&&t.name===n.name&&0===Object.keys(t.labels).length;if(!i&&!s)throw Object.assign(new Error(`Managed volume ${n.name} ownership does not match instance ${e.instance.id}.`),{code:"INSTANCE_VOLUME_IDENTITY_MISMATCH"});await this.runCommand("docker",["volume","rm",n.name]),o.push({role:n.role,name:n.name,mountPath:n.mountPath,status:"deleted"})}catch(e){o.push({role:n.role,name:n.name,mountPath:n.mountPath,status:"failed",error:{code:"object"==typeof e&&e&&"code"in e&&"string"==typeof e.code?e.code:"INSTANCE_VOLUME_DELETE_FAILED",message:e instanceof Error?e.message:String(e)}})}else o.push({role:n.role,name:n.name,mountPath:n.mountPath,status:"retained"});return await this.deleteRuntimeVolume(e),Kt.parse({instanceId:e.instance.id,containerDeleted:!0,completed:o.every(e=>"failed"!==e.status),deletedVolumes:o.filter(e=>"deleted"===e.status||"missing"===e.status),retainedVolumes:o.filter(e=>"retained"===e.status),volumeResults:o})}async deleteRuntimeVolume(e){const t=Wi(e.instance.id,e.node?.id||"node_unset"),n=await this.inspectVolumeForDelete(t.name);if(n){if(n.name!==t.name||"task-handoff"!==n.labels["task-handoff.owner"]||n.labels["task-handoff.instance-id"]!==e.instance.id||"runtime"!==n.labels["task-handoff.volume-role"])throw ar("INSTANCE_VOLUME_IDENTITY_MISMATCH",`Runtime volume ${t.name} ownership does not match instance ${e.instance.id}.`);try{await this.runCommand("docker",["volume","rm",t.name])}catch(e){throw ar("INSTANCE_VOLUME_DELETE_FAILED",`Could not delete runtime volume ${t.name}.`,e)}}}async inspectVolumeForDelete(e){try{const t=await this.runCommand("docker",["volume","inspect","--format","{{json .}}",e]),n=JSON.parse(t.stdout||"{}");return{name:"string"==typeof n.Name?n.Name:"",labels:n.Labels&&"object"==typeof n.Labels&&!Array.isArray(n.Labels)?Object.fromEntries(Object.entries(n.Labels).filter(e=>"string"==typeof e[1])):{}}}catch(t){if(function(e){const t=cr(e)?.toLowerCase()||"";return t.includes("no such volume")||t.includes("no such object")}(t))return;throw ar("INSTANCE_VOLUME_INSPECT_FAILED",`Could not inspect managed volume ${e}.`,t)}}async installRuntime(e){const t=await this.installRuntimeRelease(e);lr(e.containerName,t,e.expectedContainerId,"before runtime restart","INSTANCE_RUNTIME_RESTART_FAILED");try{await this.runCommand("docker",["restart",t])}catch(t){throw ar("INSTANCE_RUNTIME_RESTART_FAILED",`Could not restart Docker container ${e.containerName}.`,t)}const n=await this.inspectContainerId(e.containerName);if(!n||n!==t)throw ar("INSTANCE_RUNTIME_RESTART_FAILED",`Docker container identity changed while updating ${e.containerName}.`);return lr(e.containerName,n,e.expectedContainerId,"after runtime restart","INSTANCE_RUNTIME_RESTART_FAILED"),this.inspectRuntimeVersion(e.containerName)}async installRuntimeRelease(e){const t=await this.inspectContainerId(e.containerName);if(!t)throw ar("INSTANCE_RUNTIME_INSTALL_FAILED",`Docker container ${e.containerName} does not exist.`);lr(e.containerName,t,e.expectedContainerId,"before runtime install","INSTANCE_RUNTIME_INSTALL_FAILED");const n=`/opt/task-handoff/instance-runtime/incoming/task-handoff-runtime-${i=e.identity.version,i.replace(/[^0-9A-Za-z.+_-]/g,"-")}-${e.identity.sha256.slice(0,12)}.tar.gz`;var i;await this.runCommand("docker",["exec","--user","0",t,"install","-d","-o","root","-g","root","-m","0755","/opt/task-handoff/instance-runtime/incoming"]),await this.runCommand("docker",["cp",e.artifactPath,`${t}:${n}`]);try{await this.runCommand("docker",["exec","--user","0",t,"node",Ji,"install","--artifact",n,"--version",e.identity.version,"--sha256",e.identity.sha256,"--platform",e.identity.platform,"--arch",e.identity.arch,"--launcher-abi",String(e.identity.launcherAbi)])}catch(t){throw ar("INSTANCE_RUNTIME_INSTALL_FAILED",`Could not install controlled-instance ${e.identity.version} in ${e.containerName}.`,t)}finally{await this.runCommand("docker",["exec","--user","0",t,"rm","-f",n]).catch(()=>({stdout:"",stderr:""}))}const r=await this.inspectContainerId(e.containerName);if(!r||r!==t)throw ar("INSTANCE_RUNTIME_INSTALL_FAILED",`Docker container identity changed while installing ${e.containerName}.`);return lr(e.containerName,r,e.expectedContainerId,"after runtime install","INSTANCE_RUNTIME_INSTALL_FAILED"),t}async inspectRuntimeVersion(e){const t=await this.inspectContainerId(e);if(!t)return{};const n=await this.runCommand("docker",["exec","--user","agent",e,"node",Ji,"verify-active"]).catch(()=>{});if(!n?.stdout)return{containerId:t};try{const e=Mi(yn,JSON.parse(n.stdout));return e.success?{containerId:t,...e.data}:{containerId:t}}catch{return{containerId:t}}}async removeBootstrapBackup(e,t){const n=await this.inspectContainerForStart(e);if(n){if(n.labels["task-handoff.instance-id"]!==t)throw ar("RUNTIME_EXECUTOR_FAILED",`Docker bootstrap backup ${e} does not belong to ${t}.`);await this.runCommand("docker",["rm","-f",e])}}async inspectRuntimeTarget(e){let t,n;if(e){const i=await this.runCommand("docker",["inspect","--format","{{json .}}",e]).then(e=>JSON.parse(e.stdout.trim()||"{}")).catch(()=>{});if(t=i?.Platform,"string"==typeof i?.Image&&i.Image){const e=await this.runCommand("docker",["image","inspect","--format","{{json .}}",i.Image]).then(e=>JSON.parse(e.stdout.trim()||"{}")).catch(()=>{});t=e?.Os||t,n=e?.Architecture}}if(!t||!n){const e=await this.runCommand("docker",["info","--format","{{json .}}"]).then(e=>JSON.parse(e.stdout.trim()||"{}")).catch(e=>{throw ar("INSTANCE_BASE_RUNTIME_INCOMPATIBLE","Could not inspect the Docker runtime target.",e)});t||=e.OSType,n||=e.Architecture}const i=ir(t),r=rr(n);if(!i||!r)throw ar("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Docker reported an unsupported runtime target ${String(t||"unknown")}/${String(n||"unknown")}.`);return{platform:i,arch:r,launcherAbi:1}}async ensureRuntimeInstallTargetRunning(e,t){const n=await this.inspectContainerForStart(e);if(!n)throw ar("INSTANCE_RUNTIME_INSTALL_FAILED",`Docker container ${e} does not exist.`);if(lr(e,n.id,t,"before runtime install recovery","INSTANCE_RUNTIME_INSTALL_FAILED"),n.running)return n.id;try{await this.runCommand("docker",["start",n.id])}catch(t){throw ar("INSTANCE_RUNTIME_INSTALL_FAILED",`Could not restore stopped Docker container ${e} before runtime installation.`,t)}const i=await this.inspectContainerForStart(e);if(!i)throw ar("INSTANCE_RUNTIME_INSTALL_FAILED",`Docker container ${e} disappeared during runtime install recovery.`);if(lr(e,i.id,t||n.id,"after runtime install recovery","INSTANCE_RUNTIME_INSTALL_FAILED"),!i.running)throw ar("INSTANCE_RUNTIME_INSTALL_FAILED",`Docker container ${e} stopped again during runtime install recovery.`);return i.id}async installRuntimeLauncher(e,t){const n=await this.inspectContainerId(e);if(!n)throw ar("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Docker container ${e} does not exist.`);lr(e,n,t,"before runtime launcher install","INSTANCE_BASE_RUNTIME_INCOMPATIBLE");try{await this.runCommand("docker",["exec","--user","0",n,"bash","-ceu",`test -r ${Ki}; test -r ${Bi}/instance-launcher.sh; test -r ${Ji}; install -d -o root -g root -m 0755 /opt/task-handoff/instance-runtime /opt/task-handoff/instance-runtime/releases /opt/task-handoff/instance-runtime/staging /opt/task-handoff/instance-runtime/incoming; chown -R root:root /opt/task-handoff/instance-runtime; chmod -R go-w /opt/task-handoff/instance-runtime`])}catch(t){throw ar("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Could not install the runtime launcher in ${e}.`,t)}const i=await this.inspectContainerId(e);if(i!==n)throw ar("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Docker container identity changed while installing the runtime launcher in ${e}.`);lr(e,i,t,"after runtime launcher install","INSTANCE_BASE_RUNTIME_INCOMPATIBLE")}async inspectContainerId(e){try{return(await this.runCommand("docker",["inspect","--format","{{.Id}}",e])).stdout.trim()||void 0}catch(t){if(dr(t))return;throw ar("RUNTIME_EXECUTOR_FAILED",`Could not inspect Docker container ${e}.`,t)}}async inspectContainerForStart(e){let t;try{t=await this.runCommand("docker",["inspect","--format","{{json .}}",e])}catch(t){if(dr(t))return;throw ar("RUNTIME_EXECUTOR_FAILED",`Could not inspect Docker container ${e}.`,t)}try{const e=JSON.parse(t.stdout||"{}");if("string"!=typeof e.Id||!e.Id)throw new Error("Docker inspect did not return a container id.");const n=e.Config?.Labels&&"object"==typeof e.Config.Labels&&!Array.isArray(e.Config.Labels)?Object.fromEntries(Object.entries(e.Config.Labels).filter(e=>"string"==typeof e[1])):{},i=Array.isArray(e.Mounts)?e.Mounts.flatMap(e=>{if(!e||"object"!=typeof e||Array.isArray(e))return[];const t=e,n="volume"===t.Type||"bind"===t.Type?t.Type:void 0,i="string"==typeof t.Destination?t.Destination:void 0;return n&&i?[{type:n,destination:i,name:"string"==typeof t.Name?t.Name:void 0,source:"string"==typeof t.Source?t.Source:void 0}]:[]}):[],r=Array.isArray(e.Config?.Entrypoint)?e.Config.Entrypoint.filter(e=>"string"==typeof e):"string"==typeof e.Config?.Entrypoint?[e.Config.Entrypoint]:[],o=Array.isArray(e.Config?.Cmd)?e.Config.Cmd.filter(e=>"string"==typeof e):"string"==typeof e.Config?.Cmd?[e.Config.Cmd]:[];return{id:e.Id,image:"string"==typeof e.Image?e.Image:void 0,running:!0===e.State?.Running,entrypoint:r,command:o,labels:n,mounts:i}}catch(t){throw ar("RUNTIME_EXECUTOR_FAILED",`Docker returned invalid inspection data for ${e}.`,t)}}async containerPort(e,t){let n,i=!1;for(const r of this.portResolutionRetryDelaysMs){r>0&&await nr(r);try{const n=er((await this.runCommand("docker",["port",e,t])).stdout);if(n)return n}catch(e){n=e}try{const n=tr((await this.runCommand("docker",["inspect","--format","{{json .NetworkSettings.Ports}}",e])).stdout,t);if(i=!0,n)return n}catch(e){n=e}}if(i)throw ar("RUNTIME_EXECUTOR_FAILED",`Docker container ${e} does not publish ${t}.`);throw ar("RUNTIME_EXECUTOR_FAILED",`Could not resolve the published port for Docker container ${e}.`,n)}}function er(e){const t=e.split(/\r?\n/).find(Boolean);return t?.match(/:(\d+)$/)?.[1]}function tr(e,t){const n=JSON.parse(e||"null");if(!n||"object"!=typeof n||Array.isArray(n))return;const i=n[t];if(Array.isArray(i))for(const e of i){if(!e||"object"!=typeof e||Array.isArray(e))continue;const t=e.HostPort;if("string"==typeof t&&/^\d+$/.test(t))return t}}function nr(e){return new Promise(t=>setTimeout(t,e))}function ir(e){return"linux"===e||"darwin"===e?e:"windows"===e||"win32"===e?"win32":void 0}function rr(e){return"amd64"===e||"x86_64"===e||"x64"===e?"x64":"arm64"===e||"aarch64"===e?"arm64":void 0}function or(){const e=("undefined"==typeof document?require("url").pathToFileURL(__filename).href:b&&"SCRIPT"===b.tagName.toUpperCase()&&b.src||new URL("cli.js",document.baseURI).href)?n.dirname(r.fileURLToPath("undefined"==typeof document?require("url").pathToFileURL(__filename).href:b&&"SCRIPT"===b.tagName.toUpperCase()&&b.src||new URL("cli.js",document.baseURI).href)):__dirname,i=[n.resolve(e,"../../../../../docker"),n.resolve(e,"../docker"),n.resolve(e,"../../docker")];return i.find(e=>t.existsSync(n.join(e,"runtime-installer.mjs")))||i[0]}function sr(e){return`task-handoff/environment-image:${e.replace(/^sha256:/,"")}`}function ar(e,t,n){const i=cr(n),r=new Error(i?`${t} Cause: ${i}`:t,void 0===n?void 0:{cause:n});return Object.assign(r,{statusCode:502,code:e}),r}function cr(e){if(!e||"object"!=typeof e)return void 0===e?void 0:String(e);const t=e,n=t.details?.stderr||t.details?.stdout;return"string"==typeof n&&n.trim()?n.trim():"string"==typeof t.message&&t.message.trim()?t.message.trim():void 0}function dr(e){const t=cr(e)?.toLowerCase()||"";return t.includes("no such container")||t.includes("no such object")}function lr(e,t,n,i,r){if(n&&t!==n)throw ar(r,`Docker container ${e} identity mismatch ${i}: expected ${n}, got ${t}.`)}async function ur(e=Ui){return async function(e=Ui){return(await e("docker",["images","--digests","--format","{{json .}}"])).stdout.split(/\r?\n/).map(e=>e.trim()).filter(Boolean).map(e=>{const t=JSON.parse(e),n=t.Repository||"<none>",i=t.Tag||"<none>",r=t.ID||t.IDShort||"",o="<none>"!==n&&"<none>"!==i?`${n}:${i}`:r,s="<none>"!==n&&t.Digest&&"<none>"!==t.Digest?[`${n}@${t.Digest}`]:[];return{repository:n,tag:i,id:r,createdSince:t.CreatedSince,size:t.Size,sizeBytes:Hi(t.Size),reference:o,repoDigests:s}}).filter(e=>Boolean(e.reference))}(e)}function mr(e){return`task-handoff-${e.replace(/[^a-zA-Z0-9_.-]/g,"-")}`}function pr(e,t,n){e.push("-e",`${t}=${n}`)}function hr(e,t,i={}){const r=i.publishHost||"127.0.0.1",o=n.resolve(i.launcherAssetsDir||or()),s=e.node?.id||"node_unset",a=e.runtime?.id||"runtime_local_docker",c=["run","-d","--name",t,"--user","0:0","--label",`task-handoff.instance-id=${e.instance.id}`,"--label",`task-handoff.project-id=${e.project.id}`,"--label",`task-handoff.node-id=${s}`,"--label",`task-handoff.runtime-id=${a}`,"--label",`task-handoff.image-id=${e.image.id}`,"--label","task-handoff.bootstrap-abi=1","--shm-size","1gb","--security-opt","seccomp=unconfined","--network","bridge","--no-healthcheck","--add-host","host.docker.internal:host-gateway","--tmpfs","/tmp:rw,mode=1777","-p",`${r}::8080`];if(!e.privateConfigPath)throw Object.assign(new Error(`Instance ${e.instance.id} private config was not materialized.`),{statusCode:409,code:"INSTANCE_PRIVATE_CONFIG_MISSING"});c.push("--mount",`type=bind,src=${e.privateConfigPath},dst=/run/task-handoff/instance-private-config.json,readonly`,"--mount",`type=bind,src=${o},dst=${Bi},readonly`,"--entrypoint",Gi);for(const t of Yi(e))c.push("--mount",`type=volume,src=${t.name},dst=${t.mountPath}`);const d=Wi(e.instance.id,e.node?.id||"node_unset");c.push("--mount",`type=volume,src=${d.name},dst=${d.mountPath}`);const l={TASK_HANDOFF_CONTROL_MODE:"controlled",TASK_HANDOFF_NODE_AGENT_URL:e.nodeAgentUrl||e.node?.endpoint||"",TASK_HANDOFF_INSTANCE_ID:e.instance.id,TASK_HANDOFF_INSTANCE_NAME:e.instance.name,TASK_HANDOFF_PROJECT_ID:e.project.id,TASK_HANDOFF_NODE_ID:s,TASK_HANDOFF_RUNTIME_ID:a,TASK_HANDOFF_IMAGE_ID:e.image.id,TASK_HANDOFF_INSTANCE_LAUNCHER:`${Bi}/instance-launcher.sh`,...e.image.tag?{TASK_HANDOFF_IMAGE_TAG:e.image.tag}:{},TASK_HANDOFF_CHAT_BRIDGES:"none",TASK_HANDOFF_WORKSPACE:e.project.workspacePolicy.path||"/workspace",TASK_HANDOFF_WORKSPACE_MODE:e.project.workspacePolicy.mode};for(const[e,t]of Object.entries(l))pr(c,e,t);"local-folder"===e.project.source.type?c.push("-v",`${e.project.source.path}:${e.project.workspacePolicy.path||"/workspace"}:${e.project.workspacePolicy.readOnly?"ro":"rw"}`):(pr(c,"TASK_HANDOFF_PROJECT_SOURCE",JSON.stringify(e.project.source)),pr(c,"TASK_HANDOFF_WORKSPACE_POLICY",JSON.stringify(e.project.workspacePolicy)),pr(c,"TASK_HANDOFF_GIT_URL",e.project.source.url),e.project.source.ref?.commit?pr(c,"TASK_HANDOFF_GIT_COMMIT",e.project.source.ref.commit):e.project.source.ref?.name&&pr(c,"TASK_HANDOFF_GIT_REF",e.project.source.ref.name),e.project.source.clone?.depth&&pr(c,"TASK_HANDOFF_GIT_DEPTH",String(e.project.source.clone.depth)),pr(c,"TASK_HANDOFF_GIT_SUBMODULES",e.project.source.clone?.submodules?"true":"false"),pr(c,"TASK_HANDOFF_GIT_LFS",e.project.source.clone?.lfs?"true":"false"),e.project.source.clone?.subdirectory&&pr(c,"TASK_HANDOFF_WORKSPACE_SUBDIRECTORY",e.project.source.clone.subdirectory));for(const[t,n]of Object.entries(e.image.defaultEnv))pr(c,t,n);return c.push(i.imageReference||e.instance.environmentTemplateOrigin?.imageId||e.image.resolvedReference||e.image.requestedReference,Ki,"task-handoff","web"),c}function gr(e){if("local-folder"===e.project.source.type&&e.project.source.ownerNodeId&&e.project.source.ownerNodeId!==e.node.id){const e=new Error("Local folder projects can only start on the node that owns the folder.");throw Object.assign(e,{statusCode:400,code:"LOCAL_FOLDER_REQUIRES_OWNER_NODE"}),e}if(!e.image.requestedReference?.trim()){const e=new Error("Image profile must reference a registered image.");throw Object.assign(e,{statusCode:400,code:"IMAGE_PROFILE_INVALID"}),e}}a.z.object({type:a.z.literal("snapshot"),data:a.z.string(),pendingEscape:a.z.string(),cols:a.z.number().int().positive(),rows:a.z.number().int().positive()}).passthrough();const fr=a.z.enum(["created","starting","running","stopping","stopped","exited","failed","closed","terminated","unknown"]),yr=a.z.enum(["tty","vnc","web"]);a.z.object({mode:yr,url:a.z.string().trim().min(1).max(4096),token:a.z.string().trim().min(1).max(512),expiresAt:a.z.string().datetime()}).strict(),a.z.object({revoked:a.z.boolean()}).strict();const Ir=a.z.object({type:a.z.enum(["app-session","provider-session","adapter-key"]),id:a.z.string().trim().min(1).max(240),agent:a.z.string().trim().min(1).max(80).optional(),adapter:a.z.string().trim().min(1).max(80).optional(),key:a.z.string().trim().min(1).max(240).optional()}).strict(),Ar=a.z.record(a.z.string(),a.z.unknown()).and(a.z.object({id:a.z.string().trim().min(1).max(160),appId:a.z.string().trim().min(1).max(160).optional(),title:a.z.string().trim().max(240).optional(),kind:a.z.string().trim().max(80).optional(),status:fr.default("unknown"),bindings:a.z.array(Ir).max(40).default([]),workspace:a.z.object({cwd:a.z.string().trim().max(4096).optional()}).strict().optional(),createdAt:a.z.string().datetime().optional(),updatedAt:a.z.string().datetime().optional()})),br=a.z.object({runningCount:a.z.number().int().min(0).default(0),problemCount:a.z.number().int().min(0).default(0),sessions:a.z.array(Ar).default([]),updatedAt:a.z.string().datetime()}).strict();a.z.object({streamId:a.z.string().trim().min(1).max(240),revision:a.z.number().int().min(0),lastEventAt:a.z.string().datetime(),snapshot:br}).strict(),br.pick({runningCount:!0,problemCount:!0,updatedAt:!0}).extend({revision:a.z.number().int().min(0).optional()});const wr=a.z.enum(["app-session-created","app-session-updated","app-session-deleted","app-session-recovered","control-action","heartbeat-sync","startup"]),vr=a.z.object({streamId:a.z.string().trim().min(1).max(240),instanceId:a.z.string().trim().min(1).max(160),nodeId:a.z.string().trim().min(1).max(160).optional(),revision:a.z.number().int().min(0),previousRevision:a.z.number().int().min(0).optional(),traceId:a.z.string().trim().min(1).max(160),generatedAt:a.z.string().datetime(),reason:wr}).strict(),Er=a.z.object({meta:vr,snapshot:br}).strict(),Nr=a.z.object({meta:vr,session:Ar}).strict(),Sr=a.z.object({meta:vr,sessionId:a.z.string().trim().min(1).max(160),tombstone:Ar.optional(),expiresAt:a.z.string().datetime().optional()}).strict();function Tr(e){return e.startsWith("ai-session.")||e.startsWith("ai.session.")?"ai.sessions":e.startsWith("app-session.")?"app.sessions":e.startsWith("app.management")?"apps":e.startsWith("trigger.")?"triggers":e.startsWith("instance.")?"instances":e.startsWith("node.")?"nodes":e.startsWith("project.")?"projects":e.startsWith("model.")?"models":e.startsWith("image.")?"images":e.startsWith("market.")?"market":"system"}a.z.object({streamId:a.z.string().trim().min(1).max(240),instanceId:a.z.string().trim().min(1).max(160),sinceRevision:a.z.number().int().min(0),latestRevision:a.z.number().int().min(0),earliestRetainedRevision:a.z.number().int().min(0),syncRequired:a.z.boolean().default(!1),events:a.z.array(a.z.discriminatedUnion("type",[a.z.object({type:a.z.literal("app-session.snapshot"),payload:Er}).strict(),a.z.object({type:a.z.literal("app-session.patch"),payload:Nr}).strict(),a.z.object({type:a.z.literal("app-session.removed"),payload:Sr}).strict()])).default([])}).strict();const zr=a.z.enum(["ai.sessions","app.sessions"]),_r=a.z.object({topic:zr,instanceId:a.z.string().trim().min(1).max(160),streamId:a.z.string().trim().min(1).max(240),latestRevision:a.z.number().int().min(0),earliestRetainedRevision:a.z.number().int().min(0)}).strict(),Cr=a.z.object({protocolVersion:a.z.literal(1),streams:a.z.array(_r)}).strict();class kr{attempt=0;timer;get pending(){return Boolean(this.timer)}get attempts(){return this.attempt}schedule(e,t={}){if(this.timer)return;const n=function(e,t=Math.random){const n=Math.min(3e4,1e3*2**Math.max(0,e));return Math.min(3e4,Math.round(n*(.75+.5*t())))}(this.attempt,t.random);this.attempt+=1;const i=t.setTimeoutFn||setTimeout;return this.timer=i(()=>{this.timer=void 0,e()},n),{attempt:this.attempt,delay:n}}reset(e=clearTimeout){this.timer&&e(this.timer),this.timer=void 0,this.attempt=0}cancel(e=clearTimeout){this.timer&&e(this.timer),this.timer=void 0}}function Or(e,t=6e4){const n=[];for(let i=0;i<e.length;i+=t)n.push(e.slice(i,i+t));return n}class Rr{sockets=new Map;socketUrls=new Map;retries=new Map;outputs=new Set;imagePullTerminalByInstance=new Map;state;token;logger;safetyIntervalMs;lastAiSessionEventByInstance=new Map;lastAppSessionEventByInstance=new Map;timer;reconnectAttempts=0;safetyReconciliations=0;localSequence=0;createSocket;setIntervalFn;clearIntervalFn;constructor(e,t,n={}){var i;this.state=e,this.token=t,this.logger=n.logger,this.safetyIntervalMs=(i=n.safetyIntervalMs,Math.min(6e4,Math.max(3e4,i??45e3))),this.createSocket=n.createSocket||((e,t)=>new m(e,t)),this.setIntervalFn=n.setIntervalFn||setInterval,this.clearIntervalFn=n.clearIntervalFn||clearInterval}start(){this.sync(),this.timer=this.setIntervalFn(()=>{this.safetyReconciliations+=1,this.sync()},this.safetyIntervalMs)}stop(){this.timer&&(this.clearIntervalFn(this.timer),this.timer=void 0);for(const e of this.sockets.values())e.close();this.sockets.clear(),this.socketUrls.clear();for(const e of this.retries.values())e.timer.cancel();this.retries.clear(),this.outputs.clear()}addOutput(e){this.outputs.add(e),e.on("close",()=>this.outputs.delete(e)),e.on("error",()=>this.outputs.delete(e));for(const t of this.state.listInstances()){const n=xr(t);n?this.sendForwarded(e,this.createEvent(Ti,n,{instanceId:t.id})):this.logger?.warn?.({instanceId:t.id},"instance.lifecycle.snapshot.invalid")}for(const[t,n]of this.imagePullTerminalByInstance)Or(n.tail).forEach((i,r)=>this.sendForwarded(e,this.createEvent(si,{...n.output,sequence:n.output.sequence+r,data:i,...0===r?{replay:!0}:{}},{instanceId:t}))),n.finished&&this.sendForwarded(e,this.createEvent(ai,n.finished,{instanceId:t}));return this.syncNow(),()=>{this.outputs.delete(e)}}publish(e,t,n={}){this.rememberImagePullTerminal(e,t);const i=this.createEvent(e,t,n);for(const e of this.outputs)this.sendForwarded(e,i)}rememberImagePullTerminal(e,t){if(e===si){const e=Mi(di,t);if(!e.success)return;const n=e.data,i=this.imagePullTerminalByInstance.get(n.instanceId);if(i&&n.generation<i.output.generation)return;const r=i?.output.generation===n.generation,o=n.replay||!r?n.data:`${i.tail}${n.data}`.slice(-262144);return void this.imagePullTerminalByInstance.set(n.instanceId,{output:n,tail:o})}if(e===ai){const e=Mi(li,t);if(!e.success)return;const n=e.data,i=this.imagePullTerminalByInstance.get(n.instanceId);i?.output.generation===n.generation&&(i.finished=n)}}publishInstanceLifecycle(e){this.publish(Ti,function(e){return zi.parse(Dr(e))}(e),{instanceId:e.id});const t=this.imagePullTerminalByInstance.get(e.id);"ready"===e.imageProvisioning?.phase&&"succeeded"===t?.finished?.outcome&&this.imagePullTerminalByInstance.delete(e.id)}createEvent(e,t,n){const i=++this.localSequence;return{v:1,id:`node_evt_${Date.now().toString(36)}_${i.toString(36)}`,seq:i,type:e,topic:Tr(e),createdAt:(new Date).toISOString(),payload:t,scope:n}}sendForwarded(e,t){const n=JSON.stringify({type:"node-agent.event.forwarded",event:t});e.readyState===m.OPEN&&e.send(n)}syncNow(){this.sync()}diagnostics(){return{reconnectAttempts:this.reconnectAttempts,safetyReconciliations:this.safetyReconciliations,activeConnections:this.sockets.size,pendingRetries:[...this.retries.values()].filter(e=>e.timer.pending).length,safetyIntervalMs:this.safetyIntervalMs}}sync(){const e=new Set(this.state.listInstances().map(e=>e.id));for(const t of this.imagePullTerminalByInstance.keys())e.has(t)||this.imagePullTerminalByInstance.delete(t);if(!this.outputs.size){for(const e of this.sockets.values())e.close();this.sockets.clear(),this.socketUrls.clear();for(const e of this.retries.values())e.timer.cancel();return void this.retries.clear()}const t=new Set;for(const e of this.state.listInstances()){const n=Mr(e);if(!n)continue;t.add(e.id);const i=this.retries.get(e.id);i?.timer.pending&&i.url!==n&&(i.timer.cancel(),this.retries.delete(e.id)),this.socketUrls.get(e.id)!==n&&this.sockets.has(e.id)&&(this.sockets.get(e.id)?.close(),this.sockets.delete(e.id)),this.sockets.has(e.id)||this.retries.get(e.id)?.timer.pending||this.connect(e.id,n)}for(const[e,n]of this.sockets)if(!t.has(e)){n.close(),this.sockets.delete(e),this.socketUrls.delete(e);const t=this.retries.get(e);t?.timer.cancel(),this.retries.delete(e)}for(const[e,n]of this.retries)t.has(e)||(n.timer.cancel(),this.retries.delete(e),this.socketUrls.delete(e))}connect(e,t){const n=this.token?{authorization:`Bearer ${this.token}`}:void 0,i=this.createSocket(t,{headers:n});this.sockets.set(e,i),this.socketUrls.set(e,t),i.on("open",()=>{const n=this.retries.get(e);n?.timer.reset(),this.retries.set(e,{timer:n?.timer||new kr,url:t}),i.readyState===m.OPEN&&(i.send(JSON.stringify({v:1,type:"subscribe",topics:[J,"app.sessions","apps","instances"]})),this.logger?.info?.({instanceId:e,url:t},"ai-session.event.forward.connect"),this.logger?.info?.({instanceId:e,url:t},"app-session.event.forward.connect"))}),i.on("message",t=>{const n=function(e,t){try{const n=JSON.parse(String(e));if(!n||"object"!=typeof n||Array.isArray(n))return;const i=n,r="string"==typeof i.type?i.type:"";if(!r||"events.connected"===r)return;const o=i.scope&&"object"==typeof i.scope&&!Array.isArray(i.scope)?i.scope:{};return{v:1,id:"string"==typeof i.id?i.id:`evt_${Date.now().toString(36)}`,seq:Number(i.seq)||0,type:r,topic:"string"==typeof i.topic?i.topic:Tr(r),createdAt:"string"==typeof i.createdAt?i.createdAt:(new Date).toISOString(),payload:"payload"in i?i.payload:{},scope:{...o,instanceId:t}}}catch{return}}(t,e);if(!n)return;if("streams.hello"===n.type){const t=Mi(Cr,n.payload);if(!t.success)return this.logger?.warn?.({instanceId:e,issues:t.error.issues},"session-stream.handshake.invalid"),void i.close(1002,"Incompatible session stream handshake.");const r=JSON.stringify({type:"node-agent.streams.hello",instanceId:e,payload:t.data});for(const e of this.outputs)e.readyState===m.OPEN&&e.send(r);return}this.recordAiSessionEvent(e,n),this.recordAppSessionEvent(e,n);const r=JSON.stringify({type:"node-agent.event.forwarded",event:n});for(const e of this.outputs)e.readyState===m.OPEN&&e.send(r)}),i.on("close",()=>{this.sockets.get(e)===i&&(this.sockets.delete(e),this.socketUrls.delete(e),this.scheduleReconnect(e))}),i.on("error",()=>{this.logger?.warn?.({instanceId:e,url:t},"ai-session.event.forward.error"),this.logger?.warn?.({instanceId:e,url:t},"app-session.event.forward.error"),i.close()})}scheduleReconnect(e){const t=this.state.listInstances().find(t=>t.id===e),n=t&&Mr(t);if(!n||!this.outputs.size)return;const i=this.retries.get(e)??{timer:new kr};if(i.timer.pending)return;i.url=n;const r=i.timer.schedule(()=>{this.sockets.has(e)||this.connect(e,n)});r&&(this.reconnectAttempts+=1,this.logger?.info?.({instanceId:e,url:n,attempt:r.attempt,delay:r.delay,reconnectAttempts:this.reconnectAttempts},"session-stream.connection.reconnect-scheduled")),this.retries.set(e,i)}recordAiSessionEvent(e,t){if(t.topic!==J)return;if("ai-session.message-delta"===t.type)return;const n=Pr(t.payload),i=this.lastAiSessionEventByInstance.get(e);i?.streamId===n.streamId&&void 0!==i.revision&&void 0!==n.revision&&n.revision>i.revision+1&&this.logger?.warn?.({instanceId:e,traceId:n.traceId,streamId:n.streamId,previousRevision:i.revision,revision:n.revision},"ai-session.event.forward.gap"),this.lastAiSessionEventByInstance.set(e,{streamId:n.streamId??i?.streamId,revision:n.revision??i?.revision}),this.logger?.info?.({instanceId:e,traceId:n.traceId,eventType:t.type,streamId:n.streamId,revision:n.revision},"ai-session.event.forward.message")}recordAppSessionEvent(e,t){if("app.sessions"!==t.topic)return;const n=Pr(t.payload),i=this.lastAppSessionEventByInstance.get(e);i?.streamId===n.streamId&&void 0!==i.revision&&void 0!==n.revision&&n.revision>i.revision+1&&this.logger?.warn?.({instanceId:e,traceId:n.traceId,streamId:n.streamId,previousRevision:i.revision,revision:n.revision},"app-session.event.forward.gap"),this.lastAppSessionEventByInstance.set(e,{streamId:n.streamId??i?.streamId,revision:n.revision??i?.revision}),this.logger?.info?.({instanceId:e,traceId:n.traceId,eventType:t.type,streamId:n.streamId,revision:n.revision},"app-session.event.forward.message")}}function xr(e){const t=zi.safeParse(Dr(e));return t.success?t.data:void 0}function Dr(e){return{instanceId:e.id,revision:e.stateRevision,updatedAt:e.updatedAt,status:e.status,health:e.health,connectionStatus:e.connectionStatus,accessStatus:"online"===e.connectionStatus||"online"===e.agentStatus?"reachable":"endpoint-unreachable",imageProvisioning:e.imageProvisioning,workspace:e.workspace,runtime:e.runtime,runtimeVersion:e.runtimeVersion,ready:e.ready,lastHeartbeatAt:e.lastHeartbeatAt}}function Pr(e){const t=e&&"object"==typeof e&&!Array.isArray(e)?e:{},n=t.meta&&"object"==typeof t.meta&&!Array.isArray(t.meta)?t.meta:{};return{streamId:"string"==typeof n.streamId?n.streamId:void 0,revision:"number"==typeof n.revision?n.revision:void 0,traceId:"string"==typeof n.traceId?n.traceId:void 0}}function Mr(e){if(!function(e){return!1!==e.ready&&(!e.runtimeVersion||["matched","failed"].includes(e.runtimeVersion.phase))}(e))return;const t=e.target?.api||e.target?.web;if(t)try{const e=new URL("/api/events",t);return e.protocol="https:"===e.protocol?"wss:":"ws:",e.toString()}catch{return}}const Lr=new Set(["provisioning","starting","registering","registered","running","unhealthy"]),jr=JSON.stringify({id:"{{.ID}}",name:"{{.Name}}",cpu:"{{.CPUPerc}}",memory:"{{.MemUsage}}",memoryPercent:"{{.MemPerc}}",network:"{{.NetIO}}",blockIo:"{{.BlockIO}}",pids:"{{.PIDs}}"});class $r{snapshots=new Map;runCommand;targets;publish;intervalMs;timer;inFlight;pendingTargets=new Map;collectingTargets=new Map;constructor(e,t,n,i=3e3){this.runCommand=e,this.targets=t,this.publish=n,this.intervalMs=i}start(){this.collect().catch(()=>{}),this.timer=setInterval(()=>{this.collect().catch(()=>{})},this.intervalMs)}stop(){this.timer&&clearInterval(this.timer),this.timer=void 0}async snapshot(e){const t=this.targets().find(t=>t.id===e);if(!t)return;if(!Lr.has(t.status))return Br(t.id);const n=this.snapshots.get(e);return n&&Date.now()-Date.parse(n.sampledAt)<=this.intervalMs?n:(await this.collect([t]),this.snapshots.get(e))}async collect(e){const t=e||this.targets();if(!e){const e=new Set(t.map(e=>e.id));for(const t of this.snapshots.keys())e.has(t)||this.snapshots.delete(t)}for(const e of t){const t=Fr(e);this.collectingTargets.get(e.id)!==t&&this.pendingTargets.set(e.id,e)}this.inFlight||(this.inFlight=this.drain().finally(()=>{this.inFlight=void 0})),await this.inFlight}async drain(){for(;this.pendingTargets.size;){const e=[...this.pendingTargets.values()];this.pendingTargets.clear();for(const t of e)this.collectingTargets.set(t.id,Fr(t));try{await this.collectOnce(e)}finally{for(const t of e)this.collectingTargets.delete(t.id)}}}async collectOnce(e){const t=e.filter(e=>Lr.has(e.status)&&(e.runtime.containerId||e.runtime.containerName));for(const t of e.filter(e=>Lr.has(e.status)&&!e.runtime.containerId&&!e.runtime.containerName))this.update(Kr(t.id));for(const t of e.filter(e=>!Lr.has(e.status)))this.update(Br(t.id));if(!t.length)return;const n=t.map(e=>e.runtime.containerId||e.runtime.containerName),i=(new Date).toISOString();try{const e=await this.runCommand("docker",["stats","--no-stream","--format",jr,...n],{timeoutMs:5e3});this.applyDockerOutput(t,e.stdout,i)}catch(e){if(1===t.length)return void this.update(Gr(t[0].id,i,e instanceof Error?e.message:String(e)));await Promise.all(t.map(async e=>{const t=e.runtime.containerId||e.runtime.containerName;try{const n=await this.runCommand("docker",["stats","--no-stream","--format",jr,t],{timeoutMs:5e3});this.applyDockerOutput([e],n.stdout,i)}catch(t){this.update(Gr(e.id,i,t instanceof Error?t.message:String(t)))}}))}}applyDockerOutput(e,t,n){const i=function(e,t=(new Date).toISOString()){const n=new Map;for(const i of e.split(/\r?\n/).filter(Boolean)){let e;try{e=JSON.parse(i)}catch{continue}const r=Hr(e.id),o=Hr(e.name),s=r||o;if(!s)continue;const a=Ur(Hr(e.memory)),c=Ur(Hr(e.network)),d=Ur(Hr(e.blockIo)),l=gi.parse({instanceId:s,runtimeKind:"docker",state:"available",sampledAt:t,cpu:Vr(e.cpu,"usagePercent"),memory:a?{usageBytes:a[0],...void 0!==a[1]?{limitBytes:a[1]}:{},...Vr(e.memoryPercent,"usagePercent")}:void 0,network:c?{rxBytes:c[0],txBytes:c[1]||0}:void 0,blockIo:d?{readBytes:d[0],writeBytes:d[1]||0}:void 0,pids:qr(e.pids)});r&&n.set(r,l),o&&n.set(o,l)}return n}(t,n);for(const t of e){const e=[t.runtime.containerId,t.runtime.containerName].filter(Boolean),r=[...i.entries()].find(([t])=>e.some(e=>e===t||e.startsWith(t)||t.startsWith(e)))?.[1];this.update(r?{...r,instanceId:t.id}:Gr(t.id,n,"Container metrics were not returned by Docker."))}}update(e){const t=gi.parse(e);this.snapshots.set(t.instanceId,t),this.publish?.(t)}}function Fr(e){return[e.status,e.runtime.containerId||"",e.runtime.containerName||""].join("\0")}function Ur(e){if(!e)return;const[t,n]=e.split("/").map(e=>function(e){const t=e.trim().match(/^([0-9]+(?:\.[0-9]+)?)\s*([kmgtpe]?i?b)$/i);if(!t)return;const n=Number(t[1]),i=t[2].toLowerCase(),r=i.includes("i"),o="b"===i[0]?"":i[0],s=o?"kmgtpe".indexOf(o)+1:0;return Math.round(n*(r?1024:1e3)**s)}(e||""));return void 0===t?void 0:[t,n]}function Vr(e,t){const n=Number(Hr(e).replace(/%$/,""));return Number.isFinite(n)&&n>=0?{[t]:n}:void 0}function qr(e){const t=Number(Hr(e));return Number.isFinite(t)&&t>=0?t:void 0}function Hr(e){return"string"==typeof e||"number"==typeof e?String(e).trim():""}function Br(e){return{instanceId:e,runtimeKind:"docker",state:"stopped",sampledAt:(new Date).toISOString()}}function Kr(e){return{instanceId:e,runtimeKind:"docker",state:"pending",sampledAt:(new Date).toISOString()}}function Gr(e,t,n){return{instanceId:e,runtimeKind:"docker",state:"unavailable",sampledAt:t,error:n.slice(0,2048)}}function Jr(e){try{return t.statSync(e).isDirectory()}catch{return!1}}function Wr(e,i){let r;try{r=t.statSync(e)}catch{return}if(!r.isDirectory())return;const o=n.resolve(e),s=n.basename(o)||o;let a=[];try{a=i>0?t.readdirSync(o,{withFileTypes:!0}):[]}catch{a=[]}const c=i>0?a.filter(e=>e.isDirectory()||e.isSymbolicLink()&&Jr(n.join(o,e.name))).sort((e,t)=>e.name.localeCompare(t.name)).slice(0,80).flatMap(e=>{const t=Wr(n.join(o,e.name),i-1);return t?[t]:[]}):[];return{name:s,path:o,children:c}}function Yr(e){return(e.path?[e.path]:function(){if("win32"!==process.platform)return[n.parse(n.resolve(process.cwd())).root];const e=n.parse(n.resolve(process.cwd())).root,t=Array.from({length:26},(e,t)=>`${String.fromCharCode(65+t)}:\\`);return[...new Set([e,...t])].filter(Jr)}()).flatMap(t=>{const n=Wr(t,e.depth);return n?[n]:[]})}function Xr(){return process.env.TASK_HANDOFF_NODE_AGENT_DATA_DIR||n.join(c.homedir(),".config","task-handoff","node-agent")}function Qr(e=Xr()){const t=n.resolve(e);return{dataDir:t,identityPath:n.join(t,"identity.json"),settingsPath:n.join(t,"runtime-settings.json"),localFoldersDir:n.join(t,"local-folders"),nodeRuntimesDir:n.join(t,"node-runtimes"),controlledInstancesDir:n.join(t,"controlled-instances"),environmentTemplatesDir:n.join(t,"environment-templates"),instancePrivateConfigsDir:n.join(t,"instance-private-configs"),nodeModelsDir:n.join(t,"models"),modelAssignmentsDir:n.join(t,"model-assignments"),modelEnvironmentsDir:n.join(t,"model-environments"),updatesDir:n.join(t,"updates"),logsDir:n.join(t,"logs")}}function Zr(e,t){const i=n.extname(e);return`${i?e.slice(0,-i.length):e}.${t}${i}`}function eo(e,n=10485760,i=2){if(!t.existsSync(e))return!1;const r=t.lstatSync(e);if(!r.isFile()||r.isSymbolicLink()||r.size<=n)return!1;if(i>0){!function(e,n){if(!(n<=0)){t.rmSync(Zr(e,n),{force:!0});for(let i=n-1;i>=1;i-=1){const n=Zr(e,i);t.existsSync(n)&&t.renameSync(n,Zr(e,i+1))}}}(e,i);const r=function(e,n){const i=t.statSync(e),r=Math.min(i.size,n),o=Buffer.allocUnsafe(r),s=t.openSync(e,"r");let a=0;try{for(;a<r;){const e=t.readSync(s,o,a,r-a,i.size-r+a);if(0===e)break;a+=e}}finally{t.closeSync(s)}return a===r?o:o.subarray(0,a)}(e,n);t.writeFileSync(Zr(e,1),r,{mode:384})}return t.truncateSync(e,0),t.chmodSync(e,384),!0}class to{localInstancesRoot;localInstancesTrashRoot;options;constructor(e,t={}){this.options=t,this.localInstancesRoot=n.join(e.dataDir,"local-instances"),this.localInstancesTrashRoot=n.join(e.dataDir,"local-instances-trash")}run(e){const n=new Set(e);if(t.existsSync(this.localInstancesRoot)){K(this.localInstancesRoot);for(const e of t.readdirSync(this.localInstancesRoot,{withFileTypes:!0}))e.isDirectory()&&!e.isSymbolicLink()&&(n.has(e.name)?this.capControlledInstanceLogs(e.name):this.retire(e.name))}return function(e){if(!t.existsSync(e.trashRoot))return[];const n=e.nowMs??Date.now(),i=e.retentionMs??H,r=[];for(const o of t.readdirSync(e.trashRoot,{withFileTypes:!0})){const s=B(e.trashRoot,o.name);try{const e=Number(o.name.split("-",1)[0]);if(!Number.isFinite(e)||e+i>n)continue;const a=t.lstatSync(s);a.isSymbolicLink()?t.unlinkSync(s):a.isDirectory()?t.rmSync(s,{recursive:!0,force:!0}):t.unlinkSync(s),r.push(s)}catch(t){e.logger?.("retired persistence entry cleanup failed",{path:s,error:t instanceof Error?t.message:String(t)})}}return r}({trashRoot:this.localInstancesTrashRoot,retentionMs:this.options.retentionMs??H,nowMs:this.now(),logger:this.options.logger})}capActiveInstanceLogs(e){for(const t of e)this.capControlledInstanceLogs(t)}capControlledInstanceLogs(e){const t=n.resolve(this.localInstancesRoot,e);if(n.dirname(t)!==n.resolve(this.localInstancesRoot))return[];const i=n.join(t,"logs"),r=[];for(const t of["controlled-instance.out.log","controlled-instance.err.log"]){const o=n.join(i,t);try{eo(o)&&r.push(o)}catch(t){this.options.logger?.("controlled instance log rotation failed",{instanceId:e,filePath:o,error:t instanceof Error?t.message:String(t)})}}return r}retire(e){try{return function(e){const n=B(e.sourceRoot,e.entryName);if(!t.existsSync(n))return;const i=t.lstatSync(n);if(!i.isDirectory()||i.isSymbolicLink())throw new Error(`Retention source must be a real directory: ${n}`);K(e.trashRoot);const r=e.nowMs??Date.now();let o=0,s=`${r}-${e.entryName}`;for(;t.existsSync(B(e.trashRoot,s));)o+=1,s=`${r}-${o}-${e.entryName}`;const a=B(e.trashRoot,s);return t.renameSync(n,a),a}({sourceRoot:this.localInstancesRoot,entryName:e,trashRoot:this.localInstancesTrashRoot,nowMs:this.now()})}catch(t){return void this.options.logger?.("local instance persistence retirement failed",{instanceId:e,error:t instanceof Error?t.message:String(t)})}}now(){return this.options.now?.()??Date.now()}}function no(e,t=process.platform){const i=n.resolve(e),r=d.createHash("sha256").update(i).digest("hex").slice(0,16);return"win32"===t?`\\\\.\\pipe\\task-handoff-node-agent-${r}`:n.join("/tmp",`task-handoff-node-agent-${process.getuid?.()??"user"}`,`${r}.sock`)}const io="runtime-manifest.json";class ro extends Error{code;retryable;constructor(e,t,n){super(t,void 0===n?.cause?void 0:{cause:n.cause}),this.name="RuntimeArtifactError",this.code=e,this.retryable=n?.retryable??!1}}async function oo(e,t=""){const i=[],r=await g.readdir(n.join(e,t),{withFileTypes:!0});for(const o of r){const r=t?n.posix.join(t,o.name):o.name;if(!t&&r===io)continue;const s=n.join(e,...r.split("/"));if(o.isDirectory()){i.push(...await oo(e,r));continue}if(o.isSymbolicLink()){const t=await g.readlink(s);if(n.isAbsolute(t))throw new ro("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload symlink is absolute: ${r}`);const o=n.resolve(n.dirname(s),t),a=n.relative(n.resolve(e),o);if(!a||".."===a||a.startsWith(`..${n.sep}`)||n.isAbsolute(a))throw new ro("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload symlink escapes the artifact: ${r}`);if(!await g.lstat(o).catch(()=>{}))throw new ro("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload symlink is broken: ${r}`);i.push({absolutePath:s,relativePath:r,kind:"symlink",target:t,size:Buffer.byteLength(t)});continue}if(!o.isFile())throw new ro("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload contains unsupported entry: ${r}`);const a=await g.lstat(s);i.push({absolutePath:s,relativePath:r,kind:"file",size:a.size})}return i}async function so(e){const n=(await oo(e)).sort((e,t)=>function(e,t){return Buffer.compare(Buffer.from(e,"utf8"),Buffer.from(t,"utf8"))}(e.relativePath,t.relativePath)),i=d.createHash("sha256");for(const e of n){if(i.update("file"===e.kind?"F":"L","ascii"),i.update(Buffer.from(e.relativePath,"utf8")),i.update(Buffer.from([0])),i.update(Buffer.from(String(e.size),"ascii")),i.update(Buffer.from([0])),"file"===e.kind)for await(const n of t.createReadStream(e.absolutePath))i.update(n);else i.update(Buffer.from(e.target,"utf8"));i.update(Buffer.from([0]))}return i.digest("hex")}function ao(e){for(const[t,n]of[["version",e.version],["platform",e.platform],["arch",e.arch]])if(!/^[0-9A-Za-z._-]+$/.test(n))throw new ro("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Invalid runtime artifact ${t}: ${n}`);return`${e.version}-${e.platform}-${e.arch}`}function co(e,t){return`${ao(e)}-${e.sha256}-${t}`}async function lo(e){const n=d.createHash("sha256");for await(const i of t.createReadStream(e))n.update(i);return n.digest("hex")}class uo{#e;#t;#n=new Map;constructor(e){this.#e=e.cacheDir,this.#t=e.fetchImpl??fetch}resolve(e,t){const n=yn.parse(e);if(!/^[a-f0-9]{64}$/.test(t.archiveSha256))throw new ro("INSTANCE_RUNTIME_ARTIFACT_INVALID","Runtime archive SHA-256 is invalid.");if((t.archiveUrl?1:0)+(t.archivePath?1:0)!=1)throw new ro("INSTANCE_RUNTIME_ARTIFACT_INVALID","Runtime artifact source must specify exactly one archive location.");const i=co(n,t.archiveSha256),r=this.#n.get(i);if(r)return r;const o=this.#i(n,t).finally(()=>this.#n.delete(i));return this.#n.set(i,o),o}async#i(e,i){if(!/^[a-f0-9]{64}$/.test(i.archiveSha256))throw new ro("INSTANCE_RUNTIME_ARTIFACT_INVALID","Runtime archive SHA-256 is invalid.");const r=co(e,i.archiveSha256),o=n.join(this.#e,"archives"),s=n.join(o,`${r}.tar.gz`);if(await g.mkdir(o,{recursive:!0}),await this.#r(s,e,i.archiveSha256))return{identity:e,archivePath:s,cacheHit:!0};await g.rm(s,{force:!0});const a=n.join(o,`.${r}.${d.randomUUID()}.part`);try{const n=await g.open(a,"wx");if(i.archivePath)await f.pipeline(t.createReadStream(i.archivePath),n.createWriteStream());else{const e=await this.#t(i.archiveUrl);if(!e.ok||!e.body)throw await n.close(),new ro("INSTANCE_RUNTIME_ARTIFACT_UNAVAILABLE",`Runtime artifact download failed with HTTP ${e.status}.`,{retryable:e.status>=500});await f.pipeline(e.body,n.createWriteStream())}if(await lo(a)!==i.archiveSha256)throw new ro("INSTANCE_RUNTIME_ARTIFACT_INVALID","Downloaded runtime archive SHA-256 does not match release metadata.");return await this.#o(a,e),await g.rename(a,s),{identity:e,archivePath:s,cacheHit:!1}}catch(e){if(e instanceof ro)throw e;throw new ro("INSTANCE_RUNTIME_ARTIFACT_UNAVAILABLE","Could not download runtime artifact.",{cause:e,retryable:!0})}finally{await g.rm(a,{force:!0})}}async#r(e,t,n){try{return await lo(e)===n&&(await this.#o(e,t),!0)}catch{return!1}}async#o(e,t){const i=n.join(this.#e,"validation",`${ao(t)}-${d.randomUUID()}`);try{await async function(e,t){await g.mkdir(t,{recursive:!0});try{await y.extract({file:e,cwd:t,strict:!0,preservePaths:!1,filter:(e,t)=>{const i=n.posix.normalize(e.replace(/^\.\//,""));if(!i||".."===i||i.startsWith("../")||n.posix.isAbsolute(i))throw new ro("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime archive entry escapes the artifact root: ${e}`);const r=t.type;if("File"!==r&&"OldFile"!==r&&"Directory"!==r&&"SymbolicLink"!==r)throw new ro("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime archive contains unsupported entry type ${r??"unknown"}: ${e}`);return!0}})}catch(e){throw new ro("INSTANCE_RUNTIME_ARTIFACT_INVALID","Could not extract runtime artifact safely.",{cause:e})}}(e,i),await async function(e,t,i){const r=await async function(e){let t;try{t=JSON.parse(await g.readFile(n.join(e,io),"utf8"))}catch(e){throw new ro("INSTANCE_RUNTIME_ARTIFACT_INVALID","Runtime artifact manifest is missing or invalid JSON.",{cause:e})}const i=Mi(yn,t);if(!i.success)throw new ro("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime artifact manifest is invalid: ${i.error.message}`);return i.data}(e);if(function(e,t){for(const n of["packageName","version","platform","arch","formatVersion","launcherAbi","entrypoint","sha256"])if(e[n]!==t[n])throw new ro("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime artifact ${"sha256"===n?"SHA-256":n} mismatch: expected ${t[n]}, got ${e[n]}.`)}(r,t),1!==r.formatVersion)throw new ro("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Unsupported runtime artifact format ${r.formatVersion}.`);if(i?.platform&&"universal"!==r.platform&&r.platform!==i.platform)throw new ro("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime artifact platform ${r.platform} does not match ${i.platform}.`);if(i?.arch&&"universal"!==r.arch&&r.arch!==i.arch)throw new ro("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime artifact architecture ${r.arch} does not match ${i.arch}.`);if(void 0!==i?.launcherAbi&&r.launcherAbi>i.launcherAbi)throw new ro("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Runtime requires launcher ABI ${r.launcherAbi}, but the base runtime provides ${i.launcherAbi}.`);const o=function(e,t){if(!e||e.includes("\\")||n.posix.isAbsolute(e))throw new ro("INSTANCE_RUNTIME_ARTIFACT_INVALID",`${t} must be a non-empty POSIX relative path.`);const i=n.posix.normalize(e);if("."===i||".."===i||i.startsWith("../"))throw new ro("INSTANCE_RUNTIME_ARTIFACT_INVALID",`${t} escapes the runtime root.`);return i}(r.entrypoint,"Runtime entrypoint"),s=await g.lstat(n.join(e,...o.split("/"))).catch(()=>{});if(!s?.isFile())throw new ro("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime entrypoint is missing: ${o}`);const a=await so(e);if(a!==r.sha256)throw new ro("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload SHA-256 mismatch: expected ${r.sha256}, got ${a}.`);return r}(i,t,{platform:t.platform,arch:t.arch})}finally{await g.rm(i,{recursive:!0,force:!0})}}}async function mo(e,t,i,r=fetch){if("linux"!==t||!["x64","arm64"].includes(i))throw new ro("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Managed controlled-instance updates require a Linux x64 or arm64 target, received ${t}/${i}.`);const o=await async function(e){const t=`controlled-instance-runtime-${e}-linux-universal`,i=function(){const e=process.env.TASK_HANDOFF_BUNDLED_RUNTIME_DIR?.trim();return n.resolve(e||n.join(n.dirname(process.argv[1]||process.cwd()),"..","runtime-artifacts"))}();try{const[r,o]=await Promise.all([g.readFile(n.join(i,`${t}.manifest.json`),"utf8"),g.readFile(n.join(i,`${t}.tar.gz.sha256`),"utf8")]),s=Mi(yn,JSON.parse(r));if(!s.success||s.data.version!==e||"linux"!==s.data.platform||"universal"!==s.data.arch)throw new ro("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Bundled controlled-instance ${e} has an invalid Linux manifest.`);const a=o.trim().split(/\s+/)[0]?.toLowerCase();if(!a||!/^[a-f0-9]{64}$/.test(a))throw new ro("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Bundled controlled-instance ${e} has an invalid archive checksum.`);return{identity:s.data,source:{archivePath:n.join(i,`${t}.tar.gz`),archiveSha256:a}}}catch(t){if("ENOENT"===t.code)return;if(t instanceof ro)throw t;throw new ro("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Could not read bundled controlled-instance ${e}.`,{cause:t})}}(e);if(o)return o;const s=`controlled-instance-runtime-${e}-linux-universal`,a=function(e){const t=process.env.TASK_HANDOFF_RUNTIME_RELEASE_BASE_URL?.trim();return t?t.replaceAll("{version}",e).replace(/\/$/,""):`https://github.com/edgestorage/task-handoff/releases/download/v${e}`}(e),c=`${a}/${s}.manifest.json`,d=`${a}/${s}.tar.gz`,l=`${a}/${s}.tar.gz.sha256`,[u,m]=await Promise.all([r(c),r(l)]).catch(t=>{throw new ro("INSTANCE_RUNTIME_ARTIFACT_UNAVAILABLE",`Could not read release metadata for controlled-instance ${e}.`,{cause:t,retryable:!0})});if(!u.ok||!m.ok)throw new ro("INSTANCE_RUNTIME_ARTIFACT_UNAVAILABLE",`Release metadata for controlled-instance ${e} is unavailable (manifest HTTP ${u.status}, checksum HTTP ${m.status}).`,{retryable:u.status>=500||m.status>=500});let p;try{p=await u.json()}catch(t){throw new ro("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Release manifest for controlled-instance ${e} is not valid JSON.`,{cause:t})}const h=Mi(yn,p);if(!h.success)throw new ro("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Release manifest for controlled-instance ${e} is invalid: ${h.error.message}`);if(h.data.version!==e||"linux"!==h.data.platform||"universal"!==h.data.arch)throw new ro("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Release identity mismatch: requested ${e}-linux-universal, received ${h.data.version}-${h.data.platform}-${h.data.arch}.`);const f=(await m.text()).trim().split(/\s+/)[0]?.toLowerCase();if(!f||!/^[a-f0-9]{64}$/.test(f))throw new ro("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Release checksum for controlled-instance ${e} is invalid.`);return{identity:h.data,source:{archiveUrl:d,archiveSha256:f}}}class po{store;desiredVersion;hooks;inFlight=new Map;requests=new Map;cancelled=new Set;now;delay;drainTimeoutMs;verificationTimeoutMs;pollIntervalMs;maxAttempts;retryBaseDelayMs;retryMaxDelayMs;constructor(e,t,n,i={}){this.store=e,this.desiredVersion=t,this.hooks=n,this.now=i.now||(()=>new Date),this.delay=i.delay||(e=>new Promise(t=>setTimeout(t,e))),this.drainTimeoutMs=i.drainTimeoutMs??3e5,this.verificationTimeoutMs=i.verificationTimeoutMs??6e4,this.pollIntervalMs=i.pollIntervalMs??250,this.maxAttempts=function(e){if(!Number.isInteger(e)||e<=0)throw new TypeError("maxAttempts must be a positive integer.");return e}(i.maxAttempts??3),this.retryBaseDelayMs=wo(i.retryBaseDelayMs??1e3,"retryBaseDelayMs"),this.retryMaxDelayMs=wo(i.retryMaxDelayMs??3e4,"retryMaxDelayMs")}schedule(e,t={}){const n=this.requests.get(e)||{startRequested:!1,resumeCancelled:!1};n.startRequested||=!0===t.startRequested,n.resumeCancelled||=!0===t.resumeCancelled||!0===t.startRequested,n.resumeCancelled&&this.cancelled.delete(e),this.requests.set(e,n);const i=this.inFlight.get(e);if(i)return i;const r=Promise.resolve().then(()=>this.reconcile(e,n)).finally(()=>{this.inFlight.delete(e),this.requests.delete(e)});return this.inFlight.set(e,r),r}isRunning(e){return this.inFlight.has(e)}cancel(e){return this.cancelled.add(e),this.inFlight.get(e)}async reconcile(e,t){let n=this.requireInstance(e);const i=this.desiredVersion();if(this.cancelled.has(e)&&!t.resumeCancelled)return this.storePhase(n,"pending");const r=n.runtimeVersion?.desiredVersion!==i||t.startRequested||fo(n)?0:this.remainingRetryDelayMs(n.runtimeVersion);if(r>0&&(await this.delay(r),n=this.requireInstance(e),this.cancelled.has(e)))return this.storePhase(n,"pending");const o=ho(n),s=o===i&&(await(this.hooks.isInstalled?.(n,i))??!0);if(this.cancelled.has(e))return this.storePhase(this.requireInstance(e),"pending");if(o===i&&s)return this.storeState(n,{desiredVersion:i,actualVersion:o,phase:"matched",attempt:n.runtimeVersion?.attempt||0,matchedAt:this.timestamp()},!fo(n)&&"failed"!==n.health);if(n=this.storeState(n,function(e,t,n,i=!1){const r=e.runtimeVersion,o=r?.desiredVersion===t&&"matched"!==r.phase;return{desiredVersion:t,...n?{actualVersion:n}:{},phase:"pending",attempt:o?r.attempt:0,error:(o?r.error:void 0)||(n!==t||i?yo(t,n):Io("INSTANCE_RUNTIME_VERIFICATION_FAILED",`Controlled-instance ${t} is running, but the active runtime artifact does not match the desired release identity.`,t,n,!0))}}(n,i,o,s)),fo(n)&&!t.startRequested)return n;let a=!1,c=0;try{for(;c<this.maxAttempts;){if(this.cancelled.has(e))return this.storePhase(this.requireInstance(e),"pending");let r;try{if(n=this.storePhase(n,"draining"),await(this.hooks.beginDrain?.(n)),a=!0,n=this.requireInstance(e),go(n)){const t=await this.waitUntil(e,this.drainTimeoutMs,e=>!go(e));if(n=this.requireInstance(e),!t){if(this.cancelled.has(e))return this.storePhase(n,"pending");await(this.hooks.onForcedDrain?.(n))}}if(n=this.storePhase(this.requireInstance(e),"installing",!0),c+=1,await this.hooks.install(n,i),this.cancelled.has(e)||fo(this.requireInstance(e))&&!t.startRequested)return this.storePhase(this.requireInstance(e),"pending");if(n=this.storePhase(this.requireInstance(e),"restarting"),await this.hooks.restart(n),this.cancelled.has(e))return this.storePhase(this.requireInstance(e),"pending");n=this.storePhase(this.requireInstance(e),"verifying");const r=await this.waitUntil(e,this.verificationTimeoutMs,e=>ho(e)===i);if(this.cancelled.has(e))return this.storePhase(this.requireInstance(e),"pending");if(!r)throw Io("INSTANCE_RUNTIME_VERIFICATION_FAILED",`Instance ${e} did not register controlled-instance ${i} after restart.`,i,ho(this.requireInstance(e)),!0);const o=this.requireInstance(e);if(this.hooks.isInstalled&&!await this.hooks.isInstalled(o,i))throw Io("INSTANCE_RUNTIME_VERIFICATION_FAILED",`Instance ${e} reported controlled-instance ${i}, but its active runtime release is missing.`,i,ho(o),!0);return this.storeState(o,{desiredVersion:i,actualVersion:i,phase:"matched",attempt:o.runtimeVersion?.attempt||1,matchedAt:this.timestamp()},!fo(o)&&"failed"!==o.health)}catch(t){if(this.cancelled.has(e))return this.storePhase(this.requireInstance(e),"pending");r=Ao(t,i,ho(this.store.get(e)))}n=this.requireInstance(e);const o=n.runtimeVersion?.attempt||1;if(!r.retryable||c>=this.maxAttempts)return this.storeBatchFailure(n,i,o>=this.maxAttempts&&r.retryable?bo(i,ho(n),this.maxAttempts,r):r);n=this.storeState(n,{desiredVersion:i,...ho(n)?{actualVersion:ho(n)}:{},phase:"pending",attempt:o,lastAttemptAt:this.timestamp(),error:r}),await this.delay(this.retryDelayMs(o))}return this.storeBatchFailure(n,i,bo(i,ho(n),this.maxAttempts,n.runtimeVersion?.error))}finally{a&&await(this.hooks.endDrain?.(this.requireInstance(e)))}}storeBatchFailure(e,t,n){const i=ho(e);return this.storeState(e,{desiredVersion:t,...i?{actualVersion:i}:{},phase:"pending",attempt:e.runtimeVersion?.attempt||0,lastAttemptAt:this.timestamp(),error:n})}retryDelayMs(e){return Math.min(this.retryMaxDelayMs,this.retryBaseDelayMs*2**Math.max(0,e-1))}remainingRetryDelayMs(e){if(!e?.error||!e.lastAttemptAt)return 0;const t=Date.parse(e.lastAttemptAt);return Number.isFinite(t)?Math.max(0,t+this.retryDelayMs(e.attempt||1)-this.now().getTime()):0}storePhase(e,t,n=!1){const i=this.desiredVersion(),r=ho(e),o=e.runtimeVersion?.desiredVersion===i?e.runtimeVersion.error:void 0;return this.storeState(e,{desiredVersion:i,...r?{actualVersion:r}:{},phase:t,attempt:(e.runtimeVersion?.attempt||0)+(n?1:0),lastAttemptAt:this.timestamp(),...o?{error:o}:"pending"===t?{error:yo(i,r)}:{}},"restarting"!==t&&void 0)}storeState(e,t,n){const i=this.store.get(e.id)||e;return this.store.put(Si.parse({...i,runtimeVersion:t,...void 0===n?{}:{ready:n},updatedAt:this.timestamp()}))}async waitUntil(e,t,n){const i=this.now().getTime()+t;for(;;){const t=this.store.get(e);if(t&&n(t))return!0;if(this.cancelled.has(e))return!1;if(this.now().getTime()>=i)return!1;await this.delay(Math.min(this.pollIntervalMs,Math.max(0,i-this.now().getTime())))}}requireInstance(e){const t=this.store.get(e);if(!t)throw new Error(`Instance ${e} was removed during runtime reconciliation.`);return t}timestamp(){return this.now().toISOString()}}function ho(e){return e?.build?.packageVersion||e?.instanceVersion}function go(e){return e.apps.runningCount>0||e.aiSessions.runningCount>0}function fo(e){return["created","stopped","failed"].includes(e.status)}function yo(e,t){return Io("INSTANCE_RUNTIME_VERSION_MISMATCH",`Expected controlled-instance ${e}, received ${t||"an unknown version"}.`,e,t,!0)}function Io(e,t,n,i,r){return{code:e,message:t,expectedVersion:n,...i?{actualVersion:i}:{},retryable:r}}function Ao(e,t,n){if(e&&"object"==typeof e&&"code"in e&&"message"in e){const i=e,r=In.shape.code.safeParse(i.code);if(r.success&&"string"==typeof i.message)return Io(r.data,i.message,t,n,"boolean"!=typeof i.retryable||i.retryable)}return Io("INSTANCE_RUNTIME_INSTALL_FAILED",e instanceof Error?e.message:String(e),t,n,!0)}function bo(e,t,n,i){const r=i?.message?` Last error: ${i.message}`:"";return Io(i?.code||"INSTANCE_RUNTIME_INSTALL_FAILED",`Runtime convergence paused after ${n} attempts and will retry.${r}`,e,t,!0)}function wo(e,t){if(!Number.isFinite(e)||e<0)throw new TypeError(`${t} must be a nonnegative finite number.`);return e}function vo(e,n=448){t.mkdirSync(e,{recursive:!0,mode:n}),t.chmodSync(e,n)}function Eo(e,i,r={}){const o=r.directoryMode??448,s=r.fileMode??384;vo(n.dirname(e),o),I.sync(e,`${JSON.stringify(i,null,2)}\n`,{encoding:"utf8",mode:s}),t.chmodSync(e,s)}function No(e,t){console.warn(JSON.stringify({message:e,...t}))}function So(e){return e&&"object"==typeof e&&"issues"in e?{issues:e.issues}:{error:e instanceof Error?e.message:String(e)}}function To(e,n){const i=n.logger||No;let r;try{r=JSON.parse(t.readFileSync(e,"utf8"))}catch(t){return void i("stored JSON could not be read",{filePath:e,...So(t)})}if(!n.schema)return r;const o=n.sanitize?n.sanitize(r):r,s=n.schema.safeParse(o);if(s.success)return s.data;const a="strip"in n.schema&&"function"==typeof n.schema.strip?n.schema.strip().safeParse(o):void 0;if(a?.success)return i("unknown stored fields were ignored",{filePath:e,issues:s.error.issues}),a.data;i("stored record failed validation and was isolated",{filePath:e,issues:s.error.issues})}function zo(e){return`${e}_${d.randomUUID().replace(/-/g,"").slice(0,20)}`}function _o(){return d.randomBytes(24).toString("base64url")}class Co{directory;options;permissionsInitialized=!1;constructor(e,t={}){this.directory=e,this.options=t}init(){if(this.permissionsInitialized&&t.existsSync(this.directory))return;vo(this.directory,this.options.directoryMode??448);const e=this.options.fileMode??384;for(const i of t.readdirSync(this.directory).filter(e=>e.endsWith(".json")))t.chmodSync(n.join(this.directory,i),e);this.permissionsInitialized=!0}filePath(e){return n.join(this.directory,`${e}.json`)}list(){return this.init(),t.readdirSync(this.directory).filter(e=>e.endsWith(".json")).sort().flatMap(e=>{const t=To(n.join(this.directory,e),this.options);return t?[t]:[]})}get(e){this.init();const n=this.filePath(e);return t.existsSync(n)?To(n,this.options):void 0}put(e){const t=this.options.sanitize?this.options.sanitize(e):e,n=this.options.schema?this.options.schema.parse(t):t;return Eo(this.filePath(n.id),n,this.options),n}patch(e,t){const n=this.get(e);if(!n)return;const i={...n,...t,id:n.id,createdAt:n.createdAt,updatedAt:(new Date).toISOString()};return this.put(i)}delete(e){const n=this.filePath(e);return!!t.existsSync(n)&&(t.unlinkSync(n),!0)}}class ko{filePathValue;defaults;options;constructor(e,t,n={}){this.filePathValue=e,this.defaults=t,this.options=n}init(){vo(n.dirname(this.filePathValue),this.options.directoryMode??448),t.existsSync(this.filePathValue)?t.chmodSync(this.filePathValue,this.options.fileMode??384):this.put(this.defaults())}get(){return this.init(),t.existsSync(this.filePathValue)?To(this.filePathValue,this.options)??this.defaults():this.defaults()}put(e){const t=this.options.sanitize?this.options.sanitize(e):e,n=this.options.schema?this.options.schema.parse(t):t;return Eo(this.filePathValue,n,this.options),n}}const Oo=a.z.record(a.z.string(),a.z.string()),Ro=new Set(["OPENAI_API_KEY","OPENAI_BASE_URL","CODEX_MODEL","TASK_HANDOFF_CODEX_BASE_URL","TASK_HANDOFF_CODEX_MODEL","TASK_HANDOFF_CODEX_MODEL_ID","ANTHROPIC_API_KEY","ANTHROPIC_BASE_URL","CLAUDE_MODEL","TASK_HANDOFF_CLAUDE_MODEL","TASK_HANDOFF_CLAUDE_MODEL_ID"]);class xo{directory;constructor(e){this.directory=e}get(e){try{return Oo.parse(JSON.parse(t.readFileSync(this.filePath(e),"utf8")))}catch(t){if(t&&"object"==typeof t&&"code"in t&&"ENOENT"===t.code)return{};throw new Error(`Stored model environment for instance ${e} is invalid: ${t instanceof Error?t.message:String(t)}`)}}has(e){return t.existsSync(this.filePath(e))}listInstanceIds(){return t.existsSync(this.directory)?t.readdirSync(this.directory).filter(e=>e.endsWith(".json")).map(e=>e.slice(0,-5)).sort():[]}put(e,n){const i=Oo.parse(n);t.mkdirSync(this.directory,{recursive:!0,mode:448});const r=this.filePath(e);return I.sync(r,`${JSON.stringify(i,null,2)}\n`,{encoding:"utf8",mode:384}),t.chmodSync(r,384),i}delete(e){t.rmSync(this.filePath(e),{force:!0})}filePath(e){return n.join(this.directory,`${e}.json`)}}class Do{directory;nodeId;constructor(e,t){this.directory=e,this.nodeId=t}init(){t.mkdirSync(this.directory,{recursive:!0,mode:448}),t.chmodSync(this.directory,448)}list(){return this.init(),t.readdirSync(this.directory).filter(e=>e.endsWith(".json")).sort().flatMap(e=>{const t=this.read(n.join(this.directory,e));return t?[t]:[]})}get(e){const n=this.filePath(e);return t.existsSync(n)?this.read(n):void 0}put(e){const n=Pn.parse(e);this.init();const i=this.filePath(n.id);return I.sync(i,`${JSON.stringify(n,null,2)}\n`,{encoding:"utf8",mode:384}),t.chmodSync(i,384),n}delete(e){const n=this.filePath(e);return!!t.existsSync(n)&&(t.unlinkSync(n),!0)}read(e){try{const i=JSON.parse(t.readFileSync(e,"utf8")),r=n.basename(e,".json"),o=Pn.safeParse(i);if(o.success&&o.data.id===r&&Kn(o.data)===o.data.id)return o.data;const s=Pn.strip().safeParse(i);return s.success&&s.data.id===r&&Kn(s.data)===s.data.id?(console.warn(JSON.stringify({message:"unknown stored node model fields were ignored",nodeId:this.nodeId,filePath:e})),s.data):void console.warn(JSON.stringify({message:"stored node model failed validation and was isolated",nodeId:this.nodeId,filePath:e}))}catch(t){return void console.warn(JSON.stringify({message:"stored node model could not be read",nodeId:this.nodeId,filePath:e,error:t instanceof Error?t.message:String(t)}))}}filePath(e){return n.join(this.directory,`${e}.json`)}}class Po{directory;constructor(e){this.directory=e}init(){t.mkdirSync(this.directory,{recursive:!0,mode:448}),t.chmodSync(this.directory,448)}get(e){const n=this.filePath(e);if(t.existsSync(n))try{const i=JSON.parse(t.readFileSync(n,"utf8")),r=jn.safeParse(i);if(r.success)return r.data;const o=jn.strip().safeParse(i);if(o.success)return console.warn(JSON.stringify({message:"unknown stored model assignment fields were ignored",instanceId:e,filePath:n})),o.data;throw r.error}catch(t){throw Object.assign(new Error(`Stored model assignment for instance ${e} is invalid.`),{statusCode:409,code:"NODE_MODEL_ASSIGNMENT_INVALID",cause:t})}}put(e){const n=jn.parse(e);this.init();const i=this.filePath(n.instanceId);return I.sync(i,`${JSON.stringify(n,null,2)}\n`,{encoding:"utf8",mode:384}),t.chmodSync(i,384),n}delete(e){t.rmSync(this.filePath(e),{force:!0})}filePath(e){return n.join(this.directory,`${e}.json`)}}function Mo(){return(new Date).toISOString()}class Lo{models;assignments;legacyEnvironments;nodeId;instances;constructor(e,t,n){this.nodeId=t,this.instances=n,this.models=new Do(e.nodeModelsDir,t),this.assignments=new Po(e.modelAssignmentsDir),this.legacyEnvironments=new xo(e.modelEnvironmentsDir)}init(){this.models.init(),this.assignments.init(),this.migrateLegacyEnvironments()}list(){const e=new Map;for(const t of this.instances.list()){const n=this.assignments.get(t.id);for(const t of[n?.codexModelHash,n?.claudeModelHash])t&&e.set(t,(e.get(t)||0)+1)}return this.models.list().map(t=>this.toPublic(t,e.get(t.id)||0))}create(e){const t=Mo(),n=Kn(e),i=this.models.get(n),r=Pn.parse({...e,id:n,enabled:e.enabled??!0,order:e.order??this.nextOrder(),labels:e.labels||{},createdAt:i?.createdAt||t,updatedAt:t});return this.toPublic(this.models.put(r),this.referenceIds(n).length)}deploy(e){const t=Kn(e);if(e.id!==t)throw Object.assign(new Error(`Model content hash ${t} does not match ${e.id}.`),{statusCode:400,code:"NODE_MODEL_HASH_MISMATCH"});const n=this.models.get(e.id)||this.models.put(Pn.parse(e));return this.toPublic(n,this.referenceIds(n.id).length)}update(e,t){const n=this.requireModel(e),i=Pn.parse({...n,...t,key:t.key?.trim()?t.key:n.key,createdAt:n.createdAt,updatedAt:Mo()}),r=Kn(i),o=this.models.put(Pn.parse({...i,id:r}));return this.toPublic(o,this.referenceIds(r).length)}delete(e){this.requireModel(e);const t=this.referenceIds(e);if(t.length)throw Object.assign(new Error(`Model ${e} is assigned to ${t.length} instance${1===t.length?"":"s"}.`),{statusCode:409,code:"NODE_MODEL_IN_USE",instanceIds:t});return this.models.delete(e)}assign(e,t){const n=this.instances.require(e);if(this.validateRef("codex",t.codexModelHash),this.validateRef("claude",t.claudeModelHash),void 0!==t.modelSelection.codexModelHash&&(t.modelSelection.codexModelHash??void 0)!==t.codexModelHash)throw Object.assign(new Error("Codex model selection does not match its node assignment."),{statusCode:400,code:"NODE_MODEL_SELECTION_MISMATCH"});if(void 0!==t.modelSelection.claudeModelHash&&(t.modelSelection.claudeModelHash??void 0)!==t.claudeModelHash)throw Object.assign(new Error("Claude model selection does not match its node assignment."),{statusCode:400,code:"NODE_MODEL_SELECTION_MISMATCH"});const i=this.assignments.get(e),r=jn.parse({instanceId:e,codexModelHash:t.codexModelHash,claudeModelHash:t.claudeModelHash,updatedAt:Mo()});this.assignments.put(r);try{return{assignment:r,instance:this.instances.put(Si.parse({...n,modelSelection:t.modelSelection,updatedAt:Mo()}))}}catch(t){throw i?this.assignments.put(i):this.assignments.delete(e),t}}resolvedEnvironment(e){const t=this.assignments.get(e);if(!t){if(this.legacyEnvironments.has(e))throw Object.assign(new Error(`Legacy model environment for instance ${e} requires manual migration.`),{statusCode:409,code:"NODE_MODEL_MIGRATION_REQUIRED"});return{}}return{...this.environmentForRef("codex",t.codexModelHash),...this.environmentForRef("claude",t.claudeModelHash)}}deleteInstanceMetadata(e){this.assignments.delete(e),this.legacyEnvironments.delete(e)}validateRef(e,t){if(!t)return;const n=this.requireModel(t);if(n.app!==e)throw Object.assign(new Error(`Model ${n.id} belongs to ${n.app}, not ${e}.`),{statusCode:400,code:"NODE_MODEL_APP_MISMATCH"});if(!n.enabled)throw Object.assign(new Error(`Model ${n.id} is disabled.`),{statusCode:409,code:"NODE_MODEL_DISABLED"})}environmentForRef(e,t){if(!t)return{};this.validateRef(e,t);const n=this.requireModel(t);return"codex"===e?{OPENAI_API_KEY:n.key,OPENAI_BASE_URL:n.endpoint,TASK_HANDOFF_CODEX_BASE_URL:n.endpoint,TASK_HANDOFF_CODEX_MODEL:n.model}:{ANTHROPIC_API_KEY:n.key,ANTHROPIC_BASE_URL:n.endpoint,TASK_HANDOFF_CLAUDE_MODEL:n.model}}requireModel(e){const t=this.models.get(e);if(!t)throw Object.assign(new Error(`Model ${e} was not found on node ${this.nodeId}.`),{statusCode:404,code:"NODE_MODEL_NOT_FOUND"});if(Kn(t)!==t.id)throw Object.assign(new Error(`Stored model ${e} does not match its content hash.`),{statusCode:409,code:"NODE_MODEL_HASH_INVALID"});return t}referenceIds(e){return this.instances.list().filter(t=>{const n=this.assignments.get(t.id);return n?.codexModelHash===e||n?.claudeModelHash===e}).map(e=>e.id)}toPublic(e,t){const{key:n,...i}=e;return Ln.parse({...i,keyPreview:n.length<=8?"set":`${n.slice(0,4)}...${n.slice(-4)}`,keySet:!0,referenceCount:t})}nextOrder(){return this.models.list().reduce((e,t)=>Math.max(e,t.order),0)+100}migrateLegacyEnvironments(){for(const e of this.legacyEnvironments.listInstanceIds()){if(!this.instances.has(e)){this.warnMigration(e,"instance-not-found");continue}if(this.assignments.get(e)){try{this.resolvedEnvironment(e),this.legacyEnvironments.delete(e)}catch{this.warnMigration(e,"existing-assignment-invalid")}continue}let t;try{t=this.legacyEnvironments.get(e)}catch{this.warnMigration(e,"sidecar-invalid");continue}if(!Object.keys(t).length){this.legacyEnvironments.delete(e);continue}if(Object.keys(t).some(e=>!Ro.has(e))){this.warnMigration(e,"unknown-fields");continue}const n=[];try{const i=this.migrateApp(t,"codex",n),r=this.migrateApp(t,"claude",n);if(!i&&!r)throw new Error("no complete model configuration");const o={...i?{codexModelHash:i}:{},...r?{claudeModelHash:r}:{}};this.assign(e,{modelSelection:o,codexModelHash:i,claudeModelHash:r}),this.resolvedEnvironment(e),this.legacyEnvironments.delete(e)}catch{this.assignments.delete(e);for(const e of n)this.models.delete(e);this.warnMigration(e,"mapping-failed")}}}migrateApp(e,t,n){const i=e["codex"===t?"OPENAI_API_KEY":"ANTHROPIC_API_KEY"],r="codex"===t?e.TASK_HANDOFF_CODEX_BASE_URL||e.OPENAI_BASE_URL:e.ANTHROPIC_BASE_URL,o="codex"===t?e.TASK_HANDOFF_CODEX_MODEL||e.CODEX_MODEL:e.TASK_HANDOFF_CLAUDE_MODEL||e.CLAUDE_MODEL;if(!i&&!r&&!o)return;if(!i||!r||!o)throw new Error("model configuration incomplete");const s=Kn({app:t,endpoint:r,key:i,model:o}),a=this.models.get(s);if(a){if(a.app!==t||a.key!==i||a.endpoint!==r||a.model!==o||!a.enabled)throw new Error("existing model conflicts with legacy environment");return s}const c=Mo();return this.models.put(Pn.parse({id:s,name:`Migrated ${"codex"===t?"Codex":"Claude"} model`,endpoint:r,key:i,model:o,app:t,enabled:!0,order:this.nextOrder(),labels:{migratedFrom:"instance-model-environment"},createdAt:c,updatedAt:c})),n.push(s),s}warnMigration(e,t){console.warn(JSON.stringify({message:"legacy model environment was preserved because it could not be migrated",nodeId:this.nodeId,instanceId:e,reason:t}))}}function jo(){return(new Date).toISOString()}function $o(e,t){if(!e)return!0;const n=A.valid(e),i=A.valid(t);return n&&i?A.gt(i,n):e!==t}function Fo(){return process.env.TASK_HANDOFF_NPM_COMMAND||"npm"}function Uo(e,i){const r=n.join(e,...i.split("/"),"package.json");try{const e=JSON.parse(t.readFileSync(r,"utf8"));if(e.name!==i||"string"!=typeof e.version||!e.version.trim())throw new Error(`Installed package manifest is invalid: ${r}`);return{name:i,version:e.version.trim()}}catch(e){if("ENOENT"===e.code)return;throw e}}async function Vo(e){const t=(await e(Fo(),["root","--global"])).stdout.trim();if(!t)throw new Error("npm did not return its global module root.");const n=Uo(t,"@task-handoff/server"),i=Uo(t,"@task-handoff/node-agent");return n?{packageName:"@task-handoff/server",currentVersion:n.version,relatedCurrentVersions:i?[i.version]:[]}:{packageName:"@task-handoff/node-agent",currentVersion:i?.version,relatedCurrentVersions:[]}}function qo(e){if(!e||"object"!=typeof e||Array.isArray(e))return e;const t=e,n="string"==typeof t.updatedAt?t.updatedAt:jo(),i=t.target&&"object"==typeof t.target&&!Array.isArray(t.target)?t.target:void 0,r="controlled-instance"===i?.component,o={updating:"updating-node",downloading:"updating-node",installing:"updating-node",restarting:"restarting-node",completed:"succeeded",success:"succeeded",error:"failed"},s=new Set(["queued","updating-node","restarting-node","converging-instances","succeeded","degraded","failed"]),a="string"==typeof t.status?t.status:"queued",c=r?"failed":s.has(a)?a:o[a]||"failed",d="string"==typeof t.toVersion&&t.toVersion?t.toVersion:"unknown",l=bn.strip().safeParse(t.impact).success?bn.strip().parse(t.impact):{runningInstanceCount:0,stoppedInstanceCount:0,activeInstanceCount:0,restartInstanceCount:0,runningInstanceIds:[],stoppedInstanceIds:[],activeInstanceIds:[]},u=r?{code:"LEGACY_INSTANCE_UPDATE_RETIRED",message:"Independent controlled-instance update jobs were retired in favor of Node reconciliation.",retryable:!1}:"failed"!==c||t.error||s.has(a)||a in o?"string"==typeof t.error?{code:"NODE_UPDATE_FAILED",message:t.error,retryable:!1}:In.strip().safeParse(t.error).success?In.strip().parse(t.error):t.error&&"object"==typeof t.error?{code:"NODE_UPDATE_FAILED",message:"string"==typeof t.error.message?t.error.message:"Stored update job contained an unknown error.",retryable:!1}:void 0:{code:"NODE_UPDATE_FAILED",message:`Stored update job used an unknown status: ${a}.`,retryable:!1},{target:m,error:p,...h}=t,g={phase:"succeeded"===c?"succeeded":"failed"===c?"failed":c||"queued",desiredVersion:d,expectedInstanceIds:[],expectedInstanceCount:0,matchedInstanceCount:0,pendingInstanceCount:0,failedInstanceCount:r||"failed"===c?1:0,deferredInstanceCount:0},f=wn.strip().safeParse(t.rollout);return{...h,source:"npm",status:c,impact:l,runtimeArtifacts:Array.isArray(t.runtimeArtifacts)?t.runtimeArtifacts.flatMap(e=>{const t=yn.strip().safeParse(e);return t.success?[t.data]:[]}):[],rollout:f.success?f.data:g,...u?{error:u}:{},...r?{completedAt:t.completedAt||n}:{}}}class Ho{records;constructor(e){this.records=new Co(e.updatesDir,{schema:Nn,sanitize:qo})}init(){this.records.init()}list(){return this.records.list().sort((e,t)=>t.createdAt.localeCompare(e.createdAt))}create(e,t){const n=jo();return this.records.put(Nn.parse({id:zo("update"),nodeId:e,source:t.source,channel:t.channel,fromVersion:t.currentVersion,toVersion:t.availableVersion,artifactRef:t.artifactRef,runtimeArtifacts:t.runtimeArtifacts,impact:t.impact,status:"queued",rollout:{phase:"queued",desiredVersion:t.availableVersion,expectedInstanceIds:t.impact.runningInstanceIds,expectedInstanceCount:t.impact.runningInstanceCount,matchedInstanceCount:0,pendingInstanceCount:t.impact.runningInstanceCount,failedInstanceCount:0,deferredInstanceCount:t.impact.stoppedInstanceCount},createdAt:n,updatedAt:n}))}patch(e,t){const n=this.records.get(e);if(!n)throw Object.assign(new Error(`Update job ${e} was not found.`),{statusCode:404,code:"UPDATE_JOB_NOT_FOUND"});return this.records.put(Nn.parse({...n,...t,id:e,createdAt:n.createdAt,updatedAt:jo()}))}reconcileRollouts(e,t,n={}){const i=new Map(e.map(e=>[e.id,e]));for(const e of this.list().filter(e=>["updating-node","restarting-node","converging-instances"].includes(e.status))){if(n.processStarted&&"restarting-node"===e.status&&t!==e.toVersion){this.patch(e.id,{status:"failed",rollout:{...e.rollout,phase:"failed",nodeVersion:t},error:{code:"NODE_UPDATE_FAILED",message:`Node agent restarted with version ${t}, expected ${e.toVersion}.`,retryable:!1},completedAt:jo()});continue}const r="converging-instances"!==e.status&&t===e.toVersion?this.patch(e.id,{status:"converging-instances",rollout:{...e.rollout,phase:"converging-instances",nodeVersion:t}}):e;if("converging-instances"!==r.status)continue;const o=r.rollout.expectedInstanceIds,s=o.map(e=>i.get(e)),a=s.filter(e=>e?.ready&&"matched"===e.runtimeVersion?.phase&&e.runtimeVersion.actualVersion===r.toVersion).length,c=s.filter(e=>e&&["created","stopped","failed"].includes(e.status||"")&&"failed"!==e.runtimeVersion?.phase).length,d=s.filter(e=>!e||"failed"===e.runtimeVersion?.phase).length,l=Math.max(0,o.length-a-d-c),u=d>0?"degraded":0===l?"succeeded":"converging-instances";this.patch(r.id,{status:u,rollout:{...r.rollout,phase:u,nodeVersion:t,expectedInstanceCount:o.length,matchedInstanceCount:a,pendingInstanceCount:l,failedInstanceCount:d,deferredInstanceCount:r.impact.stoppedInstanceCount+c},..."succeeded"===u||"degraded"===u?{completedAt:jo()}:{}})}}run(e,t){(async()=>{this.patch(e.id,{status:"updating-node",rollout:{...e.rollout,phase:"updating-node"},startedAt:jo(),error:void 0});try{await t(e),this.patch(e.id,{status:"succeeded",completedAt:jo()})}catch(t){this.patch(e.id,{status:"failed",rollout:{...e.rollout,phase:"failed"},error:{code:"NODE_UPDATE_FAILED",message:t instanceof Error?t.message:String(t),retryable:!1},completedAt:jo()})}})()}}function Bo(){return(new Date).toISOString()}class Ko{records;constructor(e){this.records=new Co(e.environmentTemplatesDir,{schema:Zt,sanitize:e=>function(e,t){if(!e||"object"!=typeof e||Array.isArray(e))return e;const n=e,i=new Set(["id","name","sourceInstanceId","nodeId","imageId","internalTag","platform","architecture","sizeBytes","status","error","createdAt","updatedAt"]),r="string"==typeof n.id?n.id:void 0;for(const e of Object.keys(n))i.has(e)||t?.({templateId:r,field:e});const o=Ri(n,[...i]);if(n.error&&"object"==typeof n.error&&!Array.isArray(n.error)){const e=n.error;for(const n of Object.keys(e))["code","message","phase"].includes(n)||t?.({templateId:r,field:`error.${n}`});o.error=Ri(e,["code","message","phase"])}return o}(e,e=>{console.warn(JSON.stringify({message:"unknown stored environment template field was ignored",...e}))})})}init(){this.records.init();for(const e of this.records.list())"creating"===e.status&&this.records.put(Zt.parse({...e,status:"failed",error:{code:"ENVIRONMENT_TEMPLATE_CREATION_INTERRUPTED",message:"Environment template creation was interrupted by a node-agent restart.",phase:"recovery"},updatedAt:Bo()}))}list(){return this.records.list()}get(e){return this.records.get(e)}put(e){return this.records.put(Zt.parse(e))}patch(e,t){return this.records.patch(e,t)}delete(e){return this.records.delete(e)}}const Go=a.z.record(a.z.string().regex(/^[A-Za-z_][A-Za-z0-9_]*$/),a.z.string()),Jo=a.z.object({version:a.z.literal(1),instanceId:a.z.string().trim().min(1).max(120),instanceCredential:a.z.string().trim().min(1).max(240),environment:Go,updatedAt:a.z.string().datetime()}).strict();class Wo{directory;constructor(e){this.directory=e.instancePrivateConfigsDir}init(){t.mkdirSync(this.directory,{recursive:!0,mode:448}),t.chmodSync(this.directory,448);for(const e of t.readdirSync(this.directory).filter(e=>e.endsWith(".json")))t.chmodSync(n.join(this.directory,e),384)}filePath(e){return n.join(this.directory,`${e}.json`)}get(e){const n=this.filePath(e);if(!t.existsSync(n))return;const i=JSON.parse(t.readFileSync(n,"utf8")),r=i&&"object"==typeof i&&!Array.isArray(i)?i:{},o=Jo.parse({version:r.version,instanceId:r.instanceId,instanceCredential:r.instanceCredential??r.registrationToken,environment:r.environment,updatedAt:r.updatedAt});if(o.instanceId!==e)throw Object.assign(new Error(`Private config identity mismatch for instance ${e}.`),{statusCode:409,code:"INSTANCE_PRIVATE_CONFIG_IDENTITY_MISMATCH"});return void 0===r.instanceCredential&&void 0!==r.registrationToken&&this.put(o),o}put(e){const n=Jo.parse(e);this.init();const i=this.filePath(n.instanceId);return I.sync(i,`${JSON.stringify(n,null,2)}\n`,{encoding:"utf8",mode:384}),t.chmodSync(i,384),n}materialize(e,t,n){if(!t)throw Object.assign(new Error(`Instance ${e} does not have a long-lived credential.`),{statusCode:409,code:"INSTANCE_PRIVATE_CONFIG_CREDENTIAL_MISSING"});return this.put({version:1,instanceId:e,instanceCredential:t,environment:n,updatedAt:(new Date).toISOString()})}delete(e){t.rmSync(this.filePath(e),{force:!0})}}const Yo=function(e,t=process.env,n=e){let i;return()=>{const r=t.TASK_HANDOFF_VERSION?.trim();return r||(i||=E(e,t,n),i)}}("@task-handoff/node-agent",process.env,"@task-handoff/control-plane");function Xo(){return Yo()}function Qo(e,t){return{code:"INSTANCE_RUNTIME_VERSION_MISMATCH",message:`Expected controlled-instance ${e}, received ${t||"an unknown version"}.`,expectedVersion:e,...t?{actualVersion:t}:{},retryable:!0}}function Zo(e){const t=Xo();return e===t?{desiredVersion:t,actualVersion:e,phase:"matched",attempt:0,matchedAt:(new Date).toISOString()}:{desiredVersion:t,...e?{actualVersion:e}:{},phase:"pending",attempt:0,error:Qo(t,e)}}function es(e,t,n=!0){if(!n)return Zo(t);const i=Xo(),r=e.runtimeVersion;if(!r||r.desiredVersion!==i)return Zo(t);const o="INSTANCE_RUNTIME_VERSION_MISMATCH"!==r.error?.code?r.error:t===i?void 0:Qo(i,t);return An.parse({...r,desiredVersion:i,...t?{actualVersion:t}:{actualVersion:void 0},..."pending"===r.phase?{error:o||(t!==i?Qo(i,t):void 0)}:{}})}const ts="runtime_local_host",ns="task-handoff.node-agent.builtin";function is(){return(new Date).toISOString()}function rs(e){const t={...e};return delete t[ns],t}function os(e){return"local-folder"===e.type?On.parse({mode:"local-bind",path:"/workspace",readOnly:!1}):On.parse({mode:"git-clone",path:"/workspace",readOnly:!1})}function ss(e){const t=kn.parse(e.source),n=e.projectId||("local-folder"===t.type?t.localFolderId:void 0)||("git-repository"===t.type?t.repositoryId:void 0)||("git-template"===t.type?t.templateId:void 0)||`project_${e.id}`;return xn.parse({id:n,name:"string"==typeof e.sourceSnapshot.name?e.sourceSnapshot.name:e.name,source:t,defaultImageSelection:e.imageSelection,defaultNodeId:e.nodeId,defaultRuntimeId:e.runtimeId,workspacePolicy:os(t),labels:{},createdAt:e.createdAt,updatedAt:e.updatedAt})}function as(e,t){throw Object.assign(new Error(t),{statusCode:403,code:e})}function cs(e,t){e!==It&&console.warn(JSON.stringify({message:"protocol version mismatch",peer:t,expectedProtocolVersion:It,actualProtocolVersion:e||"missing",errorCode:"PROTOCOL_VERSION_MISMATCH"}))}function ds(e){return"none"!==e.capabilities.artifactKind}function ls(e={}){return{...e,requiresImage:!1,supportsControlledInstanceApi:!0,supportsContainerLifecycle:!1,supportsAppSessions:!0,supportsHostSessions:!0,artifactKind:"none",isolation:"none"}}class us extends Co{onStored;privateConfigs;constructor(e,t,n){super(e,t),this.privateConfigs=n}setOnStored(e){this.onStored=e}put(e){const t=super.get(e.id)?.stateRevision||0,n=this.privateConfigs.get(e.id),i=e.registrationToken||n?.instanceCredential;i&&this.privateConfigs.materialize(e.id,i,n?.environment||{});const{registrationToken:r,...o}=e,s=super.put(Si.parse({...o,stateRevision:Math.max(e.stateRevision||0,t)+1})),a=this.hydrate(s);return this.onStored?.(a),a}get(e){const t=super.get(e);return t?this.hydrate(t):void 0}list(){return super.list().map(e=>this.hydrate(e))}hydrate(e){const t=this.privateConfigs.get(e.id)?.instanceCredential||e.registrationToken;return Si.parse({...e,registrationToken:t})}}class ms{nodeId;paths;localFolders;nodeRuntimes;controlledInstances;environmentTemplates;instancePrivateConfigs;modelRegistry;updateJobs;node;listenerPort;containerUrlOverride;platform;constructor(e,t,n,i,r,o){this.paths=e,this.nodeId=t,this.localFolders=new Co(e.localFoldersDir,{schema:Cn,sanitize:Wt}),this.nodeRuntimes=new Co(e.nodeRuntimesDir,{schema:hi}),this.instancePrivateConfigs=new Wo(e),this.controlledInstances=new us(e.controlledInstancesDir,{schema:Si,sanitize:e=>Ci(e,e=>{console.warn(JSON.stringify({message:"legacy controlled instance field was ignored",...e}))})},this.instancePrivateConfigs),this.environmentTemplates=new Ko(e),this.modelRegistry=new Lo(e,t,{has:e=>Boolean(this.controlledInstances.get(e)),list:()=>this.listInstances(),require:e=>this.requireInstance(e),put:e=>this.controlledInstances.put(e)}),this.updateJobs=new Ho(e),this.listenerPort=r,this.platform=o,this.containerUrlOverride=i;const s=is();this.node=pi.parse({id:t,name:t,connectionMode:"direct-http",endpoint:n,controlEndpoint:n,containerEndpoint:this.containerUrl,publicWebBase:n?n.replace(/:\d+$/,""):void 0,status:"online",health:"ok",capabilities:{},labels:{},createdAt:s,updatedAt:s})}init(){this.localFolders.init();for(const e of this.localFolders.list())this.localFolders.put(e);if(this.nodeRuntimes.init(),this.instancePrivateConfigs.init(),this.controlledInstances.init(),this.environmentTemplates.init(),this.modelRegistry.init(),this.updateJobs.init(),this.updateJobs.reconcileRollouts(this.controlledInstances.list(),Xo(),{processStarted:!0}),!this.nodeRuntimes.get("runtime_local_docker")){const e=is();this.nodeRuntimes.put(hi.parse({id:"runtime_local_docker",nodeId:this.nodeId,name:"Local Docker",type:"docker",status:"unknown",accessStrategy:"direct-port",capabilities:{},labels:{},createdAt:e,updatedAt:e}))}if("win32"!==this.platform){const e=this.nodeRuntimes.get(ts),t=is();this.nodeRuntimes.put(hi.parse({id:ts,nodeId:this.nodeId,name:"Local Runtime",type:"local",status:e?.status||"unknown",accessStrategy:"node-proxy",capabilities:ls(e?.capabilities),labels:{...e?.labels,[ns]:"true"},createdAt:e?.createdAt||t,updatedAt:e?.updatedAt||t}))}for(const e of this.nodeRuntimes.list())e.nodeId!==this.nodeId&&this.nodeRuntimes.put(hi.parse({...e,nodeId:this.nodeId,updatedAt:is()}));for(const e of this.localFolders.list())e.nodeId!==this.nodeId&&this.localFolders.put(Cn.parse({...e,nodeId:this.nodeId,updatedAt:is()}));this.normalizeInstanceRuntimeVersions()}normalizeInstanceRuntimeVersions(){for(const e of this.controlledInstances.list()){const t=Zo(e.build?.packageVersion||e.instanceVersion),n=ds(this.requireRuntime(e.runtimeId)),i=["created","stopped","failed"].includes(e.status),r=n&&e.runtimeVersion?.desiredVersion===t.desiredVersion?e.runtimeVersion:void 0,o=n?"matched"===t.phase?i?t:{...t,phase:"verifying",matchedAt:void 0}:{...t,phase:"pending",attempt:r?.attempt||0,lastAttemptAt:r?.lastAttemptAt,error:r?.error||t.error}:t;this.controlledInstances.put(Si.parse({...e,ready:!1,runtimeVersion:o,updatedAt:is()}))}}get localNodeAgentUrl(){return`http://127.0.0.1:${this.listenerPort}`}get currentListenerPort(){return this.listenerPort}get containerUrl(){return this.containerUrlOverride||`http://host.docker.internal:${this.listenerPort}`}setListenerPort(e){this.listenerPort=e,this.node.containerEndpoint=this.containerUrl,this.node.updatedAt=is()}runningInstanceCount(){const e=new Set(["created","stopped","failed"]);return this.listInstances().filter(t=>!e.has(t.status)).length}createLocalFolder(e){const t=is(),n=Cn.parse({...e,id:e.id||zo("folder"),nodeId:this.nodeId,labels:e.labels||{},createdAt:t,updatedAt:t});return this.localFolders.put(n)}createRuntime(e){if("local"===e.type){const e="win32"===this.platform,t=new Error(e?"Local Runtime is not supported on Windows.":"Local Runtime is built in and cannot be added manually.");throw Object.assign(t,{statusCode:e?400:409,code:e?"LOCAL_RUNTIME_UNSUPPORTED":"LOCAL_RUNTIME_BUILTIN"}),t}const t=is(),n=hi.parse({...e,id:e.id||zo("runtime"),nodeId:this.nodeId,accessStrategy:e.accessStrategy||(i=e.type,"docker"===i?"direct-port":"node-proxy"),capabilities:e.capabilities||{},labels:rs(e.labels),createdAt:t,updatedAt:t});var i;return this.nodeRuntimes.put(n)}updateRuntime(e,t){const n=this.requireRuntime(e);if("true"===n.labels[ns]){const t=new Error(`Built-in runtime ${e} cannot be modified.`);throw Object.assign(t,{statusCode:400,code:"NODE_RUNTIME_BUILTIN"}),t}if("local"===n.type||"local"===t.type){const e="win32"===this.platform,t=new Error(e?"Local Runtime is not supported on Windows.":"Local Runtime is built in and cannot be configured manually.");throw Object.assign(t,{statusCode:e?400:409,code:e?"LOCAL_RUNTIME_UNSUPPORTED":"LOCAL_RUNTIME_BUILTIN"}),t}const i=hi.parse({...n,...t,id:n.id,nodeId:this.nodeId,accessStrategy:t.accessStrategy||n.accessStrategy,capabilities:t.capabilities||n.capabilities,labels:t.labels?rs(t.labels):n.labels,createdAt:n.createdAt,updatedAt:is()});return this.nodeRuntimes.put(i)}deleteRuntime(e){if("true"===this.requireRuntime(e).labels[ns]){const t=new Error(`Built-in runtime ${e} cannot be deleted.`);throw Object.assign(t,{statusCode:400,code:"NODE_RUNTIME_BUILTIN"}),t}const t=this.listInstances().filter(t=>t.runtimeId===e);if(t.length){const n=new Error(`Runtime ${e} is used by ${t.length} instance${1===t.length?"":"s"}.`);throw Object.assign(n,{statusCode:409,code:"NODE_RUNTIME_IN_USE"}),n}return this.nodeRuntimes.delete(e)}checkRuntime(e,t){const n=this.requireRuntime(e);return t.check?t.check(n).then(e=>{const t=hi.parse({...n,...e,id:n.id,nodeId:this.nodeId,createdAt:n.createdAt,updatedAt:is()});return this.nodeRuntimes.put(t)}):this.nodeRuntimes.put(hi.parse({...n,status:"unknown",updatedAt:is()}))}requireRuntime(e){const t=this.nodeRuntimes.get(e);if(!t){const t=new Error(`Node runtime ${e} was not found.`);throw Object.assign(t,{statusCode:404,code:"NODE_RUNTIME_NOT_FOUND"}),t}return t}requireInstance(e){const t=this.controlledInstances.get(e);if(!t){const t=new Error(`Instance ${e} was not found on node ${this.nodeId}.`);throw Object.assign(t,{statusCode:404,code:"NODE_INSTANCE_NOT_FOUND"}),t}const n=_i(t);if(!n.success)throw function(e,t){const n=t.map(e=>`${e.path.join(".")||"body"}: ${e.message}`).join("; ");return Object.assign(new Error(`Stored instance ${e} is not compatible with protocol ${It}: ${n}`),{statusCode:409,code:"NODE_INSTANCE_PAYLOAD_INVALID"})}(e,n.error.issues);return n.data}applyInstanceLifecycle(e,t){return this.controlledInstances.put(function(e,t,n=(new Date).toISOString()){switch(t.type){case"start-requested":return Si.parse({...e,status:"starting",ready:!1,updatedAt:n});case"stop-requested":return Si.parse({...e,status:"stopping",ready:!1,updatedAt:n});case"stop-failed":return"stopping"!==e.status?e:Si.parse({...e,status:t.baseline.status,health:t.baseline.health,connectionStatus:t.baseline.connectionStatus,agentStatus:t.baseline.agentStatus,targetStatus:t.baseline.targetStatus,uiAccessStatus:t.baseline.uiAccessStatus,ready:t.baseline.ready,target:{...e.target,status:t.baseline.target.status},updatedAt:n});case"convergence-restart-requested":return Si.parse({...e,build:void 0,instanceVersion:void 0,ready:!1,updatedAt:n});case"runtime-lifecycle-completed":return function(e,t,n,i){if(t.stateRevision>e.stateRevision&&["failed","stopping","stopped","deleting"].includes(t.status))return t;const r=t.stateRevision>e.stateRevision&&t.lastHeartbeatAt!==e.lastHeartbeatAt&&"online"===t.agentStatus;return Si.parse({...t,...n,...r?{status:t.status,health:t.health,connectionStatus:t.connectionStatus,agentStatus:t.agentStatus,targetStatus:t.targetStatus,uiAccessStatus:t.uiAccessStatus}:{},ready:!!r&&t.ready,target:n.target?r?{...n.target,...t.target}:{...t.target,...n.target}:t.target,workspace:n.workspace?r?{...n.workspace,...t.workspace}:{...t.workspace,...n.workspace}:t.workspace,runtime:n.runtime?{...t.runtime,...n.runtime}:t.runtime,updatedAt:i})}(t.baseline,e,t.observation,n);case"stop-completed":return Si.parse({...e,status:"stopped",health:"unknown",connectionStatus:"offline",ready:!1,agentStatus:"offline",targetStatus:"unknown",uiAccessStatus:"unknown",target:{...e.target,status:"unknown"},updatedAt:n});case"runtime-exited":case"start-failed":return Si.parse({...e,status:"failed",ready:!1,health:"failed",connectionStatus:"offline",agentStatus:"offline",targetStatus:"unknown",uiAccessStatus:"unknown",workspace:{...e.workspace,error:(i=t.error,i instanceof Error?i.message:String(i))},updatedAt:n})}var i}(this.requireInstance(e),t))}listInstances(){return this.controlledInstances.list().flatMap(e=>{const t=_i(e);return t.success?[t.data]:[]})}resolvedAssignedModelEnvironment(e){return this.modelRegistry.resolvedEnvironment(e)}createInstance(e){const t=this.requireRuntime(e.runtimeId),i=is(),r=e.id||zo("inst"),o=kn.parse(e.source),s=e.environmentSource||(e.imageSelection?{type:"image",imageSelection:e.imageSelection}:void 0);if("template"===s?.type&&"docker"!==t.type){const e=new Error(`Runtime ${t.name} does not support environment templates.`);throw Object.assign(e,{statusCode:409,code:"ENVIRONMENT_TEMPLATE_RUNTIME_UNSUPPORTED"}),e}const a="template"===s?.type?this.environmentTemplates.get(s.environmentTemplateId):void 0;if("template"===s?.type&&(!a||"ready"!==a.status)){const e=new Error(`Environment template ${s.environmentTemplateId} is not ready on node ${this.nodeId}.`);throw Object.assign(e,{statusCode:a?409:404,code:a?"ENVIRONMENT_TEMPLATE_NOT_READY":"ENVIRONMENT_TEMPLATE_NOT_FOUND"}),e}if(a&&a.nodeId!==this.nodeId){const e=new Error(`Environment template ${a.id} belongs to node ${a.nodeId}, not ${this.nodeId}.`);throw Object.assign(e,{statusCode:409,code:"ENVIRONMENT_TEMPLATE_NODE_MISMATCH"}),e}if(function(e){return"boolean"==typeof e.capabilities.requiresImage?e.capabilities.requiresImage:"local"!==e.type}(t)&&(!s||"image"===s.type&&!e.image)){const e=new Error(`Runtime ${t.name} requires an image.`);throw Object.assign(e,{statusCode:400,code:"NODE_RUNTIME_IMAGE_REQUIRED"}),e}if("local"===t.type&&"local-folder"!==o.type){const e=new Error("Localhost runtime currently supports local folder sources only.");throw Object.assign(e,{statusCode:400,code:"LOCAL_RUNTIME_REQUIRES_LOCAL_FOLDER"}),e}if("local"===t.type&&this.listInstances().some(e=>"local"===this.requireRuntime(e.runtimeId).type)){const e=new Error("A localhost instance already exists on this node.");throw Object.assign(e,{statusCode:409,code:"LOCAL_RUNTIME_INSTANCE_EXISTS"}),e}const c=a?ri.parse({id:a.id,origin:"custom",name:a.name,repository:"task-handoff/environment-template",tag:a.id.toLowerCase().replace(/[^a-z0-9_.-]/g,"-"),requestedReference:a.internalTag,resolvedDigest:a.imageId,resolvedReference:a.internalTag,downloadSizeBytes:a.sizeBytes||void 0,pullPolicy:"if-not-present",capabilities:[],optionalApps:[],defaultEnv:{},labels:{},createdAt:a.createdAt,updatedAt:a.updatedAt}):e.image?ri.parse(e.image):void 0,d="local"===t.type&&"local-folder"===o.type?n.resolve(o.path):void 0,l=Si.parse({id:r,name:e.name||`instance-${r.replace(/^inst_?/,"").slice(0,6)}`,source:o,sourceSnapshot:e.sourceSnapshot||{},modelSelection:e.modelSelection,projectId:e.projectId,nodeId:this.nodeId,runtimeId:t.id,imageSelection:"image"===s?.type?s.imageSelection:void 0,environmentSource:s,environmentTemplateOrigin:a?{templateId:a.id,nodeId:a.nodeId,imageId:a.imageId,name:a.name,platform:a.platform,architecture:a.architecture}:void 0,imageSnapshot:c,imageProvisioning:c&&"docker"===t.type&&"template"!==s?.type?{phase:"checking-image",requestedReference:c.requestedReference,generation:0,startedAt:i,updatedAt:i}:void 0,status:c&&"docker"===t.type&&"template"!==s?.type?"provisioning":"created",health:"unknown",connectionStatus:"unknown",agentStatus:"unknown",targetStatus:"unknown",uiAccessStatus:"unknown",controlMode:"controlled",ready:!1,runtimeVersion:Zo(),capabilities:{},config:{autoImportAgentConfigs:e.config?.autoImportAgentConfigs??!0,defaultCodexPermissionMode:e.config?.defaultCodexPermissionMode??("docker"===t.type?"full-access":"ask")},workspace:"local"===t.type?{mode:"local-bind",status:"unknown",path:d}:{status:"unknown"},target:{strategy:"node-proxy",status:"unknown"},runtime:"local"===t.type?{kind:"local",workspacePath:d,labels:{"task-handoff.runtime-kind":"local"}}:{labels:{}},registrationToken:_o(),createdAt:i,updatedAt:i}),u=this.controlledInstances.put(l);return this.instancePrivateConfigs.materialize(u.id,u.registrationToken,this.resolvedAssignedModelEnvironment(u.id)),u}registerInstance(e,t,n){const i=xi.parse(t),r=is(),o=this.controlledInstances.get(e);if(!o){const t=new Error(`Instance ${e} was not found on node ${this.nodeId}.`);throw Object.assign(t,{statusCode:404,code:"NODE_INSTANCE_NOT_FOUND"}),t}if(this.validateInstanceReport(o,i,n),i.processIncarnationId&&i.processIncarnationId===o.processIncarnationId)return o;cs(i.protocolVersion,`Instance ${e}`);const s=i.build?.packageVersion||i.instanceVersion,a=ds(this.requireRuntime(o.runtimeId)),c=es(o,s,a),d=Si.parse({...o,status:"registered",health:s===Xo()?"ok":"degraded",ready:!a&&s===Xo(),connectionStatus:"online",agentStatus:"online",targetStatus:"endpoint-unreachable"===i.target.status?"endpoint-unreachable":"reachable"===i.target.status?"reachable":o.targetStatus,uiAccessStatus:"endpoint-unreachable"===i.target.status?"endpoint-unreachable":o.uiAccessStatus,controlMode:i.controlMode,protocolVersion:i.protocolVersion,instanceVersion:i.instanceVersion,build:i.build,runtimeVersion:c,processIncarnationId:i.processIncarnationId||o.processIncarnationId,capabilities:i.capabilities,appInventory:i.appInventory,workspace:i.workspace,target:{...o.target,...i.target},registrationToken:o.registrationToken||i.registrationToken,lastHeartbeatAt:r,updatedAt:r});return this.controlledInstances.put(d)}heartbeatInstance(e,t,n){const i=this.requireInstance(e);this.validateInstanceToken(i,n);const r=Di.parse(t);i.processIncarnationId&&r.processIncarnationId&&r.processIncarnationId!==i.processIncarnationId&&function(e,t){throw Object.assign(new Error(t),{statusCode:409,code:"INSTANCE_PROCESS_INCARNATION_MISMATCH"})}(0,`Instance ${e} report belongs to an obsolete controlled-instance process.`),cs(r.protocolVersion,`Instance ${e}`);const o=is(),s=r.target?{...i.target,...r.target}:i.target,a={...s,status:"unknown"===s.status&&(s.web||s.api)?"reachable":s.status},c="endpoint-unreachable"===a.status?"endpoint-unreachable":"reachable"===a.status?"reachable":i.targetStatus,d=es(i,r.build?.packageVersion||i.build?.packageVersion||i.instanceVersion,ds(this.requireRuntime(i.runtimeId))),l=r.health||i.health,u="running"===(r.status||i.status)&&"failed"!==l,m=Si.parse({...i,...r,target:a,ready:u,health:l,runtimeVersion:d,processIncarnationId:r.processIncarnationId||i.processIncarnationId,agentStatus:"online",targetStatus:c,uiAccessStatus:c,connectionStatus:"online",build:r.build||i.build,lastHeartbeatAt:o,updatedAt:o});return this.controlledInstances.put(m)}validateInstanceReport(e,t,n){this.validateInstanceToken(e,n||t.registrationToken),t.instanceId&&t.instanceId!==e.id&&as("INSTANCE_ID_MISMATCH",`Instance ${t.instanceId} cannot register as ${e.id}.`),t.nodeId&&t.nodeId!==this.nodeId&&as("INSTANCE_NODE_MISMATCH",`Instance ${e.id} belongs to node ${this.nodeId}.`),t.runtimeId&&t.runtimeId!==e.runtimeId&&as("INSTANCE_RUNTIME_MISMATCH",`Instance ${e.id} belongs to runtime ${e.runtimeId}.`),t.imageSelection&&t.imageSelection.imageId!==e.imageSelection?.imageId&&as("INSTANCE_IMAGE_MISMATCH",`Instance ${e.id} belongs to image ${e.imageSelection?.imageId}.`)}validateInstanceToken(e,t){e.registrationToken&&t===e.registrationToken||as("INSTANCE_REGISTRATION_TOKEN_INVALID",`Invalid registration token for instance ${e.id}.`)}context(e,t=this.resolvedAssignedModelEnvironment(e.id)){const n=e.imageSnapshot||ri.parse({id:"img_localhost",origin:"custom",name:"Localhost",repository:"localhost",tag:"local",requestedReference:"localhost:local",pullPolicy:"if-not-present",capabilities:[],optionalApps:[],defaultEnv:{},labels:{},createdAt:e.createdAt,updatedAt:e.updatedAt}),i=this.instancePrivateConfigs.materialize(e.id,e.registrationToken,t);return{project:ss(e),image:n,node:this.node,runtime:this.requireRuntime(e.runtimeId),instance:e,nodeAgentUrl:this.containerUrl,modelEnv:t,privateConfigPath:this.instancePrivateConfigs.filePath(i.instanceId)}}}const ps=a.z.object({path:a.z.string().trim().min(1).max(2048),method:a.z.string().trim().min(1).max(20).default("GET"),headers:a.z.record(a.z.string(),a.z.string()).default({}),body:a.z.string().optional(),bodyBase64:a.z.string().optional()}).strict(),hs=a.z.object({id:a.z.string().trim().min(1).max(120).optional(),name:a.z.string().trim().min(1).max(160),path:a.z.string().trim().min(1).max(4096),defaultImageSelection:Mt.optional(),labels:a.z.record(a.z.string(),a.z.string()).default({})}).strict(),gs=a.z.object({path:a.z.string().trim().min(1).max(4096).optional(),depth:a.z.coerce.number().int().min(0).max(1).default(0)}).strict(),fs=a.z.object({id:a.z.string().trim().min(1).max(120).optional(),name:a.z.string().trim().min(1).max(160).optional(),runtimeId:a.z.string().trim().min(1).max(120),imageSelection:Mt.optional(),environmentSource:Lt.optional(),projectId:a.z.string().trim().min(1).max(120).optional(),image:ri.optional(),source:kn,sourceSnapshot:a.z.record(a.z.string(),a.z.unknown()).default({}),config:a.z.object({autoImportAgentConfigs:a.z.boolean().optional(),defaultCodexPermissionMode:me.optional()}).strict().optional(),modelSelection:Si.shape.modelSelection}).strict().superRefine((e,t)=>{e.environmentSource&&e.imageSelection&&t.addIssue({code:"custom",path:["environmentSource"],message:"environmentSource and imageSelection are mutually exclusive."}),"template"===e.environmentSource?.type&&e.image&&t.addIssue({code:"custom",path:["image"],message:"Template environment source is resolved by the node-agent and cannot include an image snapshot."})}),ys=a.z.object({name:a.z.string().trim().min(1).max(160).optional(),config:a.z.object({autoImportAgentConfigs:a.z.boolean().optional(),defaultCodexPermissionMode:me.optional()}).strict().optional(),modelSelection:Si.shape.modelSelection.optional()}).strict(),Is=a.z.object({id:a.z.string().trim().min(1).max(120).optional(),name:a.z.string().trim().min(1).max(160),type:a.z.enum(["docker","kubernetes","local"]),status:a.z.enum(["unknown","online","offline","degraded"]).default("unknown"),accessStrategy:a.z.enum(["node-proxy","direct-port","kubernetes-ingress","kubernetes-port-forward"]).optional(),capabilities:a.z.record(a.z.string(),a.z.unknown()).default({}),labels:a.z.record(a.z.string(),a.z.string()).default({})}).strict(),As=Is.omit({id:!0}).partial().strict();function bs(e){const t=e.authorization;return"string"==typeof t&&t.startsWith("Bearer ")?t.slice(7).trim():void 0}class ws{operations=new Map;intents=new Map;intent(e){const t=this.intents.get(e);if(t)return t;const n={};return this.intents.set(e,n),n}invalidate(e){const t={};return this.intents.set(e,t),t}isIntentCurrent(e,t){return this.intents.get(e)===t}clearIntent(e){this.intents.delete(e)}async run(e,t){const n=this.operations.get(e)||Promise.resolve();let i;const r=new Promise(e=>{i=e});this.operations.set(e,r),await n;try{return await t()}finally{i(),this.operations.get(e)===r&&this.operations.delete(e)}}}const vs=a.z.object({}).strict().default({});function Es(){return(new Date).toISOString()}function Ns(){return(new Date).toISOString()}class Ss{state;images;options;inFlight=new Map;abortController=new AbortController;stopped=!1;constructor(e,t,n){this.state=e,this.images=t,this.options=n}retry(e){const t=this.state.requireInstance(e);if("docker"!==this.state.requireRuntime(t.runtimeId).type||!t.imageSnapshot)throw Object.assign(new Error(`Instance ${e} does not use a Docker image.`),{statusCode:400,code:"INSTANCE_IMAGE_PROVISIONING_UNSUPPORTED"});if("failed"!==t.status||"failed"!==t.imageProvisioning?.phase)throw Object.assign(new Error(`Instance ${e} does not have failed image provisioning to retry.`),{statusCode:409,code:"INSTANCE_IMAGE_PROVISIONING_NOT_FAILED"});const n=Ns();return this.state.controlledInstances.put(Si.parse({...t,status:"provisioning",health:"unknown",imageProvisioning:{phase:"checking-image",requestedReference:t.imageSnapshot.requestedReference,generation:(t.imageProvisioning?.generation||0)+1,startedAt:n,updatedAt:n},updatedAt:n}))}provision(e,t){if(this.stopped)return Promise.resolve();const n=e.imageProvisioning?.generation;if(void 0===n)return Promise.resolve();const i=`${e.id}:${n}`,r=this.inFlight.get(i);if(r)return r;const o=this.provisionGeneration(e,n,t).finally(()=>{this.inFlight.get(i)===o&&this.inFlight.delete(i)});return this.inFlight.set(i,o),o}async stop(){this.stopped=!0,this.abortController.abort(),await Promise.allSettled([...this.inFlight.values()])}async provisionGeneration(e,t,n){const i=this.currentGeneration(e.id,t,!0,e.createdAt);if(!i)return;let r,o=0,s=!1,a=Promise.resolve();try{const c=await this.images.ensure(i.imageSnapshot.requestedReference,n=>{a=a.then(async()=>{if(!r)try{await this.updatePhase(e.id,t,n,e.createdAt)}catch(e){r={error:e}}})},n=>{this.stopped||(s=!0,o=n.sequence,this.publishTerminalOutput(e,t,n))},this.abortController.signal);if(await a,r)throw r.error;if(this.stopped)return;s&&this.publishFinished(e,t,o+1,"succeeded");const d=async()=>{if(this.stopped)return;const i=this.currentGeneration(e.id,t,!0,e.createdAt);if(!i)return;const r=this.state.controlledInstances.put(Si.parse({...i,status:"provisioning"===i.status?"created":i.status,health:"unknown",imageSnapshot:{...i.imageSnapshot,requestedReference:c.requestedReference,resolvedDigest:c.resolvedDigest,resolvedReference:c.resolvedReference},imageProvisioning:{...i.imageProvisioning,phase:"ready",error:void 0,updatedAt:Ns()},updatedAt:Ns()}));this.options.sync(),this.options.diagnostic({instanceId:e.id,action:"image.provision",reference:c.requestedReference,digest:c.resolvedDigest,pulled:c.pulled},"node instance image provisioning completed"),"starting"===r.status&&await(n?.())};await(this.options.runInstanceOperation?.(e.id,d)??d())}catch(n){if(await a,r&&(n=r.error),this.stopped)return;s&&this.publishFinished(e,t,o+1,"failed");const i=n instanceof Error?n.message:String(n),c=async()=>{if(this.stopped)return;const n=this.currentGeneration(e.id,t,!1,e.createdAt);n?.imageProvisioning&&["provisioning","starting"].includes(n.status)&&(this.state.controlledInstances.put(Si.parse({...n,status:"failed",health:"failed",imageProvisioning:{...n.imageProvisioning,phase:"failed",error:i,updatedAt:Ns()},updatedAt:Ns()})),this.options.sync(),this.options.warn({instanceId:e.id,action:"image.provision",reference:n.imageProvisioning.requestedReference,error:i},"node instance image provisioning failed"))};await(this.options.runInstanceOperation?.(e.id,c)??c())}}currentGeneration(e,t,n=!0,i){const r=this.state.controlledInstances.get(e);if(!(!r||i&&r.createdAt!==i||r.imageProvisioning?.generation!==t||n&&!r.imageSnapshot))return r}async updatePhase(e,t,n,i){if(this.stopped)return;const r=async()=>{if(this.stopped)return;const r=this.currentGeneration(e,t,!0,i);r&&["provisioning","starting"].includes(r.status)&&(this.state.controlledInstances.put(Si.parse({...r,status:"starting"===r.status?"starting":"provisioning",imageProvisioning:{...r.imageProvisioning,phase:n,error:void 0,updatedAt:Ns()},updatedAt:Ns()})),this.options.sync())};await(this.options.runInstanceOperation?.(e,r)??r())}eventBase(e,t){return{instanceId:e.id,generation:t,requestedReference:e.imageProvisioning.requestedReference,observedAt:Ns()}}publishTerminalOutput(e,t,n){for(const[i,r]of function(e,t=6e4){const n=[];for(let i=0;i<e.length;i+=t)n.push(e.slice(i,i+t));return n}(n.data).entries())this.options.publish(si,{...this.eventBase(e,t),sequence:1e3*n.sequence+i,data:r,...n.replay?{replay:!0}:{}},e.id)}publishFinished(e,t,n,i){this.options.publish(ai,{...this.eventBase(e,t),sequence:1e3*n,outcome:i},e.id)}}const Ts=a.z.object({name:a.z.string().trim().min(1).max(160)}).strict();function zs(){return(new Date).toISOString()}function _s(e,t,n){return{code:"object"==typeof e&&e&&"code"in e&&"string"==typeof e.code?e.code:t,message:e instanceof Error?e.message:String(e),phase:n}}class Cs{templateOperations=new ws;store;privateConfigs;docker;requireInstanceValue;requireRuntimeValue;runInstanceOperationValue;isImageReferencedValue;constructor(e,t,n,i,r,o,s=()=>!1){this.store=e,this.privateConfigs=t,this.docker=n,this.requireInstanceValue=i,this.requireRuntimeValue=r,this.runInstanceOperationValue=o,this.isImageReferencedValue=s}list(){return this.store.list()}require(e){const t=this.store.get(e);if(!t)throw Object.assign(new Error(`Environment template ${e} was not found.`),{statusCode:404,code:"ENVIRONMENT_TEMPLATE_NOT_FOUND"});return t}runTemplateOperation(e,t){return this.templateOperations.run(e,async()=>t())}async create(e,t){const n=Ts.parse(t),i=this.requireInstanceValue(e),r=this.requireRuntimeValue(i.runtimeId);if("docker"!==r.type)throw Object.assign(new Error(`Runtime ${r.name} does not support environment templates.`),{statusCode:409,code:"ENVIRONMENT_TEMPLATE_RUNTIME_UNSUPPORTED"});if(!i.runtime.containerName)throw Object.assign(new Error(`Instance ${i.id} does not have a Docker container.`),{statusCode:409,code:"ENVIRONMENT_TEMPLATE_CONTAINER_NOT_FOUND"});const o=zs(),s=zo("envtpl"),a=`task-handoff/environment-template:${s.toLowerCase().replace(/[^a-z0-9_.-]/g,"-")}`;return this.store.put(Zt.parse({id:s,name:n.name,sourceInstanceId:i.id,nodeId:i.nodeId,internalTag:a,status:"creating",createdAt:o,updatedAt:o})),this.runInstanceOperationValue(i.id,async()=>{let e,t=!1;try{const n=this.requireInstanceValue(i.id);if("docker"!==this.requireRuntimeValue(n.runtimeId).type||!n.runtime.containerName)throw Object.assign(new Error(`Instance ${i.id} is no longer a valid Docker template source.`),{code:"ENVIRONMENT_TEMPLATE_SOURCE_CHANGED"});const r=this.privateConfigs.get(i.id);if(!r)throw Object.assign(new Error(`Instance ${i.id} private configuration is missing.`),{code:"INSTANCE_PRIVATE_CONFIG_MISSING"});const o=[r.instanceCredential,...Object.values(r.environment)];await this.docker.inspectContainerConfigSecurity(n.runtime.containerName,o),e=await this.docker.commitEnvironmentTemplate(n.runtime.containerName,n.runtime.containerId,a),t=!0;const c=await this.docker.inspectEnvironmentTemplateImage(a);return await this.docker.inspectImageConfigSecurity(a,o),this.store.put(Zt.parse({...this.require(s),...c,status:"ready",error:void 0,updatedAt:zs()}))}catch(n){return t&&(await this.docker.untagEnvironmentTemplate(a,e).catch(()=>!1),e&&await this.docker.garbageCollectEnvironmentTemplateImage(e).catch(()=>!1)),this.store.put(Zt.parse({...this.require(s),status:"failed",error:_s(n,"ENVIRONMENT_TEMPLATE_CREATE_FAILED","commit"),updatedAt:zs()}))}})}async delete(e){return this.runTemplateOperation(e,async()=>{const t=this.require(e);this.store.put(Zt.parse({...t,status:"deleting",error:void 0,updatedAt:zs()}));try{const n=t.internalTag?await this.docker.untagEnvironmentTemplate(t.internalTag,t.imageId):void 0,i=t.imageId||n;return i&&!this.isImageReferencedValue(i)&&await this.docker.garbageCollectEnvironmentTemplateImage(i),this.store.delete(e),{deleted:!0,templateId:e}}catch(e){throw this.store.put(Zt.parse({...t,status:"failed",error:_s(e,"ENVIRONMENT_TEMPLATE_DELETE_FAILED","delete"),updatedAt:zs()})),e}})}async releaseUnusedImage(e){return!this.store.list().some(t=>t.imageId===e)&&!this.isImageReferencedValue(e)&&this.docker.garbageCollectEnvironmentTemplateImage(e)}}const ks=new Set(["DELETE","GET","HEAD","PATCH","POST","PUT","OPTIONS"]);function Os(e){return"string"==typeof e&&ks.has(e.toUpperCase())?e.toUpperCase():"GET"}const Rs=new Set(["content-encoding","content-length","transfer-encoding"]),xs=67108864;function Ds(e){return Object.fromEntries([...e.entries()].filter(([e])=>!Rs.has(e.toLowerCase())))}function Ps(e){return e.bodyBase64?Buffer.from(e.bodyBase64,"base64"):e.body}function Ms(){const e=Number(process.env.TASK_HANDOFF_INSTANCE_PROXY_MAX_RESPONSE_BYTES);return Number.isSafeInteger(e)&&e>0?e:67108864}function Ls(e){return e.startsWith("/")?e:`/${e}`}function js(e,t){return e.code(502).send({error:{code:"INSTANCE_PROXY_RESPONSE_TOO_LARGE",message:`Instance response exceeds ${t} bytes.`}})}const $s=a.z.object({version:a.z.literal(1),externalListener:fi}).strict();function Fs(e){return"all-ipv4"===e?"0.0.0.0":"127.0.0.1"}function Us(e){if(!e||"object"!=typeof e||Array.isArray(e))return e;const t=e,n=t.externalListener&&"object"==typeof t.externalListener&&!Array.isArray(t.externalListener)?t.externalListener:{},i=Object.keys(t).filter(e=>"version"!==e&&"externalListener"!==e),r=Object.keys(n).filter(e=>"bindScope"!==e&&"port"!==e);return(i.length||r.length)&&console.warn(JSON.stringify({message:"unknown stored node agent runtime setting fields were ignored",filePath:"runtime-settings.json",fields:[...i,...r.map(e=>`externalListener.${e}`)]})),{version:t.version,externalListener:{bindScope:n.bindScope,port:n.port}}}async function Vs(e){const t=Fs(e.bindScope);return!await new Promise(t=>{const n=p.createConnection({host:"127.0.0.1",port:e.port}),i=e=>{n.removeAllListeners(),n.destroy(),t(e)};n.once("connect",()=>i(!0)),n.once("error",()=>i(!1)),n.setTimeout(250,()=>i(!1))})&&new Promise(n=>{const i=p.createServer();i.once("error",()=>n(!1)),i.listen({host:t,port:e.port,exclusive:!0},()=>i.close(()=>n(!0)))})}class qs{app;state;settings;sockets=new Set;config;source;status="error";error;onActiveListener;updateQueue=Promise.resolve();constructor(e){this.app=e.app,this.state=e.state,this.settings=e.settings,this.config=e.config,this.source=e.source,this.onActiveListener=e.onActiveListener,this.app.server.on("connection",e=>{this.sockets.add(e),e.once("close",()=>this.sockets.delete(e))})}current(){return yi.parse({...this.config,host:Fs(this.config.bindScope),status:this.status,source:this.source,...this.error?{error:this.error}:{}})}async start(){try{await this.listen(this.config),this.status="listening",this.error=void 0,this.state.setListenerPort(this.config.port)}catch(e){throw this.status="error",this.error=e instanceof Error?e.message:String(e),this.app.log.error({host:Fs(this.config.bindScope),port:this.config.port,error:this.error},"node agent TCP listener failed to start"),Object.assign(new Error(`Failed to bind node agent TCP listener at ${Fs(this.config.bindScope)}:${this.config.port}: ${this.error}`),{statusCode:409,code:"NODE_AGENT_LISTENER_BIND_FAILED"})}const e=this.current();return this.onActiveListener?.(e),e}update(e){const t=this.updateQueue.then(()=>this.updateOnce(e));return this.updateQueue=t.then(()=>{},()=>{}),t}async updateOnce(e){const t=Ii.parse(e);if(t.bindScope===this.config.bindScope&&t.port===this.config.port)return this.current();if(t.port!==this.config.port){const e=this.state.runningInstanceCount();if(e>0)throw Object.assign(new Error(`Cannot change the node agent port while ${e} controlled instance(s) are running.`),{statusCode:409,code:"NODE_AGENT_LISTENER_PORT_IN_USE_BY_INSTANCES",blockingInstanceCount:e})}const n=this.snapshot();await this.stop();try{await this.listen(t)}catch(e){throw await this.restore(n),Object.assign(new Error(`Failed to bind node agent TCP listener at ${Fs(t.bindScope)}:${t.port}: ${e instanceof Error?e.message:String(e)}`),{statusCode:409,code:"NODE_AGENT_LISTENER_BIND_FAILED"})}try{this.settings.put({version:1,externalListener:t})}catch(e){throw await this.stop(),await this.restore(n),Object.assign(new Error(`Failed to persist node agent TCP listener: ${e instanceof Error?e.message:String(e)}`),{statusCode:500,code:"NODE_AGENT_LISTENER_PERSIST_FAILED"})}this.config=t,this.source="persisted",this.status="listening",this.error=void 0,this.state.setListenerPort(t.port);const i=this.current();return this.onActiveListener?.(i),i}async shutdown(){await this.updateQueue,await this.stop()}snapshot(){return{config:this.config,source:this.source,status:this.status,error:this.error}}async restore(e){if(this.config=e.config,this.source=e.source,this.status=e.status,this.error=e.error,"listening"===e.status)try{await this.listen(e.config)}catch(e){this.status="error",this.error=`Failed to restore previous listener: ${e instanceof Error?e.message:String(e)}`,this.app.log.error({error:this.error},"node agent TCP listener rollback failed")}this.state.setListenerPort(e.config.port),"listening"===this.status&&this.onActiveListener?.(this.current())}async listen(e){await new Promise((t,n)=>{const i=e=>{this.app.server.off("listening",r),n(e)},r=()=>{this.app.server.off("error",i),t()};this.app.server.once("error",i),this.app.server.once("listening",r),this.app.server.listen({host:Fs(e.bindScope),port:e.port})})}async stop(){this.app.server.listening&&await new Promise((e,t)=>{this.app.server.close(n=>n?t(n):e());for(const e of this.sockets)e.destroy()})}}const Hs="TASK_HANDOFF_NODE_AGENT_V1",Bs="/api/node-tunnel";function Ks(e=""){return d.createHash("sha256").update(e).digest("hex")}function Gs(e,t){return d.createHmac("sha256",e).update(function(e){return[Hs,e.keyId,e.method.toUpperCase(),e.pathWithQuery,e.timestamp,e.nonce,e.bodySha256].join("\n")}(t)).digest("hex")}function Js(e){const t=e.timestamp||(new Date).toISOString(),n=e.nonce||d.randomBytes(18).toString("base64url"),i=Ks(e.body||""),r=Gs(e.secret,{keyId:e.keyId,method:e.method,pathWithQuery:e.pathWithQuery,timestamp:t,nonce:n,bodySha256:i});return{"x-taskhandoff-node-id":e.nodeId,"x-taskhandoff-key-id":e.keyId,"x-taskhandoff-timestamp":t,"x-taskhandoff-nonce":n,"x-taskhandoff-body-sha256":i,"x-taskhandoff-signature":r}}class Ws{usedNonces=new Map;identity;nodeId;overrideSecret;overrideKeyId;nowMs;constructor(e,t,n,i,r=Date.now){this.identity=e,this.nodeId=t,this.overrideSecret=n,this.overrideKeyId=i,this.nowMs=r}hasRemoteSecrets(){return this.identity.remoteSecrets(this.overrideSecret,this.overrideKeyId).length>0}verify(e){const t=function(e){const t=new Map;for(const[n,i]of Object.entries(e)){const e=Array.isArray(i)?i.join(","):"string"==typeof i?i:void 0===i?"":String(i);t.set(n.toLowerCase(),e)}return{nodeId:t.get("x-taskhandoff-node-id")||"",keyId:t.get("x-taskhandoff-key-id")||"",timestamp:t.get("x-taskhandoff-timestamp")||"",nonce:t.get("x-taskhandoff-nonce")||"",bodySha256:t.get("x-taskhandoff-body-sha256")||"",signature:t.get("x-taskhandoff-signature")||""}}(e.headers);if(!t.nodeId&&!t.signature)return!1;const n="DELETE"===e.method&&"/api/node-agent/pairing/current"===e.url.split("?")[0],i=this.identity.remoteSecrets(this.overrideSecret,this.overrideKeyId,n);if(!i.length)return!1;if(t.nodeId!==this.nodeId)throw Object.assign(new Error("Invalid node agent HMAC node id."),{statusCode:401,code:"NODE_AGENT_HMAC_NODE_MISMATCH"});if(!t.keyId)throw Object.assign(new Error("Node agent HMAC key id is missing."),{statusCode:401,code:"NODE_AGENT_HMAC_KEY_MISSING"});const r=i.filter(e=>t.keyId===e.keyId);if(!r.length)throw Object.assign(new Error("Invalid node agent HMAC key id."),{statusCode:401,code:"NODE_AGENT_HMAC_KEY_INVALID"});const o=Date.parse(t.timestamp);if(!Number.isFinite(o)||Math.abs(this.nowMs()-o)>6e4)throw Object.assign(new Error("Node agent HMAC timestamp is outside the allowed window."),{statusCode:401,code:"NODE_AGENT_HMAC_TIMESTAMP_INVALID"});if(!t.nonce)throw Object.assign(new Error("Node agent HMAC nonce is missing."),{statusCode:401,code:"NODE_AGENT_HMAC_NONCE_MISSING"});this.pruneNonces();const s=`${t.nodeId}:${t.keyId}:${t.nonce}`;if(this.usedNonces.has(s))throw Object.assign(new Error("Node agent HMAC nonce was already used."),{statusCode:401,code:"NODE_AGENT_HMAC_NONCE_REPLAY"});const a=Ks(null==(c=e.body)?"":"string"==typeof c||Buffer.isBuffer(c)?c:JSON.stringify(c));var c;if(t.bodySha256!==a)throw Object.assign(new Error("Node agent HMAC body hash mismatch."),{statusCode:401,code:"NODE_AGENT_HMAC_BODY_HASH_INVALID"});if(!r.some(n=>function(e,t){const n=Buffer.from(e,"hex"),i=Buffer.from(t,"hex");return n.length===i.length&&d.timingSafeEqual(n,i)}(t.signature,Gs(n.secret,{keyId:t.keyId,method:e.method,pathWithQuery:e.url,timestamp:t.timestamp,nonce:t.nonce,bodySha256:a}))))throw Object.assign(new Error("Invalid node agent HMAC signature."),{statusCode:401,code:"NODE_AGENT_HMAC_SIGNATURE_INVALID"});return this.usedNonces.set(s,o+6e4+1),t.keyId}pruneNonces(){const e=this.nowMs();for(const[t,n]of this.usedNonces)n<=e&&this.usedNonces.delete(t)}}const Ys=a.z.string().trim().min(1).max(160),Xs=a.z.string().datetime(),Qs=a.z.string().min(1).max(4096),Zs=a.z.string().trim().url().max(2048),ea=a.z.object({id:Ys,keyId:Ys,name:a.z.string().trim().min(1).max(160).optional(),secret:Qs,pairedAt:Xs,revokedAt:Xs.optional(),updatedAt:Xs}).strip(),ta=a.z.object({id:Ys,pairingKeyId:Ys,name:a.z.string().trim().min(1).max(160).optional(),url:Zs,enabled:a.z.boolean().default(!0),createdAt:Xs,updatedAt:Xs}).strip(),na=a.z.object({controlPlaneName:a.z.string().trim().min(1).max(160).optional(),controlPlaneUrl:a.z.string().trim().max(2048).optional(),expiresInMs:a.z.number().int().positive().max(36e5).optional()}).strict(),ia=a.z.object({joinToken:a.z.string().trim().min(1).max(4096),controlPlaneId:a.z.string().trim().min(1).max(160).optional(),controlPlaneName:a.z.string().trim().min(1).max(160).optional()}).strict(),ra=a.z.object({controlPlaneUrl:a.z.string().trim().url().max(2048),joinToken:a.z.string().trim().min(1).max(4096),controlPlaneName:a.z.string().trim().min(1).max(160).optional(),activate:a.z.boolean().optional()}).strict();function oa(){return(new Date).toISOString()}const sa=new Set(["nodeId","createdAt","updatedAt","pairingInvites","controlPlanePairings","controlPlaneConnections","remoteControlPlanes"]),aa=new Set(["id","keyId","name","secret","pairedAt","revokedAt","updatedAt"]),ca=new Set(["id","pairingKeyId","name","url","enabled","createdAt","updatedAt"]),da=new Set(["id","keyId","name","url","secret","pairedAt","updatedAt","active"]);function la(e,t){console.warn(JSON.stringify({message:e,...t}))}function ua(e,t){return Object.assign(new Error(e,void 0===t?void 0:{cause:t}),{code:"NODE_AGENT_IDENTITY_INVALID"})}function ma(e,t){return Object.keys(e).filter(e=>!t.has(e))}function pa(e,t,n){const i=Xs.safeParse(e);return i.success?i.data:(n("invalid node agent identity timestamp was replaced",{field:t}),oa())}function ha(e,t){if(!e||"object"!=typeof e||Array.isArray(e))throw ua("Node agent identity must be a JSON object.");const n=e,i=Ys.safeParse(n.nodeId);if(!i.success)throw ua("Node agent identity has an invalid nodeId.",i.error);const r=i.data,o=ma(n,sa);o.length&&t("unknown node agent identity fields were ignored",{fields:o}),Array.isArray(n.pairingInvites)&&n.pairingInvites.length&&t("persisted node agent pairing invites were discarded",{count:n.pairingInvites.length});const s=Array.isArray(n.remoteControlPlanes)?n.remoteControlPlanes.flatMap(e=>{if(!e||"object"!=typeof e||Array.isArray(e))return[];const n=e,i=ma(n,da);i.length&&t("unknown legacy node agent remote control-plane fields were ignored",{fields:i});const r=ea.safeParse(n);if(!r.success)return t("invalid legacy node agent control-plane pairing was ignored",{issues:r.error.issues}),[];const o=n.url?ta.safeParse({id:`connection_${r.data.keyId}`,pairingKeyId:r.data.keyId,name:n.name,url:n.url,enabled:!1!==n.active,createdAt:r.data.pairedAt,updatedAt:r.data.updatedAt}):void 0;return[{pairing:r.data,...o?.success?{connection:o.data}:{}}]}):[],a=(e,n,i,r)=>Array.isArray(e)?e.flatMap(e=>{if(!e||"object"!=typeof e||Array.isArray(e))return t(`invalid node agent ${r} was ignored`,{}),[];const o=ma(e,n);o.length&&t(`unknown node agent ${r} fields were ignored`,{fields:o});const s=i.safeParse(e);return s.success?[s.data]:(t(`invalid node agent ${r} was ignored`,{issues:s.error.issues}),[])}):[];return{nodeId:r,createdAt:pa(n.createdAt,"createdAt",t),updatedAt:pa(n.updatedAt,"updatedAt",t),controlPlanePairings:n.controlPlanePairings?a(n.controlPlanePairings,aa,ea,"control-plane pairing"):s.map(e=>e.pairing),controlPlaneConnections:n.controlPlaneConnections?a(n.controlPlaneConnections,ca,ta,"control-plane connection"):s.flatMap(e=>e.connection?[e.connection]:[])}}class ga{paths;logger;constructor(e,t={}){this.paths=e,this.logger=t.logger||la}read(){let e,n;try{e=t.readFileSync(this.paths.identityPath,"utf8")}catch(e){if("ENOENT"===e.code)return;throw Object.assign(new Error(`Node agent identity could not be read: ${this.paths.identityPath}`,{cause:e}),{code:"NODE_AGENT_IDENTITY_READ_FAILED"})}try{n=JSON.parse(e)}catch(e){throw ua(`Node agent identity contains invalid JSON: ${this.paths.identityPath}`,e)}return ha(n,this.logger)}init(){const e=this.read();if(!e)return;const n=JSON.parse(t.readFileSync(this.paths.identityPath,"utf8"));("pairingInvites"in n||"remoteControlPlanes"in n)&&this.write(e)}write(e){t.mkdirSync(n.dirname(this.paths.identityPath),{recursive:!0});const i=ha({...e,updatedAt:oa()},this.logger);I.sync(this.paths.identityPath,`${JSON.stringify(i,null,2)}\n`,{encoding:"utf8",mode:384})}}class fa{values=new Map;put(e,t){this.prune(),this.values.set(e,t)}take(e){this.prune();const t=this.values.get(e);return t&&this.values.delete(e),t}prune(e=Date.now()){for(const[t,n]of this.values)Date.parse(n.expiresAt)<=e&&this.values.delete(t)}}function ya(){return(new Date).toISOString()}class Ia{store;pairingInvites=new fa;controlPlaneConnectionOperations=new Map;constructor(e){this.store=new ga(e),this.store.init()}async runControlPlaneConnectionOperation(e,t){const n=e.replace(/\/$/,""),i=this.controlPlaneConnectionOperations.get(n)||Promise.resolve();let r;const o=new Promise(e=>{r=e});this.controlPlaneConnectionOperations.set(n,o),await i;try{return await t()}finally{r(),this.controlPlaneConnectionOperations.get(n)===o&&this.controlPlaneConnectionOperations.delete(n)}}resolveNodeId(e){if(e?.trim())return this.writeNodeId(e.trim()),e.trim();const t=this.store.read();if(t?.nodeId)return t.nodeId;const n=zo("node");return this.writeNodeId(n),n}createPairingInvite(e){const t=ya(),n=new Date(Date.now()+(e.expiresInMs||6e5)).toISOString(),i=_o(),r={tokenHash:Ks(i),createdAt:t,expiresAt:n,...e.controlPlaneName?{controlPlaneName:e.controlPlaneName}:{}};return this.pairingInvites.put(r.tokenHash,r),{...r,token:i}}completePairingInvite(e){const t=this.store.read()||this.newIdentity(),n=Ks(e.joinToken),i=this.pairingInvites.take(n);if(!i){const e=new Error("Node agent pairing invite is invalid or expired.");throw Object.assign(e,{statusCode:401,code:"NODE_AGENT_PAIRING_INVITE_INVALID"}),e}const r=ya(),o={id:e.controlPlaneId||zo("cp"),keyId:zo("key"),...e.controlPlaneName||i.controlPlaneName?{name:e.controlPlaneName||i.controlPlaneName}:{},secret:_o(),pairedAt:r,updatedAt:r};return this.store.write({...t,controlPlanePairings:[...(t.controlPlanePairings||[]).filter(e=>e.id!==o.id),o]}),o}stageControlPlaneConnection(e){const{pairing:t,connection:n}=this.createControlPlaneConnection(e),i=this.store.read()||this.newIdentity(),r=n.url.replace(/\/$/,""),o=(i.controlPlaneConnections||[]).filter(e=>e.id===n.id||e.url.replace(/\/$/,"")===r);return this.store.write({...i,controlPlanePairings:[...(i.controlPlanePairings||[]).filter(e=>e.keyId!==t.keyId),t],controlPlaneConnections:[...(i.controlPlaneConnections||[]).filter(e=>e.id!==n.id&&e.url.replace(/\/$/,"")!==r),n]}),{pairing:t,connection:n,replacedConnections:o}}commitControlPlaneConnection(e,t={}){const n=this.store.read()||this.newIdentity(),i={...e.pairing,...t.name?{name:t.name}:{}},r={...e.connection,...t.name?{name:t.name}:{}},o=new Set((n.controlPlaneConnections||[]).map(e=>e.pairingKeyId)),s=new Set(e.replacedConnections.map(e=>e.pairingKeyId));return this.store.write({...n,controlPlanePairings:[...(n.controlPlanePairings||[]).filter(e=>e.keyId!==i.keyId&&(!s.has(e.keyId)||o.has(e.keyId))),i],controlPlaneConnections:[...(n.controlPlaneConnections||[]).filter(e=>e.id!==r.id),r]}),{pairing:i,connection:r}}rollbackControlPlaneConnection(e){const t=this.store.read();if(!t)return;const n=new Set(e.replacedConnections.map(e=>e.id));this.store.write({...t,controlPlanePairings:(t.controlPlanePairings||[]).filter(t=>t.keyId!==e.pairing.keyId),controlPlaneConnections:[...(t.controlPlaneConnections||[]).filter(t=>t.id!==e.connection.id&&!n.has(t.id)),...e.replacedConnections]})}createControlPlaneConnection(e){const t=ya(),n={id:zo("cp"),keyId:zo("key"),...e.name?{name:e.name}:{},secret:_o(),pairedAt:t,updatedAt:t};return{pairing:n,connection:{id:zo("connection"),pairingKeyId:n.keyId,...e.name?{name:e.name}:{},url:e.url,enabled:!1!==e.enabled,createdAt:t,updatedAt:t}}}resolvedControlPlaneAccess(){const e=this.store.read(),t=new Map((e?.controlPlanePairings||[]).filter(e=>!e.revokedAt).map(e=>[e.keyId,e])),n=e?.controlPlaneConnections||[];return{hasPersistedAccess:n.length>0||t.size>0,connections:n.map(e=>({connection:e,pairing:t.get(e.pairingKeyId)}))}}listControlPlanePairings(e=""){return(this.store.read()?.controlPlanePairings||[]).filter(e=>!e.revokedAt).map(({secret:t,...n})=>({...n,current:Boolean(e&&n.keyId===e)})).sort((e,t)=>Number(t.current)-Number(e.current)||t.updatedAt.localeCompare(e.updatedAt))}listControlPlaneConnections(){return[...this.store.read()?.controlPlaneConnections||[]].sort((e,t)=>t.updatedAt.localeCompare(e.updatedAt))}deleteControlPlanePairing(e,t=""){if(t&&e===t){const e=new Error("Cannot delete the pairing used to authenticate the current request.");throw Object.assign(e,{statusCode:409,code:"NODE_AGENT_PAIRING_CURRENT_REQUEST"}),e}const n=this.store.read();if(!n)return!1;if((n.controlPlaneConnections||[]).some(t=>t.pairingKeyId===e))throw Object.assign(new Error("Cannot delete a pairing used by a configured control-plane connection."),{statusCode:409,code:"NODE_AGENT_PAIRING_IN_USE"});const i=(n.controlPlanePairings||[]).filter(t=>t.keyId!==e);return i.length!==(n.controlPlanePairings||[]).length&&(this.store.write({...n,controlPlanePairings:i}),!0)}revokeCurrentControlPlanePairing(e){if(!e)throw Object.assign(new Error("Current paired-HMAC authentication is required to revoke this pairing."),{statusCode:403,code:"NODE_AGENT_PAIRING_SELF_REVOKE_HMAC_REQUIRED"});const t=this.store.read(),n=t?.controlPlanePairings?.find(t=>t.keyId===e);if(!t||!n)throw Object.assign(new Error("The current control-plane pairing no longer exists."),{statusCode:404,code:"NODE_AGENT_PAIRING_NOT_FOUND"});if(n.revokedAt)return{keyId:e,revoked:!0,revokedAt:n.revokedAt};if((t.controlPlaneConnections||[]).some(t=>t.pairingKeyId===e))throw Object.assign(new Error("Cannot revoke a pairing used by a configured control-plane connection."),{statusCode:409,code:"NODE_AGENT_PAIRING_IN_USE"});const i=ya();return this.store.write({...t,controlPlanePairings:t.controlPlanePairings.map(t=>t.keyId===e?{...t,revokedAt:i,updatedAt:i}:t)}),{keyId:e,revoked:!0,revokedAt:i}}deleteControlPlaneConnection(e){const t=this.store.read();if(!t)return!1;const n=(t.controlPlaneConnections||[]).filter(t=>t.id!==e);return n.length!==(t.controlPlaneConnections||[]).length&&(this.store.write({...t,controlPlaneConnections:n}),!0)}remoteSecrets(e,t,n=!1){return[...(this.store.read()?.controlPlanePairings||[]).filter(e=>n||!e.revokedAt).map(e=>({keyId:e.keyId,secret:e.secret})),...e&&t?[{keyId:t,secret:e}]:[]]}isRevokedPairing(e){return Boolean(this.store.read()?.controlPlanePairings?.some(t=>t.keyId===e&&t.revokedAt))}reverseTunnelSecret(e,t,n){if(t&&n)return{keyId:n,secret:t};const i=this.store.read(),r=(i?.controlPlanePairings||[]).filter(e=>!e.revokedAt);if(!r.length)return;if(e){const t=e.replace(/\/$/,""),n=(i?.controlPlaneConnections||[]).find(e=>e.url.replace(/\/$/,"")===t),o=n&&r.find(e=>e.keyId===n.pairingKeyId);if(o)return{keyId:o.keyId,secret:o.secret}}const o=[...r].sort((e,t)=>t.updatedAt.localeCompare(e.updatedAt))[0];return o?{keyId:o.keyId,secret:o.secret}:void 0}newIdentity(){return{nodeId:this.resolveNodeId(),createdAt:ya(),updatedAt:ya(),controlPlanePairings:[],controlPlaneConnections:[]}}writeNodeId(e){const t=this.store.read();this.store.write({...t||{createdAt:ya()},nodeId:e,updatedAt:ya(),controlPlanePairings:t?.controlPlanePairings||[],controlPlaneConnections:t?.controlPlaneConnections||[]})}}const Aa=a.z.string().trim().min(1).max(160);const ba=Sn.strict();function wa(e){const t=e.filter(e=>!["created","stopped","failed"].includes(e.status)),n=new Set(t.map(e=>e.id)),i=t.filter(e=>e.apps.runningCount>0||e.aiSessions.runningCount>0);return{runningInstanceCount:t.length,stoppedInstanceCount:e.length-t.length,activeInstanceCount:i.length,restartInstanceCount:t.length,runningInstanceIds:t.map(e=>e.id).sort(),stoppedInstanceIds:e.filter(e=>!n.has(e.id)).map(e=>e.id).sort(),activeInstanceIds:i.map(e=>e.id).sort()}}class va{preflights=new Map;options;constructor(e){this.options=e}async check(e){const t=vn.parse(e),n=wa(this.options.listInstances()),i=await Vo(this.options.runCommand),r=this.options.currentRuntimeVersion(),o="@task-handoff/server"===i.packageName?[...new Set([...i.relatedCurrentVersions,r])]:i.relatedCurrentVersions,s=await async function(e){const t=e.packageName||"@task-handoff/node-agent",n=await async function(e,t,n){const i=function(e){return"stable"===e?"latest":e}(n),r=await e(Fo(),["view",`${t}@${i}`,"version","--json"]).catch(e=>{if(!function(e){if(!e||"object"!=typeof e)return!1;const t=e,n=[t.message,t.details?.stdout,t.details?.stderr].filter(e=>"string"==typeof e).join("\n");return/\bE404\b/i.test(n)}(e))throw e});if(!r)return;const o=JSON.parse(r.stdout);if("string"!=typeof o)throw new Error(`npm did not resolve ${t}@${i} to one version.`);return o}(e.runCommand,t,e.channel);if(!n)return function(e){return En.parse({source:"npm",channel:e.channel,currentVersion:e.currentVersion,availableVersion:e.currentVersion||"unavailable",impact:e.impact||{runningInstanceCount:0,stoppedInstanceCount:0,activeInstanceCount:0,restartInstanceCount:0,runningInstanceIds:[],stoppedInstanceIds:[],activeInstanceIds:[]},updateAvailable:!1,reason:`No ${e.channel} release is currently published.`,checkedAt:jo()})}({channel:e.channel,currentVersion:e.currentVersion,impact:e.impact});const i=$o(e.currentVersion,n)||(e.relatedCurrentVersions||[]).some(e=>$o(e,n)),r=i?await async function(e,t,n){const i=await e(Fo(),["view",`${t}@${n}`,"dist.integrity","--json"]),r=JSON.parse(i.stdout);if("string"!=typeof r||!/^sha(?:256|384|512)-[A-Za-z0-9+/=]+$/.test(r))throw Object.assign(new Error(`npm did not return immutable integrity metadata for ${t}@${n}.`),{statusCode:502,code:"NODE_UPDATE_PREFLIGHT_FAILED",retryable:!0});return r}(e.runCommand,t,n):void 0;return En.parse({source:"npm",channel:e.channel,currentVersion:e.currentVersion,availableVersion:n,...r?{artifactRef:`npm:${t}@${n}#${r}`}:{},runtimeArtifacts:e.runtimeArtifacts||[],impact:e.impact||{runningInstanceCount:0,stoppedInstanceCount:0,activeInstanceCount:0,restartInstanceCount:0,runningInstanceIds:[],stoppedInstanceIds:[],activeInstanceIds:[]},updateAvailable:i,checkedAt:jo()})}({channel:t.channel,currentVersion:i.currentVersion||r,runCommand:this.options.runCommand,packageName:i.packageName,relatedCurrentVersions:o,impact:n});if(!s.updateAvailable)return s;const a={...s,runtimeArtifacts:await this.options.resolveRuntimeArtifacts(s.availableVersion),preflightToken:_o()};return this.preflights.set(a.preflightToken,{result:a,expiresAt:Date.now()+6e5}),a}async apply(e){const i=ba.parse(e),r=await this.consumePreflight(i);if(!r.supported)throw Object.assign(new Error(r.reason||"The requested update is not supported."),{statusCode:400,code:"UPDATE_UNSUPPORTED"});if(!r.updateAvailable)throw Object.assign(new Error(r.reason||"No update is available for the selected channel."),{statusCode:409,code:"UPDATE_NOT_AVAILABLE"});const o=this.options.jobs.create(this.options.nodeId,r),{worker:s,packaged:a,expectedWorker:c}=function(e,i=t.existsSync){const r=[n.resolve(e,"..","bin","task-handoff-node-update-worker"),n.resolve(e,"..","..","bin","task-handoff-node-update-worker")],o=r.find(i),s=n.resolve(e,"..","..","..","..","scripts","node-update-worker.cts");return o?{worker:o,packaged:!0,expectedWorker:r[0]}:i(s)?{worker:s,packaged:!1,expectedWorker:r[0]}:{worker:void 0,packaged:!1,expectedWorker:r[0]}}(this.options.moduleDir);if(!s)throw this.options.jobs.patch(o.id,{status:"failed",rollout:{...o.rollout,phase:"failed"},error:{code:"NODE_UPDATE_FAILED",message:`Update worker was not found: ${c}`,retryable:!1},completedAt:(new Date).toISOString()}),Object.assign(new Error(`Node agent update worker was not found: ${c}`),{statusCode:500,code:"UPDATE_WORKER_NOT_FOUND"});const d=process.env.TASK_HANDOFF_CONTROL_PLANE_HEALTH_URL?.trim();try{await this.options.runCommand("systemd-run",["--unit",`task-handoff-update-${o.id}`,"--collect","--property=Type=exec",...a?[s]:[process.execPath,s],"--job-file",this.options.jobs.records.filePath(o.id),"--target-version",o.toVersion,"--npm-command",Fo(),...d?["--control-plane-health-url",d]:[]])}catch(e){const t=e instanceof Error?e.message:String(e);throw this.options.jobs.patch(o.id,{status:"failed",rollout:{...o.rollout,phase:"failed"},error:{code:"NODE_UPDATE_FAILED",message:`Failed to launch the node update worker: ${t}`,retryable:!0},completedAt:(new Date).toISOString()}),Object.assign(new Error(`Failed to launch the node update worker: ${t}`),{statusCode:500,code:"NODE_UPDATE_WORKER_LAUNCH_FAILED",cause:e})}return o}async consumePreflight(e){const t=this.preflights.get(e.preflightToken);if(this.preflights.delete(e.preflightToken),!t||t.expiresAt<=Date.now())throw Object.assign(new Error("The update preflight is missing or expired. Check for updates again."),{statusCode:409,code:"UPDATE_PREFLIGHT_EXPIRED"});const n=t.result,i=await Vo(this.options.runCommand);n.channel===e.channel&&n.availableVersion===e.targetVersion&&n.currentVersion===(i.currentVersion||this.options.currentRuntimeVersion())&&!0===n.artifactRef?.startsWith(`npm:${i.packageName}@`)&&JSON.stringify(n.impact)===JSON.stringify(wa(this.options.listInstances()))||this.throwStale();const r=await this.options.resolveRuntimeArtifacts(n.availableVersion);return JSON.stringify(n.runtimeArtifacts)!==JSON.stringify(r)&&this.throwStale(),n}throwStale(){throw Object.assign(new Error("The update target or affected instances changed after preflight. Check for updates again."),{statusCode:409,code:"UPDATE_PREFLIGHT_STALE"})}}const Ea=new Set(["provisioning","starting","registering","registered","running"]);function Na(e){return Si.parse({...e,health:"unknown",connectionStatus:"offline",agentStatus:"offline",targetStatus:"unknown",uiAccessStatus:"unknown",target:{...e.target,status:"unknown"},updatedAt:(new Date).toISOString()})}class Sa{options;restoredInstances=new Set;restoreErrors=new Map;unexpectedExitRetries=new Map;suppressedInstances=new Set;pendingUnexpectedExits=new Map;activeRestores=new Map;timer;activeCycle;cycleRequested=!1;cycleRequestDelayMs;started=!1;stopped=!1;constructor(e){this.options=e}markRestored(e){const t=this.options.state.requireInstance(e).status;return!["failed","stopping","stopped"].includes(t)&&(this.restoredInstances.add(e),this.restoreErrors.delete(e),!0)}allowRecovery(e){this.suppressedInstances.delete(e);const t=this.pendingUnexpectedExits.get(e);void 0!==t&&(this.pendingUnexpectedExits.delete(e),this.applyUnexpectedLocalExit(e,t))}completeSuppressedOperation(e){this.pendingUnexpectedExits.delete(e),this.restoredInstances.delete(e),this.restoreErrors.delete(e),this.unexpectedExitRetries.delete(e)}forgetInstance(e){this.restoredInstances.delete(e),this.restoreErrors.delete(e),this.unexpectedExitRetries.delete(e),this.suppressedInstances.delete(e),this.activeRestores.delete(e),this.pendingUnexpectedExits.delete(e)}async suppressRecovery(e){this.suppressedInstances.add(e),await(this.activeRestores.get(e)?.catch(()=>{}))}handleUnexpectedLocalExit(e,t){this.stopped||(this.suppressedInstances.has(e)?this.pendingUnexpectedExits.set(e,t):this.applyUnexpectedLocalExit(e,t))}applyUnexpectedLocalExit(e,t){const n=this.options.state.requireInstance(e);if("local"!==this.options.state.requireRuntime(n.runtimeId).type)return;this.restoredInstances.delete(e);const i=this.options.nowMs?.()??Date.now(),r=this.unexpectedExitRetries.get(e),o=this.options.crashStableWindowMs??3e4,s=r&&i-r.lastExitAt<o?r.attempt+1:1;this.unexpectedExitRetries.set(e,{attempt:s,lastExitAt:i});const a=this.options.retryBaseDelayMs??1e3,c=1===s?0:Math.min(this.options.retryMaxDelayMs??3e4,a*2**Math.min(s-2,10)),d=t instanceof Error?t.message:String(t);this.restoreErrors.set(e,{message:d,attempt:s,nextAttemptAt:i+c}),this.options.state.applyInstanceLifecycle(e,{type:"runtime-exited",error:t}),this.requestCycle(c)}async restoreManagedInstances(){if(this.stopped)return;const{state:e}=this.options;for(const t of e.listInstances()){if(this.stopped)return;"docker"===e.requireRuntime(t.runtimeId).type&&["provisioning","starting"].includes(t.status)&&"ready"!==t.imageProvisioning?.phase&&this.options.provisionImage(t)}const t=e.listInstances().filter(t=>{if(this.restoredInstances.has(t.id))return!1;if(this.suppressedInstances.has(t.id))return!1;const n=e.requireRuntime(t.runtimeId);if("local"===n.type){const e=this.restoreErrors.get(t.id);return(Ea.has(t.status)||"failed"===t.status)&&(!e||e.nextAttemptAt<=(this.options.nowMs?.()??Date.now()))}return"docker"===n.type&&(Ea.has(t.status)||"provisioning"===t.status&&"ready"===t.imageProvisioning?.phase)});await Promise.all(t.map(async t=>{if(this.stopped)return;const n=async()=>{if(this.stopped)return;const n=e.listInstances().find(e=>e.id===t.id);if(!n)return;if(!this.isRestoreCandidate(n))return;const i=this.restoreErrors.get(n.id);try{const t=this.options.restoreInstance(n.id);this.activeRestores.set(n.id,t);try{await t}finally{this.activeRestores.get(n.id)===t&&this.activeRestores.delete(n.id)}if(this.stopped||this.suppressedInstances.has(n.id))return;if(await this.options.autoImport(e.requireInstance(n.id)),this.stopped||this.suppressedInstances.has(n.id))return;if(this.restoreErrors.get(n.id)!==i)return;if(!this.markRestored(n.id))throw new Error(`Restored instance ${n.id} did not reach a recoverable running state.`)}catch(t){if(this.stopped||this.suppressedInstances.has(n.id))return;"local"===e.requireRuntime(n.runtimeId).type&&e.applyInstanceLifecycle(n.id,{type:"start-failed",error:t});const i=t instanceof Error?t.message:String(t),r=this.restoreErrors.get(n.id),o=(r?.attempt??0)+1,s=this.options.retryBaseDelayMs??1e3,a=Math.min(this.options.retryMaxDelayMs??3e4,s*2**Math.min(o-1,10)),c=(this.options.nowMs?.()??Date.now())+a;this.restoreErrors.set(n.id,{message:i,attempt:o,nextAttemptAt:c}),r?.message===i&&r.attempt===o||this.options.warn({instanceId:n.id,action:"restore",runtimeId:n.runtimeId,error:i,attempt:o,nextAttemptAt:new Date(c).toISOString()},"node instance restore failed; recovery will retry")}};await(this.options.runInstanceOperation?.(t.id,n)??n())}))}isRestoreCandidate(e){if(this.restoredInstances.has(e.id)||this.suppressedInstances.has(e.id))return!1;const t=this.options.state.requireRuntime(e.runtimeId);if("local"===t.type){const t=this.restoreErrors.get(e.id);return(Ea.has(e.status)||"failed"===e.status)&&(!t||t.nextAttemptAt<=(this.options.nowMs?.()??Date.now()))}return"docker"===t.type&&(Ea.has(e.status)||"provisioning"===e.status&&"ready"===e.imageProvisioning?.phase)}async recoverManagedInstances(){if(this.stopped)return;const{state:e,convergence:t}=this.options,n=e.listInstances().filter(e=>this.options.usesManagedArtifact(e)&&!t.isRunning(e.id)&&(this.restoredInstances.has(e.id)||"unknown"!==e.target.status)&&(!e.ready||"matched"!==e.runtimeVersion?.phase)&&!["created","stopped","failed","provisioning","stopping"].includes(e.status));await Promise.all(n.map(async e=>{if(!this.stopped)try{await t.schedule(e.id)}catch(t){this.options.error({instanceId:e.id,error:t},"runtime convergence recovery failed")}}))}start(){this.started||this.stopped||(this.started=!0,this.runAndContinue())}async stop(){this.stopped=!0,this.timer&&clearTimeout(this.timer),this.timer=void 0;const e=this.options.stopImageProvisioning(),t=this.options.state.listInstances().map(e=>this.options.convergence.cancel(e.id));await Promise.all(t),await this.activeCycle,await e,await this.options.runtimeAdapters.stopAll();for(const e of this.options.state.listInstances())"local"===this.options.state.requireRuntime(e.runtimeId).type&&this.options.state.controlledInstances.put(Na(e))}async runCycle(){await this.restoreManagedInstances(),this.stopped||await this.recoverManagedInstances()}runAndContinue(){if(this.stopped)return;const e=this.runCycle().catch(e=>this.options.error({error:e},"node agent startup recovery cycle failed"));this.activeCycle=e,e.finally(()=>{this.activeCycle===e&&(this.activeCycle=void 0),this.cycleRequested?(this.cycleRequested=!1,this.cycleRequestDelayMs=void 0,this.scheduleNext()):this.scheduleNext()})}scheduleNext(){if(this.stopped)return;const e=this.options.nowMs?.()??Date.now(),t=new Map(this.options.state.listInstances().map(e=>[e.id,e])),n=[...this.restoreErrors.entries()].reduce((e,[n,i])=>{const r=t.get(n);return!r||this.restoredInstances.has(n)||this.suppressedInstances.has(n)||"local"!==this.options.state.requireRuntime(r.runtimeId).type?e:Ea.has(r.status)||"failed"===r.status?Math.min(e,i.nextAttemptAt):e},Number.POSITIVE_INFINITY),i=Math.min(this.options.intervalMs??1e4,Math.max(0,n-e));this.timer=setTimeout(()=>{this.timer=void 0,this.runAndContinue()},i),this.timer.unref?.()}requestCycle(e=0){if(this.started&&!this.stopped){if(this.activeCycle)return this.cycleRequested=!0,void(this.cycleRequestDelayMs=void 0===this.cycleRequestDelayMs?e:Math.min(this.cycleRequestDelayMs,e));this.timer&&clearTimeout(this.timer),this.timer=setTimeout(()=>{this.timer=void 0,this.runAndContinue()},e),this.timer.unref?.()}}}function Ta(e){return e.readyState===(e.OPEN??1)}function za(e){const t=Buffer.isBuffer(e)?e.toString("utf8"):"string"==typeof e?e:"";if(Buffer.byteLength(t,"utf8")<=123)return t;let n="";for(const e of t){const t=`${n}${e}`;if(Buffer.byteLength(t,"utf8")>123)break;n=t}return n}function _a(e){if("number"==typeof e&&Number.isInteger(e))return e>=3e3&&e<=4999||e>=1e3&&e<=1014&&1004!==e&&1005!==e&&1006!==e?e:void 0}function Ca(e,t,n){e.close(_a(t),za(n)||void 0)}function ka(e,t,n,i){if(Ta(e))for(const e of t.splice(0))if(i(e),!n(e))return}function Oa(e,t){const n=new URL(t.tunnelUrl);n.searchParams.set("nodeId",t.nodeId);const i=t.secret?Js({nodeId:t.nodeId,keyId:t.keyId,secret:t.secret,method:"GET",pathWithQuery:`${n.pathname}${n.search}`}):{},r=new m(n,{headers:i}),o=new Map,s=new Map,a=new Map;let c;r.on("error",i=>{e.log.warn({nodeId:t.nodeId,tunnelUrl:`${n.origin}${n.pathname}`,error:i instanceof Error?i.message:String(i)},"node agent reverse tunnel connection failed")});const d=e=>{const n=e.startsWith("/")?e:`/${e}`,i="function"==typeof t.port?t.port():t.port,r=new URL(`/api/node-agent${n}`,`http://127.0.0.1:${i}`);return r.protocol="ws:",r},l=(e,n,i,r={})=>{const o=e.startsWith("/")?e:`/${e}`;return{...r,...t.secret&&t.keyId?Js({nodeId:t.nodeId,keyId:t.keyId,secret:t.secret,method:n,pathWithQuery:`/api/node-agent${o}`,body:i}):t.token?{authorization:`Bearer ${t.token}`}:{}}},u=e=>t.secret?Js({nodeId:t.nodeId,keyId:t.keyId,secret:t.secret,method:"GET",pathWithQuery:`${e.pathname}${e.search}`}):{},p=(e,t,n)=>{const i=o.get(e);o.delete(e),i?.upstream&&Ca(i.upstream,t,n),i?.tunnel&&Ca(i.tunnel,t,n)},h=(e,t,n=!1)=>new Promise((i,r)=>{e.send(t,{binary:n},e=>e?r(e):i())});r.on("open",()=>{r.send(JSON.stringify({type:"node-agent.identify",nodeId:t.nodeId,serverTime:(new Date).toISOString()})),c=e.nodeAgentEventForwarder?.addOutput(r)}),r.on("close",()=>{for(const e of o.keys())p(e,1001,"Reverse tunnel disconnected.");for(const[e,t]of s)s.delete(e),t.controller.abort(),Ca(t.tunnel,1001,"Reverse tunnel disconnected.");for(const[e,t]of a)a.delete(e),t.abort();c?.(),c=void 0});return r.on("message",i=>{(async i=>{let c;try{c=JSON.parse(String(i))}catch{return void r.send(JSON.stringify({type:"node-agent.error",code:"INVALID_JSON"}))}const g=c&&"object"==typeof c?c:{};if("control-plane.http.open"===g.type){const i="string"==typeof g.streamId?g.streamId:"",o="string"==typeof g.route&&g.route.startsWith("/")?g.route:"/health",a=g.init&&"object"==typeof g.init?g.init:{},c=a.headers&&"object"==typeof a.headers?a.headers:{},d=Os(a.method);let p;try{p=Tt(a.body)}catch(n){return e.log.warn({nodeId:t.nodeId,messageType:g.type,streamId:i,error:n instanceof Error?n.message:String(n)},"node agent reverse tunnel request body rejected"),void r.send(JSON.stringify({type:"node-agent.error",code:"NODE_TUNNEL_REQUEST_BODY_INVALID",streamId:i}))}const f=new AbortController,y=(e=>{const t=new URL(n);return t.pathname=`${t.pathname.replace(/\/$/,"")}/http-streams/${encodeURIComponent(e)}`,t})(i),I=new m(y,{headers:u(y)});return s.set(i,{tunnel:I,controller:f}),I.on("open",async()=>{try{const e=await fetch((e=>{const n=e.startsWith("/")?e:`/${e}`,i="function"==typeof t.port?t.port():t.port;return new URL(`/api/node-agent${n}`,`http://127.0.0.1:${i}`)})(o),{method:d,headers:l(o,d,p,c),body:Buffer.isBuffer(p)?new Uint8Array(p):p,signal:f.signal});if(await h(I,JSON.stringify({type:"node-agent.http.head",streamId:i,status:e.status,headers:Object.fromEntries(e.headers.entries())})),e.body){const t=e.body.getReader();for(;;){const{done:e,value:n}=await t.read();if(e)break;await h(I,Buffer.from(n),!0)}}await h(I,JSON.stringify({type:"node-agent.http.end",streamId:i})),I.close(1e3,"HTTP stream completed.")}catch(e){I.readyState===m.OPEN&&(await h(I,JSON.stringify({type:"node-agent.http.error",streamId:i,message:e instanceof Error?e.message:String(e)})).catch(()=>{}),I.close(1011,"HTTP stream failed."))}finally{s.delete(i)}}),I.on("close",()=>{f.abort(),s.delete(i)}),void I.on("error",()=>f.abort())}if("control-plane.http.cancel"===g.type){const e="string"==typeof g.streamId?g.streamId:"",t=s.get(e);if(!t)return;return s.delete(e),t.controller.abort(),void Ca(t.tunnel,1e3,"string"==typeof g.reason?g.reason:"HTTP stream canceled.")}if("control-plane.websocket.open"===g.type){const e="string"==typeof g.streamId?g.streamId:"",t="string"==typeof g.route?g.route:"",i=Array.isArray(g.protocols)?g.protocols.filter(e=>"string"==typeof e):void 0;try{const s=l(t,"GET",void 0),a=i?.length?new m(d(t),i,{headers:s}):new m(d(t),{headers:s}),c=(e=>{const t=new URL(n);return t.pathname=`${t.pathname.replace(/\/$/,"")}/streams/${encodeURIComponent(e)}`,t})(e),p=new m(c,{headers:u(c)});o.set(e,{upstream:a,tunnel:p,close:(e=1e3,t="")=>{Ca(a,e,t),Ca(p,e,t)}}),a.on("open",()=>{r.send(JSON.stringify({type:"node-agent.websocket.open",streamId:e,protocol:a.protocol}))}),function(e,t,n={}){const i=n.pendingFrameLimit??256,r=n.maxFrameBytes??8388608,o=n.maxTotalBytes??1073741824,s=n.maxBufferedBytes??16777216;let a=!1,c=Ta(t);const d=[],l=[];let u,m=0,p=0,h=0;const g=e=>Buffer.isBuffer(e)||e instanceof ArrayBuffer||ArrayBuffer.isView(e)?e.byteLength:Buffer.byteLength("string"==typeof e?e:String(e),"utf8"),f=(i,s)=>{const a=g(s);return h+=a,n.onFrame?.(i,a),!(a>r||h>o)||(Ca(e,1009,"WebSocket bridge traffic limit exceeded."),Ca(t,1009,"WebSocket bridge traffic limit exceeded."),!1)},y=()=>{u&&(clearTimeout(u),u=void 0)},I=(n,i)=>{const r=i.bytes;if((n.bufferedAmount??0)+r>s)return Ca(e,1013,"WebSocket bridge consumer is too slow."),Ca(t,1013,"WebSocket bridge consumer is too slow."),!1;try{return function(e,t){e.send(t.data,{binary:t.isBinary})}(n,i),!0}catch{return Ca(e,1011,"WebSocket bridge send failed."),Ca(t,1011,"WebSocket bridge send failed."),!1}},A=(n,r,o)=>{if(r.length>=i)return Ca(e,1011,"WebSocket bridge pending frame limit exceeded."),void Ca(t,1011,"WebSocket bridge pending frame limit exceeded.");const a="upstream"===n?m:p;if((("upstream"===n?t:e).bufferedAmount??0)+a+o.bytes>s)return Ca(e,1013,"WebSocket bridge consumer is too slow."),void Ca(t,1013,"WebSocket bridge consumer is too slow.");r.push(o),"upstream"===n?m+=o.bytes:p+=o.bytes};n.upstreamOpenTimeoutMs&&!c&&(u=setTimeout(()=>{c||a||(Ca(e,1011,"Upstream websocket did not open."),Ca(t))},n.upstreamOpenTimeoutMs)),e.on("open",()=>ka(e,l,t=>I(e,t),e=>{p-=e.bytes})),t.on("open",()=>{y(),c=!0,n.onUpstreamOpen?.(),ka(t,d,e=>I(t,e),e=>{m-=e.bytes})}),e.on("message",(e,n=!1)=>{if(!f("client-to-upstream",e))return;const i={data:e,isBinary:Boolean(n),bytes:g(e)};Ta(t)?I(t,i):A("upstream",d,i)}),t.on("message",(t,n=!1)=>{if(!f("upstream-to-client",t))return;const i={data:t,isBinary:Boolean(n),bytes:g(t)};Ta(e)?I(e,i):A("client",l,i)}),t.on("close",(t,i)=>{y(),n.onUpstreamClose?.(t,i),(c||a||!n.onUpstreamCloseBeforeOpen?.())&&Ca(e,t,i)}),t.on("error",t=>{n.onUpstreamError?.(t),(c||a||!n.onUpstreamErrorBeforeOpen?.(t))&&Ca(e)}),e.on("close",(e,i)=>{y(),a=!0,n.onClientClose?.(e,i),Ca(t,e,i)}),e.on("error",e=>{y(),a=!0,n.onClientError?.(e),Ca(t,1011,"WebSocket bridge client failed.")})}(p,a,{pendingFrameLimit:256,upstreamOpenTimeoutMs:1e4,onClientClose:()=>{o.delete(e)},onClientError:t=>{o.delete(e),r.send(JSON.stringify({type:"node-agent.websocket.error",streamId:e,message:t instanceof Error?t.message:String(t)}))},onUpstreamClose:(t,n)=>{o.delete(e);const i=_a(t),s=za(n);r.send(JSON.stringify({type:"node-agent.websocket.close",streamId:e,...void 0===i?{}:{code:i},...s?{reason:s}:{}}))},onUpstreamError:t=>{o.delete(e),r.send(JSON.stringify({type:"node-agent.websocket.error",streamId:e,message:t instanceof Error?t.message:String(t)}))}})}catch(t){r.send(JSON.stringify({type:"node-agent.websocket.error",streamId:e,message:t instanceof Error?t.message:String(t)}))}return}if("control-plane.websocket.close"===g.type){const e="string"==typeof g.streamId?g.streamId:"";return void p(e,"number"==typeof g.code?g.code:1e3,"string"==typeof g.reason?g.reason:"")}if("control-plane.request.cancel"===g.type){const e="string"==typeof g.requestId?g.requestId:"";return a.get(e)?.abort(),void a.delete(e)}if("control-plane.request"===g.type){const n="string"==typeof g.requestId?g.requestId:"",i=g.init&&"object"==typeof g.init?g.init:{},o="string"==typeof g.route&&g.route.startsWith("/")?g.route:"/health",s=i.headers&&"object"==typeof i.headers?i.headers:{},c=Os(i.method);let d;try{d=Tt(i.body)}catch(i){return e.log.warn({nodeId:t.nodeId,messageType:g.type,requestId:n,error:i instanceof Error?i.message:String(i)},"node agent reverse tunnel request body rejected"),void r.send(JSON.stringify({type:"node-agent.response",requestId:n,status:400,error:{code:"NODE_TUNNEL_REQUEST_BODY_INVALID",message:"Reverse tunnel request body does not match the negotiated protocol."}}))}const u=new AbortController;a.set(n,u);try{const t=await e.inject({method:c,url:`/api/node-agent${o}`,headers:l(o,c,d,s),payload:d,signal:u.signal});if(u.signal.aborted)return;r.send(JSON.stringify({type:"node-agent.response",requestId:n,status:t.statusCode,headers:t.headers,body:t.body}))}catch(e){if(u.signal.aborted)return;r.send(JSON.stringify({type:"node-agent.response",requestId:n,status:502,error:{code:"NODE_AGENT_REVERSE_INJECT_FAILED",message:e instanceof Error?e.message:String(e)}}))}finally{a.delete(n)}}})(i).catch(n=>{e.log.warn({nodeId:t.nodeId,error:n instanceof Error?n.message:String(n)},"node agent reverse tunnel message rejected");try{r.send(JSON.stringify({type:"node-agent.error",code:"INVALID_TUNNEL_MESSAGE"}))}catch{}})}),r}function Ra(e,t){return Number.isFinite(e)&&Number(e)>0?Number(e):t}function xa(e){return e.unref?.(),e}class Da{connectTimeoutMs;handshakeTimeoutMs;heartbeatIntervalMs;heartbeatTimeoutMs;stableThresholdMs;now;setTimeoutFn;clearTimeoutFn;ping;onTimeout;onStable;onPhase;connectTimer;handshakeTimer;heartbeatTimer;stableTimer;awaitingPongSince;stable=!1;stopped=!1;currentPhase="connecting";lastActivityAt;lastPongAt;constructor(e){this.connectTimeoutMs=Ra(e.connectTimeoutMs,1e4),this.handshakeTimeoutMs=Ra(e.handshakeTimeoutMs,1e4),this.heartbeatIntervalMs=Ra(e.heartbeatIntervalMs,25e3),this.heartbeatTimeoutMs=Ra(e.heartbeatTimeoutMs,1e4),this.stableThresholdMs=Ra(e.stableThresholdMs,6e4),this.now=e.now||Date.now,this.setTimeoutFn=e.setTimeoutFn||setTimeout,this.clearTimeoutFn=e.clearTimeoutFn||clearTimeout,this.ping=e.ping,this.onTimeout=e.onTimeout,this.onStable=e.onStable,this.onPhase=e.onPhase}get phase(){return this.currentPhase}start(){this.stopped=!1,this.setPhase("connecting"),this.clearTimer("connectTimer"),this.connectTimer=xa(this.setTimeoutFn(()=>this.timeout("connect"),this.connectTimeoutMs))}opened(){this.stopped||(this.clearTimer("connectTimer"),this.setPhase("handshaking"),this.handshakeTimer=xa(this.setTimeoutFn(()=>this.timeout("handshake"),this.handshakeTimeoutMs)),this.scheduleHeartbeat(this.heartbeatIntervalMs))}healthy(){this.stopped||(this.clearTimer("handshakeTimer"),this.activity(),this.setPhase("healthy"),this.stable||this.stableTimer||(this.stableTimer=xa(this.setTimeoutFn(()=>{this.stableTimer=void 0,this.stopped||"healthy"!==this.currentPhase||(this.stable=!0,this.onStable?.())},this.stableThresholdMs))))}activity(){this.stopped||(this.lastActivityAt=this.now())}pong(){if(this.stopped)return;const e=this.now();this.awaitingPongSince=void 0,this.lastPongAt=e,this.lastActivityAt=e,this.scheduleHeartbeat(this.heartbeatIntervalMs)}close(){this.stopped||(this.stopped=!0,this.clearTimers(),this.awaitingPongSince=void 0,this.setPhase("closed"))}diagnostics(){return{phase:this.currentPhase,stable:this.stable,...void 0===this.lastActivityAt?{}:{lastActivityAt:new Date(this.lastActivityAt).toISOString()},...void 0===this.lastPongAt?{}:{lastPongAt:new Date(this.lastPongAt).toISOString()}}}scheduleHeartbeat(e){this.stopped||(this.clearTimer("heartbeatTimer"),this.heartbeatTimer=xa(this.setTimeoutFn(()=>{if(this.heartbeatTimer=void 0,!this.stopped){if(void 0!==this.awaitingPongSince){const e=Math.max(0,this.now()-this.awaitingPongSince);return e>=this.heartbeatTimeoutMs?void this.timeout("heartbeat"):void this.scheduleHeartbeat(this.heartbeatTimeoutMs-e)}this.awaitingPongSince=this.now();try{this.ping()}catch{return void this.timeout("heartbeat")}this.scheduleHeartbeat(this.heartbeatTimeoutMs)}},e)))}timeout(e){this.stopped||(this.clearTimers(),this.setPhase("failed"),this.onTimeout(e))}setPhase(e){this.currentPhase!==e&&(this.currentPhase=e,this.onPhase?.(e))}clearTimers(){this.clearTimer("connectTimer"),this.clearTimer("handshakeTimer"),this.clearTimer("heartbeatTimer"),this.clearTimer("stableTimer")}clearTimer(e){const t=this[e];t&&this.clearTimeoutFn(t),this[e]=void 0}}function Pa(e){const t=new URL(Bs,e);return t.protocol="https:"===t.protocol?"wss:":"ws:",t.toString()}const Ma=new Set(["linux","darwin","win32","freebsd","openbsd","aix","sunos"]);function La(e){return Ma.has(e)?e:"unknown"}function ja(e){return!0===e.managedArtifacts}class $a{managedArtifacts=!0;executor;runCommand;platform;arch;constructor(e,t,n,i){this.executor=e,this.runCommand=t,this.platform=n,this.arch=i}artifactTarget(e){return this.executor.inspectRuntimeTarget(e?.instance.runtime.containerName)}async installRuntime(e,t){const n=e.instance.runtime.containerName;if(!n)throw Object.assign(new Error(`Instance ${e.instance.id} does not have a Docker container.`),{code:"INSTANCE_RUNTIME_INSTALL_FAILED"});const i=await this.executor.ensureRuntimeInstallTargetRunning(n,e.instance.runtime.containerId);await this.executor.installRuntimeLauncher(n,i),await this.executor.installRuntimeRelease({containerName:n,expectedContainerId:i,artifactPath:t.archivePath,identity:t.identity})}async inspectRuntime(e,t){const n=e.instance.runtime.containerName;if(!n)return!1;const i=function(e,t){return e.packageName===t.packageName&&e.version===t.version&&e.platform===t.platform&&e.arch===t.arch&&e.formatVersion===t.formatVersion&&e.launcherAbi===t.launcherAbi&&e.entrypoint===t.entrypoint&&e.sha256===t.sha256}(await this.executor.inspectRuntimeVersion(n),t),r=e.instance.runtime.labels["task-handoff.bootstrap-backup"];return i&&r&&await this.executor.removeBootstrapBackup(r,e.instance.id),i}start(e){return this.executor.start(e)}stop(e){return this.executor.stop(e)}restart(e){return this.executor.restart(e,e.instance.runtime.containerId)}delete(e,t){return this.executor.delete(e,t)}async check(e){try{const t=(await this.runCommand("docker",["version","--format","{{.Server.Version}}"],{timeoutMs:5e3})).stdout.trim();return{status:"online",capabilities:{...e.capabilities,daemon:{status:"online",hostPlatform:La(this.platform),...t?{serverVersion:t}:{}}}}}catch(t){return{status:"offline",capabilities:{...e.capabilities,daemon:{status:"offline",hostPlatform:La(this.platform),error:t instanceof Error?t.message:String(t)}}}}}}class Fa{docker;local;constructor(e,t){this.docker=e,this.local=t}forRuntime(e){if("docker"===e.type)return this.docker;if("local"===e.type)return this.local;throw Object.assign(new Error(`Runtime type ${e.type} is not supported by this node agent.`),{statusCode:400,code:"NODE_RUNTIME_TYPE_UNSUPPORTED"})}managedAdapters(){return[this.docker,this.local].filter(ja)}async stopAll(){await(this.local.stopAll?.())}}const Ua="task-handoff.local-process-nonce",Va=1e3,qa=1e4,Ha=2e3;function Ba(e,t){try{e?.(t)}catch{}}function Ka(e){return e.runtime.port?`http://127.0.0.1:${e.runtime.port}`:e.target.web}async function Ga(e,t){try{const n=await fetch(`${e}/api/internal/node-agent/process-identity`,{headers:{authorization:`Bearer ${t}`},signal:AbortSignal.timeout(Va)});if(!n.ok)return;const i=(await n.json()).data;if("string"!=typeof i?.instanceId||"number"!=typeof i.pid||"string"!=typeof i.processNonce)return;return{instanceId:i.instanceId,pid:i.pid,processNonce:i.processNonce,startIdentity:"string"==typeof i.startIdentity?i.startIdentity:void 0}}catch{return}}async function Ja(e,t){if(C(e)!==t)return!1;try{process.kill(e,"SIGTERM")}catch{return!0}const n=Date.now()+qa;for(;Date.now()<n;){try{process.kill(e,0)}catch{return!0}await new Promise(e=>setTimeout(e,50))}try{process.kill(e,"SIGKILL")}catch{}const i=Date.now()+Ha;for(;Date.now()<i;){try{process.kill(e,0)}catch{return!0}await new Promise(e=>setTimeout(e,50))}return!1}function Wa(e,t){return Object.assign(new Error(t),{statusCode:503,code:"LOCAL_INSTANCE_STOP_UNCONFIRMED",instanceId:e.id})}async function Ya(e){return!await function(e){return new Promise(t=>{const n=p.createConnection({host:"127.0.0.1",port:e}),i=e=>{n.removeAllListeners(),n.destroy(),t(e)};n.once("connect",()=>i(!0)),n.once("error",()=>i(!1)),n.setTimeout(250,()=>i(!1))})}(e)&&new Promise(t=>{const n=p.createServer();n.once("error",()=>t(!1)),n.listen({host:"127.0.0.1",port:e,exclusive:!0},()=>n.close(()=>t(!0)))})}const Xa=Ya;function Qa(e,t){return null!==e.exitCode||null!==e.signalCode?Promise.resolve(!0):new Promise(n=>{const i=setTimeout(()=>{e.off("exit",r),n(null!==e.exitCode||null!==e.signalCode)},t);i.unref();const r=()=>{clearTimeout(i),n(!0)};e.once("exit",r)})}async function Za(e,t=1e4,n=2e3,i){if(await Qa(e,t))return;Ba(i,{stage:"graceful-timeout",pid:e.pid,timeoutMs:t});let r=!1;if(null===e.exitCode&&null===e.signalCode&&(e.kill("SIGKILL"),r=!0,Ba(i,{stage:"force-signal-sent",pid:e.pid,signal:"SIGKILL"})),!await Qa(e,n))throw Ba(i,{stage:"force-exit-unconfirmed",pid:e.pid,signal:"SIGKILL",timeoutMs:n}),Object.assign(new Error(`Controlled instance process pid=${e.pid??"unknown"} did not exit after SIGKILL.`),{statusCode:503,code:"LOCAL_INSTANCE_PROCESS_EXIT_UNCONFIRMED",pid:e.pid});r&&Ba(i,{stage:"force-exit-confirmed",pid:e.pid,signal:"SIGKILL"})}class ec{children=new Map;readyChildren=new WeakSet;expectedExits=new WeakSet;lifecycleReporters=new WeakMap;lockPath;onUnexpectedExit;onUnexpectedExitError;constructor(e,t,n){this.lockPath=e,this.onUnexpectedExit=t,this.onUnexpectedExitError=n}track(e,t,n){this.children.set(e,t),n&&this.lifecycleReporters.set(t,n),t.once("exit",(n,i)=>{if(this.release(e,t),this.readyChildren.has(t)&&!this.expectedExits.has(t)){const r={instanceId:e,pid:t.pid,code:n,signal:i},o=e=>{try{this.onUnexpectedExitError?.(e,r)}catch{}};try{Promise.resolve(this.onUnexpectedExit?.(r)).catch(o)}catch(e){o(e)}}})}markReady(e,t){return this.children.get(e)===t&&null===t.exitCode&&null===t.signalCode&&(this.readyChildren.add(t),!0)}release(e,t){this.children.get(e)===t&&this.children.delete(e)}async stop(e){const t=this.children.get(e.id);if(t){this.expectedExits.add(t);const n=this.lifecycleReporters.get(t);return t.killed||(t.kill("SIGTERM"),Ba(n,{stage:"graceful-signal-sent",pid:t.pid,signal:"SIGTERM"})),this.children.delete(e.id),void await Za(t,qa,Ha,n)}const i=await async function(e){const t=Ka(e),n=e.runtime.labels?.[Ua];if(!t||!n||!e.registrationToken)return;const i=await Ga(t,e.registrationToken);if(i&&i.instanceId===e.id&&i.processNonce===n)try{return(await fetch(`${t}/api/internal/node-agent/shutdown`,{method:"POST",headers:{authorization:`Bearer ${e.registrationToken}`},signal:AbortSignal.timeout(Va)})).ok?i:void 0}catch{return}}(e);if(i){const t=Ka(e),n=Date.now()+qa;for(;t&&Date.now()<n;){if(!await Ga(t,e.registrationToken))return;await new Promise(e=>setTimeout(e,50))}const r=t?await Ga(t,e.registrationToken):void 0;if(r&&r.instanceId===i.instanceId&&r.pid===i.pid&&r.processNonce===i.processNonce&&r.startIdentity===i.startIdentity&&r.startIdentity&&await Ja(r.pid,r.startIdentity))return;throw Wa(e,`Controlled instance ${e.id} accepted shutdown but its exit could not be confirmed.`)}const r=function(e=function(){const e="win32"===process.platform?c.tmpdir():"/tmp";return n.join(e,`task-handoff-local-controlled-instance-${function(){const e=process.getuid?.();return void 0!==e?String(e):c.userInfo().username.replace(/[^a-zA-Z0-9_.-]/g,"_")}()}.lock`)}()){return k(e)}(this.lockPath),o=await async function(e){const t=Ka(e);if(t)try{const[n,i]=await Promise.all([fetch(`${t}/api/instance/status`,{signal:AbortSignal.timeout(Va)}),fetch(`${t}/api/diagnostics`,{signal:AbortSignal.timeout(Va)})]);if(!n.ok||!i.ok)return;const r=await n.json(),o=await i.json(),s=o.data?.runtime?.pid;if(r.data?.id!==e.id||"controlled"!==r.data.controlMode||"number"!=typeof s||!Number.isInteger(s)||s<=0)return;const a=C(s);return a?{pid:s,startIdentity:a}:void 0}catch{return}}(e);if(o){if(await Ja(o.pid,o.startIdentity))return;throw Wa(e,`Legacy controlled instance ${e.id} did not exit after termination.`)}if(r?.instanceId===e.id&&x(r))throw Wa(e,`Local controlled instance ${e.id} is still owned by pid ${r.pid}, but its process identity could not be verified.`)}async waitUntilHealthy(e,t,n,i,r=function(e=process.env.TASK_HANDOFF_LOCAL_PROCESS_READY_TIMEOUT_MS){const t=Number(e);return Number.isFinite(t)&&t>0?t:3e4}()){const o=Date.now()+r;for(;Date.now()<o;){if(null!==n.exitCode||null!==n.signalCode)return!1;const r=await Ga(e,i);if(r&&r.instanceId===t.instanceId&&r.pid===t.pid&&r.processNonce===t.processNonce&&r.startIdentity===t.startIdentity)return!0;await new Promise(e=>setTimeout(e,100))}return!1}async stopAll(){const e=Array.from(this.children.values());for(const t of e){this.expectedExits.add(t);const e=this.lifecycleReporters.get(t);t.killed||(t.kill("SIGTERM"),Ba(e,{stage:"graceful-signal-sent",pid:t.pid,signal:"SIGTERM"}))}this.children.clear(),await Promise.all(e.map(e=>Za(e,qa,Ha,this.lifecycleReporters.get(e))))}}async function tc(e,t){try{const n=await e(t,["--version"]);return{available:!0,command:t,version:(n.stdout||n.stderr).split(/\r?\n/)[0]?.trim()||void 0}}catch{return{available:!1}}}class nc{runCommand;paths;nodeAgentUrl;processSupervisor;commandOverride;lockPath;constructor(e,t,n,i,r,o,s){this.runCommand=e,this.paths=t,this.nodeAgentUrl=n,this.commandOverride=i,this.lockPath=r,this.processSupervisor=new ec(r,o,s)}async start(e){await this.processSupervisor.stop(e.instance);const i=function(e){if("local-folder"!==e.source.type){const e=new Error("Localhost runtime currently supports local folder sources only.");throw Object.assign(e,{statusCode:400,code:"LOCAL_RUNTIME_REQUIRES_LOCAL_FOLDER"}),e}return n.resolve(e.source.path)}(e.instance),r=e.instance.runtime.port,o=!!r&&await Ya(r),s="allocate"===process.env.TASK_HANDOFF_LOCAL_INSTANCE_PORT_CONFLICT;if(r&&!o&&!s)throw Object.assign(new Error(`Local controlled instance port 127.0.0.1:${r} is already in use.`),{statusCode:409,code:"LOCAL_INSTANCE_PORT_IN_USE"});const a=r&&o?r:await async function(){const e=Number(process.env.TASK_HANDOFF_LOCAL_INSTANCE_PORT_START||19e3),t=Number.isInteger(e)&&e>0?e:19e3;for(let e=t;e<t+1e3&&e<=65535;e+=1)if(await Xa(e))return e;throw Object.assign(new Error(`No free localhost port found in range ${t}-${Math.min(t+999,65535)}.`),{statusCode:503,code:"LOCAL_INSTANCE_PORT_UNAVAILABLE"})}(),c=n.join(this.paths.dataDir,"local-instances",e.instance.id),u=n.join(c,"logs");t.mkdirSync(u,{recursive:!0,mode:448}),t.chmodSync(c,448),t.chmodSync(u,448);const[m,...p]=function(e){if(e)return e;const i=n.resolve(process.cwd(),"bin","task-handoff.js");if(t.existsSync(i))return[process.execPath,i,"web"];throw Object.assign(new Error("The bundled controlled-instance command is unavailable."),{statusCode:500,code:"LOCAL_CONTROLLED_COMMAND_MISSING"})}(this.commandOverride),h=[...p,"--host","127.0.0.1","--port",String(a)],g=d.randomUUID(),f=n.join(u,"controlled-instance.out.log"),y=n.join(u,"controlled-instance.err.log");eo(f),eo(y);const I=t.openSync(f,"a",384),A=t.openSync(y,"a",384),b=l.spawn(m,h,{cwd:i,detached:!1,stdio:["ignore",I,A],env:{...process.env,TASK_HANDOFF_CONTROL_MODE:"controlled",TASK_HANDOFF_RUNTIME_KIND:"local",TASK_HANDOFF_CONTROLLED_INSTANCE_VERSION:Xo(),...this.lockPath?{TASK_HANDOFF_LOCAL_CONTROLLED_INSTANCE_LOCK_PATH:this.lockPath}:{},TASK_HANDOFF_NODE_AGENT_URL:this.nodeAgentUrl(),TASK_HANDOFF_INSTANCE_ID:e.instance.id,TASK_HANDOFF_INSTANCE_NAME:e.instance.name,TASK_HANDOFF_REGISTRATION_TOKEN:e.instance.registrationToken||"",TASK_HANDOFF_PROJECT_ID:e.project.id,TASK_HANDOFF_NODE_ID:e.node.id,TASK_HANDOFF_RUNTIME_ID:e.runtime.id,TASK_HANDOFF_LOCAL_PROCESS_NONCE:g,TASK_HANDOFF_WORKSPACE:i,TASK_HANDOFF_WORKSPACE_MODE:"local-bind",TASK_HANDOFF_DATA_DIR:c,TASK_HANDOFF_LOG_DIR:u,TASK_HANDOFF_APP_SESSION_PERSIST:"1",TASK_HANDOFF_CODEX_APP_SERVER:process.env.TASK_HANDOFF_CODEX_APP_SERVER||"1",TASK_HANDOFF_WEB_PORT:String(a),TASK_HANDOFF_WEB_HOST:"127.0.0.1",...e.modelEnv||{}}});t.closeSync(I),t.closeSync(A);try{await function(e){return new Promise((t,n)=>{const i=()=>{e.off("error",r),t()},r=t=>{e.off("spawn",i),n(t)};e.once("spawn",i),e.once("error",r)})}(b)}catch(e){const r=e instanceof Error?e.message:String(e);try{t.appendFileSync(n.join(u,"controlled-instance.lifecycle.log"),`[${(new Date).toISOString()}] spawn failed command=${m} cwd=${i} error=${r}\n`)}catch{}throw Object.assign(new Error(`Controlled instance process could not start with command ${m} in ${i}: ${r}`),{statusCode:500,code:"LOCAL_INSTANCE_PROCESS_SPAWN_FAILED"})}const w=n.join(u,"controlled-instance.lifecycle.log");this.processSupervisor.track(e.instance.id,b,e=>{t.appendFileSync(w,`[${(new Date).toISOString()}] shutdown stage=${e.stage} pid=${e.pid??""} signal=${e.signal??""} timeoutMs=${e.timeoutMs??""}\n`)}),b.on("error",e=>{try{t.appendFileSync(w,`[${(new Date).toISOString()}] process error pid=${b.pid??""} error=${e.message}\n`)}catch{}}),b.once("exit",(e,n)=>{try{t.appendFileSync(w,`[${(new Date).toISOString()}] exited pid=${b.pid??""} code=${e??""} signal=${n??""}\n`)}catch{}});const v=`http://127.0.0.1:${a}`,E=b.pid?C(b.pid):void 0;if(!(b.pid&&e.instance.registrationToken&&await this.processSupervisor.waitUntilHealthy(v,{instanceId:e.instance.id,pid:b.pid,processNonce:g,startIdentity:E},b,e.instance.registrationToken)&&this.processSupervisor.markReady(e.instance.id,b)))throw this.processSupervisor.release(e.instance.id,b),null===b.exitCode&&null===b.signalCode&&b.kill("SIGTERM"),await Za(b),Object.assign(new Error(`Controlled instance process did not become ready for instance ${e.instance.id} on ${v}.`),{statusCode:503,code:"LOCAL_INSTANCE_PROCESS_NOT_READY"});return{status:"registering",health:"unknown",connectionStatus:"online",agentStatus:"unknown",targetStatus:"unknown",uiAccessStatus:"unknown",target:{strategy:"direct-port",status:"unknown",web:v,api:`${v}/api`},workspace:{mode:"local-bind",status:"pending",path:i},runtime:{kind:"local",workspacePath:i,pid:b.pid,port:a,labels:{...e.instance.runtime.labels,"task-handoff.runtime-kind":"local",[Ua]:g}}}}async stop(e){return await this.processSupervisor.stop(e.instance),{status:"stopped",health:"unknown",connectionStatus:"offline",agentStatus:"offline",targetStatus:"unknown",uiAccessStatus:"unknown",target:{...e.instance.target,status:"unknown"},runtime:e.instance.runtime}}async restart(e){return this.start(e)}async delete(e,t){return await this.stop(e),Kt.parse({instanceId:e.instance.id,containerDeleted:!0,completed:!0,deletedVolumes:[],retainedVolumes:[],volumeResults:[]})}async check(e){const[t,n]=await Promise.all([tc(this.runCommand,"codex"),tc(this.runCommand,"claude")]);return{status:"online",capabilities:ls({...e.capabilities,apps:{terminal:!0,codex:t,claude:n}})}}async stopAll(){await this.processSupervisor.stopAll()}}const ic=["codex","claude"],rc=5e3,oc=C(process.pid);function sc(e){const t=process.env[e]?.trim();return t||void 0}function ac(e){const t=e.authorization;return"string"==typeof t&&t.startsWith("Bearer ")?t.slice(7).trim():void 0}function cc(e){if("string"!=typeof e)return!1;const t=e.trim().toLowerCase();return"localhost"===t||"127.0.0.1"===t||"::1"===t||"::ffff:127.0.0.1"===t}function dc(e){return!e.ip&&!e.socket.remoteAddress&&!e.socket.remoteFamily}function lc(){return(new Date).toISOString()}async function uc(e,t){if(!t.target.web)return"unknown";const n=new AbortController,i=setTimeout(()=>n.abort(),2e3);try{return(await e(`${gc(t)}/api/health`,{signal:n.signal})).ok?"reachable":"endpoint-unreachable"}catch{return"endpoint-unreachable"}finally{clearTimeout(i)}}async function mc(e,t,n,i){const r=new AbortController,o=setTimeout(()=>r.abort(),i);try{return await e(t,{...n,signal:r.signal})}finally{clearTimeout(o)}}async function pc(e,t,n,i){if(!t.config.autoImportAgentConfigs)return void i.diagnostic({instanceId:t.id,action:n},"node instance config auto-import skipped");if("reachable"!==t.targetStatus)return;const r=gc(t),o=Number(process.env.TASK_HANDOFF_CONFIG_AUTO_IMPORT_TIMEOUT_MS||rc);for(const s of ic)try{const a=await mc(e,`${r}/api/config-sync/import/${encodeURIComponent(s)}`,{method:"POST"},Number.isFinite(o)&&o>0?o:rc);if(!a.ok){i.warn({instanceId:t.id,action:n,preset:s,statusCode:a.status},"node instance config auto-import failed");continue}i.diagnostic({instanceId:t.id,action:n,preset:s},"node instance config auto-import completed")}catch(e){i.warn({instanceId:t.id,action:n,preset:s,error:e instanceof Error?e.message:String(e)},"node instance config auto-import failed")}}async function hc(e,t,n){const i=t.requireInstance(n);if(t.instancePrivateConfigs.materialize(i.id,i.registrationToken,t.resolvedAssignedModelEnvironment(n)),"reachable"!==i.targetStatus||!i.target.web)return!1;const r=await mc(e,`${gc(i)}/api/internal/model-environment`,{method:"PUT",headers:{"content-type":"application/json",authorization:`Bearer ${i.registrationToken}`},body:JSON.stringify(t.resolvedAssignedModelEnvironment(n))},rc);if(!r.ok)throw Object.assign(new Error(`Instance ${n} rejected its managed model environment with HTTP ${r.status}.`),{statusCode:502,code:"INSTANCE_MODEL_ENVIRONMENT_APPLY_FAILED"});return!0}function gc(e){const t=e.target.web;if(!t){const t=new Error(`Instance ${e.id} does not have a web endpoint.`);throw Object.assign(t,{statusCode:409,code:"NODE_INSTANCE_WEB_ENDPOINT_MISSING"}),t}if("direct-port"!==e.target.strategy)return t.replace(/\/$/,"");try{const e=new URL(t);return e.port?(e.hostname=process.env.TASK_HANDOFF_NODE_AGENT_PROXY_HOST||"127.0.0.1",e.toString().replace(/\/$/,"")):t.replace(/\/$/,"")}catch{return t.replace(/\/$/,"")}}async function fc(e,t,n,i,r,o="request"){const s=e.requireInstance(i);if(s.imageProvisioning&&"ready"!==s.imageProvisioning.phase&&"docker"===e.requireRuntime(s.runtimeId).type)return r.diagnostic({instanceId:i,action:"start",reason:o,runtimeId:s.runtimeId,imageId:s.imageSelection?.imageId,imagePhase:s.imageProvisioning.phase},"node instance start queued until image provisioning completes"),e.controlledInstances.put(Si.parse({...s,status:"starting",updatedAt:lc()}));r.diagnostic({instanceId:i,action:"start",reason:o,runtimeId:s.runtimeId,imageId:s.imageSelection?.imageId},"node instance start requested");const a=e.applyInstanceLifecycle(i,{type:"start-requested"}),c=t.forRuntime(e.requireRuntime(a.runtimeId)),d=await c.start(e.context(a)),l=await uc(n,Si.parse({...a,...d,target:d.target?{...a.target,...d.target}:a.target,workspace:d.workspace?{...a.workspace,error:void 0,...d.workspace}:a.workspace,runtime:d.runtime?{...a.runtime,...d.runtime}:a.runtime,updatedAt:lc()})),u=e.applyInstanceLifecycle(i,{type:"runtime-lifecycle-completed",baseline:a,observation:{...d,target:d.target?{...d.target,status:l}:void 0,workspace:d.workspace?{error:void 0,...d.workspace}:void 0,targetStatus:l,uiAccessStatus:l}});return r.diagnostic({instanceId:i,action:"start",reason:o,status:u.status,connectionStatus:u.connectionStatus,targetStatus:u.targetStatus,targetWeb:u.target.web,containerName:u.runtime.containerName},"node instance start completed"),u}async function yc(e={}){const t=e.token||process.env.TASK_HANDOFF_NODE_AGENT_TOKEN,i=Number(e.port||process.env.TASK_HANDOFF_NODE_AGENT_PORT||"8091"),c=`http://127.0.0.1:${i}`,d=e.containerUrl||process.env.TASK_HANDOFF_NODE_AGENT_CONTAINER_URL,l=Qr(e.dataDir),u=e.remoteSecret||process.env.TASK_HANDOFF_NODE_AGENT_REMOTE_SECRET,p=e.remoteKeyId||process.env.TASK_HANDOFF_NODE_AGENT_REMOTE_KEY_ID,g=new Ia(l),f=g.resolveNodeId(e.nodeId||process.env.TASK_HANDOFF_NODE_ID),y=e.connectionMode||("local-ipc"===process.env.TASK_HANDOFF_NODE_AGENT_CONNECTION_MODE?"local-ipc":"local-loopback"),I=e.ipcPath||process.env.TASK_HANDOFF_NODE_AGENT_IPC_PATH||no(l.dataDir),A="local-ipc"===y?`ipc://${encodeURIComponent(I)}`:c,w=e.platform||process.platform,v=e.arch||process.arch,E=new ms(l,f,c,d,i,w);E.node.connectionMode=y,E.node.controlEndpoint=A,E.node.endpoint=A,E.init();const N=e.dockerCommandRunner||Ui,S=new qi(N,e.dockerTerminalCommandRunner),T=new Zi(N,{publishHost:"127.0.0.1",imageService:S});let z;const _=new Fa(new $a(T,N,w,v),new nc(e.dockerCommandRunner||Ui,l,()=>E.localNodeAgentUrl,function(){const e=process.env.TASK_HANDOFF_LOCAL_CONTROLLED_COMMAND_ARGV?.trim();if(!e){const e=process.env.TASK_HANDOFF_LOCAL_CONTROLLED_COMMAND?.trim();return e?e.split(/\s+/):void 0}let t;try{t=JSON.parse(e)}catch{throw Object.assign(new Error("TASK_HANDOFF_LOCAL_CONTROLLED_COMMAND_ARGV must be valid JSON."),{code:"LOCAL_CONTROLLED_COMMAND_INVALID"})}if(!Array.isArray(t)||!t.length||t.some(e=>"string"!=typeof e||!e))throw Object.assign(new Error("TASK_HANDOFF_LOCAL_CONTROLLED_COMMAND_ARGV must be a non-empty string array."),{code:"LOCAL_CONTROLLED_COMMAND_INVALID"});return t}(),e.localControlledInstanceLockPath||process.env.TASK_HANDOFF_LOCAL_CONTROLLED_INSTANCE_LOCK_PATH,e=>z.handleUnexpectedLocalExit(e.instanceId,new Error(`Local controlled instance exited unexpectedly (pid=${e.pid??"unknown"}, code=${e.code??"none"}, signal=${e.signal??"none"}).`)),(e,t)=>$.log.error({error:e,instanceId:t.instanceId,pid:t.pid},"local controlled instance exit recovery failed"))),C=e.updateCommandRunner||e.dockerCommandRunner||Ui,k=e.fetchImpl||fetch,O=new uo({cacheDir:n.join(l.dataDir,"runtime-artifacts"),fetchImpl:k}),R=e.resolveRuntimeArtifactRelease||((e,t,n)=>mo(e,t,n,k)),x=async(t,n,i)=>{const r=await n.artifactTarget(i);if(e.resolveRuntimeArtifact)return e.resolveRuntimeArtifact(t,r.platform,r.arch);const o=await R(t,r.platform,r.arch);if(o.identity.launcherAbi>r.launcherAbi)throw Object.assign(new Error(`Runtime requires launcher ABI ${o.identity.launcherAbi}, but ${r.platform}-${r.arch} provides ABI ${r.launcherAbi}.`),{code:"INSTANCE_BASE_RUNTIME_INCOMPATIBLE",retryable:!1});return O.resolve(o.identity,o.source)},D=e=>_.forRuntime(E.requireRuntime(e.runtimeId)),P=e=>{const t=D(e);return ja(t)?t:void 0},M=e=>{const t=P(e);if(t)return t;throw Object.assign(new Error(`Runtime for instance ${e.id} does not use managed artifacts.`),{code:"INSTANCE_RUNTIME_ARTIFACT_UNMANAGED",retryable:!1})},L=e=>Boolean(P(e)),j=(e,t)=>{const n=E.context(e);return x(t,M(e),n)},$=o({logger:e.logger??!0}),F=new to(l,{logger:(e,t)=>$.log.warn(t,e)}),U=()=>E.listInstances().map(e=>e.id),V=()=>{try{F.run(U())}catch(e){$.log.warn({error:e},"node-agent persistence maintenance failed")}};V();const q=setInterval(()=>{V()},216e5);q.unref();const H=setInterval(()=>{(()=>{try{F.capActiveInstanceLogs(U())}catch(e){$.log.warn({error:e},"node-agent active log maintenance failed")}})()},6e4);H.unref();const B={requests:0,active:0,completed:0,aborted:0,limitRejected:0,responseBytes:0,totalDurationMs:0,maxResponseBytes:Ms()};$.decorate("nodeAgentState",E),await $.register(s);const K=new Rr(E,t,{logger:$.log,safetyIntervalMs:Number(process.env.TASK_HANDOFF_EVENT_CONNECTION_SAFETY_INTERVAL_MS)||void 0}),G=new po(E.controlledInstances,Xo,{isInstalled:async(e,t)=>{const n=await j(e,t),i=await M(e).inspectRuntime(E.context(e),n.identity);if(i&&e.runtime.labels["task-handoff.bootstrap-backup"]){const t=E.requireInstance(e.id),n={...t.runtime.labels};delete n["task-handoff.bootstrap-backup"],E.controlledInstances.put(Si.parse({...t,runtime:{...t.runtime,labels:n},updatedAt:lc()}))}return i},beginDrain:async e=>{try{const t=await async function(e,t){const n=gc(t);if(t.registrationToken&&(await mc(e,`${n}/api/internal/node-agent/drain`,{method:"POST",headers:{authorization:`Bearer ${t.registrationToken}`}},1e4)).ok)return{requested:t.apps.runningCount,failures:[]};const i=await mc(e,`${n}/api/apps/sessions`,{method:"GET",headers:{"cache-control":"no-cache"}},5e3);if(!i.ok)throw new Error(`Could not list app sessions for runtime drain (HTTP ${i.status}).`);const r=function(e){if(!e||"object"!=typeof e||Array.isArray(e))return[];const t=e.data;if(Array.isArray(t))return t;if(!t||"object"!=typeof t||Array.isArray(t))return[];const n=t.snapshot,i=(n&&"object"==typeof n&&!Array.isArray(n)?n:t).sessions;return Array.isArray(i)?i:[]}(await i.json()).flatMap(e=>{if(!e||"object"!=typeof e||Array.isArray(e))return[];const t=e;return"running"===t.status&&"string"==typeof t.id&&t.id?[t.id]:[]}),o=await Promise.all(r.map(async t=>{try{const i=await mc(e,`${n}/api/apps/sessions/${encodeURIComponent(t)}/stop`,{method:"POST"},5e3);return i.ok?void 0:{sessionId:t,error:`HTTP ${i.status}`}}catch(e){return{sessionId:t,error:e instanceof Error?e.message:String(e)}}}));return{requested:r.length,failures:o.filter(e=>Boolean(e))}}(k,e);t.failures.length?$.log.warn({instanceId:e.id,requested:t.requested,failures:t.failures},"runtime convergence could not stop every app session"):$.log.info({instanceId:e.id,requested:t.requested},"runtime convergence requested app session drain")}catch(t){$.log.warn({instanceId:e.id,error:t instanceof Error?t.message:String(t)},"runtime convergence could not request app session drain")}},endDrain:async e=>{try{await async function(e,t){return!!t.registrationToken&&(await mc(e,`${gc(t)}/api/internal/node-agent/resume`,{method:"POST",headers:{authorization:`Bearer ${t.registrationToken}`}},5e3)).ok}(k,e)&&$.log.info({instanceId:e.id},"runtime convergence released app session drain")}catch(t){$.log.warn({instanceId:e.id,error:t instanceof Error?t.message:String(t)},"runtime convergence could not release app session drain")}},install:async(e,t)=>{const n=M(e);await n.installRuntime(E.context(e),await j(e,t))},restart:async e=>{const t=D(e),n=E.applyInstanceLifecycle(e.id,{type:"convergence-restart-requested"}),i=await t.restart(E.context(n));E.applyInstanceLifecycle(e.id,{type:"runtime-lifecycle-completed",baseline:n,observation:i})},onForcedDrain:e=>$.log.warn({instanceId:e.id},"runtime convergence drain deadline reached; restarting instance")},{drainTimeoutMs:Number(process.env.TASK_HANDOFF_RUNTIME_DRAIN_TIMEOUT_MS)||void 0,verificationTimeoutMs:Number(process.env.TASK_HANDOFF_RUNTIME_VERIFY_TIMEOUT_MS)||void 0,maxAttempts:Number(process.env.TASK_HANDOFF_RUNTIME_MAX_ATTEMPTS)||void 0});E.controlledInstances.setOnStored(e=>{K.publishInstanceLifecycle(e),E.updateJobs.reconcileRollouts(E.listInstances(),Xo())}),K.start(),$.decorate("nodeAgentEventForwarder",K);const J=new $r(N,()=>E.listInstances().filter(e=>"docker"===E.requireRuntime(e.runtimeId).type),e=>K.publish("instance.metrics.snapshot",e,{instanceId:e.instanceId}));J.start(),$.decorate("nodeAgentRuntimeMetrics",J);const W=(re=process.env.TASK_HANDOFF_DIAGNOSTIC_LOGS,["1","true","yes","on"].includes(String(re||"").trim().toLowerCase())),Y=new Ws(g,f,u,p),X=(e,t)=>{W&&$.log.info(e,t)},Q={diagnostic:X,warn:(e,t)=>$.log.warn(e,t)},Z=new ws,ee=new Cs(E.environmentTemplates,E.instancePrivateConfigs,T,e=>E.requireInstance(e),e=>E.requireRuntime(e),(e,t)=>Z.run(e,t),e=>E.listInstances().some(t=>t.environmentTemplateOrigin?.imageId===e)),te=async(e,t,n=()=>!0)=>{try{if(!n())return E.requireInstance(e);let i=E.requireInstance(e);"failed"===i.runtimeVersion?.phase&&L(i)&&(i=E.controlledInstances.put(Si.parse({...i,ready:!1,runtimeVersion:Zo(ho(i)),updatedAt:lc()})));const r=E.requireRuntime(i.runtimeId);await fc(E,_,k,e,Q);const o=E.requireInstance(e);if("docker"===r.type&&o.imageProvisioning&&"ready"!==o.imageProvisioning.phase)return K.syncNow(),o;if(!n())return E.requireInstance(e);z.markRestored(e);let s=E.requireInstance(e);if(L(s)){try{s=await G.schedule(e,{startRequested:!0})}catch(n){s=E.requireInstance(e),Q.warn({instanceId:e,action:"runtime.converge",reason:t,error:n instanceof Error?n.message:String(n)},"node instance runtime convergence failed after start")}"matched"!==s.runtimeVersion?.phase&&s.runtimeVersion?.error&&Q.warn({instanceId:e,action:"runtime.converge",reason:t,error:s.runtimeVersion.error},"node instance started with pending runtime convergence")}return n()?(await pc(k,s,"start",Q),K.syncNow(),s):E.requireInstance(e)}catch(n){throw E.applyInstanceLifecycle(e,{type:"start-failed",error:n}),K.syncNow(),Q.warn({instanceId:e,action:"start",reason:t,error:n instanceof Error?n.message:String(n)},"node instance start failed"),n}},ne=new Ss(E,S,{sync:()=>K.syncNow(),diagnostic:Q.diagnostic,warn:Q.warn,publish:(e,t,n)=>K.publish(e,t,{instanceId:n}),runInstanceOperation:(e,t)=>Z.run(e,t)}),ie=e=>{const t=Z.intent(e.id);ne.provision(e,async()=>{await te(e.id,"image-ready",()=>Z.isIntentCurrent(e.id,t)).catch(()=>{})})};var re;z=new Sa({state:E,runtimeAdapters:_,convergence:G,restoreInstance:e=>fc(E,_,k,e,Q,"restore"),autoImport:e=>pc(k,e,"start",Q),provisionImage:ie,stopImageProvisioning:()=>ne.stop(),usesManagedArtifact:L,warn:Q.warn,error:(e,t)=>$.log.error(e,t),runInstanceOperation:(e,t)=>Z.run(e,t)});const oe=new va({nodeId:f,jobs:E.updateJobs,runCommand:C,currentRuntimeVersion:Xo,listInstances:()=>E.listInstances(),resolveRuntimeArtifacts:async e=>(await(async e=>{const t=new Map;for(const e of _.managedAdapters()){const n=await e.artifactTarget();t.set(`${n.platform}-${n.arch}`,{adapter:e})}for(const e of E.listInstances()){const n=P(e);if(!n)continue;const i=E.context(e),r=await n.artifactTarget(i);t.set(`${r.platform}-${r.arch}`,{adapter:n,context:i})}return(await Promise.all([...t.values()].map(({adapter:t,context:n})=>x(e,t,n)))).sort((e,t)=>`${e.identity.platform}/${e.identity.arch}`.localeCompare(`${t.identity.platform}/${t.identity.arch}`))})(e)).map(e=>e.identity),moduleDir:("undefined"==typeof document?require("url").pathToFileURL(__filename).href:b&&"SCRIPT"===b.tagName.toUpperCase()&&b.src||new URL("cli.js",document.baseURI).href)?n.dirname(r.fileURLToPath("undefined"==typeof document?require("url").pathToFileURL(__filename).href:b&&"SCRIPT"===b.tagName.toUpperCase()&&b.src||new URL("cli.js",document.baseURI).href)):__dirname});return $.setErrorHandler((e,t,n)=>{const i=function(e){if(e instanceof a.z.ZodError)return{statusCode:400,code:"VALIDATION_ERROR",message:e.issues.map(e=>`${e.path.join(".")||"body"}: ${e.message}`).join("; "),details:{issues:e.issues.map(e=>({path:e.path.map(String),code:e.code,message:e.message}))}};const t=e&&"object"==typeof e?e:{};return{statusCode:"number"==typeof t.statusCode?t.statusCode:500,code:"string"==typeof t.code?t.code:"NODE_AGENT_ERROR",message:e instanceof Error?e.message:String(e),...t.details&&"object"==typeof t.details&&!Array.isArray(t.details)?{details:t.details}:{},..."boolean"==typeof t.retryable?{retryable:t.retryable}:{}}}(e);(W||i.statusCode>=500)&&(i.statusCode>=500?$.log.error.bind($.log):$.log.warn.bind($.log))({method:t.method,url:t.url,statusCode:i.statusCode,errorCode:i.code,error:i.message},"node agent request failed"),n.code(i.statusCode).send({error:{code:i.code,message:i.message,...e&&"object"==typeof e&&"string"==typeof e.expectedVersion?{expectedVersion:e.expectedVersion}:{},...e&&"object"==typeof e&&"string"==typeof e.actualVersion?{actualVersion:e.actualVersion}:{},...e&&"object"==typeof e&&"string"==typeof e.phase?{phase:e.phase}:{},...e&&"object"==typeof e&&"boolean"==typeof e.retryable?{retryable:e.retryable}:{},...e&&"object"==typeof e&&"number"==typeof e.blockingInstanceCount?{blockingInstanceCount:e.blockingInstanceCount}:{}}})}),$.addHook("preHandler",async e=>{const n=Y.verify(e);if(n){if(g.isRevokedPairing(n)&&"/api/node-agent/pairing/current"!==e.url.split("?")[0]){const e=new Error("The node agent pairing used for this request has been revoked.");throw Object.assign(e,{statusCode:401,code:"NODE_AGENT_HMAC_KEY_REVOKED"}),e}e.nodeAgentAuthKeyId=n}else if(dc(e)){if(t&&ac(e.headers)!==t){const e=new Error("Invalid node agent token.");throw Object.assign(e,{statusCode:401,code:"NODE_AGENT_UNAUTHORIZED"}),e}}else if("/api/node-agent/pairing/complete"!==e.url.split("?")[0]&&!function(e){const t=e.split("?")[0];return/^\/api\/node-agent\/instances\/[^/]+\/(register|heartbeat)$/.test(t)}(e.url)){if(Y.hasRemoteSecrets()){const e=new Error("Node agent HMAC signature is required.");throw Object.assign(e,{statusCode:401,code:"NODE_AGENT_HMAC_SIGNATURE_REQUIRED"}),e}if(!function(e){return cc(e.ip)||cc(e.socket.remoteAddress)||!e.ip&&!e.socket.remoteAddress&&!e.socket.remoteFamily}(e)){const e=new Error("Local node agent access is only accepted from loopback or local IPC connections.");throw Object.assign(e,{statusCode:401,code:"NODE_AGENT_LOCAL_TOKEN_REQUIRES_LOOPBACK"}),e}if(t&&ac(e.headers)!==t){const e=new Error("Invalid node agent token.");throw Object.assign(e,{statusCode:401,code:"NODE_AGENT_UNAUTHORIZED"}),e}}}),$.addHook("onClose",async()=>{clearInterval(q),clearInterval(H),J.stop(),K.stop(),await z.stop()}),$.decorate("nodeAgentRestoreManagedInstances",()=>z.restoreManagedInstances()),$.decorate("nodeAgentRecoverManagedInstances",()=>z.recoverManagedInstances()),$.decorate("nodeAgentStartRecoverySupervisor",()=>z.start()),$.get("/api/node-agent/health",async()=>{return{data:{ok:!0,role:"node-agent",process:{pid:process.pid,...oc?{startIdentity:oc}:{}},listener:{host:"127.0.0.1",port:E.currentListenerPort},nodeId:f,platform:La(w),arch:process.arch,protocolVersion:It,build:(e="node-agent",{component:e,packageName:"@task-handoff/node-agent",packageVersion:Xo(),protocolVersion:It,buildId:sc("TASK_HANDOFF_BUILD_ID"),builtAt:sc("TASK_HANDOFF_BUILT_AT"),gitCommit:sc("TASK_HANDOFF_GIT_COMMIT"),imageRef:sc("TASK_HANDOFF_IMAGE_REF"),imageDigest:sc("TASK_HANDOFF_IMAGE_DIGEST")}),instanceProxy:{...B},serverTime:(new Date).toISOString()}};var e}),function(e,t){e.get("/api/node-agent/settings/external-listener",async e=>({data:t(e).current()})),e.patch("/api/node-agent/settings/external-listener",async e=>({data:await t(e).update(e.body)}))}($,e=>{if(!dc(e)){const e=new Error("Node agent TCP listener settings are available only over local Unix IPC.");throw Object.assign(e,{statusCode:403,code:"NODE_AGENT_LISTENER_LOCAL_IPC_ONLY"}),e}if(!$.nodeAgentListenerManager){const e=new Error("Node agent TCP listener manager is not initialized.");throw Object.assign(e,{statusCode:503,code:"NODE_AGENT_LISTENER_UNAVAILABLE"}),e}return $.nodeAgentListenerManager}),function(e,t,n){e.get("/api/node-agent/updates/jobs",async()=>({data:n.list()})),e.post("/api/node-agent/updates/check",async e=>({data:await t.check(e.body)})),e.post("/api/node-agent/updates/apply",async(e,n)=>n.code(202).send({data:await t.apply(e.body)}))}($,oe,E.updateJobs),function(e,t){const{identity:n,nodeId:i,fetchImpl:r}=t;e.post("/api/node-agent/pairing/invites",async(e,t)=>{const r=n.createPairingInvite(na.parse(e.body||{}));return t.code(201).send({data:{nodeId:i,joinToken:r.token,expiresAt:r.expiresAt}})}),e.post("/api/node-agent/pairing/complete",async(e,t)=>{const r=n.completePairingInvite(ia.parse(e.body));return t.code(201).send({data:{nodeId:i,keyId:r.keyId,secret:r.secret,pairedAt:r.pairedAt}})}),e.get("/api/node-agent/control-plane-pairings",async e=>({data:n.listControlPlanePairings(e.nodeAgentAuthKeyId)})),e.delete("/api/node-agent/control-plane-pairings/:keyId",async e=>{const t=Aa.parse(e.params.keyId);return{data:{deleted:n.deleteControlPlanePairing(t,e.nodeAgentAuthKeyId)}}}),e.delete("/api/node-agent/pairing/current",async e=>({data:n.revokeCurrentControlPlanePairing(e.nodeAgentAuthKeyId||"")})),e.get("/api/node-agent/control-plane-connections",async()=>({data:n.listControlPlaneConnections().map(e=>({...e,...t.reverseTunnels()?.state(e.id)||{status:e.enabled?"connecting":"disabled"}}))})),e.delete("/api/node-agent/control-plane-connections/:connectionId",async e=>{const i=Aa.parse(e.params.connectionId),r=n.deleteControlPlaneConnection(i);return r&&t.reverseTunnels()?.connectConfigured(),{data:{deleted:r}}}),e.post("/api/node-agent/control-plane-connections",async(e,o)=>{const s=ra.parse(e.body),a=function(e){const t=new URL(e);if("http:"!==t.protocol&&"https:"!==t.protocol){const e=new Error("Control-plane URL must use http or https.");throw Object.assign(e,{statusCode:400,code:"NODE_AGENT_REMOTE_CONTROL_PLANE_URL_INVALID"}),e}return t.toString().replace(/\/$/,"")}(s.controlPlaneUrl);return n.runControlPlaneConnectionOperation(a,async()=>{const e=n.stageControlPlaneConnection({url:a,...s.controlPlaneName?{name:s.controlPlaneName}:{},enabled:!1!==s.activate});let c;try{c=await async function(e,t,n){const i=await e(new URL("/api/node-join/complete",t).toString(),{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(n)}),r=await i.json().catch(()=>({}));if(!i.ok){const e=new Error(r.error?.message||`Control-plane node join failed with HTTP ${i.status}.`);throw Object.assign(e,{statusCode:i.status,code:r.error?.code||"NODE_AGENT_REMOTE_JOIN_FAILED"}),e}return r.data||{}}(r,a,{joinToken:s.joinToken,nodeId:i,nodeName:t.nodeName(),keyId:e.pairing.keyId,secret:e.pairing.secret,pairedAt:e.pairing.pairedAt})}catch(t){throw n.rollbackControlPlaneConnection(e),t}const d=n.commitControlPlaneConnection(e,{name:s.controlPlaneName||("string"==typeof c.name&&c.name?c.name:void 0)});let l,u=d.connection.enabled?"saved":"disabled";const m=t.reverseTunnels();if(m)try{m.connectConfigured(),d.connection.enabled&&(u="connecting")}catch(e){u="failed",l=e instanceof Error?e.message:String(e)}return o.code(201).send({data:{pairing:n.listControlPlanePairings().find(e=>e.keyId===d.pairing.keyId),connection:d.connection,tunnel:{status:u,...l?{error:l}:{}}}})})})}($,{identity:g,nodeId:f,nodeName:()=>E.node.name,fetchImpl:k,reverseTunnels:()=>$.nodeAgentReverseTunnels}),function(e,t){e.get("/api/node-agent/runtimes",async()=>({data:t.listRuntimes()})),e.post("/api/node-agent/runtimes",async(e,n)=>n.code(201).send({data:t.createRuntime(Is.parse(e.body))})),e.patch("/api/node-agent/runtimes/:id",async e=>({data:t.updateRuntime(e.params.id,As.parse(e.body))})),e.delete("/api/node-agent/runtimes/:id",async e=>({data:{deleted:t.deleteRuntime(e.params.id)}})),e.post("/api/node-agent/runtimes/:id/check",async e=>({data:await t.checkRuntime(e.params.id)})),e.get("/api/node-agent/local-folders",async()=>({data:t.listLocalFolders()})),e.get("/api/node-agent/folders/tree",async e=>({data:t.listFolderTree(gs.parse(e.query))})),e.post("/api/node-agent/local-folders",async(e,n)=>n.code(201).send({data:t.createLocalFolder(hs.parse(e.body))})),e.delete("/api/node-agent/local-folders/:id",async e=>({data:{deleted:t.deleteLocalFolder(e.params.id)}}))}($,{listRuntimes:()=>E.nodeRuntimes.list(),createRuntime:e=>E.createRuntime(e),updateRuntime:(e,t)=>E.updateRuntime(e,t),deleteRuntime:e=>E.deleteRuntime(e),checkRuntime:async e=>{const t=E.requireRuntime(e);return E.checkRuntime(e,_.forRuntime(t))},listLocalFolders:()=>E.localFolders.list(),listFolderTree:Yr,createLocalFolder:e=>E.createLocalFolder(e),deleteLocalFolder:e=>E.localFolders.delete(e)}),function(e,t){e.get("/api/node-agent/models",async()=>({data:t.list()})),e.post("/api/node-agent/models",async(e,n)=>n.code(201).send({data:t.create(Vn.parse(e.body))})),e.put("/api/node-agent/models/:id/deploy",async e=>{const n=e.params.id,i=Hn.parse(e.body);if(i.id!==n)throw Object.assign(new Error(`Model payload id ${i.id} does not match route id ${n}.`),{statusCode:400,code:"NODE_MODEL_ID_MISMATCH"});return{data:t.deploy(i)}}),e.patch("/api/node-agent/models/:id",async e=>({data:t.update(e.params.id,qn.parse(e.body))})),e.delete("/api/node-agent/models/:id",async e=>({data:{deleted:t.delete(e.params.id)}})),e.put("/api/node-agent/instances/:id/model-assignment",async e=>{const n=e.params.id,i=t.assign(n,Bn.parse(e.body));return await(e=>hc(k,E,e))(n),{data:i}})}($,E.modelRegistry),function(e,t){e.get("/api/node-agent/environment-templates",async()=>({data:t.list()})),e.get("/api/node-agent/environment-templates/:id",async e=>({data:Zt.parse(t.require(e.params.id))})),e.post("/api/node-agent/instances/:id/environment-templates",async(e,n)=>{const i=await t.create(e.params.id,e.body);return n.code(201).send({data:i})}),e.delete("/api/node-agent/environment-templates/:id",async e=>({data:await t.delete(e.params.id)}))}($,ee),function(e,t){e.get("/api/node-agent/instances",async()=>({data:t.list()})),e.post("/api/node-agent/instances",async(e,n)=>{const i=await t.create(fs.parse(e.body));return t.afterCreate(i),n.code(201).send({data:i})}),e.post("/api/node-agent/instances/:id/image-provisioning/retry",async e=>{const n=t.retryImageProvisioning(e.params.id);return t.afterImageRetry(n),{data:n}}),e.patch("/api/node-agent/instances/:id",async e=>{const n=t.update(e.params.id,ys.parse(e.body));return t.afterUpdate(n),{data:n}}),e.post("/api/node-agent/instances/:id/register",async(e,n)=>{const i=e.params.id,r=t.sanitizeReport(i,"register",e.body),o=t.register(i,xi.parse(r),bs(e.headers));return t.afterReport(o,"register"),n.code(201).send({data:o})}),e.post("/api/node-agent/instances/:id/heartbeat",async e=>{const n=e.params.id,i=t.sanitizeReport(n,"heartbeat",e.body),r=t.heartbeat(n,Di.parse(i),bs(e.headers));return t.afterReport(r,"heartbeat"),{data:r}})}($,{list:()=>E.listInstances(),create:e=>"template"===e.environmentSource?.type?ee.runTemplateOperation(e.environmentSource.environmentTemplateId,()=>E.createInstance(e)):E.createInstance(e),retryImageProvisioning:e=>ne.retry(e),update:(e,t)=>{const n=E.requireInstance(e);return E.controlledInstances.put(Si.parse({...n,...t,...t.config?{config:{...n.config,...t.config}}:{},updatedAt:lc()}))},register:(e,t,n)=>E.registerInstance(e,t,n),heartbeat:(e,t,n)=>E.heartbeatInstance(e,t,n),sanitizeReport:(e,t,n)=>{const i=n&&"object"==typeof n&&!Array.isArray(n)?n.protocolVersion:void 0;if("string"!=typeof i||i===It)return n;const r=({field:n,action:r})=>$.log.warn({instanceId:e,report:t,protocolVersion:i,expectedProtocolVersion:It,field:n,action:r},"cross-version controlled instance report sanitized");return"register"===t?function(e,t){if(!e||"object"!=typeof e||Array.isArray(e))return e;const n=e,i=["instanceId","projectId","source","nodeId","runtimeId","imageSelection","instanceVersion","protocolVersion","build","controlMode","capabilities","appInventory","target","workspace","registrationToken","processIncarnationId"],r=new Set([...i,"imageId"]);for(const e of Object.keys(n))r.has(e)||t?.({field:e,action:"ignored"});return Object.prototype.hasOwnProperty.call(n,"imageId")&&t?.({field:"imageId",action:"migrated"}),{...Ri(n,i),imageSelection:Jt(n.imageSelection,n.imageId)}}(n,r):function(e,t){if(!e||"object"!=typeof e||Array.isArray(e))return e;const n=["status","health","protocolVersion","build","capabilities","appInventory","apps","aiSessions","triggers","workspace","target","processIncarnationId"],i=new Set(n);for(const n of Object.keys(e))i.has(n)||t?.({field:n,action:"ignored"});return Ri(e,n)}(n,r)},afterCreate:e=>{K.syncNow(),e.imageProvisioning&&ie(e)},afterImageRetry:e=>{K.syncNow(),ie(e)},afterUpdate:()=>K.syncNow(),afterReport:(e,t)=>{K.syncNow(),"register"===t?X({instanceId:e.id,action:t,protocolVersion:e.protocolVersion,build:e.build,targetStatus:e.targetStatus,targetStrategy:e.target.strategy},"node instance registered"):X({instanceId:e.id,action:t,status:e.status,health:e.health,protocolVersion:e.protocolVersion,build:e.build,targetStatus:e.targetStatus,apps:e.apps.runningCount},"node instance heartbeat accepted"),!L(e)||e.ready&&"matched"===e.runtimeVersion?.phase||G.schedule(e.id).catch(n=>$.log.error({instanceId:e.id,error:n},`runtime convergence after ${t} failed`))}}),$.get("/api/node-agent/events",{websocket:!0},e=>{const t=e;t.send(JSON.stringify({type:"node-agent.events.connected",nodeId:f,serverTime:(new Date).toISOString()}));const n=K.addOutput(t);t.on("close",n),t.on("error",n)}),$.get("/api/node-agent/docker/images",async()=>({data:await ur(e.dockerCommandRunner)})),$.get("/api/node-agent/instances/:id/metrics",async e=>{const t=e.params.id,n=E.requireInstance(t);if("docker"!==E.requireRuntime(n.runtimeId).type){const e=new Error(`Runtime type ${E.requireRuntime(n.runtimeId).type} does not provide resource metrics.`);throw Object.assign(e,{statusCode:409,code:"INSTANCE_METRICS_UNSUPPORTED"}),e}return{data:await J.snapshot(t)}}),function(e,t,n,i,r,o=new ws){const s=e=>o.intent(e),a=e=>Promise.resolve(i.cancel(e)).then(()=>({ok:!0}),e=>({ok:!1,error:e})),c=(e,t)=>{if(!o.isIntentCurrent(e,t))throw Object.assign(new Error(`Instance operation for ${e} was superseded by stop or delete.`),{statusCode:409,code:"INSTANCE_OPERATION_SUPERSEDED"})};e.post("/api/node-agent/instances/:id/start",async e=>{vs.parse(e.body);const t=e.params.id,n=s(t);return o.run(t,async()=>(c(t,n),r.allowRecovery(t),{data:await r.start(t,()=>o.isIntentCurrent(t,n))}))}),e.post("/api/node-agent/instances/:id/runtime/reconcile",async e=>{const n=e.params.id;vs.parse(e.body);const a=s(n);return o.run(n,async()=>{c(n,a);const e=t.requireInstance(n);t.putInstance(Si.parse({...e,ready:!1,runtimeVersion:Zo(ho(e)),updatedAt:Es()})),c(n,a);const o=await i.schedule(n,{startRequested:!["created","stopped"].includes(e.status),resumeCancelled:!0});return c(n,a),r.sync(),{data:o}})}),e.post("/api/node-agent/instances/:id/stop",async e=>{const i=e.params.id;t.requireInstance(i),o.invalidate(i);const s=a(i);return o.run(i,async()=>{const e=t.requireInstance(i);t.applyLifecycle(i,{type:"stop-requested"});try{await r.suppressRecovery(i);const e=await s;if("error"in e)throw e.error;const o=t.requireInstance(i);r.diagnostic({instanceId:i,action:"stop",runtimeId:o.runtimeId,containerName:o.runtime.containerName},"node instance stop requested"),await n.forRuntime(t.requireRuntime(o.runtimeId)).stop(t.context(o))}catch(n){try{t.applyLifecycle(i,{type:"stop-failed",baseline:e}),r.sync()}finally{r.allowRecovery(i)}throw n}const o=t.applyLifecycle(i,{type:"stop-completed"});return r.completeSuppressedRecovery(i),r.sync(),r.diagnostic({instanceId:i,action:"stop",status:o.status,connectionStatus:o.connectionStatus,containerName:o.runtime.containerName},"node instance stop completed"),{data:o}})}),e.post("/api/node-agent/instances/:id/restart",async e=>{const a=e.params.id;vs.parse(e.body);const d=s(a);return o.run(a,async()=>{c(a,d),r.allowRecovery(a);let e=t.requireInstance(a);if(r.isManaged(e)&&(!e.ready||"matched"!==e.runtimeVersion?.phase)){"failed"===e.runtimeVersion?.phase&&(e=t.putInstance(Si.parse({...e,runtimeVersion:Zo(ho(e)),updatedAt:Es()}))),c(a,d);const n=await i.schedule(a,{startRequested:!0});return c(a,d),r.sync(),{data:n}}r.diagnostic({instanceId:a,action:"restart",runtimeId:e.runtimeId,imageId:e.imageSelection?.imageId,containerName:e.runtime.containerName},"node instance restart requested");const o=await n.forRuntime(t.requireRuntime(e.runtimeId)).restart(t.context(e));let s=t.applyLifecycle(a,{type:"runtime-lifecycle-completed",baseline:e,observation:{...o,target:o.target?{...e.target,...o.target}:void 0}});r.markRestarted(a),c(a,d);const l=Si.parse({...s,updatedAt:Es()}),u=await r.probe(l);return c(a,d),s=t.applyLifecycle(a,{type:"runtime-lifecycle-completed",baseline:s,observation:{target:{...s.target,status:u},targetStatus:u,uiAccessStatus:u}}),await r.autoImport(s),r.sync(),r.diagnostic({instanceId:a,action:"restart",status:s.status,connectionStatus:s.connectionStatus,targetStatus:s.targetStatus,targetWeb:s.target.web,containerName:s.runtime.containerName},"node instance restart completed"),{data:s}})}),e.post("/api/node-agent/instances/:id/delete",async e=>{const i=e.params.id,s=Ht.parse(e.body);t.requireInstance(i),o.invalidate(i);const c=a(i);return o.run(i,async()=>{const e=t.requireInstance(i);"deleting"!==e.status&&t.applyLifecycle(i,{type:"stop-requested"});try{await r.suppressRecovery(i);const e=await c;if("error"in e)throw e.error;const a=t.requireInstance(i);t.putInstance(Si.parse({...a,status:"deleting",ready:!1,updatedAt:Es()})),r.diagnostic({instanceId:i,action:"delete",runtimeId:a.runtimeId,containerName:a.runtime.containerName},"node instance delete requested");const d=await n.forRuntime(t.requireRuntime(a.runtimeId)).delete(t.context(a,{}),s);if(!d.completed)return r.diagnostic({instanceId:i,action:"delete",volumeResults:d.volumeResults},"node instance delete requires retry"),r.sync(),{data:d};r.diagnostic({instanceId:i,action:"delete"},"node instance delete completed");const l=t.deleteInstance(i);return l&&(r.forgetRecovery(i),o.clearIntent(i)),r.deleteMetadata(i),l&&r.retireInstanceData(i),l&&a.environmentTemplateOrigin?.imageId&&r.releaseEnvironmentImage&&await r.releaseEnvironmentImage(a.environmentTemplateOrigin.imageId).catch(e=>{r.diagnostic({instanceId:i,action:"release-environment-image",error:e instanceof Error?e.message:String(e)},"environment image cleanup deferred after instance deletion")}),r.sync(),{data:d}}catch(n){try{t.putInstance(Si.parse({...e,updatedAt:Es()})),r.sync()}finally{r.allowRecovery(i)}throw n}})})}($,{requireInstance:e=>E.requireInstance(e),requireRuntime:e=>E.requireRuntime(e),putInstance:e=>E.controlledInstances.put(e),deleteInstance:e=>E.controlledInstances.delete(e),applyLifecycle:(e,t)=>E.applyInstanceLifecycle(e,t),context:(e,t)=>E.context(e,t)},_,G,{start:(e,t)=>te(e,"request",t),sync:()=>K.syncNow(),isManaged:L,probe:e=>uc(k,e),autoImport:e=>pc(k,e,"restart",Q),markRestarted:e=>z.markRestored(e),allowRecovery:e=>z.allowRecovery(e),suppressRecovery:e=>z.suppressRecovery(e),forgetRecovery:e=>z.forgetInstance(e),completeSuppressedRecovery:e=>z.completeSuppressedOperation(e),deleteMetadata:e=>{E.modelRegistry.deleteInstanceMetadata(e),E.instancePrivateConfigs.delete(e)},retireInstanceData:e=>{F.retire(e)},releaseEnvironmentImage:e=>ee.releaseUnusedImage(e),diagnostic:X},Z),function(e,t){const{fetchImpl:n,metrics:i,diagnostic:r}=t;e.post("/api/node-agent/instances/:id/proxy",async(e,i)=>{const o=e.params.id,s=ps.parse(e.body),a=t.instanceBase(o),c=Ls(s.path);"POST"===s.method&&"/api/apps/sessions"===c&&await t.syncModelEnvironment(o),r({instanceId:o,action:"proxy",method:s.method,path:c,instanceBase:a},"node instance proxy requested");const d=await n(`${a}${c}`,{method:s.method,headers:{...s.headers},body:Ps(s)}),l=d.headers.get("content-type")||"application/octet-stream",u=await d.text();r({instanceId:o,action:"proxy",method:s.method,path:c,statusCode:d.status,contentType:l},"node instance proxy completed"),i.code(d.status).type(l).send(u)}),e.post("/api/node-agent/instances/:id/proxy/stream",{bodyLimit:xs},async(e,o)=>{const s=Date.now();i.requests+=1,i.active+=1;const a=new AbortController;let c=0,d=!1,l=!1;const u=e=>{l||(l=!0,i.active-=1,i.totalDurationMs+=Date.now()-s,i.responseBytes+=c,i[e]+=1)},m=()=>{a.abort(),d&&u("aborted")};e.raw.once("aborted",m),o.raw.once("close",m);try{const s=e.params.id,l=ps.parse(e.body),m=t.instanceBase(s),p=Ls(l.path);r({instanceId:s,action:"proxy.stream",method:l.method,path:p,instanceBase:m},"node instance streaming proxy requested");const g=await n(`${m}${p}`,{method:l.method,headers:{...l.headers},body:Ps(l),signal:a.signal}),f=Number(g.headers.get("content-length"));if(Number.isFinite(f)&&f>i.maxResponseBytes)return i.limitRejected+=1,a.abort(),js(o,i.maxResponseBytes);o.code(g.status);for(const[e,t]of Object.entries(Ds(g.headers)))o.header(e,t);if(!g.body||"HEAD"===l.method)return u("completed"),o.send();const y=new h.Transform({transform(e,t,n){if(c+=e.length,c>i.maxResponseBytes)return i.limitRejected+=1,a.abort(),void n(Object.assign(new Error("Instance proxy response limit exceeded."),{code:"INSTANCE_PROXY_RESPONSE_TOO_LARGE"}));n(null,e)}});return d=!0,y.once("end",()=>u("completed")),y.once("error",()=>u("aborted")),o.send(h.Readable.fromWeb(g.body).pipe(y))}catch(e){throw u("aborted"),e}finally{e.raw.off("aborted",m),d||u("completed")}}),e.post("/api/node-agent/instances/:id/proxy/raw",{bodyLimit:xs},async(e,o)=>{const s=e.params.id,a=ps.parse(e.body),c=t.instanceBase(s),d=Ls(a.path);r({instanceId:s,action:"proxy.raw",method:a.method,path:d,instanceBase:c},"node instance raw proxy requested");const l=await n(`${c}${d}`,{method:a.method,headers:{...a.headers},body:Ps(a)}),u=Number(l.headers.get("content-length"));if(Number.isFinite(u)&&u>i.maxResponseBytes)return i.limitRejected+=1,await(l.body?.cancel("Instance proxy response limit exceeded.").catch(()=>{})),js(o,i.maxResponseBytes);let m;try{m=await async function(e,t){if(!e.body)return Buffer.alloc(0);const n=[];let i=0;const r=e.body.getReader();for(;;){const{done:e,value:o}=await r.read();if(e)break;if(i+=o.byteLength,i>t)throw await r.cancel("Instance proxy response limit exceeded.").catch(()=>{}),Object.assign(new Error("Instance proxy response limit exceeded."),{code:"INSTANCE_PROXY_RESPONSE_TOO_LARGE"});n.push(Buffer.from(o))}return Buffer.concat(n,i)}(l,i.maxResponseBytes)}catch(e){if(!(e instanceof Error)||"INSTANCE_PROXY_RESPONSE_TOO_LARGE"!==e.code)throw e;return i.limitRejected+=1,js(o,i.maxResponseBytes)}return r({instanceId:s,action:"proxy.raw",method:a.method,path:d,statusCode:l.status,byteLength:m.length},"node instance raw proxy completed"),{data:{status:l.status,headers:Ds(l.headers),bodyBase64:m.toString("base64")}}}),e.get("/api/node-agent/instances/:id/proxy/ws/*",{websocket:!0},(e,n)=>{const i=n.params.id,o=n.params["*"]||"",s=n.url.indexOf("?"),a=s>=0?n.url.slice(s):"";let c;try{const s=t.instanceBase(i),d=new URL(`/${o}${a}`,`${s}/`);d.protocol="https:"===d.protocol?"wss:":"ws:";const l=function(e){const t=e["sec-websocket-protocol"],n=(Array.isArray(t)?t.join(","):"string"==typeof t?t:"").split(",").map(e=>e.trim()).filter(Boolean);return n.length?n:void 0}(n.headers);r({instanceId:i,action:"proxy.ws",path:`/${o}${a}`,upstreamUrl:d.toString(),protocols:l||[]},"node instance websocket proxy opening"),c=l?new m(d,l):new m(d),c.on("open",()=>{r({instanceId:i,action:"proxy.ws",path:`/${o}${a}`},"node instance websocket proxy opened"),e.on("message",(e,t)=>c?.readyState===m.OPEN&&c.send(function(e,t){return t?e:e.toString()}(e,t))),e.on("close",()=>c?.close()),e.on("error",()=>c?.close())}),c.on("message",(t,n)=>e.readyState===m.OPEN&&e.send(n?t:t.toString())),c.on("close",()=>{r({instanceId:i,action:"proxy.ws",path:`/${o}${a}`},"node instance websocket proxy closed"),e.close()}),c.on("error",t=>{r({instanceId:i,action:"proxy.ws",path:`/${o}${a}`,error:t instanceof Error?t.message:String(t)},"node instance websocket proxy failed"),e.close(1011,"Instance websocket proxy failed.")})}catch(t){r({instanceId:i,action:"proxy.ws",path:`/${o}${a}`,error:t instanceof Error?t.message:String(t)},"node instance websocket endpoint unavailable"),c?.close(),e.close(1011,"Instance websocket endpoint is not reachable.")}})}($,{fetchImpl:k,metrics:B,instanceBase:e=>gc(E.requireInstance(e)),syncModelEnvironment:e=>hc(k,E,e),diagnostic:X}),$}async function Ic(e){const r=Qr(e.dataDir),o=function(e,i={}){return function(e,i={}){t.mkdirSync(n.dirname(e),{recursive:!0});const r=C(process.pid),o={pid:process.pid,hostname:c.hostname(),command:process.argv.join(" "),acquiredAt:(new Date).toISOString(),token:d.randomUUID(),...void 0!==i.component?{component:i.component}:{},...r?{startIdentity:r}:{},...void 0!==i.dataDir?{dataDir:i.dataDir}:{},...void 0!==i.host?{host:i.host}:{},...void 0!==i.port?{port:i.port}:{},...void 0!==i.instanceId?{instanceId:i.instanceId}:{}};for(let n=0;n<5;n+=1)try{return t.mkdirSync(e),t.writeFileSync(T(e),`${JSON.stringify({token:o.token,pid:o.pid,startIdentity:o.startIdentity,startedAt:(new Date).toISOString()})}\n`,{encoding:"utf8",mode:384,flag:"wx"}),D(e,o),{lockPath:e,owner:o,updateDetails:t=>P(e,o,t),release(){const n=O(e);n?.token===o.token&&t.rmSync(e,{recursive:!0,force:!0})}}}catch(r){if("EEXIST"!==r.code)throw r;const o=O(e);if(x(o))throw new N(e,o,i.error);if(!o&&(L(e)||F(e)<(i.incompleteLockStaleMs??2e3))){if(n+1<5){$();continue}throw new N(e,void 0,i.error)}const s=d.randomUUID();if(!U(e,s)){if(n+1<5){$();continue}throw new N(e,O(e),i.error)}const a=O(e);if(x(a))throw j(z(e)),new N(e,a,i.error);if(o?.token&&a?.token!==o.token){j(z(e));continue}if(!q(e,s))continue;t.rmSync(e,{recursive:!0,force:!0})}const s=O(e);throw new N(e,s,i.error)}(e,{...i,component:"node-agent",error:{label:"Node agent",code:"NODE_AGENT_ALREADY_RUNNING"}})}(function(){const e=process.env.TASK_HANDOFF_NODE_AGENT_LOCK_PATH?.trim();return e?n.resolve(e):n.join(c.tmpdir(),`task-handoff-node-agent-${process.getuid?.()??"user"}.lock`)}(),{dataDir:r.dataDir});try{const c=(s=e.host,a=e.port,fi.parse({bindScope:"0.0.0.0"===s.trim()?"all-ipv4":"loopback",port:a})),d=t.existsSync(r.settingsPath),l=function(e,t){return new ko(e.settingsPath,()=>({version:1,externalListener:t}),{schema:$s,sanitize:Us})}(r,c);let u=l.get().externalListener;if("allocate"===process.env.TASK_HANDOFF_NODE_AGENT_PORT_CONFLICT){const e=await async function(e,t=20){for(let n=0;n<t&&e.port+n<=65535;n+=1){const t={...e,port:e.port+n};if(await Vs(t))return t}throw Object.assign(new Error(`No available node-agent port found starting at ${e.port}.`),{statusCode:503,code:"NODE_AGENT_LISTENER_PORT_UNAVAILABLE"})}(u);e.port!==u.port&&(l.put({version:1,externalListener:e}),u=e)}const m=e=>{if(!o.updateDetails({dataDir:r.dataDir,host:e.host,port:e.port,instanceId:void 0}))throw new Error("Node agent singleton ownership changed while publishing listener state.")},p={...e,port:u.port},h=await yc(p),g=h.nodeAgentState;if(!g)throw new Error("Node agent state was not initialized.");const f=new Ia(r).resolveNodeId(e.nodeId||process.env.TASK_HANDOFF_NODE_ID),y=function(e,t,n,i){const r=t.token||process.env.TASK_HANDOFF_NODE_AGENT_TOKEN,o=new Ia(n),s=new Map;let a=!1;const c=(t,n)=>{if(a||n.retry.pending||s.get(t)!==n)return;const r=n.retry.schedule(()=>{a||s.get(t)!==n||n.socket||d(t,n)});r&&(n.status="reconnecting",n.nextRetryAt=new Date(Date.now()+r.delay).toISOString(),e.log.info({nodeId:i,tunnelUrl:new URL(n.config.tunnelUrl).origin,attempt:r.attempt,delay:r.delay},"node agent reverse tunnel reconnect scheduled"))},d=(n,o)=>{let d;o.status=o.lastDisconnectedAt?"reconnecting":"connecting",o.error=void 0,o.nextRetryAt=void 0;try{d=Oa(e,{...o.config,nodeId:i,port:()=>e.nodeAgentState.currentListenerPort,token:r})}catch(e){return o.status="failed",o.lastDisconnectedAt=(new Date).toISOString(),o.error=e instanceof Error?e.message:String(e),void c(n,o)}o.socket=d;const l=new Da({connectTimeoutMs:t.connectTimeoutMs,handshakeTimeoutMs:t.handshakeTimeoutMs,heartbeatIntervalMs:t.heartbeatIntervalMs,heartbeatTimeoutMs:t.heartbeatTimeoutMs,stableThresholdMs:t.stableThresholdMs,ping:()=>d.ping(),onTimeout:e=>{s.get(n)===o&&o.socket===d&&(o.status="failed",o.error=`Reverse tunnel ${e} timeout.`,d.terminate())},onStable:()=>o.retry.reset()});return o.supervisor=l,l.start(),d.on("open",()=>{s.get(n)===o&&o.socket===d&&(o.status="connecting",l.opened())}),d.on("message",t=>{if(s.get(n)!==o||o.socket!==d||"connected"===o.status)return;let r;try{r=JSON.parse(String(t))}catch{return}const a=r&&"object"==typeof r?r.type:void 0;"control-plane.hello"!==a&&"control-plane.identified"!==a||(l.activity(),l.healthy(),o.status="connected",o.lastConnectedAt=(new Date).toISOString(),o.nextRetryAt=void 0,o.error=void 0,e.log.info({nodeId:i,tunnelUrl:new URL(o.config.tunnelUrl).origin},"node agent reverse tunnel connected"))}),d.on("pong",()=>l.pong()),d.on("close",(t,r)=>{s.get(n)===o&&o.socket===d&&(l.close(),o.socket=void 0,o.lastDisconnectedAt=(new Date).toISOString(),o.error=`WebSocket closed${t?` (${t})`:""}${r?`: ${Buffer.isBuffer(r)?r.toString("utf8"):String(r)}`:""}`,a||(e.log.warn({nodeId:i,tunnelUrl:new URL(o.config.tunnelUrl).origin,code:t,reason:Buffer.isBuffer(r)?r.toString("utf8"):String(r||"")},"node agent reverse tunnel disconnected"),c(n,o)))}),d.on("error",e=>{s.get(n)===o&&o.socket===d&&(o.status="failed",o.error=e instanceof Error?e.message:String(e),d.terminate())}),d},l=(e,t)=>{const n=s.get(e);n?.retry.cancel(),n?.supervisor?.close();const i={config:t,retry:new kr,status:"connecting"};return s.set(e,i),n?.socket?.close(1e3,"Reverse tunnel reconnecting."),d(e,i)},u=(e,t)=>e.tunnelUrl===t.tunnelUrl&&e.keyId===t.keyId&&e.secret===t.secret;return{connectConfigured:()=>{a=!1;const n=new Map,r=o.resolvedControlPlaneAccess(),c=new Set;for(const{connection:t,pairing:o}of r.connections){if(!t.enabled)continue;if(!o){e.log.warn({nodeId:i,connectionId:t.id,pairingKeyId:t.pairingKeyId},"node agent control-plane connection has no pairing");continue}const r=Pa(t.url);n.set(t.id,{tunnelUrl:r,keyId:o.keyId,secret:o.secret}),c.add(r)}const d=function(e){const t=e.controlPlaneTunnelUrl||process.env.TASK_HANDOFF_CONTROL_PLANE_TUNNEL_URL;return t?new URL(t).toString():void 0}(t);if(d&&!c.has(d)){const e=o.reverseTunnelSecret(process.env.TASK_HANDOFF_CONTROL_PLANE_URL,t.remoteSecret||process.env.TASK_HANDOFF_NODE_AGENT_REMOTE_SECRET,t.remoteKeyId||process.env.TASK_HANDOFF_NODE_AGENT_REMOTE_KEY_ID);n.set(`explicit:${d}`,{tunnelUrl:d,keyId:e?.keyId,secret:e?.secret}),c.add(d)}const m=r.hasPersistedAccess?void 0:function(){const e=process.env.TASK_HANDOFF_CONTROL_PLANE_URL;if(!e)return;const t=new URL(Bs,e);return t.protocol="https:"===t.protocol?"wss:":"ws:",t.toString()}();if(m&&!c.has(m)){const e=o.reverseTunnelSecret(process.env.TASK_HANDOFF_CONTROL_PLANE_URL,t.remoteSecret||process.env.TASK_HANDOFF_NODE_AGENT_REMOTE_SECRET,t.remoteKeyId||process.env.TASK_HANDOFF_NODE_AGENT_REMOTE_KEY_ID);n.set(`bootstrap:${m}`,{tunnelUrl:m,keyId:e?.keyId,secret:e?.secret})}(e=>{for(const[t,n]of s)e.has(t)||(n.retry.cancel(),n.supervisor?.close(),s.delete(t),n.socket?.close(1e3,"Reverse tunnel configuration removed."));for(const[t,n]of e){const e=s.get(t);e&&u(e.config,n)||l(t,n)}})(n)},state:e=>{const t=s.get(e);if(t)return{status:t.status,connection:t.supervisor?.diagnostics(),...t.lastConnectedAt?{lastConnectedAt:t.lastConnectedAt}:{},...t.lastDisconnectedAt?{lastDisconnectedAt:t.lastDisconnectedAt}:{},...t.nextRetryAt?{nextRetryAt:t.nextRetryAt}:{},...t.error?{error:t.error}:{}}},closeAll:()=>{a=!0;for(const e of s.values())e.retry.cancel(),e.supervisor?.close(),e.socket?.close(1001,"Node agent shutting down.");s.clear()}}}({log:h.log,inject:e=>h.inject(e),nodeAgentEventForwarder:h.nodeAgentEventForwarder,nodeAgentState:g},p,r,f);h.decorate("nodeAgentReverseTunnels",y);const I=new qs({app:h,state:g,settings:l,config:u,source:d?"persisted":"bootstrap",onActiveListener:m});let A;h.decorate("nodeAgentListenerManager",I),function(e){let t=!1;const n=async n=>{if(!t){t=!0,y.closeAll(),A?.close();try{await e.close()}finally{process.exitCode=n?0:process.exitCode}}},i=()=>{n("SIGINT")},r=()=>{n("SIGTERM")};process.once("SIGINT",i),process.once("SIGTERM",r),e.addHook("onClose",async()=>{process.off("SIGINT",i),process.off("SIGTERM",r)})}(h),h.addHook("onClose",async()=>{A?.close(),o.release()});try{await h.ready();const o=e.ipcPath||process.env.TASK_HANDOFF_NODE_AGENT_IPC_PATH||no(r.dataDir);A=await async function(e,r){!function(e,i=process.platform){if("win32"!==i){t.mkdirSync(n.dirname(e),{recursive:!0,mode:448});try{t.chmodSync(n.dirname(e),448)}catch{}try{t.unlinkSync(e)}catch(e){if("ENOENT"!==e.code)throw e}}}(r);const o=i.createServer((t,n)=>{e.server.emit("request",t,n)});return o.on("upgrade",(t,n,i)=>{e.server.emit("upgrade",t,n,i)}),await new Promise((e,t)=>{o.once("error",t),o.listen(r,()=>{o.off("error",t),e()})}),o}(h,o),await I.start(),y.connectConfigured(),h.nodeAgentStartRecoverySupervisor?.()}catch(e){throw await h.close(),e}}catch(e){throw o.release(),e}var s,a}function Ac(e){const t=Number(e);if(!Number.isInteger(t)||t<=0||t>65535)throw new Error("Port must be a valid TCP port.");return t}function bc(e){if("local-ipc"!==e&&"local-loopback"!==e)throw new Error("Connection mode must be local-ipc or local-loopback.");return e}function wc(e){const t=Number(e);if(!Number.isInteger(t)||t<=0)throw new Error("Expiry must be a positive integer.");return t}(async function(){const t=new e.Command;t.name("task-handoff-node-agent").description("Run a TaskHandoff node agent.").version(E("@task-handoff/cli")).option("--host <host>","Node agent host",process.env.TASK_HANDOFF_NODE_AGENT_HOST||"127.0.0.1").option("-p, --port <port>","Node agent port",Ac,Number(process.env.TASK_HANDOFF_NODE_AGENT_PORT)||8091).option("--data-dir <path>","Node agent data directory").option("--token <token>","Bearer token required by the control plane").option("--connection-mode <mode>","Local control connection mode",bc).option("--ipc-path <path>","Unix socket path used by local-ipc mode").option("--control-plane-tunnel-url <url>","Control plane reverse WebSocket tunnel URL").action(async e=>{await Ic({host:e.host,port:e.port,dataDir:e.dataDir,token:e.token,connectionMode:e.connectionMode,ipcPath:e.ipcPath,controlPlaneTunnelUrl:e.controlPlaneTunnelUrl})}),t.command("invite").description("Create a one-time token for pairing this node agent with a control plane.").option("--endpoint <url>","Use the node-agent HTTP endpoint instead of its local IPC socket").option("--ipc-path <path>","Local node-agent IPC socket path").option("--data-dir <path>","Node-agent data directory used to locate its IPC socket").option("--token <token>","Bearer token for local node-agent access",process.env.TASK_HANDOFF_NODE_AGENT_TOKEN).option("--expires-in-ms <ms>","Invite expiry in milliseconds",wc).option("--json","Print raw JSON output").action(async e=>{const n=t.opts(),r=e.ipcPath||n.ipcPath||process.env.TASK_HANDOFF_NODE_AGENT_IPC_PATH,o=e.dataDir||n.dataDir||process.env.TASK_HANDOFF_NODE_AGENT_DATA_DIR,s=e.endpoint?void 0:r||no(o||Xr()),a=await async function(e){const t={"content-type":"application/json",...e.token?{authorization:`Bearer ${e.token}`}:{}},n=JSON.stringify({...e.expiresInMs?{expiresInMs:e.expiresInMs}:{}}),r=e.endpoint?await fetch(`${e.endpoint.replace(/\/$/,"")}/api/node-agent/pairing/invites`,{method:"POST",headers:t,body:n}):await async function(e,t,n={}){const r=n.method||"GET",o="string"==typeof n.body||n.body instanceof Buffer?n.body:void 0===n.body||null===n.body?void 0:String(n.body),s=new Headers(n.headers||{});return void 0===o||s.has("content-length")||s.set("content-length",String(Buffer.byteLength(o))),new Promise((a,c)=>{const d=i.request({socketPath:e,method:r,path:`/api/node-agent${t}`,headers:Object.fromEntries(s.entries())},e=>{const t=e.statusCode||500;a(new Response("HEAD"!==r&&204!==t&&205!==t&&304!==t?h.Readable.toWeb(e):null,{status:t,headers:e.headers}))});d.on("error",c);const l=()=>d.destroy(new DOMException("The operation was aborted.","AbortError"));n.signal?.aborted?l():n.signal?.addEventListener("abort",l,{once:!0}),d.once("close",()=>n.signal?.removeEventListener("abort",l)),void 0!==o&&d.write(o),d.end()})}(e.ipcPath,"/pairing/invites",{method:"POST",headers:t,body:n}),o=await r.json().catch(()=>({}));if(!r.ok)throw new Error(o.error?.message||`Node agent pairing invite failed with HTTP ${r.status}`);const s="string"==typeof o.data?.joinToken?o.data.joinToken:"";if(!s)throw new Error("Node agent pairing invite response did not include a join token.");return{nodeId:"string"==typeof o.data?.nodeId?o.data.nodeId:"",joinToken:s,expiresAt:"string"==typeof o.data?.expiresAt?o.data.expiresAt:""}}({endpoint:e.endpoint,ipcPath:s,token:e.token,expiresInMs:e.expiresInMs});e.json?console.log(JSON.stringify(a,null,2)):(a.nodeId&&console.log(`Node: ${a.nodeId}`),console.log(`Join token: ${a.joinToken}`),a.expiresAt&&console.log(`Expires: ${a.expiresAt}`))}),await t.parseAsync(process.argv)})().catch(e=>{console.error(e instanceof Error?e.message:String(e)),process.exitCode=1});
1
+ "use strict";var e=require("commander"),t=require("node:fs"),n=require("node:path"),i=require("node:http"),r=require("node:url"),o=require("fastify"),s=require("@fastify/websocket"),a=require("zod"),c=require("node:os"),d=require("node:crypto"),l=require("node:child_process"),u=require("node-pty"),m=require("ws"),p=require("node:net"),h=require("node:stream"),g=require("node:fs/promises"),f=require("node:stream/promises"),y=require("tar"),I=require("write-file-atomic"),A=require("semver"),b="undefined"!=typeof document?document.currentScript:null;function w(e,n){try{const i=JSON.parse(t.readFileSync(e,"utf8"));if(n&&i.name!==n)return;return"string"==typeof i.version&&i.version.trim()?i.version.trim():void 0}catch{return}}function v(e){if(e)try{return n.dirname(t.realpathSync(e))}catch{return}}function E(e,t=process.env,i=e){const r=t.TASK_HANDOFF_VERSION?.trim();if(r)return r;const o=i.split("/").at(-1),s=process.argv[1]?n.resolve(process.argv[1]):void 0,a=s?n.dirname(s):void 0,c=[v(s),a,process.cwd()].filter(e=>Boolean(e));for(const t of new Set(c)){let i=t;for(;;){const t=w(n.join(i,"package.json"),e);if(t)return t;const r=n.dirname(i);if(r===i)break;i=r}}let d;for(const e of new Set(c)){let t=e;for(;;){if(o){const e=w(n.join(t,"packages",o,"package.json"),i);if(e)return e}d||=w(n.join(t,"package.json"));const e=n.dirname(t);if(e===t)break;t=e}}return d||"unknown"}class N extends Error{code;lockPath;owner;constructor(e,t,n={}){const i=t?.pid?` pid ${t.pid}`:"";super(`${n.label||"Process"} is already running${i}. Lock: ${e}`),this.name="ProcessSingletonError",this.code=n.code||"PROCESS_ALREADY_RUNNING",this.lockPath=e,this.owner=t}}function S(e){return n.join(e,"owner.json")}function T(e){return n.join(e,"initializing.json")}function z(e){return n.join(e,"recovering.json")}function _(e){return Number.isInteger(e)&&Number(e)>0}function C(e,n=process.platform){if(_(e)){if("linux"===n)try{const n=t.readFileSync(`/proc/${e}/stat`,"utf8"),i=n.lastIndexOf(")");if(i<0)return;const r=n.slice(i+2).trim().split(/\s+/)[19];return r?`linux:${r}`:void 0}catch{return}if(["darwin","freebsd","openbsd","aix","sunos"].includes(n)){const t=l.spawnSync("ps",["-o","lstart=","-p",String(e)],{encoding:"utf8",timeout:1e3}),i=0===t.status?t.stdout.trim().replace(/\s+/g," "):"";return i?`${n}:${i}`:void 0}if("win32"===n){const t=`(Get-Process -Id ${e} -ErrorAction Stop).StartTime.ToUniversalTime().Ticks`,n=l.spawnSync("powershell.exe",["-NoProfile","-NonInteractive","-Command",t],{encoding:"utf8",timeout:2e3}),i=0===n.status?n.stdout.trim():"";return/^\d+$/.test(i)?`win32:${i}`:void 0}}}function k(e){try{const n=JSON.parse(t.readFileSync(S(e),"utf8"));if(_(n.pid)&&"string"==typeof n.startTime){const e=n;return{pid:e.pid,hostname:"string"==typeof e.hostname&&e.hostname?e.hostname:c.hostname(),component:e.component||"server-update",command:"string"==typeof e.command?e.command:"",acquiredAt:"string"==typeof e.createdAt&&Number.isFinite(Date.parse(e.createdAt))?e.createdAt:new Date(0).toISOString(),token:"string"==typeof e.token&&e.token?e.token:`legacy:${e.pid}:${e.startTime}`,startIdentity:e.startTime.startsWith("linux:")?e.startTime:`linux:${e.startTime}`}}if(!(_(n.pid)&&"string"==typeof n.hostname&&n.hostname&&"string"==typeof n.command&&"string"==typeof n.acquiredAt&&Number.isFinite(Date.parse(n.acquiredAt))&&"string"==typeof n.token&&n.token))return;return n}catch{return}}const O=k;function R(e){if(!_(e))return!1;try{return process.kill(Number(e),0),!0}catch(e){return"EPERM"===e.code}}function x(e){if(!e||!R(e.pid))return!1;if(!e.startIdentity)return!0;const t=C(e.pid);return void 0===t||t===e.startIdentity}function D(e,i){const r=n.join(e,`.owner-${i.token}.tmp`);t.writeFileSync(r,`${JSON.stringify(i,null,2)}\n`,{encoding:"utf8",mode:384,flag:"wx"});const o=M(e);if(o?.token!==i.token)throw j(r),new Error(`Process lock initialization was superseded: ${e}`);t.renameSync(r,S(e)),j(T(e))}function P(e,i,r){const o=O(e);if(o?.token!==i.token)return!1;const s={...i};for(const[e,t]of Object.entries(r))void 0===t?delete s[e]:Object.assign(s,{[e]:t});const a=n.join(e,`.owner-update-${i.token}-${d.randomUUID()}.tmp`);try{if(t.writeFileSync(a,`${JSON.stringify(s,null,2)}\n`,{encoding:"utf8",mode:384,flag:"wx"}),O(e)?.token!==i.token)return!1;t.renameSync(a,S(e));for(const e of Object.keys(i))delete i[e];return Object.assign(i,s),!0}catch(e){if("ENOENT"===e.code)return!1;throw e}finally{j(a)}}function M(e){try{return JSON.parse(t.readFileSync(T(e),"utf8"))}catch{return}}function L(e){const t=M(e);return _(t?.pid)&&x({pid:t.pid,startIdentity:t.startIdentity})}function j(e){try{t.unlinkSync(e)}catch(e){if("ENOENT"!==e.code)throw e}}function $(){Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,20)}function F(e){try{const n=M(e),i=Date.parse(n?.startedAt||"");return Number.isFinite(i)?Math.max(0,Date.now()-i):Math.max(0,Date.now()-t.statSync(e).mtimeMs)}catch{return 0}}function U(e,i){try{return t.writeFileSync(z(e),`${JSON.stringify({token:i,pid:process.pid,startedAt:(new Date).toISOString()})}\n`,{encoding:"utf8",mode:384,flag:"wx"}),!0}catch(r){if("EEXIST"===r.code)return!!function(e){const i=z(e),r=V(i),o=Date.parse(r?.startedAt||"");if(R(r?.pid)||Number.isFinite(o)&&Date.now()-o<2e3)return!1;const s=n.join(e,`.recovering-${d.randomUUID()}.stale`);try{t.renameSync(i,s)}catch(e){if(["ENOENT","EEXIST"].includes(e.code||""))return!1;throw e}const a=V(s);if(a?.token===r?.token)return j(s),!0;try{t.linkSync(s,i)}catch(e){if("EEXIST"!==e.code)throw e}finally{j(s)}return!1}(e)&&U(e,i);if("ENOENT"===r.code)return!1;throw r}}function V(e){try{return JSON.parse(t.readFileSync(e,"utf8"))}catch{return}}function q(e,t){return V(z(e))?.token===t}const H=6048e5;function B(e,t){const i=n.resolve(e),r=n.resolve(i,t);if(n.dirname(r)!==i||n.basename(r)!==t)throw new Error(`Retention entry is not a direct child of its managed root: ${t}`);return r}function K(e){if(t.existsSync(e)){const n=t.lstatSync(e);if(!n.isDirectory()||n.isSymbolicLink())throw new Error(`Managed persistence path must be a real directory: ${e}`)}t.mkdirSync(e,{recursive:!0,mode:448}),t.chmodSync(e,448)}const G=41943040,J="ai.sessions",W=a.z.string().trim().min(1).max(80),Y=a.z.enum(["app-session","ai-session"]),X=a.z.enum(["running","waiting","idle","failed"]);a.z.object({instanceId:a.z.string().trim().min(1).max(160),sessionId:a.z.string().trim().min(1).max(120),unread:a.z.boolean(),sessionUpdatedAt:a.z.string().datetime(),updatedAt:a.z.string().datetime()}).strict();const Q=a.z.enum(["thinking","tool","editing","approval","responding","unknown"]),Z=a.z.object({id:a.z.string().trim().min(1).max(240).optional(),kind:a.z.string().trim().min(1).max(80).optional(),name:a.z.string().trim().min(1).max(120),inputPreview:a.z.string().trim().max(500).optional(),startedAt:a.z.string().datetime().optional()}).strict(),ee=a.z.enum(["pending-init","running","interrupted","completed","errored","shutdown","not-found"]),te=a.z.enum(["started","interacted","interrupted"]),ne=a.z.object({threadId:a.z.string().trim().min(1).max(240),path:a.z.string().trim().max(4096).optional(),status:ee,activity:te.optional(),message:a.z.string().trim().max(1e3).optional(),updatedAt:a.z.string().datetime()}).strict(),ie=a.z.object({toolCalls:a.z.number().int().min(0).default(0),edits:a.z.number().int().min(0).default(0),approvals:a.z.number().int().min(0).default(0)}).strict().default({toolCalls:0,edits:0,approvals:0}),re=a.z.object({send:a.z.boolean().optional(),interrupt:a.z.boolean().optional(),approval:a.z.boolean().optional(),fork:a.z.boolean().optional(),openApp:a.z.boolean().optional(),close:a.z.boolean().optional()}).strict(),oe=a.z.object({kind:a.z.literal("fork"),parentProviderSessionId:a.z.string().trim().min(1).max(240),throughTurnId:a.z.string().trim().min(1).max(240).optional()}).strict(),se=a.z.enum(["image","file"]),ae=a.z.object({id:a.z.string().trim().min(1).max(120),kind:se,name:a.z.string().trim().min(1).max(240),mime:a.z.string().trim().min(1).max(120),size:a.z.number().int().min(0).max(Number.MAX_SAFE_INTEGER)}),ce=a.z.union([ae.extend({source:a.z.object({type:a.z.literal("inline"),encoding:a.z.literal("base64"),data:a.z.string().min(1).max(31457280)}).strict()}).strict().superRefine((e,t)=>{const n="image"===e.kind?20971520:512e3;(e.size<=0||("file"===e.kind?e.size>=n:e.size>n))&&t.addIssue({code:a.z.ZodIssueCode.custom,path:["size"],message:`Inline ${e.kind} must be between 1 byte and ${n} bytes.`})}),ae.extend({source:a.z.object({type:a.z.literal("runtime-path"),path:a.z.string().trim().min(1).max(4096)}).strict()}).strict()]),de=ae.extend({sourceType:a.z.enum(["inline","runtime-path"])}).strict(),le=a.z.union([a.z.object({id:a.z.string().trim().min(1).max(120),kind:se.optional(),source:a.z.object({type:a.z.literal("upload-ref")}).strict().default({type:"upload-ref"})}).strict(),a.z.object({id:a.z.string().trim().min(1).max(120),kind:se,name:a.z.string().trim().min(1).max(240),mime:a.z.string().trim().min(1).max(120),size:a.z.number().int().min(0).max(Number.MAX_SAFE_INTEGER),source:a.z.object({type:a.z.literal("runtime-path"),path:a.z.string().trim().min(1).max(4096)}).strict()}).strict()]),ue=a.z.enum(["auto","queue","steer","immediate"]),me=a.z.enum(["ask","auto-review","full-access"]),pe=a.z.enum(["review","rename","goal","compact"]);a.z.object({command:pe,argument:a.z.string().trim().max(4e3).optional()}).strict().superRefine((e,t)=>{"rename"!==e.command||e.argument||t.addIssue({code:"custom",path:["argument"],message:"Rename requires a thread name."}),"review"!==e.command&&"compact"!==e.command||!e.argument||t.addIssue({code:"custom",path:["argument"],message:`${e.command} does not accept an argument.`})}),a.z.object({command:pe,value:a.z.string().max(4e3).optional(),turnId:a.z.string().trim().min(1).max(240).optional()}).strict(),a.z.enum(["skill","app","plugin"]);const he=a.z.object({name:a.z.string().trim().min(1).max(240),path:a.z.string().trim().min(1).max(4096)}),ge=a.z.discriminatedUnion("kind",[he.extend({kind:a.z.literal("skill"),path:a.z.string().trim().min(1).max(4096).refine(e=>e.startsWith("/"),"Skill paths must be absolute.")}).strict(),he.extend({kind:a.z.literal("app"),path:a.z.string().trim().min(7).max(4096).regex(/^app:\/\/[^\s/]+$/,"App paths must use app://<id>.")}).strict(),he.extend({kind:a.z.literal("plugin"),path:a.z.string().trim().min(10).max(4096).regex(/^plugin:\/\/[^\s/]+$/,"Plugin paths must use plugin://<id>.")}).strict()]),fe=a.z.array(ge).max(20).default([]),ye=a.z.enum(["plugin","skill","file","directory","app"]),Ie=a.z.object({kind:ye,name:a.z.string().trim().min(1).max(240),description:a.z.string().trim().max(1e3).optional(),path:a.z.string().trim().min(1).max(4096),icon:a.z.string().trim().max(4096).optional()}).strict().superRefine((e,t)=>{"skill"!==e.kind||e.path.startsWith("/")||t.addIssue({code:"custom",path:["path"],message:"Skill paths must be absolute."}),"app"!==e.kind||/^app:\/\/[^\s/]+$/.test(e.path)||t.addIssue({code:"custom",path:["path"],message:"App paths must use app://<id>."}),"plugin"!==e.kind||/^plugin:\/\/[^\s/]+$/.test(e.path)||t.addIssue({code:"custom",path:["path"],message:"Plugin paths must use plugin://<id>."}),"file"!==e.kind&&"directory"!==e.kind||!e.path.startsWith("/")&&!e.path.split(/[\\/]+/).includes("..")||t.addIssue({code:"custom",path:["path"],message:"File and directory paths must be relative to the session cwd."})}),Ae=a.z.object({category:a.z.enum(["skills","plugins","apps","files"]),code:a.z.string().trim().min(1).max(160),message:a.z.string().trim().min(1).max(2e3)}).strict();a.z.object({sessionId:a.z.string().trim().min(1).max(120),providerSessionId:a.z.string().trim().min(1).max(240),cwd:a.z.string().trim().min(1).max(4096),candidates:a.z.array(Ie).max(1e3).default([]),diagnostics:a.z.array(Ae).max(20).default([])}).strict(),a.z.object({query:a.z.string().trim().max(240).default("")}).strict(),a.z.object({sessionId:a.z.string().trim().min(1).max(120),cwd:a.z.string().trim().min(1).max(4096),query:a.z.string().trim().max(240),requestId:a.z.string().trim().min(1).max(160),candidates:a.z.array(Ie.refine(e=>"file"===e.kind||"directory"===e.kind,"File search only returns files and directories.")).max(200).default([]),complete:a.z.boolean().default(!1)}).strict();const be=a.z.object({message:a.z.string().trim().min(1).max(2e4),mode:ue.optional(),permissionMode:me.optional()}),we=be.extend({attachments:a.z.array(ce).max(6).default([]),references:fe}).strict().superRefine((e,t)=>{e.attachments.reduce((e,t)=>e+("inline"===t.source.type?t.size:0),0)>G&&t.addIssue({code:a.z.ZodIssueCode.custom,path:["attachments"],message:"Inline attachments must be 41943040 bytes or less in total."})}),ve=be.extend({attachments:a.z.array(le).max(6).default([]),references:fe}).strict(),Ee=a.z.object({type:a.z.literal("runtime-path"),path:a.z.string().trim().min(1).max(4096).refine(e=>e.startsWith("/")||/^[A-Za-z]:[\\/]/.test(e),"Runtime paths must be absolute in the target controlled instance.")}).strict();we.extend({agent:W,cwd:Ee,cwdFolderId:a.z.string().trim().min(1).max(120).optional(),clientRequestId:a.z.string().trim().min(1).max(160)}).strict();const Ne=a.z.object({mode:a.z.enum(["current-folder","worktree"]),branch:a.z.string().trim().min(1).max(1024)}).strict();ve.extend({agent:W,cwdFolderId:a.z.string().trim().min(1).max(120).optional(),gitSelection:Ne.optional(),clientRequestId:a.z.string().trim().min(1).max(160)}).strict(),a.z.object({disposition:a.z.enum(["created","already-created"]),aiSessionId:a.z.string().trim().min(1).max(120),providerSessionId:a.z.string().trim().min(1).max(240),creationSource:a.z.literal("ai-session")}).strict();const Se=a.z.object({mode:a.z.enum(["current","managed-worktree"]).default("current")}).strict().default({mode:"current"});a.z.object({clientRequestId:a.z.string().trim().min(1).max(160),throughTurnId:a.z.string().trim().min(1).max(240).optional(),workspace:Se.optional().default({mode:"current"})}).strict(),a.z.object({disposition:a.z.enum(["created","already-created"]),aiSessionId:a.z.string().trim().min(1).max(120),providerSessionId:a.z.string().trim().min(1).max(240),creationSource:a.z.literal("ai-session")}).strict(),a.z.object({clientRequestId:a.z.string().trim().min(1).max(160)}).strict(),a.z.object({disposition:a.z.enum(["opened","already-open"]),aiSessionId:a.z.string().trim().min(1).max(120),providerSessionId:a.z.string().trim().min(1).max(240),appSessionId:a.z.string().trim().min(1).max(120),creationSource:Y}).strict(),a.z.object({clientRequestId:a.z.string().trim().min(1).max(160)}).strict(),a.z.object({disposition:a.z.enum(["closed","already-closed"]),aiSessionId:a.z.string().trim().min(1).max(120),providerSessionId:a.z.string().trim().min(1).max(240),creationSource:Y}).strict(),a.z.object({code:a.z.enum(["invalid-request","not-found","unsupported","provider-unavailable","materialization-failed","open-app-failed","close-failed","conflict"]),message:a.z.string().trim().min(1).max(4e3),retryable:a.z.boolean().default(!1),aiSessionId:a.z.string().trim().min(1).max(120).optional(),providerSessionId:a.z.string().trim().min(1).max(240).optional()}).strict(),a.z.object({decision:a.z.enum(["allow","deny","skip"])}).strict(),a.z.object({expectedRevision:a.z.number().int().min(0),queueIds:a.z.array(a.z.string().trim().min(1).max(120)).max(100)}).strict(),a.z.object({expectedRevision:a.z.number().int().min(0),message:a.z.string().trim().min(1).max(2e4)}).strict(),a.z.object({code:a.z.string().trim().min(1).max(160),message:a.z.string(),instanceId:a.z.string().trim().min(1).max(160).optional(),nodeId:a.z.string().trim().min(1).max(160).optional(),route:a.z.string().trim().min(1).max(4096).optional()}).strict();const Te=a.z.object({id:a.z.string().trim().min(1).max(120),message:a.z.string().trim().min(1).max(2e4),attachments:a.z.array(de).max(6).default([]),references:fe,permissionMode:me.optional(),status:a.z.enum(["queued","sending","failed"]).default("queued"),createdAt:a.z.string().datetime(),updatedAt:a.z.string().datetime(),error:a.z.string().trim().max(4e3).optional()}).strict(),ze=a.z.object({revision:a.z.number().int().min(0).default(0),pendingCount:a.z.number().int().min(0).default(0),items:a.z.array(Te).max(100).default([])}).strict().default({revision:0,pendingCount:0,items:[]}),_e=a.z.enum(["control","realtime","adapter-snapshot","transcript-tail","transcript-scan","process-scan","app-session"]),Ce=a.z.object({id:a.z.string().trim().min(1).max(240),status:a.z.enum(["running","completed"]),startedAt:a.z.string().datetime().optional(),completedAt:a.z.string().datetime().optional()}).strict(),ke=a.z.object({id:a.z.string().trim().min(1).max(240),providerTurnId:a.z.string().trim().max(240).optional(),source:_e.optional(),userPrompt:a.z.string().trim().optional(),status:a.z.enum(["queued","running","waiting","completed","failed"]).default("running"),phase:Q.optional(),summary:a.z.string().trim().max(1e3).optional(),lastMessage:a.z.string().trim().optional(),lastMessageItemId:a.z.string().trim().max(240).optional(),contextCompactions:a.z.array(Ce).max(20).optional(),revision:a.z.number().int().min(0).default(0),sourcePriority:a.z.number().int().min(0).max(100).optional(),snapshotVersion:a.z.number().int().min(0).optional(),observedAt:a.z.string().datetime().optional(),startedAt:a.z.string().datetime().optional(),updatedAt:a.z.string().datetime().optional(),completedAt:a.z.string().datetime().optional()}).strict(),Oe=ke.pick({id:!0,providerTurnId:!0,userPrompt:!0,status:!0,phase:!0,summary:!0,lastMessage:!0,contextCompactions:!0,startedAt:!0,updatedAt:!0,completedAt:!0}).strict(),Re=a.z.object({id:a.z.string().trim().min(1).max(120),agent:W,creationSource:Y.default("app-session"),appSessionId:a.z.string().trim().max(120).optional(),appId:a.z.string().trim().max(120).optional(),providerSessionId:a.z.string().trim().max(240).optional(),lineage:oe.optional(),providerMeta:a.z.record(a.z.string(),a.z.unknown()).optional(),appBindingKeys:a.z.array(a.z.string().trim().min(1).max(240)).max(20).optional(),actions:re.optional(),activeTurnId:a.z.string().trim().max(240).optional(),title:a.z.string().trim().max(240).optional(),cwd:a.z.string().trim().max(4096).optional(),cwdFolderId:a.z.string().trim().min(1).max(120).optional(),userPrompt:a.z.string().trim().optional(),turns:a.z.array(ke).max(50).optional(),status:X.default("running"),phase:Q.default("unknown"),summary:a.z.string().trim().max(1e3).optional(),lastMessage:a.z.string().trim().optional(),lastMessageItemId:a.z.string().trim().max(240).optional(),currentTool:Z.optional(),toolCallsSinceLastMessage:a.z.number().int().min(0).default(0),subAgents:a.z.array(ne).max(50).default([]),transcriptPath:a.z.string().trim().max(4096).optional(),transcriptSize:a.z.number().int().min(0).optional(),startedAt:a.z.string().datetime(),updatedAt:a.z.string().datetime(),completedAt:a.z.string().datetime().optional(),error:a.z.string().trim().max(4e3).optional(),counters:ie,queue:ze}).strict();a.z.object({session:Re,provider:a.z.string().trim().min(1).max(80),action:a.z.enum(["send","queue","steer","interrupt","approval"]),decision:a.z.enum(["allow","deny","skip"]).optional(),turnId:a.z.string().trim().min(1).max(240).optional(),providerTurnId:a.z.string().trim().min(1).max(240).optional(),queueId:a.z.string().trim().min(1).max(120).optional()}).strict();const xe=a.z.object({id:a.z.string().trim().min(1).max(120),agent:a.z.enum(["codex","claude"]),creationSource:Y,providerSessionId:a.z.string().trim().min(1).max(240),lineage:oe.optional(),title:a.z.string().trim().max(240).optional(),userPrompt:a.z.string().trim().optional(),lastMessage:a.z.string().trim().optional(),cwd:a.z.string().trim().min(1).max(4096),cwdFolderId:a.z.string().trim().min(1).max(120).optional(),lastActiveAt:a.z.string().datetime(),archivedAt:a.z.string().datetime()}).strict();a.z.object({schemaVersion:a.z.literal(1).default(1),items:a.z.array(xe).max(50).default([])}).strict(),a.z.object({items:a.z.array(xe).max(50).default([])}).strict(),a.z.object({item:xe,turns:a.z.array(Oe).max(50).default([])}).strict(),a.z.object({disposition:a.z.enum(["resumed","already-open"]),aiSessionId:a.z.string().trim().min(1).max(120),providerSessionId:a.z.string().trim().min(1).max(240),appSessionId:a.z.string().trim().min(1).max(120).optional(),creationSource:Y}).strict();const De=Re.pick({id:!0,agent:!0,creationSource:!0,appSessionId:!0,appId:!0,providerSessionId:!0,lineage:!0,providerMeta:!0,appBindingKeys:!0,actions:!0,activeTurnId:!0,title:!0,cwd:!0,cwdFolderId:!0,userPrompt:!0,turns:!0,status:!0,phase:!0,summary:!0,lastMessage:!0,lastMessageItemId:!0,currentTool:!0,toolCallsSinceLastMessage:!0,subAgents:!0,queue:!0,startedAt:!0,updatedAt:!0,error:!0}),Pe=a.z.object({runningCount:a.z.number().int().min(0).default(0),waitingCount:a.z.number().int().min(0).default(0),staleCount:a.z.number().int().min(0).default(0),sessions:a.z.array(De).default([]),updatedAt:a.z.string().datetime()}).strict();a.z.object({streamId:a.z.string().trim().min(1).max(240),revision:a.z.number().int().min(0),lastEventAt:a.z.string().datetime(),snapshot:Pe}).strict(),Pe.pick({runningCount:!0,waitingCount:!0,staleCount:!0,updatedAt:!0}).extend({idleCount:a.z.number().int().min(0).default(0),problemCount:a.z.number().int().min(0).default(0),revision:a.z.number().int().min(0).optional()});const Me=a.z.enum(["provider-event","app-session-created","app-session-updated","app-session-deleted","discovery-scan","control-action","heartbeat-sync","startup"]),Le=a.z.object({streamId:a.z.string().trim().min(1).max(240),instanceId:a.z.string().trim().min(1).max(160),nodeId:a.z.string().trim().min(1).max(160).optional(),revision:a.z.number().int().min(0),previousRevision:a.z.number().int().min(0).optional(),traceId:a.z.string().trim().min(1).max(160),generatedAt:a.z.string().datetime(),reason:Me}).strict(),je=a.z.object({meta:Le,snapshot:Pe}).strict(),$e=a.z.object({meta:Le,upserted:a.z.array(De).default([]),removed:a.z.array(a.z.string().trim().min(1).max(120)).default([])}).strict(),Fe=a.z.object({meta:Le,sessionIds:a.z.array(a.z.string().trim().min(1).max(120)).default([]),expiresAt:a.z.string().datetime()}).strict();a.z.object({instanceId:a.z.string().trim().min(1).max(160),nodeId:a.z.string().trim().min(1).max(160).optional(),sessionId:a.z.string().trim().min(1).max(120),providerSessionId:a.z.string().trim().min(1).max(240),turnId:a.z.string().trim().min(1).max(240),itemId:a.z.string().trim().min(1).max(240),delta:a.z.string().min(1),generatedAt:a.z.string().datetime()}).strict(),a.z.object({streamId:a.z.string().trim().min(1).max(240),instanceId:a.z.string().trim().min(1).max(160),sinceRevision:a.z.number().int().min(0),latestRevision:a.z.number().int().min(0),earliestRetainedRevision:a.z.number().int().min(0),syncRequired:a.z.boolean().default(!1),events:a.z.array(a.z.discriminatedUnion("type",[a.z.object({type:a.z.literal("ai-session.snapshot"),payload:je}).strict(),a.z.object({type:a.z.literal("ai-session.patch"),payload:$e}).strict(),a.z.object({type:a.z.literal("ai-session.removed"),payload:Fe}).strict()])).default([])}).strict();const Ue=a.z.object({source:_e,sourcePriority:a.z.number().int().min(0).max(100).optional(),observedAt:a.z.string().datetime().optional(),snapshotVersion:a.z.number().int().min(0).optional()}).strict(),Ve=Ue.extend({type:a.z.literal("snapshot"),agent:a.z.string().trim().min(1).max(80),creationSource:Y.optional(),appSessionId:a.z.string().trim().max(120).optional(),appId:a.z.string().trim().max(120).optional(),providerSessionId:a.z.string().trim().max(240).optional(),lineage:oe.optional(),providerMeta:a.z.record(a.z.string(),a.z.unknown()).optional(),appBindingKeys:a.z.array(a.z.string().trim().min(1).max(240)).max(20).optional(),actions:re.optional(),title:a.z.string().trim().max(240).optional(),cwd:a.z.string().trim().max(4096).optional(),cwdFolderId:a.z.string().trim().min(1).max(120).optional(),activeTurnId:a.z.string().trim().max(240).optional(),userPrompt:a.z.string().trim().optional(),turns:a.z.array(ke).max(50).optional(),status:X.optional(),phase:Q.optional(),summary:a.z.string().trim().max(1e3).optional(),lastMessage:a.z.string().trim().optional(),lastMessageItemId:a.z.string().trim().max(240).optional(),error:a.z.string().trim().max(4e3).optional(),currentTool:Z.optional(),toolCallsSinceLastMessage:a.z.number().int().min(0).optional(),subAgents:a.z.array(ne).max(50).optional(),transcriptPath:a.z.string().trim().max(4096).optional(),transcriptSize:a.z.number().int().min(0).optional(),replaceActivity:a.z.boolean().optional()}).strict(),qe=Ue.extend({type:a.z.literal("event"),sessionId:a.z.string().trim().min(1).max(120),kind:a.z.enum(["lifecycle","send-ack","turn-started","user-message","assistant-message","approval-requested","turn-completed","session-error","tool-activity","sub-agent-activity","context-compaction"]),activeTurnId:a.z.string().trim().max(240).optional(),providerTurnId:a.z.string().trim().max(240).optional(),userPrompt:a.z.string().trim().optional(),text:a.z.string().optional(),itemId:a.z.string().trim().max(240).optional(),status:X.optional(),phase:Q.optional(),summary:a.z.string().trim().max(1e3).optional(),error:a.z.string().trim().max(4e3).optional(),currentTool:Z.nullable().optional(),toolCallsSinceLastMessage:a.z.number().int().min(0).optional(),subAgents:a.z.array(ne).max(50).optional(),contextCompaction:Ce.optional(),counters:a.z.object({toolCalls:a.z.number().int().min(0).optional(),edits:a.z.number().int().min(0).optional(),approvals:a.z.number().int().min(0).optional()}).strict().optional()}).strict().superRefine((e,t)=>{if("session-error"!==e.kind||e.error||t.addIssue({code:"custom",path:["error"],message:"session-error events require error"}),"context-compaction"===e.kind?e.contextCompaction||t.addIssue({code:"custom",path:["contextCompaction"],message:"context-compaction events require contextCompaction"}):void 0!==e.contextCompaction&&t.addIssue({code:"custom",path:["contextCompaction"],message:"contextCompaction is only valid for context-compaction events"}),"sub-agent-activity"===e.kind?e.subAgents||t.addIssue({code:"custom",path:["subAgents"],message:"sub-agent-activity events require subAgents"}):void 0!==e.subAgents&&t.addIssue({code:"custom",path:["subAgents"],message:"subAgents is only valid for sub-agent-activity events"}),"tool-activity"!==e.kind)return void 0!==e.currentTool&&t.addIssue({code:"custom",path:["currentTool"],message:"currentTool is only valid for tool-activity events"}),void(void 0!==e.toolCallsSinceLastMessage&&t.addIssue({code:"custom",path:["toolCallsSinceLastMessage"],message:"toolCallsSinceLastMessage is only valid for tool-activity events"}));"currentTool"in e||t.addIssue({code:"custom",path:["currentTool"],message:"tool-activity events require currentTool"}),void 0===e.toolCallsSinceLastMessage&&t.addIssue({code:"custom",path:["toolCallsSinceLastMessage"],message:"tool-activity events require toolCallsSinceLastMessage"})});a.z.discriminatedUnion("type",[Ve,qe]);const He=a.z.union([a.z.object({type:a.z.literal("schedule"),scheduleKind:a.z.literal("interval").default("interval"),intervalMs:a.z.number().int().min(1e3)}).strict(),a.z.object({type:a.z.literal("schedule"),scheduleKind:a.z.literal("daily"),timeOfDay:a.z.string().regex(/^([01]\d|2[0-3]):[0-5]\d$/),timezone:a.z.string().trim().min(1).max(120)}).strict(),a.z.object({type:a.z.literal("schedule"),scheduleKind:a.z.literal("weekly"),weekdays:a.z.array(a.z.number().int().min(0).max(6)).min(1).max(7),timeOfDay:a.z.string().regex(/^([01]\d|2[0-3]):[0-5]\d$/),timezone:a.z.string().trim().min(1).max(120)}).strict()]),Be=a.z.union([He,a.z.object({type:a.z.literal("file-change"),roots:a.z.array(a.z.string().trim().min(1).max(4096)).min(1).max(50),globs:a.z.array(a.z.string().trim().min(1).max(500)).min(1).max(100),ignore:a.z.array(a.z.string().trim().min(1).max(500)).max(100).optional(),debounceMs:a.z.number().int().min(100).max(6e4).default(1500)}).strict(),a.z.object({type:a.z.literal("ai-session"),agent:a.z.string().trim().min(1).max(80).optional(),statuses:a.z.array(a.z.enum(["running","waiting","idle","failed"])).max(20).optional(),phases:a.z.array(a.z.enum(["thinking","tool","editing","approval","responding","unknown"])).max(20).optional()}).strict()]),Ke=a.z.object({promptTemplate:a.z.string().trim().min(1).max(2e4)}).strict(),Ge=a.z.object({cooldownMs:a.z.number().int().min(0).max(864e5).optional(),maxConcurrentRuns:a.z.number().int().min(1).max(20).default(1),whenBusy:a.z.enum(["skip","queue"]).default("skip")}).strict(),Je=a.z.object({configHash:a.z.string().trim().min(8).max(80),name:a.z.string().trim().min(1).max(160),description:a.z.string().trim().max(1e3).optional(),source:Be,action:Ke,policy:Ge.default({maxConcurrentRuns:1,whenBusy:"skip"}),createdAt:a.z.string().datetime(),updatedAt:a.z.string().datetime()}).strict(),We=a.z.object({type:a.z.literal("ai-session"),aiSessionId:a.z.string().trim().min(1).max(160)}).strict(),Ye=a.z.object({configHash:a.z.string().trim().min(8).max(80),deploymentId:a.z.string().trim().min(1).max(240).optional(),instanceId:a.z.string().trim().min(1).max(160),origin:a.z.enum(["control-plane","controlled-instance"]).default("controlled-instance"),enabled:a.z.boolean().default(!0),target:We,localName:a.z.string().trim().min(1).max(160).optional(),createdAt:a.z.string().datetime(),updatedAt:a.z.string().datetime()}).strict(),Xe=a.z.object({configHash:a.z.string().trim().min(8).max(80),deploymentId:a.z.string().trim().min(1).max(240).optional(),instanceId:a.z.string().trim().min(1).max(160),status:a.z.enum(["idle","running","disabled","error"]).default("idle"),lastTriggeredAt:a.z.string().datetime().optional(),lastCompletedAt:a.z.string().datetime().optional(),lastSkippedAt:a.z.string().datetime().optional(),lastError:a.z.string().trim().max(4e3).optional(),runCount:a.z.number().int().min(0).default(0),skippedCount:a.z.number().int().min(0).default(0)}).strict(),Qe=a.z.object({id:a.z.string().trim().min(1).max(160),configHash:a.z.string().trim().min(8).max(80),deploymentId:a.z.string().trim().min(1).max(240).optional(),instanceId:a.z.string().trim().min(1).max(160),eventType:a.z.enum(["manual","schedule","file-change","ai-session"]),status:a.z.enum(["started","completed","failed","skipped"]),target:We,promptPreview:a.z.string().trim().max(500),eventSummary:a.z.string().trim().max(1e3).optional(),error:a.z.string().trim().max(4e3).optional(),startedAt:a.z.string().datetime(),completedAt:a.z.string().datetime().optional()}).strict();a.z.object({schemaVersion:a.z.literal(1).default(1),configs:a.z.array(Je).default([]),deployments:a.z.array(Ye).default([]),runtime:a.z.array(Xe).default([]),recentRuns:a.z.array(Qe).default([])}).strict();const Ze=a.z.object({instanceId:a.z.string().trim().min(1).max(160),instanceName:a.z.string().trim().min(1).max(160),deployment:Ye,runtime:Xe.optional()}).strip(),et=Qe.extend({instanceName:a.z.string().trim().min(1).max(160).optional()}).strip(),tt=a.z.object({configHash:a.z.string().trim().min(8).max(80),config:Je,deploymentCount:a.z.number().int().min(0),enabledCount:a.z.number().int().min(0),runningCount:a.z.number().int().min(0),errorCount:a.z.number().int().min(0),ownedByControlPlane:a.z.boolean(),controlPlaneDeploymentCount:a.z.number().int().min(0),deployments:a.z.array(Ze),recentRuns:a.z.array(et)}).strip();a.z.object({updatedAt:a.z.string().datetime(),triggers:a.z.array(tt)}).strip(),a.z.object({name:Je.shape.name,description:Je.shape.description,source:Be,action:Ke,policy:Ge.partial().optional()}).strict();const nt=a.z.string().regex(/^\d{4}-\d{2}-\d{2}$/,"Proxy protocol version must use YYYY-MM-DD format."),it=a.z.string().trim().min(1).max(160).regex(/^[a-zA-Z0-9][a-zA-Z0-9_.:-]*$/),rt=a.z.string().datetime(),ot=a.z.string().trim().min(32).max(4096),st=a.z.string().trim().max(2048).transform((e,t)=>{try{return function(e){const t=new URL(e.trim());if("https:"!==t.protocol||t.username||t.password||"/"!==t.pathname||t.search||t.hash)throw new Error("Proxy origin must be an HTTPS origin without credentials, path, query, or fragment.");return t.origin}(e)}catch(e){return t.addIssue({code:"custom",message:e instanceof Error?e.message:String(e)}),a.z.NEVER}});a.z.string().trim().min(1).max(4096).transform((e,t)=>{try{return function(e){const t=e.trim();if(!t.startsWith("/")||t.startsWith("//")||t.includes("\\")||/%25/i.test(t))throw new Error("Proxy route must be a single-encoded node-agent relative route.");const n=t.split("?",1)[0];let i,r;try{i=n.split("/").map(e=>decodeURIComponent(e))}catch{throw new Error("Proxy route contains invalid percent encoding.")}if(i.some(e=>".."===e||"."===e))throw new Error("Proxy route cannot traverse outside the node-agent API.");try{r=new URL(t,"https://node-agent.invalid")}catch{throw new Error("Proxy route is invalid.")}if("https://node-agent.invalid"!==r.origin||r.username||r.password)throw new Error("Proxy route cannot select an absolute upstream URL.");return`${r.pathname}${r.search}`}(e)}catch(e){return t.addIssue({code:"custom",message:e instanceof Error?e.message:String(e)}),a.z.NEVER}});const at=a.z.enum(Object.values({ProtocolUnsupported:"CONTROL_PLANE_PROXY_PROTOCOL_UNSUPPORTED",InviteInvalid:"CONTROL_PLANE_PROXY_INVITE_INVALID",InviteExpired:"CONTROL_PLANE_PROXY_INVITE_EXPIRED",InviteConsumed:"CONTROL_PLANE_PROXY_INVITE_CONSUMED",InviteRevoked:"CONTROL_PLANE_PROXY_INVITE_REVOKED",TargetUnavailable:"CONTROL_PLANE_PROXY_TARGET_UNAVAILABLE",TargetMismatch:"CONTROL_PLANE_PROXY_TARGET_MISMATCH",BindingUnknown:"CONTROL_PLANE_PROXY_BINDING_UNKNOWN",BindingRevoked:"CONTROL_PLANE_PROXY_BINDING_REVOKED",BindingIdentityConflict:"CONTROL_PLANE_PROXY_BINDING_IDENTITY_CONFLICT",AuthenticationFailed:"CONTROL_PLANE_PROXY_AUTHENTICATION_FAILED",RouteInvalid:"CONTROL_PLANE_PROXY_ROUTE_INVALID",HeaderInvalid:"CONTROL_PLANE_PROXY_HEADER_INVALID",ResourceLimit:"CONTROL_PLANE_PROXY_RESOURCE_LIMIT",SnapshotRequired:"CONTROL_PLANE_PROXY_SNAPSHOT_REQUIRED",Unavailable:"CONTROL_PLANE_PROXY_UNAVAILABLE",TransportFailed:"CONTROL_PLANE_PROXY_TRANSPORT_FAILED"})),ct=a.z.object({code:at,message:a.z.string().trim().min(1).max(2048),retryable:a.z.boolean(),details:a.z.record(a.z.string(),a.z.unknown()).optional()}).strict(),dt=a.z.enum(["active","consumed","revoked","expired"]),lt=a.z.object({id:it,targetNodeId:it,tokenHash:a.z.string().trim().min(32).max(256),status:dt,createdBy:it,expiresAt:rt,consumedByClaimId:it.optional(),consumedAt:rt.optional(),revokedAt:rt.optional(),createdAt:rt,updatedAt:rt}).strict().omit({tokenHash:!0});a.z.object({targetNodeId:it,expiresInSeconds:a.z.number().int().min(60).max(3600).default(600)}).strict(),a.z.object({invite:lt,token:a.z.string().trim().min(24).max(512),proxyOrigin:st,protocolVersion:nt}).strict();const ut=a.z.enum(["active","revoked"]),mt=a.z.object({id:it,claimId:it,sourceControlPlaneId:it,targetNodeId:it,bindingKeyId:it,credentialHash:a.z.string().trim().min(32).max(256),status:ut,revision:a.z.number().int().positive(),lastError:ct.optional(),revokedAt:rt.optional(),createdAt:rt,updatedAt:rt}).strict().omit({credentialHash:!0});a.z.object({protocolVersion:nt,inviteToken:a.z.string().trim().min(24).max(512).optional(),claimId:it,sourceControlPlaneId:it,targetNodeId:it.optional(),bindingKeyId:it,credential:ot}).strict(),a.z.object({sourceControlPlaneId:it,bindingKeyId:it,credential:ot}).strict();const pt=a.z.object({id:it,name:a.z.string().trim().min(1).max(160),status:a.z.enum(["unknown","online","offline","degraded"]),health:a.z.enum(["unknown","ok","degraded","failed"]),lastSeenAt:rt.optional(),capabilities:a.z.record(a.z.string(),a.z.unknown()).default({})}).strict(),ht=a.z.object({protocolVersion:nt,binding:mt,streamId:it,revision:a.z.number().int().nonnegative(),observedAt:rt,target:pt}).strict(),gt=a.z.object({type:a.z.literal("control-plane-proxy.event"),protocolVersion:nt,streamId:it,bindingId:it,sourceControlPlaneId:it,targetNodeId:it,revision:a.z.number().int().positive(),source:a.z.object({id:a.z.string().trim().min(1).max(512),seq:a.z.number().int().nonnegative()}).strict(),target:pt,event:a.z.object({type:a.z.string().trim().min(1).max(240),topic:a.z.string().trim().min(1).max(240),createdAt:rt}).strict()}).strict(),ft=a.z.object({type:a.z.literal("control-plane-proxy.events.ready"),protocolVersion:nt,streamId:it,bindingId:it,sourceControlPlaneId:it,targetNodeId:it,latestRevision:a.z.number().int().nonnegative(),earliestRetainedRevision:a.z.number().int().nonnegative()}).strict(),yt=a.z.object({type:a.z.literal("control-plane-proxy.snapshot-required"),protocolVersion:nt,streamId:it,bindingId:it,sourceControlPlaneId:it,targetNodeId:it,sinceRevision:a.z.number().int().nonnegative(),latestRevision:a.z.number().int().nonnegative(),earliestRetainedRevision:a.z.number().int().nonnegative(),error:ct}).strict();a.z.discriminatedUnion("type",[gt,ft,yt]),a.z.object({protocolVersion:nt,binding:mt,target:ht.shape.target}).strict(),a.z.object({id:it,claimId:it,proxyOrigin:st,requestedName:a.z.string().trim().min(1).max(160).optional(),sourceControlPlaneId:it,targetNodeId:it.optional(),bindingKeyId:it,credential:ot,status:a.z.enum(["pending","compensation-required"]),createdAt:rt,updatedAt:rt,expiresAt:rt}).strict().omit({credential:!0}),a.z.object({id:it,nodeId:it,proxyOrigin:st,proxyBindingId:it,targetNodeId:it,sourceControlPlaneId:it,bindingKeyId:it,credential:ot,createdAt:rt,updatedAt:rt}).strict();const It="2026-08-01",At=a.z.string(),bt=a.z.string().trim().min(1).max(120).regex(/^[a-zA-Z0-9][a-zA-Z0-9_.:-]*$/),wt=a.z.string().datetime(),vt=a.z.record(a.z.string(),a.z.string()).default({}),Et=a.z.record(a.z.string(),a.z.string()).default({}),Nt=a.z.string().regex(/^\d{4}-\d{2}-\d{2}$/,"Protocol version must use YYYY-MM-DD format."),St=a.z.object({encoding:a.z.enum(["utf8","base64"]),data:a.z.string()}).strict().superRefine((e,t)=>{"base64"===e.encoding&&Buffer.from(e.data,"base64").toString("base64")!==e.data&&t.addIssue({code:"custom",path:["data"],message:"Node tunnel binary body must use canonical base64 encoding."})});function Tt(e){if(null==e)return;const t=St.parse(e);return"utf8"===t.encoding?t.data:Buffer.from(t.data,"base64")}const zt=/^[A-Za-z0-9_][A-Za-z0-9_.-]{0,127}$/,_t=/^sha256:([a-fA-F0-9]{64})$/,Ct=/^(?:localhost|[a-z0-9](?:[a-z0-9.-]*[a-z0-9])?)(?::[1-9][0-9]{0,4})?$/,kt=/^[a-z0-9]+(?:(?:[._]|__|-+)[a-z0-9]+)*$/;function Ot(e){const t=e.trim();if(!t||t.length>512||t.includes("://")||/\s/.test(t))throw new Error("Docker image reference must not contain a URL scheme or whitespace.");const n=t.indexOf("@");if(-1!==n&&n!==t.lastIndexOf("@"))throw new Error("Docker image reference contains more than one digest separator.");const i=-1===n?void 0:t.slice(n+1),r=-1===n?t:t.slice(0,n),o=i?_t.exec(i):void 0;if(i&&!o)throw new Error("Docker image digest must use sha256 followed by 64 hexadecimal characters.");const s=r.lastIndexOf("/"),a=r.lastIndexOf(":"),c=a>s,d=c?r.slice(a+1):void 0,l=c?r.slice(0,a):r;if(d&&!zt.test(d))throw new Error("Docker image tag is invalid.");if(!d&&!o)throw new Error("Docker image reference must include an explicit tag or sha256 digest.");const u=l.split("/");if(!u.length||u.some(e=>!e))throw new Error("Docker image repository path is invalid.");const m=u.length>1&&(u[0].includes(".")||u[0].includes(":")||"localhost"===u[0]),p=m?u.slice(1):u;if(m&&!Ct.test(u[0].toLowerCase()))throw new Error("Docker image registry host or port is invalid.");if(!p.length||p.some(e=>!kt.test(e)))throw new Error("Docker image repository names must be lowercase and use valid separators.");const h=u.map((e,t)=>m&&0===t?e.toLowerCase():e).join("/"),g=o?`sha256:${o[1].toLowerCase()}`:void 0;return`${h}${d?`:${d}`:""}${g?`@${g}`:""}`}function Rt(e){const t=Ot(e),n=t.indexOf("@"),i=-1===n?void 0:t.slice(n+1),r=-1===n?t:t.slice(0,n),o=r.lastIndexOf("/"),s=r.lastIndexOf(":"),a=s>o;return{reference:t,repository:a?r.slice(0,s):r,tag:a?r.slice(s+1):void 0,digest:i}}const xt=a.z.string().trim().min(1).max(512).transform((e,t)=>{try{return Ot(e)}catch(e){return t.addIssue({code:"custom",message:e instanceof Error?e.message:String(e)}),a.z.NEVER}}),Dt=a.z.string().trim().transform((e,t)=>{const n=_t.exec(e);return n?`sha256:${n[1].toLowerCase()}`:(t.addIssue({code:"custom",message:"Docker image digest must use sha256 followed by 64 hexadecimal characters."}),a.z.NEVER)}),Pt=a.z.object({codexModelHash:bt.nullable().optional(),claudeModelHash:bt.nullable().optional()}).strict().default({}),Mt=a.z.object({imageId:bt,tag:a.z.string().trim().min(1).max(128).regex(zt).optional()}).strict(),Lt=a.z.discriminatedUnion("type",[a.z.object({type:a.z.literal("image"),imageSelection:Mt}).strict(),a.z.object({type:a.z.literal("template"),environmentTemplateId:bt}).strict()]),jt=a.z.enum(["creating","ready","failed","deleting"]),$t=a.z.enum(["linux","darwin","win32","freebsd","openbsd","aix","sunos","unknown"]),Ft=a.z.enum(["x64","arm64","arm","ia32","ppc64","s390x","riscv64","unknown"]),Ut=a.z.object({code:a.z.string().trim().min(1).max(120),message:a.z.string().trim().min(1).max(2048),phase:a.z.enum(["validate","commit","inspect","security-check","persist","delete","recovery"]).optional()}).strict(),Vt=a.z.object({templateId:bt,nodeId:bt,imageId:Dt,name:a.z.string().trim().min(1).max(160),platform:$t,architecture:Ft}).strict(),qt=a.z.enum(["data","agent-home","workspace"]),Ht=a.z.object({deleteVolumes:a.z.boolean()}).strict(),Bt=a.z.object({role:qt,name:a.z.string().trim().min(1).max(255),mountPath:a.z.string().trim().startsWith("/").max(4096),status:a.z.enum(["deleted","retained","missing","failed"]),error:a.z.object({code:a.z.string().trim().min(1).max(120),message:a.z.string().trim().min(1).max(2048)}).strict().optional()}).strict(),Kt=a.z.object({instanceId:bt,containerDeleted:a.z.boolean(),completed:a.z.boolean(),deletedVolumes:a.z.array(Bt),retainedVolumes:a.z.array(Bt),volumeResults:a.z.array(Bt)}).strict(),Gt={img_default:"market_taskhandoff_browser",img_codex:"market_taskhandoff_codex",img_ai:"market_taskhandoff_ai"};function Jt(e,t){if(e&&"object"==typeof e&&!Array.isArray(e)){const t=e;return{imageId:"string"==typeof t.imageId&&Gt[t.imageId]||t.imageId,..."string"==typeof t.tag?{tag:t.tag}:{}}}if("string"==typeof t)return{imageId:Gt[t]||t}}function Wt(e){if(!e||"object"!=typeof e||Array.isArray(e))return e;const t=e,{defaultImageId:n,...i}=t;return{...i,defaultImageSelection:Jt(t.defaultImageSelection,n)}}const Yt=a.z.object({id:bt,name:a.z.string().trim().min(1).max(120),kind:a.z.enum(["tty","gui","web"]),source:a.z.enum(["builtin","custom"]),availability:a.z.enum(["available","missing-dependency"]),capabilities:a.z.object({automation:a.z.enum(["cdp"]).optional(),supportsCwdSelection:a.z.boolean().default(!1)}).strict().default({supportsCwdSelection:!1}),diagnosticCode:a.z.enum(["APP_EXECUTABLE_NOT_FOUND"]).optional()}).strict(),Xt=a.z.object({code:a.z.enum(["APP_CATALOG_INVALID"]),message:a.z.string().trim().min(1).max(500)}).strict(),Qt=a.z.object({items:a.z.array(Yt).max(256),observedAt:wt,issues:a.z.array(Xt).max(32).default([])}).strict(),Zt=a.z.object({id:bt,name:a.z.string().trim().min(1).max(160),sourceInstanceId:bt,nodeId:bt,imageId:Dt.optional(),internalTag:a.z.string().trim().min(1).max(512).optional(),platform:$t.optional(),architecture:Ft.optional(),sizeBytes:a.z.number().int().nonnegative().optional(),status:jt,error:Ut.optional(),createdAt:wt,updatedAt:wt}).strict().superRefine((e,t)=>{if("ready"===e.status)for(const n of["imageId","internalTag","platform","architecture","sizeBytes"])void 0===e[n]&&t.addIssue({code:"custom",path:[n],message:`Ready environment template requires ${n}.`});"failed"!==e.status||e.error||t.addIssue({code:"custom",path:["error"],message:"Failed environment template requires an error diagnostic."})}),en=a.z.enum(["apt","dnf","brew","npm"]),tn=a.z.enum(["user","passwordless-sudo","root"]),nn=a.z.object({platform:$t,arch:Ft,installers:a.z.array(en).max(8),privilege:tn,installerAccess:a.z.object({npmGlobalWritable:a.z.boolean().optional()}).strict().optional()}).strict(),rn=a.z.enum(["installed","not-installed","broken","unsupported"]),on=a.z.enum(["recipe","bundled","external","none"]),sn=a.z.object({code:a.z.enum(["BUNDLED","EXTERNALLY_MANAGED","ALREADY_INSTALLED","NOT_INSTALLED","UNSUPPORTED_PLATFORM","INSTALLER_UNAVAILABLE","INSTALLER_NOT_WRITABLE","INSUFFICIENT_PRIVILEGE","OPERATION_IN_PROGRESS"]),message:a.z.string().trim().min(1).max(500)}).strict(),an=a.z.object({id:bt,name:a.z.string().trim().min(1).max(120),kind:a.z.enum(["tty","gui","web"]),description:a.z.string().trim().max(500).optional(),state:rn,managementSource:on,version:a.z.string().trim().max(120).optional(),canInstall:a.z.boolean(),canUninstall:a.z.boolean(),installReason:sn.optional(),uninstallReason:sn.optional(),activeJobId:bt.optional()}).strict(),cn=a.z.enum(["install","uninstall"]),dn=a.z.enum(["queued","running","succeeded","failed","cancelled","interrupted"]),ln=a.z.object({current:a.z.number().finite().nonnegative().optional(),total:a.z.number().finite().positive().optional(),unit:a.z.string().trim().min(1).max(40).optional()}).strict().refine(e=>void 0===e.total||void 0===e.current||e.current<=e.total,{message:"Progress current must not exceed total.",path:["current"]}),un=a.z.object({executable:a.z.string().trim().min(1).max(4096),args:a.z.array(a.z.string().max(4096)).max(128)}).strict(),mn=a.z.object({code:a.z.string().trim().min(1).max(120).regex(/^[a-z0-9][a-z0-9._-]*$/),message:a.z.string().trim().min(1).max(4096),retryable:a.z.boolean(),sessionIds:a.z.array(bt).max(64).optional()}).strict(),pn=a.z.object({id:bt,requestId:bt.optional(),appId:bt,operation:cn,state:dn,phase:a.z.string().trim().min(1).max(120).optional(),progress:ln.optional(),command:un.optional(),logTail:a.z.string().max(32768).optional(),logTruncated:a.z.boolean().optional(),error:mn.optional(),requestedAt:wt,startedAt:wt.optional(),finishedAt:wt.optional(),updatedAt:wt}).strict(),hn=a.z.object({streamId:bt,sequence:a.z.number().int().nonnegative(),capabilities:nn,apps:a.z.array(an).max(256),activeJobs:a.z.array(pn).max(256),recentJobs:a.z.array(pn).max(256),observedAt:wt}).strict();a.z.object({requestId:bt.optional()}).strict(),a.z.object({job:pn}).strict(),a.z.object({type:a.z.literal("app-management"),streamId:bt,sequence:a.z.number().int().nonnegative(),observedAt:wt,job:pn.optional(),snapshot:hn.optional()}).strict().refine(e=>void 0!==e.job||void 0!==e.snapshot,{message:"An app management event requires a job or snapshot."});const gn=a.z.object({component:a.z.enum(["control-plane","node-agent","controlled-instance"]),packageName:a.z.string().trim().max(160).optional(),packageVersion:a.z.string().trim().max(80).optional(),protocolVersion:At.optional(),buildId:a.z.string().trim().max(160).optional(),builtAt:a.z.string().trim().max(120).optional(),gitCommit:a.z.string().trim().max(120).optional(),imageRef:a.z.string().trim().max(512).optional(),imageDigest:a.z.string().trim().max(240).optional()}).strict();a.z.object({data:a.z.object({ok:a.z.literal(!0),role:a.z.literal("control-plane"),protocolVersion:At,build:gn.extend({component:a.z.literal("control-plane"),packageVersion:a.z.string().trim().min(1).max(80)}).loose(),dataDir:a.z.string().min(1),serverTime:wt}).loose()}).loose();const fn=a.z.enum(["stable","beta","alpha"]),yn=a.z.object({packageName:a.z.literal("@task-handoff/controlled-instance"),version:a.z.string().trim().min(1).max(80),platform:a.z.string().trim().min(1).max(40),arch:a.z.string().trim().min(1).max(40),formatVersion:a.z.number().int().positive(),launcherAbi:a.z.number().int().positive(),entrypoint:a.z.string().trim().min(1).max(512),sha256:a.z.string().regex(/^[a-f0-9]{64}$/)}).strict(),In=a.z.object({code:a.z.enum(["INSTANCE_RUNTIME_VERSION_MISMATCH","INSTANCE_RUNTIME_ARTIFACT_UNAVAILABLE","INSTANCE_RUNTIME_ARTIFACT_INVALID","INSTANCE_RUNTIME_INSTALL_FAILED","INSTANCE_RUNTIME_RESTART_FAILED","INSTANCE_RUNTIME_VERIFICATION_FAILED","INSTANCE_BASE_RUNTIME_INCOMPATIBLE","NODE_UPDATE_PREFLIGHT_FAILED","NODE_UPDATE_FAILED","LEGACY_INSTANCE_UPDATE_RETIRED"]),message:a.z.string().trim().min(1).max(4096),expectedVersion:a.z.string().trim().min(1).max(80).optional(),actualVersion:a.z.string().trim().min(1).max(80).optional(),retryable:a.z.boolean().default(!1)}).strict(),An=a.z.object({desiredVersion:a.z.string().trim().min(1).max(80),actualVersion:a.z.string().trim().min(1).max(80).optional(),phase:a.z.enum(["pending","draining","installing","restarting","verifying","matched","failed"]),attempt:a.z.number().int().nonnegative().default(0),lastAttemptAt:wt.optional(),matchedAt:wt.optional(),error:In.optional()}).strict(),bn=a.z.object({runningInstanceCount:a.z.number().int().nonnegative(),stoppedInstanceCount:a.z.number().int().nonnegative(),activeInstanceCount:a.z.number().int().nonnegative(),restartInstanceCount:a.z.number().int().nonnegative(),runningInstanceIds:a.z.array(bt).max(1024).default([]),stoppedInstanceIds:a.z.array(bt).max(1024).default([]),activeInstanceIds:a.z.array(bt).max(1024).default([])}).strict(),wn=a.z.object({phase:a.z.enum(["queued","updating-node","restarting-node","converging-instances","succeeded","degraded","failed"]),desiredVersion:a.z.string().trim().min(1).max(80),nodeVersion:a.z.string().trim().min(1).max(80).optional(),expectedInstanceIds:a.z.array(bt).max(1024).default([]),expectedInstanceCount:a.z.number().int().nonnegative(),matchedInstanceCount:a.z.number().int().nonnegative(),pendingInstanceCount:a.z.number().int().nonnegative(),failedInstanceCount:a.z.number().int().nonnegative(),deferredInstanceCount:a.z.number().int().nonnegative().default(0)}).strict(),vn=a.z.object({channel:fn.default("stable")}).strict(),En=a.z.object({source:a.z.literal("npm"),channel:fn,currentVersion:a.z.string().trim().max(240).optional(),availableVersion:a.z.string().trim().min(1).max(240),artifactRef:a.z.string().trim().min(1).max(512).optional(),runtimeArtifacts:a.z.array(yn).default([]),impact:bn,updateAvailable:a.z.boolean(),supported:a.z.boolean().default(!0),reason:a.z.string().trim().max(2048).optional(),checkedAt:wt,preflightToken:a.z.string().trim().min(16).max(240).optional()}).strict(),Nn=a.z.object({id:bt,nodeId:bt,source:a.z.literal("npm"),channel:fn,fromVersion:a.z.string().trim().max(240).optional(),toVersion:a.z.string().trim().min(1).max(240),artifactRef:a.z.string().trim().min(1).max(512).optional(),runtimeArtifacts:a.z.array(yn).default([]),impact:bn,rollout:wn,status:a.z.enum(["queued","updating-node","restarting-node","converging-instances","succeeded","degraded","failed"]),error:In.optional(),startedAt:wt.optional(),completedAt:wt.optional(),createdAt:wt,updatedAt:wt}).strict(),Sn=a.z.object({channel:fn,targetVersion:a.z.string().trim().min(1).max(240),preflightToken:a.z.string().trim().min(16).max(240)}).strict(),Tn=a.z.object({type:a.z.enum(["branch","tag","commit"]),name:a.z.string().trim().min(1).max(240).optional(),commit:a.z.string().trim().max(80).optional()}).strict(),zn=a.z.object({type:a.z.enum(["none","ssh-key","https-token"]).default("none"),secretId:a.z.string().trim().min(1).max(120).optional()}).strict(),_n=a.z.object({depth:a.z.number().int().positive().max(1e5).optional(),submodules:a.z.boolean().default(!1),lfs:a.z.boolean().default(!1),subdirectory:a.z.string().trim().max(240).default("")}).strict();a.z.object({id:bt,name:a.z.string().trim().min(1).max(160),url:a.z.string().trim().min(1).max(2048),provider:a.z.string().trim().max(80).optional(),ref:Tn.default({type:"branch",name:"main"}),auth:zn.default({type:"none"}),clone:_n.default({submodules:!1,lfs:!1,subdirectory:""}),defaultImageSelection:Mt.optional(),labels:vt,createdAt:wt,updatedAt:wt}).strict();const Cn=a.z.object({id:bt,nodeId:bt,name:a.z.string().trim().min(1).max(160),path:a.z.string().trim().min(1).max(4096),defaultImageSelection:Mt.optional(),labels:vt,createdAt:wt,updatedAt:wt}).strict(),kn=a.z.discriminatedUnion("type",[a.z.object({type:a.z.literal("git-repository"),repositoryId:bt.optional(),url:a.z.string().trim().min(1).max(2048),provider:a.z.string().trim().max(80).optional(),ref:Tn.default({type:"branch",name:"main"}),auth:zn.default({type:"none"}),clone:_n.default({submodules:!1,lfs:!1,subdirectory:""})}).strict(),a.z.object({type:a.z.literal("git-template"),url:a.z.string().trim().min(1).max(2048),templateId:a.z.string().trim().min(1).max(120).optional(),ref:Tn.default({type:"branch",name:"main"}),auth:zn.default({type:"none"}),clone:_n.default({submodules:!1,lfs:!1,subdirectory:""})}).strict(),a.z.object({type:a.z.literal("local-folder"),localFolderId:bt.optional(),path:a.z.string().trim().min(1).max(4096),ownerNodeId:bt.optional()}).strict()]),On=a.z.object({mode:a.z.enum(["local-bind","git-clone","empty-volume","persistent-volume"]),path:a.z.string().trim().min(1).max(4096).default("/workspace"),volumeName:a.z.string().trim().max(240).optional(),readOnly:a.z.boolean().default(!1)}).strict(),Rn=a.z.enum(["codex","claude"]),xn=a.z.object({id:bt,name:a.z.string().trim().min(1).max(160),source:kn,defaultImageSelection:Mt.optional(),defaultNodeId:bt.optional(),defaultRuntimeId:bt.optional(),workspacePolicy:On,labels:vt,createdAt:wt,updatedAt:wt}).strict(),Dn=a.z.object({id:bt,name:a.z.string().trim().min(1).max(160),endpoint:a.z.string().trim().min(1).max(2048),key:a.z.string().trim().min(1).max(4096),model:a.z.string().trim().min(1).max(240),app:Rn,enabled:a.z.boolean().default(!0),order:a.z.number().int().min(0).max(1e6).default(0),labels:vt,createdAt:wt,updatedAt:wt}).strict(),Pn=Dn,Mn=Dn.omit({key:!0}).extend({keyPreview:a.z.string().trim().min(1).max(160),keySet:a.z.boolean()}).strict(),Ln=Mn.extend({referenceCount:a.z.number().int().min(0)}).strict(),jn=a.z.object({instanceId:bt,codexModelHash:bt.optional(),claudeModelHash:bt.optional(),updatedAt:wt}).strict(),$n=a.z.discriminatedUnion("type",[a.z.object({type:a.z.literal("control-plane"),name:Dn.shape.name,enabled:Dn.shape.enabled,order:Dn.shape.order}).strict(),a.z.object({type:a.z.literal("node"),nodeId:bt,name:Dn.shape.name,enabled:Dn.shape.enabled,order:Dn.shape.order,referenceCount:a.z.number().int().min(0)}).strict()]),Fn=a.z.object({id:bt,model:Mn,locations:a.z.array($n).min(1),referenceCount:a.z.number().int().min(0).default(0)}).strict(),Un=a.z.object({nodeId:bt,code:a.z.string().trim().min(1).max(120),message:a.z.string().trim().min(1).max(2e3)}).strict();a.z.object({models:a.z.array(Fn),nodeDiagnostics:a.z.array(Un).default([]),updatedAt:wt}).strict();const Vn=Dn.omit({id:!0,createdAt:!0,updatedAt:!0}).strict(),qn=Vn.partial().strict(),Hn=Dn,Bn=a.z.object({modelSelection:Pt,codexModelHash:bt.optional(),claudeModelHash:bt.optional()}).strict();function Kn(e){const t={app:Rn.parse(e.app),endpoint:Dn.shape.endpoint.parse(e.endpoint),key:Dn.shape.key.parse(e.key),model:Dn.shape.model.parse(e.model)};return`mdl_${d.createHash("sha256").update(JSON.stringify(t)).digest("hex")}`}const Gn=a.z.enum(["market","custom"]),Jn=a.z.enum(["active","deprecated","yanked"]),Wn=a.z.discriminatedUnion("kind",[a.z.object({kind:a.z.literal("builtin"),key:a.z.string().trim().min(1).max(120)}).strict(),a.z.object({kind:a.z.literal("remote"),url:a.z.string().trim().url().max(2048),mediaType:a.z.enum(["image/png","image/jpeg","image/webp"]).optional(),digest:Dt.optional()}).strict()]),Yn=a.z.array(a.z.string().trim().min(1).max(80)).default([]),Xn=a.z.array(a.z.string().trim().min(1).max(120)).default([]),Qn=a.z.record(a.z.string().trim().min(2).max(35),a.z.string().trim().min(1).max(4096)),Zn=a.z.object({os:a.z.string().trim().min(1).max(40),architecture:a.z.string().trim().min(1).max(40),digest:Dt.optional(),downloadSizeBytes:a.z.number().int().positive().optional(),unpackedSizeBytes:a.z.number().int().positive().optional()}).strict(),ei=a.z.object({name:a.z.string().trim().min(1).max(128).regex(zt),version:a.z.string().trim().min(1).max(160).optional(),reference:xt,manifestDigest:Dt.optional(),publishedAt:wt.optional(),platforms:a.z.array(Zn).default([]),status:Jn.default("active")}).strict(),ti=a.z.object({id:bt,publisher:a.z.string().trim().min(1).max(160),slug:a.z.string().trim().min(1).max(160),name:a.z.string().trim().min(1).max(160),description:a.z.string().trim().min(1).max(4096),localizedDescriptions:Qn.optional(),cover:Wn.optional(),repository:a.z.string().trim().min(1).max(512),defaultTag:a.z.string().trim().min(1).max(128).regex(zt),tags:a.z.array(ei).min(1),capabilities:Yn,optionalApps:Xn,defaultEnv:Et,labels:vt,status:Jn.default("active")}).strict().superRefine((e,t)=>{e.tags.some(t=>t.name===e.defaultTag)||t.addIssue({code:"custom",path:["defaultTag"],message:"Market defaultTag must identify one of the image tags."})});a.z.object({protocolVersion:Nt,catalogId:bt,revision:a.z.string().trim().min(1).max(240),source:a.z.enum(["embedded","remote","cache"]),generatedAt:wt,expiresAt:wt.optional(),items:a.z.array(ti)}).strict(),a.z.object({source:a.z.enum(["embedded","remote","cache"]),state:a.z.enum(["ready","refreshing","stale","failed"]),revision:a.z.string().trim().min(1).max(240),updatedAt:wt,error:a.z.string().trim().max(4096).optional()}).strict(),a.z.object({id:bt,origin:a.z.literal("custom"),name:a.z.string().trim().min(1).max(160),description:a.z.string().trim().max(4096).optional(),localizedDescriptions:Qn.optional(),cover:Wn.optional(),reference:xt,repository:a.z.string().trim().min(1).max(512),tag:a.z.string().trim().min(1).max(128).regex(zt).optional(),pullPolicy:a.z.literal("if-not-present").default("if-not-present"),capabilities:Yn,optionalApps:Xn,defaultEnv:Et,labels:vt,createdAt:wt,updatedAt:wt}).strict();const ni=a.z.object({name:a.z.string().trim().min(1).max(128).regex(zt),version:a.z.string().trim().min(1).max(160).optional(),reference:xt,manifestDigest:Dt.optional(),status:Jn}).strict(),ii=a.z.object({id:bt,origin:Gn,name:a.z.string().trim().min(1).max(160),description:a.z.string().trim().max(4096).optional(),localizedDescriptions:Qn.optional(),cover:Wn,repository:a.z.string().trim().min(1).max(512),tag:a.z.string().trim().min(1).max(128).regex(zt).optional(),availableTags:a.z.array(ni),reference:xt,digest:Dt.optional(),downloadSizeBytes:a.z.number().int().positive().optional(),unpackedSizeBytes:a.z.number().int().positive().optional(),capabilities:Yn,optionalApps:Xn,defaultEnv:Et,labels:vt,readOnly:a.z.boolean(),lifecycleStatus:Jn.optional(),market:a.z.object({catalogId:bt,catalogRevision:a.z.string().trim().min(1).max(240),publisher:a.z.string().trim().min(1).max(160),version:a.z.string().trim().min(1).max(160).optional()}).strict().optional()}).strict(),ri=a.z.object({id:bt,origin:Gn,name:a.z.string().trim().min(1).max(160),description:a.z.string().trim().max(4096).optional(),localizedDescriptions:Qn.optional(),cover:Wn.optional(),repository:a.z.string().trim().min(1).max(512),tag:a.z.string().trim().min(1).max(128).regex(zt).optional(),requestedReference:xt,resolvedDigest:Dt.optional(),resolvedReference:xt.optional(),downloadSizeBytes:a.z.number().int().positive().optional(),pullPolicy:a.z.literal("if-not-present").default("if-not-present"),capabilities:Yn,optionalApps:Xn,defaultEnv:Et,labels:vt,market:a.z.object({catalogId:bt,catalogRevision:a.z.string().trim().min(1).max(240),publisher:a.z.string().trim().min(1).max(160),version:a.z.string().trim().min(1).max(160).optional()}).strict().optional(),createdAt:wt,updatedAt:wt}).strict(),oi=a.z.object({phase:a.z.enum(["checking-image","pulling-image","resolving-image","ready","failed"]),requestedReference:xt,generation:a.z.number().int().nonnegative().default(0),error:a.z.string().trim().max(4096).optional(),startedAt:wt,updatedAt:wt}).strict(),si="image.pull.terminal.output",ai="image.pull.terminal.finished",ci=a.z.object({instanceId:bt,generation:a.z.number().int().nonnegative(),requestedReference:xt,sequence:a.z.number().int().nonnegative(),observedAt:wt}).strict(),di=ci.extend({data:a.z.string().min(1).max(65536),replay:a.z.boolean().optional()}).strict(),li=ci.extend({outcome:a.z.enum(["succeeded","failed"])}).strict();ci.extend({status:a.z.enum(["connecting","pulling","extracting","complete","failed"]),layers:a.z.object({total:a.z.number().int().nonnegative(),completed:a.z.number().int().nonnegative(),downloaded:a.z.number().int().nonnegative(),downloading:a.z.number().int().nonnegative(),extracting:a.z.number().int().nonnegative()}).strict(),bytes:a.z.object({current:a.z.number().finite().nonnegative(),total:a.z.number().finite().positive()}).strict().optional(),percent:a.z.number().finite().min(0).max(100).optional(),message:a.z.string().trim().min(1).max(500),terminalTail:a.z.string().max(262144).optional(),terminalTruncated:a.z.boolean().optional()}).strict();const ui=a.z.discriminatedUnion("kind",[a.z.object({kind:a.z.literal("direct")}).strict(),a.z.object({kind:a.z.literal("control-plane-proxy"),proxyId:bt,proxyBindingId:bt,targetNodeId:bt}).strict()]),mi=a.z.object({reachability:a.z.enum(["unknown","reachable","unreachable"]),bindingStatus:a.z.enum(["unknown","active","revoked"]),bindingRevision:a.z.number().int().positive().optional(),streamId:a.z.string().trim().min(1).max(160).optional(),revision:a.z.number().int().nonnegative().optional(),observedAt:wt.optional(),target:pt.optional(),lastError:ct.optional(),updatedAt:wt}).strict(),pi=a.z.object({id:bt,name:a.z.string().trim().min(1).max(160),connectionMode:a.z.enum(["local-ipc","local-loopback","direct-http","reverse-wss","control-plane-proxy"]).default("direct-http"),connectionPath:ui.default({kind:"direct"}),connectionEnabled:a.z.boolean().default(!0),auth:a.z.object({mode:a.z.enum(["local-static-key","paired-hmac","proxy-binding"]).default("local-static-key"),keyId:bt.optional(),secret:a.z.string().trim().max(4096).optional(),pairedAt:wt.optional(),pairing:a.z.object({status:a.z.enum(["pending","paired","expired"]).default("pending"),joinToken:a.z.string().trim().max(4096).optional(),expiresAt:wt.optional()}).strict().optional()}).strict().default({mode:"local-static-key"}),endpoint:a.z.string().trim().max(2048).optional(),controlEndpoint:a.z.string().trim().max(2048).optional(),containerEndpoint:a.z.string().trim().max(2048).optional(),publicWebBase:a.z.string().trim().max(2048).optional(),status:a.z.enum(["unknown","online","offline","degraded"]).default("unknown"),health:a.z.enum(["unknown","ok","degraded","failed"]).default("unknown"),capabilities:a.z.record(a.z.string(),a.z.unknown()).default({}),proxyState:mi.optional(),appInventory:Qt.optional(),labels:vt,lastSeenAt:wt.optional(),createdAt:wt,updatedAt:wt}).strict().superRefine((e,t)=>{"control-plane-proxy"===e.connectionPath.kind&&"control-plane-proxy"!==e.connectionMode&&t.addIssue({code:"custom",path:["connectionPath"],message:"Control-plane proxy paths require control-plane-proxy connection mode."}),"control-plane-proxy"===e.connectionMode&&"control-plane-proxy"!==e.connectionPath.kind&&t.addIssue({code:"custom",path:["connectionPath"],message:"Control-plane proxy nodes require a control-plane-proxy connection path."})}),hi=a.z.object({id:bt,nodeId:bt,name:a.z.string().trim().min(1).max(160),type:a.z.enum(["docker","kubernetes","local"]),status:a.z.enum(["unknown","online","offline","degraded"]).default("unknown"),accessStrategy:a.z.enum(["node-proxy","direct-port","kubernetes-ingress","kubernetes-port-forward"]).default("node-proxy"),capabilities:a.z.record(a.z.string(),a.z.unknown()).default({}),labels:vt,createdAt:wt,updatedAt:wt}).strict(),gi=a.z.object({instanceId:bt,runtimeKind:a.z.literal("docker"),state:a.z.enum(["pending","available","stopped","unavailable"]),sampledAt:wt,cpu:a.z.object({usagePercent:a.z.number().nonnegative()}).strict().optional(),memory:a.z.object({usageBytes:a.z.number().nonnegative(),limitBytes:a.z.number().nonnegative().optional(),usagePercent:a.z.number().nonnegative().optional()}).strict().optional(),network:a.z.object({rxBytes:a.z.number().nonnegative(),txBytes:a.z.number().nonnegative()}).strict().optional(),blockIo:a.z.object({readBytes:a.z.number().nonnegative(),writeBytes:a.z.number().nonnegative()}).strict().optional(),pids:a.z.number().int().nonnegative().optional(),error:a.z.string().trim().max(2048).optional()}).strict();a.z.object({ok:a.z.boolean().optional(),role:a.z.string().optional(),nodeId:bt.optional(),platform:$t.optional(),arch:Ft.optional(),protocolVersion:At.optional(),build:gn.strip().optional(),process:a.z.object({pid:a.z.number().int().positive(),startIdentity:a.z.string().trim().min(1).optional()}).strip().optional(),listener:a.z.object({host:a.z.string().trim().min(1),port:a.z.number().int().min(1).max(65535)}).strip().optional(),instanceProxy:a.z.object({requests:a.z.number().int().nonnegative(),active:a.z.number().int().nonnegative(),completed:a.z.number().int().nonnegative(),aborted:a.z.number().int().nonnegative(),limitRejected:a.z.number().int().nonnegative(),responseBytes:a.z.number().nonnegative(),totalDurationMs:a.z.number().nonnegative(),maxResponseBytes:a.z.number().int().nonnegative()}).partial().strip().optional(),serverTime:wt.optional()}).strip();const fi=a.z.object({bindScope:a.z.enum(["loopback","all-ipv4"]),port:a.z.number().int().min(1).max(65535)}).strict(),yi=fi.extend({host:a.z.enum(["127.0.0.1","0.0.0.0"]),status:a.z.enum(["listening","error"]),source:a.z.enum(["bootstrap","persisted"]),error:a.z.string().trim().max(2048).optional()}).strict(),Ii=fi;a.z.object({nodeId:bt,joinToken:a.z.string().trim().min(1),expiresAt:wt}).passthrough(),a.z.object({nodeId:bt,keyId:bt,secret:a.z.string().regex(/^[A-Za-z0-9_-]{32,128}$/),pairedAt:wt}).strict();const Ai=a.z.object({id:bt,keyId:bt,name:a.z.string().trim().min(1).max(160).optional(),pairedAt:wt,updatedAt:wt,current:a.z.boolean()}).passthrough();a.z.object({keyId:bt,revoked:a.z.literal(!0),revokedAt:wt}).strict(),a.z.object({id:bt,pairingKeyId:bt,url:a.z.string().trim().min(1).max(2048),name:a.z.string().trim().min(1).max(160).optional(),enabled:a.z.boolean(),createdAt:wt,updatedAt:wt,status:a.z.enum(["disabled","connecting","connected","reconnecting","failed"]),lastConnectedAt:wt.optional(),lastDisconnectedAt:wt.optional(),error:a.z.string().optional()}).passthrough(),a.z.object({pairing:Ai,connection:a.z.object({id:bt,pairingKeyId:bt,url:a.z.string().trim().min(1).max(2048),name:a.z.string().trim().min(1).max(160).optional(),enabled:a.z.boolean(),createdAt:wt,updatedAt:wt}).passthrough(),tunnel:a.z.object({status:a.z.enum(["disabled","saved","connecting","connected","failed"]),error:a.z.string().trim().max(2048).optional()}).passthrough()}).passthrough(),a.z.object({deleted:a.z.boolean().optional()}).passthrough();const bi=a.z.object({repository:a.z.string().trim().optional(),tag:a.z.string().trim().optional(),id:a.z.string().trim(),createdSince:a.z.string().trim().optional(),size:a.z.string().trim().optional(),sizeBytes:a.z.number().int().nonnegative().optional(),reference:a.z.string().trim().min(1),repoDigests:a.z.array(a.z.string().trim().min(1).max(512)).default([])}).passthrough();a.z.object({image:ii,status:a.z.enum(["available","pull-required","unknown"]),localImage:bi.optional(),localSizeBytes:a.z.number().int().nonnegative().optional(),downloadSizeBytes:a.z.number().int().positive().optional(),unpackedSizeBytes:a.z.number().int().positive().optional(),error:a.z.string().trim().max(2048).optional()}).strict();const wi=a.z.lazy(()=>a.z.object({name:a.z.string().trim().min(1),path:a.z.string().trim().min(1).max(4096),children:a.z.array(wi)}).passthrough());a.z.object({status:a.z.number().int().min(100).max(599).optional(),headers:a.z.record(a.z.string(),a.z.string()).optional(),bodyBase64:a.z.string().optional()}).passthrough();const vi=a.z.object({strategy:a.z.enum(["node-proxy","direct-port","kubernetes-ingress","kubernetes-port-forward"]).default("node-proxy"),web:a.z.string().trim().max(2048).optional(),api:a.z.string().trim().max(2048).optional(),vnc:a.z.string().trim().max(2048).optional(),tty:a.z.string().trim().max(2048).optional(),logs:a.z.string().trim().max(2048).optional(),status:a.z.enum(["unknown","reachable","endpoint-unreachable"]).default("unknown")}).strict(),Ei=a.z.object({strategy:a.z.enum(["control-plane-proxy","direct-port","node-proxy","kubernetes-ingress","kubernetes-port-forward"]).default("control-plane-proxy"),web:a.z.string().trim().max(2048).optional(),api:a.z.string().trim().max(2048).optional(),ws:a.z.string().trim().max(2048).optional(),status:a.z.enum(["unknown","reachable","endpoint-unreachable"]).default("unknown")}).strict().default({strategy:"control-plane-proxy",status:"unknown"}),Ni=a.z.object({mode:a.z.enum(["local-bind","git-clone","empty-volume","persistent-volume"]).optional(),status:a.z.enum(["unknown","pending","ready","failed"]).default("unknown"),path:a.z.string().trim().max(4096).optional(),resolvedCommit:a.z.string().trim().max(120).optional(),error:a.z.string().trim().max(2048).optional()}).passthrough(),Si=a.z.object({id:bt,name:a.z.string().trim().min(1).max(160),projectId:bt.optional(),source:kn,sourceSnapshot:a.z.record(a.z.string(),a.z.unknown()).default({}),modelSelection:Pt,nodeId:bt,runtimeId:bt,imageSelection:Mt.optional(),environmentSource:Lt.optional(),environmentTemplateOrigin:Vt.optional(),imageSnapshot:ri.optional(),imageProvisioning:oi.optional(),stateRevision:a.z.number().int().min(0).default(0),processIncarnationId:a.z.string().trim().min(1).max(120).optional(),status:a.z.enum(["created","provisioning","starting","registering","registered","running","stopping","stopped","deleting","failed","unhealthy"]).default("created"),health:a.z.enum(["unknown","ok","degraded","failed"]).default("unknown"),connectionStatus:a.z.enum(["unknown","online","offline","endpoint-unreachable"]).default("unknown"),agentStatus:a.z.enum(["unknown","online","offline"]).default("unknown"),targetStatus:a.z.enum(["unknown","reachable","endpoint-unreachable"]).default("unknown"),uiAccessStatus:a.z.enum(["unknown","reachable","endpoint-unreachable"]).default("unknown"),controlMode:a.z.enum(["standalone","controlled"]).default("controlled"),protocolVersion:At.optional(),instanceVersion:a.z.string().trim().max(80).optional(),build:gn.optional(),runtimeVersion:An.optional(),ready:a.z.boolean().default(!1),capabilities:a.z.record(a.z.string(),a.z.unknown()).default({}),appInventory:Qt.optional(),config:a.z.object({autoImportAgentConfigs:a.z.boolean().default(!0),defaultCodexPermissionMode:me.default("ask")}).strict().default({autoImportAgentConfigs:!0,defaultCodexPermissionMode:"ask"}),workspace:Ni.default({status:"unknown"}),target:vi.default({strategy:"direct-port",status:"unknown"}),access:Ei,apps:a.z.object({runningCount:a.z.number().int().min(0).default(0),problemCount:a.z.number().int().min(0).default(0),updatedAt:wt.optional(),revision:a.z.number().int().min(0).optional()}).strict().default({runningCount:0,problemCount:0}),aiSessions:Pe.default(()=>({runningCount:0,waitingCount:0,staleCount:0,sessions:[],updatedAt:(new Date).toISOString()})),triggers:a.z.object({enabledCount:a.z.number().int().min(0).default(0),runningCount:a.z.number().int().min(0).default(0),errorCount:a.z.number().int().min(0).default(0),configs:a.z.array(a.z.object({configHash:a.z.string().trim().min(1),config:Je,deployments:a.z.array(Ye).default([]),runtime:a.z.array(Xe).default([])}).strict()).default([]),recentRuns:a.z.array(Qe).default([])}).strict().optional(),runtime:a.z.object({kind:a.z.string().trim().max(80).optional(),containerName:a.z.string().trim().max(240).optional(),containerId:a.z.string().trim().max(240).optional(),workspacePath:a.z.string().trim().max(4096).optional(),pid:a.z.number().int().positive().optional(),port:a.z.number().int().positive().max(65535).optional(),labels:a.z.record(a.z.string(),a.z.string()).default({})}).strict().default({labels:{}}),registrationToken:a.z.string().trim().min(1).max(240).optional(),lastHeartbeatAt:wt.optional(),createdAt:wt,updatedAt:wt}).strict(),Ti="instance.lifecycle.snapshot",zi=a.z.object({instanceId:Si.shape.id,revision:a.z.number().int().min(0),updatedAt:wt,status:Si.shape.status.unwrap(),health:Si.shape.health.unwrap(),connectionStatus:Si.shape.connectionStatus.unwrap(),accessStatus:a.z.enum(["reachable","endpoint-unreachable"]),imageProvisioning:oi.optional(),workspace:Ni,runtime:Si.shape.runtime.unwrap(),runtimeVersion:An.optional(),ready:a.z.boolean(),lastHeartbeatAt:wt.optional()}).strict();function _i(e,t){return Si.safeParse(Ci(e,t))}function Ci(e,t){if(!e||"object"!=typeof e||Array.isArray(e))return e;const n=e,i=new Set(Object.keys(Si.shape)),r={};for(const[e,o]of Object.entries(n))i.has(e)?r[e]=o:t?.({instanceId:"string"==typeof n.id?n.id:void 0,field:e});if(n.capabilities&&"object"==typeof n.capabilities&&!Array.isArray(n.capabilities)){const e={...n.capabilities};Object.prototype.hasOwnProperty.call(e,"apps")&&(t?.({instanceId:"string"==typeof n.id?n.id:void 0,field:"capabilities.apps"}),delete e.apps),r.capabilities=e}else r.capabilities={};r.appInventory=function(e,t,n){if(!e||"object"!=typeof e||Array.isArray(e))return;const i=e;Object.keys(i).some(e=>!["observedAt","items","issues"].includes(e))&&t?.({instanceId:n,field:"appInventory"});const r={observedAt:i.observedAt,items:Array.isArray(i.items)?i.items.map(e=>{e&&"object"==typeof e&&!Array.isArray(e)&&Object.keys(e).some(e=>!["id","name","kind","source","availability","capabilities","diagnosticCode"].includes(e))&&t?.({instanceId:n,field:"appInventory.items"});const i=Ri(e,["id","name","kind","source","availability","diagnosticCode"]);return!i||"object"!=typeof i||Array.isArray(i)?i:{...i,capabilities:Ri(e.capabilities,["automation","supportsCwdSelection"])}}):i.items,issues:Array.isArray(i.issues)?i.issues.map(e=>Ri(e,["code","message"])):i.issues},o=Qt.safeParse(r);return o.success?o.data:void 0}(n.appInventory,t,"string"==typeof n.id?n.id:void 0),r.source=function(e,t,n){if(!e||"object"!=typeof e||Array.isArray(e))return e;const i=e,r=i.type,o=kn.options.find(e=>e.shape.type.value===r);if(!o)return e;const s="local-folder"===r?["type","localFolderId","path","ownerNodeId"]:"git-template"===r?["type","url","templateId","ref","auth","clone"]:["type","repositoryId","url","provider","ref","auth","clone"],a=Ri(i,s);if("local-folder"!==r){const e=ki(Tn,Ri(i.ref,["type","name","commit"]),"source.ref",t,n),r=ki(zn,Ri(i.auth,["type","secretId"]),"source.auth",t,n),o=ki(_n,Ri(i.clone,["depth","submodules","lfs","subdirectory"]),"source.clone",t,n);e?a.ref=e:delete a.ref,r?a.auth=r:delete a.auth,o?a.clone=o:delete a.clone}const c=ki(o,a,"source",t,n);return c?(Object.keys(i).some(e=>!s.includes(e))&&t?.({instanceId:n,field:"source"}),c):a}(n.source,t,"string"==typeof n.id?n.id:void 0),r.sourceSnapshot=n.sourceSnapshot&&"object"==typeof n.sourceSnapshot&&!Array.isArray(n.sourceSnapshot)?n.sourceSnapshot:{},r.build=ki(gn,n.build,"build",t,"string"==typeof n.id?n.id:void 0),r.aiSessions=function(e,t,n){if(!e||"object"!=typeof e||Array.isArray(e))return;const i=e,r=Array.isArray(i.sessions)?i.sessions.flatMap((e,i)=>{const r=ki(De,e,`aiSessions.sessions.${i}`,t,n);return r?[r]:[]}):[],o={runningCount:"number"==typeof i.runningCount&&Number.isInteger(i.runningCount)&&i.runningCount>=0?i.runningCount:0,waitingCount:"number"==typeof i.waitingCount&&Number.isInteger(i.waitingCount)&&i.waitingCount>=0?i.waitingCount:0,staleCount:"number"==typeof i.staleCount&&Number.isInteger(i.staleCount)&&i.staleCount>=0?i.staleCount:0,sessions:r,updatedAt:wt.safeParse(i.updatedAt).success?i.updatedAt:(new Date).toISOString()};return Object.keys(i).some(e=>!["runningCount","waitingCount","staleCount","sessions","updatedAt"].includes(e))&&t?.({instanceId:n,field:"aiSessions"}),Pe.parse(o)}(n.aiSessions,t,"string"==typeof n.id?n.id:void 0),r.triggers=function(e,t,n){if(!e||"object"!=typeof e||Array.isArray(e))return;const i=e;Object.keys(i).some(e=>!["enabledCount","runningCount","errorCount","configs","recentRuns"].includes(e))&&t?.({instanceId:n,field:"triggers"});const r=(e,i,r)=>Array.isArray(e)?e.flatMap((e,o)=>{const s=ki(i,e,`${r}.${o}`,t,n);return s?[s]:[]}):[],o=Array.isArray(i.configs)?i.configs.flatMap((e,i)=>{if(!e||"object"!=typeof e||Array.isArray(e))return[];const o=e;Object.keys(o).some(e=>!["configHash","config","deployments","runtime"].includes(e))&&t?.({instanceId:n,field:`triggers.configs.${i}`});const s=function(e,t,n,i){if(!e||"object"!=typeof e||Array.isArray(e))return;const r=e,o=Ri(r,["configHash","name","description","createdAt","updatedAt"]);if(r.source&&"object"==typeof r.source&&!Array.isArray(r.source)){const e=r.source,t="schedule"===e.type?"interval"===e.scheduleKind?["type","scheduleKind","intervalMs"]:"daily"===e.scheduleKind?["type","scheduleKind","timeOfDay","timezone"]:["type","scheduleKind","weekdays","timeOfDay","timezone"]:"file-change"===e.type?["type","roots","globs","ignore","debounceMs"]:["type","agent","statuses","phases"];o.source=Ri(e,t)}return o.action=Ri(r.action,["promptTemplate"]),o.policy=Ri(r.policy,["cooldownMs","maxConcurrentRuns","whenBusy"]),ki(Je,o,t,n,i)}(o.config,`triggers.configs.${i}.config`,t,n);return"string"==typeof o.configHash&&s?[{configHash:o.configHash,config:s,deployments:r(o.deployments,Ye,`triggers.configs.${i}.deployments`),runtime:r(o.runtime,Xe,`triggers.configs.${i}.runtime`)}]:[]}):[];return{enabledCount:"number"==typeof i.enabledCount&&Number.isInteger(i.enabledCount)&&i.enabledCount>=0?i.enabledCount:0,runningCount:"number"==typeof i.runningCount&&Number.isInteger(i.runningCount)&&i.runningCount>=0?i.runningCount:0,errorCount:"number"==typeof i.errorCount&&Number.isInteger(i.errorCount)&&i.errorCount>=0?i.errorCount:0,configs:o,recentRuns:r(i.recentRuns,Qe,"triggers.recentRuns")}}(n.triggers,t,"string"==typeof n.id?n.id:void 0),r.apps=ki(Si.shape.apps.unwrap(),Ri(n.apps,["runningCount","problemCount","updatedAt","revision"]),"apps",t,"string"==typeof n.id?n.id:void 0)||{runningCount:0,problemCount:0},r.config=ki(Si.shape.config.unwrap(),Ri(n.config,["autoImportAgentConfigs","defaultCodexPermissionMode"]),"config",t,"string"==typeof n.id?n.id:void 0)||{autoImportAgentConfigs:!0,defaultCodexPermissionMode:"ask"},r.modelSelection=ki(Pt.unwrap(),Ri(n.modelSelection,["codexModelHash","claudeModelHash"]),"modelSelection",t,"string"==typeof n.id?n.id:void 0)||{},r.imageSnapshot=function(e,t,n,i){if(!e||"object"!=typeof e||Array.isArray(e))return e;const r=e,o=function(e){if(!e||"object"!=typeof e||Array.isArray(e))return e;const t=e,n=new Set(["id","origin","name","description","localizedDescriptions","cover","reference","repository","tag","image","registry","pullPolicy","capabilities","optionalApps","defaultEnv","labels","createdAt","updatedAt"]);for(const e of Object.keys(t))n.has(e);"string"==typeof t.id&&t.id;const i="string"==typeof t.image?t.image:void 0;Object.prototype.hasOwnProperty.call(t,"registry");let r,o="string"==typeof t.reference?t.reference:i;if(o)try{o=Ot(o)}catch{if(!o.includes("@")&&o.lastIndexOf(":")<=o.lastIndexOf("/"))try{o=Ot(`${o}:latest`)}catch{}}try{r=o?Rt(o):void 0}catch{}return{id:t.id,origin:"custom",name:t.name,description:t.description,localizedDescriptions:t.localizedDescriptions,cover:Ri(t.cover,["kind","key","url","mediaType","digest"]),reference:r?.reference??o,repository:r?.repository??t.repository,tag:r?.tag??t.tag,pullPolicy:t.pullPolicy??"if-not-present",capabilities:t.capabilities,optionalApps:t.optionalApps,defaultEnv:t.defaultEnv,labels:t.labels,createdAt:t.createdAt,updatedAt:t.updatedAt}}(r),{reference:s,...a}=o,c=r.requestedReference??s;let d;try{d="string"==typeof c?Rt(c):void 0}catch{}const l={img_default:"market_taskhandoff_browser",img_codex:"market_taskhandoff_codex",img_ai:"market_taskhandoff_ai"},u="string"==typeof r.id?r.id:"string"==typeof t?t:void 0,m="market"===r.origin||u&&l[u]?"market":"custom";return void 0===r.image&&void 0===r.reference||n?.({instanceId:i,field:"imageSnapshot.reference"}),{...a,id:u&&l[u]?l[u]:u,origin:m,repository:d?.repository??r.repository,tag:d?.tag??r.tag,requestedReference:d?.reference??c,resolvedDigest:r.resolvedDigest,resolvedReference:r.resolvedReference,downloadSizeBytes:r.downloadSizeBytes,market:"market"===m?Ri(r.market,["catalogId","catalogRevision","publisher","version"])??{catalogId:"task_handoff_embedded",catalogRevision:"legacy",publisher:"task-handoff"}:void 0}}(n.imageSnapshot,n.imageId,t,"string"==typeof n.id?n.id:void 0);const o="string"==typeof n.imageId?{img_default:"market_taskhandoff_browser",img_codex:"market_taskhandoff_codex",img_ai:"market_taskhandoff_ai"}[n.imageId]||n.imageId:void 0,s=Ri(n.imageSelection,["imageId","tag"]);r.imageSelection=s||(o?{imageId:o,tag:r.imageSnapshot?.tag}:void 0),r.imageProvisioning=ki(oi,Ri(n.imageProvisioning,["phase","requestedReference","generation","error","startedAt","updatedAt"]),"imageProvisioning",t,"string"==typeof n.id?n.id:void 0),r.runtimeVersion=function(e,t,n){if(!e||"object"!=typeof e||Array.isArray(e))return;const i=e,r=e=>{if("string"!=typeof e)return;const t=e.trim();return t&&t.length<=80?t:void 0},o=r(i.desiredVersion);if(!o)return void t?.({instanceId:n,field:"runtimeVersion.desiredVersion"});const s=new Set(An.shape.phase.options),a="string"==typeof i.phase?i.phase:"pending",c=s.has(a)?a:{idle:"pending",queued:"pending",checking:"pending",downloading:"installing",updating:"installing",completed:"matched",succeeded:"matched",ready:"matched",error:"failed"}[a]||"pending";let d;if(c!==a&&t?.({instanceId:n,field:"runtimeVersion.phase"}),i.error&&"object"==typeof i.error&&!Array.isArray(i.error)){const e=i.error,o="string"==typeof e.message?e.message.trim().slice(0,4096):"";if(o){const i=new Set(In.shape.code.options),s="string"==typeof e.code&&i.has(e.code)?e.code:"INSTANCE_RUNTIME_INSTALL_FAILED";s!==e.code&&t?.({instanceId:n,field:"runtimeVersion.error.code"});const a=r(e.expectedVersion),c=r(e.actualVersion);d={code:s,message:o,...a?{expectedVersion:a}:{},...c?{actualVersion:c}:{},retryable:!0===e.retryable}}else t?.({instanceId:n,field:"runtimeVersion.error"})}"string"==typeof i.error&&i.error.trim()&&(d={code:"INSTANCE_RUNTIME_INSTALL_FAILED",message:i.error.trim().slice(0,4096),expectedVersion:o,...r(i.actualVersion)?{actualVersion:r(i.actualVersion)}:{},retryable:!1});const l=r(i.actualVersion),u=wt.safeParse(i.lastAttemptAt),m=wt.safeParse(i.matchedAt);return void 0===i.lastAttemptAt||u.success||t?.({instanceId:n,field:"runtimeVersion.lastAttemptAt"}),void 0===i.matchedAt||m.success||t?.({instanceId:n,field:"runtimeVersion.matchedAt"}),{desiredVersion:o,...l?{actualVersion:l}:{},phase:c,attempt:"number"==typeof i.attempt&&Number.isInteger(i.attempt)&&i.attempt>=0?i.attempt:0,...u.success?{lastAttemptAt:u.data}:{},...m.success?{matchedAt:m.data}:{},...d?{error:d}:{}}}(n.runtimeVersion,t,"string"==typeof n.id?n.id:void 0),r.workspace=ki(Ni,n.workspace,"workspace",t,"string"==typeof n.id?n.id:void 0)||{status:"unknown"},r.environmentSource=ki(Lt,n.environmentSource,"environmentSource",t,"string"==typeof n.id?n.id:void 0),r.environmentTemplateOrigin=ki(Vt,n.environmentTemplateOrigin,"environmentTemplateOrigin",t,"string"==typeof n.id?n.id:void 0),r.runtime=ki(Si.shape.runtime.unwrap(),n.runtime,"runtime",t,"string"==typeof n.id?n.id:void 0)||{labels:{}},r.target=ki(vi,Ri(n.target??n.endpoints,["strategy","web","api","vnc","tty","logs","status"]),"target",t,"string"==typeof n.id?n.id:void 0)||{strategy:"direct-port",status:"unknown"},r.access=ki(Ei,Ri(n.access,["strategy","web","api","ws","status"]),"access",t,"string"==typeof n.id?n.id:void 0)||{strategy:"control-plane-proxy",status:"unknown"};for(const[e,i]of Object.entries(Si.shape))Object.prototype.hasOwnProperty.call(r,e)&&!i.safeParse(r[e]).success&&i.safeParse(void 0).success&&(delete r[e],t?.({instanceId:"string"==typeof n.id?n.id:void 0,field:e}));return r}function ki(e,t,n,i,r){if(!t||"object"!=typeof t||Array.isArray(t))return;let o=structuredClone(t),s=!1;for(let t=0;t<20;t+=1){const t=e.safeParse(o);if(t.success)return s&&i?.({instanceId:r,field:n}),t.data;let a=!1;for(const e of t.error.issues){if("unrecognized_keys"!==e.code)continue;const t=Oi(o,e.path);if(t&&"object"==typeof t&&!Array.isArray(t))for(const n of e.keys)Object.prototype.hasOwnProperty.call(t,n)&&(delete t[n],a=!0,s=!0)}if(!a){const s=structuredClone(o);let a=!1;for(const e of t.error.issues){if(!e.path.length||"string"!=typeof e.path.at(-1))continue;const t=Oi(s,e.path.slice(0,-1)),n=e.path.at(-1);t&&"object"==typeof t&&!Array.isArray(t)&&Object.prototype.hasOwnProperty.call(t,n)&&(delete t[n],a=!0)}if(a){const t=e.safeParse(s);if(t.success)return i?.({instanceId:r,field:n}),t.data}break}}i?.({instanceId:r,field:n})}function Oi(e,t){let n=e;for(const e of t){if(!n||"object"!=typeof n)return;n=n[e]}return n}function Ri(e,t){if(!e||"object"!=typeof e||Array.isArray(e))return e;const n=e;return Object.fromEntries(t.filter(e=>Object.prototype.hasOwnProperty.call(n,e)).map(e=>[e,n[e]]))}const xi=a.z.object({instanceId:bt.optional(),projectId:bt.optional(),source:kn.optional(),nodeId:bt.optional(),runtimeId:bt.optional(),imageSelection:Mt.optional(),instanceVersion:a.z.string().trim().max(80).optional(),protocolVersion:At,build:gn.optional(),controlMode:a.z.enum(["standalone","controlled"]).default("controlled"),capabilities:a.z.record(a.z.string(),a.z.unknown()).default({}),appInventory:Qt.optional(),target:vi.default({strategy:"direct-port",status:"unknown"}),workspace:Ni.default({status:"unknown"}),registrationToken:a.z.string().trim().max(240).optional(),processIncarnationId:a.z.string().trim().min(1).max(120).optional()}).strict().superRefine((e,t)=>{e.protocolVersion!==It||e.appInventory||t.addIssue({code:"custom",path:["appInventory"],message:"Current protocol register payload requires appInventory."})}),Di=a.z.object({status:Si.shape.status.optional(),health:Si.shape.health.optional(),protocolVersion:At,build:gn.optional(),capabilities:Si.shape.capabilities.optional(),appInventory:Qt.optional(),apps:Si.shape.apps.optional(),aiSessions:Si.shape.aiSessions.optional(),triggers:Si.shape.triggers.optional(),workspace:Ni.optional(),target:vi.partial().optional(),processIncarnationId:a.z.string().trim().min(1).max(120).optional()}).strict().superRefine((e,t)=>{e.protocolVersion!==It||e.appInventory||t.addIssue({code:"custom",path:["appInventory"],message:"Current protocol heartbeat payload requires appInventory."})}),Pi=a.z.enum(["web","telegram","wechat","dingding","lark"]);function Mi(e,t){let n=Fi(t);for(let t=0;t<100;t+=1){const t=e.safeParse(n);if(t.success)return t;const i=Li(t.error.issues);let r=!1;for(const e of i){const t=$i(n,e.path);if(t&&"object"==typeof t&&!Array.isArray(t))for(const n of e.keys)Object.prototype.hasOwnProperty.call(t,n)&&(delete t[n],r=!0)}if(!r)return t}return e.safeParse(n)}function Li(e,t=[]){const n=[];for(const i of e){if("unrecognized_keys"===i.code){n.push({code:"unrecognized_keys",keys:i.keys,path:[...t,...i.path]});continue}if("invalid_union"!==i.code||!Array.isArray(i.errors))continue;const e=i.errors.filter(e=>Array.isArray(e));if(!e.length)continue;const r=e.reduce((e,t)=>ji(t)<ji(e)?t:e);n.push(...Li(r,[...t,...i.path]))}return n}function ji(e){return e.reduce((e,t)=>{if("unrecognized_keys"===t.code)return e;if("invalid_union"!==t.code||!Array.isArray(t.errors))return e+1;const n=t.errors.filter(e=>Array.isArray(e));return e+(n.length?Math.min(...n.map(ji)):1)},0)}function $i(e,t){let n=e;for(const e of t){if(!n||"object"!=typeof n)return;n=n[e]}return n}function Fi(e){return Array.isArray(e)?e.map(Fi):e&&"object"==typeof e?Object.getPrototypeOf(e)!==Object.prototype&&null!==Object.getPrototypeOf(e)?e:Object.fromEntries(Object.entries(e).map(([e,t])=>[e,Fi(t)])):e}function Ui(e,t,n={}){return new Promise((i,r)=>{if(n.signal?.aborted)return void r(Object.assign(new Error(`${e} was aborted.`),{code:"RUNTIME_COMMAND_ABORTED"}));const o=l.spawn(e,t,{stdio:["ignore","pipe","pipe"]}),s=[],a=[];let c=!1;const d=n.timeoutMs?setTimeout(()=>{c=!0,o.kill("SIGKILL")},n.timeoutMs):void 0;let u=!1;const m=()=>{u=!0,o.kill("SIGKILL")},p=()=>{d&&clearTimeout(d),n.signal?.removeEventListener("abort",m)};n.signal?.addEventListener("abort",m,{once:!0}),d?.unref?.(),o.stdout.on("data",e=>s.push(Buffer.from(e))),o.stderr.on("data",e=>a.push(Buffer.from(e))),o.on("error",e=>{p(),r(e)}),o.on("close",t=>{p();const o={stdout:Buffer.concat(s).toString("utf8").trim(),stderr:Buffer.concat(a).toString("utf8").trim()};if(c){const t=new Error(`${e} timed out after ${n.timeoutMs}ms`);return Object.assign(t,{statusCode:504,code:"RUNTIME_COMMAND_TIMEOUT",details:o}),void r(t)}if(u)return void r(Object.assign(new Error(`${e} was aborted.`),{code:"RUNTIME_COMMAND_ABORTED",details:o}));if(0===t)return void i(o);const d=new Error(o.stderr||`${e} exited with code ${t}`);Object.assign(d,{statusCode:502,code:"RUNTIME_EXECUTOR_FAILED",details:o}),r(d)})})}a.z.object({id:bt,channel:Pi,name:a.z.string().trim().min(1).max(160),enabled:a.z.boolean().default(!1),token:a.z.string().trim().max(4096).optional(),defaultChatId:a.z.string().trim().max(240).optional(),allowedUserIds:a.z.array(a.z.string().trim().min(1).max(240)).default([]),pollIntervalMs:a.z.number().int().positive().max(6e4).default(3e3),settings:a.z.record(a.z.string(),a.z.unknown()).default({}),createdAt:wt,updatedAt:wt}).strict(),a.z.object({id:bt,channel:Pi,bridgeId:bt.optional(),chatSessionId:a.z.string().trim().min(1).max(240),userId:a.z.string().trim().max(240).optional(),activeProjectId:bt.optional(),activeInstanceId:bt.optional(),activeAiSessionId:a.z.string().trim().min(1).max(120).optional(),lastUsedAt:wt,createdAt:wt,updatedAt:wt}).strict(),a.z.object({source:a.z.object({type:a.z.literal("chat-gateway").default("chat-gateway"),channel:Pi,bridgeId:bt.optional(),chatSessionId:a.z.string().trim().min(1).max(240),userId:a.z.string().trim().max(240).optional()}).strict(),message:a.z.object({text:a.z.string().trim().max(2e4).default(""),attachments:a.z.array(ce).max(6).default([])}).strict().superRefine((e,t)=>{e.attachments.reduce((e,t)=>e+("inline"===t.source.type?t.size:0),0)>G&&t.addIssue({code:a.z.ZodIssueCode.custom,path:["attachments"],message:"Inline attachments must be 41943040 bytes or less in total."})}),target:a.z.object({instanceId:bt,aiSessionId:a.z.string().trim().min(1).max(120)}).strict().optional()}).strict(),a.z.object({id:bt,instanceId:bt,projectId:bt.optional(),aiSessionId:a.z.string().trim().min(1).max(120),providerSessionId:a.z.string().trim().max(240).optional(),result:a.z.string().default(""),timeoutMs:a.z.number().positive().optional(),source:a.z.string().trim().max(120).optional(),kind:a.z.enum(["task","approval"]).default("task"),status:a.z.enum(["pending","unreachable"]).default("pending"),error:a.z.string().trim().max(2048).optional(),lastSeenAt:wt}).strict();const Vi=(e,t,n={})=>new Promise((i,r)=>{if(n.signal?.aborted)return void r(Object.assign(new Error(`${e} was aborted.`),{code:"RUNTIME_COMMAND_ABORTED"}));const o=[];let s,a=!1,c=!1;try{s=u.spawn(e,t,{name:"xterm-256color",cols:n.cols||120,rows:n.rows||40,cwd:process.cwd(),env:process.env})}catch(e){return void r(e)}const d=n.timeoutMs?setTimeout(()=>{a=!0,s.kill("SIGKILL")},n.timeoutMs):void 0,l=()=>{c=!0;try{s.kill("SIGKILL")}catch{}};n.signal?.addEventListener("abort",l,{once:!0}),d?.unref?.(),s.onData(e=>{o.push(e),n.onData?.(e)}),s.onExit(({exitCode:t})=>{d&&clearTimeout(d),n.signal?.removeEventListener("abort",l);const s={stdout:o.join(""),stderr:""};a?r(Object.assign(new Error(`${e} timed out after ${n.timeoutMs}ms`),{statusCode:504,code:"RUNTIME_COMMAND_TIMEOUT",details:s})):c?r(Object.assign(new Error(`${e} was aborted.`),{code:"RUNTIME_COMMAND_ABORTED",details:s})):0!==t?r(Object.assign(new Error(s.stdout.replace(/\u001b\[[0-?]*[ -/]*[@-~]/g,"").split(/\r?\n/).map(e=>e.trim()).filter(Boolean).at(-1)||`${e} exited with code ${t}`),{statusCode:502,code:"RUNTIME_EXECUTOR_FAILED",details:s})):i(s)})});class qi{inFlight=new Map;runCommand;runTerminalCommand;constructor(e=Ui,t){this.runCommand=e,this.runTerminalCommand=t||function(e){return e===Ui?Vi:async(t,n,i={})=>{const r=await e(t,n,{timeoutMs:i.timeoutMs,signal:i.signal});return r.stdout&&i.onData?.(r.stdout),r.stderr&&i.onData?.(r.stderr),r}}(e)}ensure(e,t,n,i){const r=Ot(e),o=this.inFlight.get(r);if(o)return t&&(o.phaseListeners.add(t),o.phase&&t(o.phase)),n&&(o.terminalListeners.add(n),o.terminalTail&&n({sequence:o.terminalSequence,data:o.terminalTail,replay:!0})),this.bindAbort(o,i),o.promise;const s=new Set,a=new Set;t&&s.add(t),n&&a.add(n);const c={promise:Promise.resolve(void 0),controller:new AbortController,abortDisposers:new Set,phaseListeners:s,terminalListeners:a,terminalSequence:0,terminalTail:""};return this.bindAbort(c,i),c.promise=this.ensureOnce(r,e=>{c.phase=e,s.forEach(t=>t(e))},e=>{c.terminalSequence+=1,c.terminalTail=`${c.terminalTail}${e}`.slice(-262144);const t={sequence:c.terminalSequence,data:e};a.forEach(e=>e(t))},c.controller.signal).finally(()=>{this.inFlight.delete(r);for(const e of c.abortDisposers)e();c.abortDisposers.clear()}),this.inFlight.set(r,c),c.promise}bindAbort(e,t){if(!t)return;if(t.aborted)return void e.controller.abort();const n=()=>e.controller.abort();t.addEventListener("abort",n,{once:!0}),e.abortDisposers.add(()=>t.removeEventListener("abort",n))}async ensureOnce(e,t,n,i){t("checking-image");let r=await this.inspect(e,i).catch(e=>{if(i.aborted)throw e}),o=!1;r||(t("pulling-image"),await this.runTerminalCommand("docker",["pull",e],{cols:120,rows:40,signal:i,onData:n}),o=!0,r=await this.inspect(e,i)),t("resolving-image");const s=(a=r,Array.isArray(a.RepoDigests)?a.RepoDigests.filter(e=>"string"==typeof e):[]).find(e=>/@sha256:[a-fA-F0-9]{64}$/.test(e));var a;const c=s?.split("@").at(-1)?.toLowerCase();return{requestedReference:e,...c?{resolvedDigest:c}:{},resolvedReference:s||e,pulled:o}}async inspect(e,t){const n=await this.runCommand("docker",["image","inspect",e,"--format","{{json .}}"],{signal:t});return JSON.parse(n.stdout.trim()||"{}")}}function Hi(e){if(!e)return;const t=/^([0-9]+(?:\.[0-9]+)?)\s*(B|kB|MB|GB|TB)$/i.exec(e.trim());if(!t)return;const n=Number(t[1])*{b:1,kb:1e3,mb:1e6,gb:1e9,tb:1e12}[t[2].toLowerCase()];return Number.isSafeInteger(Math.round(n))?Math.round(n):void 0}const Bi="/run/task-handoff/bootstrap",Ki=`${Bi}/entrypoint.sh`,Gi="/bin/bash",Ji=`${Bi}/runtime-installer.mjs`,Wi="/opt/task-handoff/instance-runtime";function Yi(e,t){return{role:"runtime",name:`${pr(e)}-runtime`,mountPath:Wi,labels:{"task-handoff.owner":"task-handoff","task-handoff.instance-id":e,"task-handoff.node-id":t,"task-handoff.volume-role":"runtime"}}}function Xi(e){return function(e,t,n){const i=pr(e);return[{role:"data",suffix:"data",mountPath:"/data"},{role:"agent-home",suffix:"agent-home",mountPath:"/home/agent"},..."local-folder"===n.type?[]:[{role:"workspace",suffix:"workspace",mountPath:"/workspace"}]].map(({role:n,suffix:r,mountPath:o})=>({role:n,name:`${i}-${r}`,mountPath:o,labels:{"task-handoff.owner":"task-handoff","task-handoff.instance-id":e,"task-handoff.node-id":t,"task-handoff.volume-role":n}}))}(e.instance.id,e.node?.id||"node_unset",e.project.source)}const Qi=new Set(["TASK_HANDOFF_REGISTRATION_TOKEN","OPENAI_API_KEY","OPENAI_BASE_URL","CODEX_MODEL","TASK_HANDOFF_CODEX_BASE_URL","TASK_HANDOFF_CODEX_MODEL","TASK_HANDOFF_CODEX_MODEL_ID","ANTHROPIC_API_KEY","ANTHROPIC_BASE_URL","CLAUDE_MODEL","TASK_HANDOFF_CLAUDE_MODEL","TASK_HANDOFF_CLAUDE_MODEL_ID"]);function Zi(e,t=[]){const n=e&&"object"==typeof e&&!Array.isArray(e)?e:{},i=n.Config&&"object"==typeof n.Config&&!Array.isArray(n.Config)?n.Config:n,r=new Set;for(const e of Array.isArray(i.Env)?i.Env:[]){if("string"!=typeof e)continue;const n=e.indexOf("="),i=-1===n?e:e.slice(0,n),o=-1===n?"":e.slice(n+1);Qi.has(i)&&r.add(`Config.Env.${i}`),t.some(e=>e&&o.includes(e))&&r.add(`Config.Env.${i||"unknown"}`)}if(i.Labels&&"object"==typeof i.Labels&&!Array.isArray(i.Labels))for(const[e,n]of Object.entries(i.Labels))(Qi.has(e)||"string"==typeof n&&t.some(e=>e&&n.includes(e)))&&r.add(`Config.Labels.${e}`);if(r.size)throw Object.assign(new Error(`Docker configuration contains instance-private values in ${[...r].sort().join(", ")}.`),{statusCode:409,code:"ENVIRONMENT_TEMPLATE_SECRET_IN_DOCKER_CONFIG",findings:[...r].sort()})}class er{runCommand;publishHost;images;launcherAssetsDir;portResolutionRetryDelaysMs;constructor(e=Ui,t={}){this.runCommand=e,this.images=t.imageService||new qi(e),this.publishHost=t.publishHost||"127.0.0.1",this.launcherAssetsDir=t.launcherAssetsDir||sr(),this.portResolutionRetryDelaysMs=t.portResolutionRetryDelaysMs?.length?t.portResolutionRetryDelaysMs:[0,100,250,500,1e3]}async start(e){fr(e);const t=e.instance.runtime.containerName||pr(e.instance.id),i=await this.inspectContainerForStart(t);if(i){ur(t,i.id,e.instance.runtime.containerId,"before start","RUNTIME_EXECUTOR_FAILED");const r=i.labels["task-handoff.instance-id"];if(r!==e.instance.id)throw cr("RUNTIME_EXECUTOR_FAILED",`Docker container ${t} belongs to ${r||"an unknown instance"}, not ${e.instance.id}.`);const o=i.mounts.find(e=>"bind"===e.type&&e.destination===Bi);if("1"!==i.labels["task-handoff.bootstrap-abi"]||i.entrypoint[0]!==Gi||i.command[0]!==Ki||!o?.source||n.resolve(o.source)!==n.resolve(this.launcherAssetsDir)){const n=new Set(Xi(e).flatMap(e=>i.mounts.some(t=>"volume"===t.type&&t.name===e.name&&t.destination===e.mountPath)?[e.name]:[]));return await this.createPersistentVolumes(e,n),this.recreateWithAuthoritativeBootstrap(e,t,i)}await this.createRuntimeVolume(e),await this.validatePersistentVolumes(e,i.mounts);try{await this.runCommand("docker",["start",t])}catch(e){throw cr("RUNTIME_EXECUTOR_FAILED",`Could not start Docker container ${t}.`,e)}return this.resumedContainerResult(e,t,i.id)}if(e.instance.environmentTemplateOrigin){const t=await this.inspectEnvironmentTemplateImage(e.instance.environmentTemplateOrigin.imageId);if(t.imageId!==e.instance.environmentTemplateOrigin.imageId||t.platform!==e.instance.environmentTemplateOrigin.platform||t.architecture!==e.instance.environmentTemplateOrigin.architecture)throw Object.assign(new Error(`Environment template image identity or platform changed for instance ${e.instance.id}.`),{statusCode:409,code:"ENVIRONMENT_TEMPLATE_IMAGE_IDENTITY_MISMATCH"})}else await this.images.ensure(e.image.resolvedReference||e.image.requestedReference);let r;await this.createPersistentVolumes(e);try{r=await this.runCommand("docker",gr(e,t,{publishHost:this.publishHost,launcherAssetsDir:this.launcherAssetsDir}))}catch(e){throw cr("RUNTIME_EXECUTOR_FAILED",`Could not create Docker container ${t}.`,e)}return this.bootstrapResult(e,t,r.stdout||void 0)}async recreateWithAuthoritativeBootstrap(e,t,n){const i=`${t}-pre-bootstrap-${n.id.slice(0,12)}`;n.running&&await this.runCommand("docker",["stop",t]);try{await this.runCommand("docker",["rename",t,i])}catch(e){throw n.running&&await this.runCommand("docker",["start",t]).catch(()=>({stdout:"",stderr:""})),cr("RUNTIME_EXECUTOR_FAILED",`Could not preserve Docker container ${t} before bootstrap migration.`,e)}try{const r=await this.runCommand("docker",gr(e,t,{publishHost:this.publishHost,launcherAssetsDir:this.launcherAssetsDir,imageReference:n.image}));return this.bootstrapResult(e,t,r.stdout||void 0,i)}catch(e){throw await this.runCommand("docker",["rm","-f",t]).catch(()=>({stdout:"",stderr:""})),await this.runCommand("docker",["rename",i,t]).catch(()=>({stdout:"",stderr:""})),n.running&&await this.runCommand("docker",["start",t]).catch(()=>({stdout:"",stderr:""})),cr("RUNTIME_EXECUTOR_FAILED",`Could not recreate Docker container ${t} with the node-agent bootstrap.`,e)}}async inspectContainerConfigSecurity(e,t){Zi(await this.runCommand("docker",["inspect","--format","{{json .}}",e]).then(e=>JSON.parse(e.stdout||"{}")).catch(t=>{throw cr("ENVIRONMENT_TEMPLATE_CONTAINER_INSPECT_FAILED",`Could not inspect Docker container ${e}.`,t)}),t)}async inspectImageConfigSecurity(e,t){Zi(await this.runCommand("docker",["image","inspect","--format","{{json .}}",e]).then(e=>JSON.parse(e.stdout||"{}")).catch(e=>{throw cr("ENVIRONMENT_TEMPLATE_IMAGE_INSPECT_FAILED","Could not inspect Docker image configuration.",e)}),t)}async commitEnvironmentTemplate(e,t,n){const i=await this.inspectContainerId(e);if(!i)throw cr("ENVIRONMENT_TEMPLATE_CONTAINER_NOT_FOUND",`Docker container ${e} does not exist.`);ur(e,i,t,"before environment template commit","ENVIRONMENT_TEMPLATE_CONTAINER_IDENTITY_MISMATCH");try{const t=(await this.runCommand("docker",["commit",e,n])).stdout.trim();if(!t)throw new Error("Docker commit did not return an image id.");return t}catch(t){throw cr("ENVIRONMENT_TEMPLATE_COMMIT_FAILED",`Could not save Docker container ${e} as an environment template.`,t)}}async inspectEnvironmentTemplateImage(e){try{const t=await this.runCommand("docker",["image","inspect","--format","{{json .}}",e]),n=JSON.parse(t.stdout||"{}"),i="string"==typeof n.Id?n.Id:"",r=rr(n.Os),o=or(n.Architecture),s="number"==typeof n.Size?n.Size:Number.NaN;if(!/^sha256:[a-f0-9]{64}$/.test(i)||!r||!o||!Number.isSafeInteger(s)||s<0)throw new Error("Docker image inspection did not return a valid immutable identity.");return{imageId:i,platform:r,architecture:o,sizeBytes:s}}catch(e){throw cr("ENVIRONMENT_TEMPLATE_IMAGE_INSPECT_FAILED","Could not inspect the committed environment template image.",e)}}async untagEnvironmentTemplate(e,t){try{const n=t||(await this.inspectEnvironmentTemplateImage(e)).imageId;return await this.runCommand("docker",["tag",n,ar(n)]),await this.runCommand("docker",["image","rm",e]),n}catch(e){const t=dr(e)?.toLowerCase()||"";if(t.includes("no such image")||t.includes("no such object"))return;throw cr("ENVIRONMENT_TEMPLATE_UNTAG_FAILED","Could not remove the environment template tag.",e)}}async garbageCollectEnvironmentTemplateImage(e){try{try{await this.runCommand("docker",["image","rm",ar(e)])}catch(e){const t=dr(e)?.toLowerCase()||"";if(t.includes("being used by")||t.includes("is referenced")||t.includes("conflict"))return!1;if(!t.includes("no such image")&&!t.includes("no such object"))throw e}return await this.runCommand("docker",["image","rm",e]),!0}catch(e){const t=dr(e)?.toLowerCase()||"";if(t.includes("being used by")||t.includes("is referenced")||t.includes("conflict"))return!1;if(t.includes("no such image")||t.includes("no such object"))return!0;throw cr("ENVIRONMENT_TEMPLATE_GC_FAILED","Could not garbage collect the environment template image.",e)}}async createPersistentVolumes(e,t=new Set){const n=Yi(e.instance.id,e.node?.id||"node_unset");for(const i of[...Xi(e),n])await this.createVolume(i),await this.validateOwnedVolume(e.instance.id,i,t.has(i.name))}async createRuntimeVolume(e){await this.createVolume(Yi(e.instance.id,e.node?.id||"node_unset"))}async createVolume(e){const t=["volume","create"];for(const[n,i]of Object.entries(e.labels).sort(([e],[t])=>e.localeCompare(t)))t.push("--label",`${n}=${i}`);t.push(e.name);try{await this.runCommand("docker",t)}catch(t){throw cr("INSTANCE_VOLUME_CREATE_FAILED",`Could not create managed volume ${e.name}.`,t)}}async validatePersistentVolumes(e,t){for(const n of Xi(e)){await this.validateOwnedVolume(e.instance.id,n);const i=t.find(e=>"volume"===e.type&&e.destination===n.mountPath);if(!i||i.name!==n.name)throw Object.assign(new Error(`Docker container mount for ${n.role} does not match managed volume ${n.name}.`),{statusCode:409,code:"INSTANCE_VOLUME_MOUNT_IDENTITY_MISMATCH"})}const i=Yi(e.instance.id,e.node?.id||"node_unset");await this.validateOwnedVolume(e.instance.id,i);const r=t.find(e=>"volume"===e.type&&e.destination===i.mountPath);if(!r||r.name!==i.name)throw Object.assign(new Error(`Docker container runtime mount does not match ${i.name}.`),{statusCode:409,code:"INSTANCE_VOLUME_MOUNT_IDENTITY_MISMATCH"});if("local-folder"===e.project.source.type){const i=t.find(t=>t.destination===(e.project.workspacePolicy.path||"/workspace"));if(!i||"bind"!==i.type||n.resolve(i.source||"")!==n.resolve(e.project.source.path))throw Object.assign(new Error(`Docker container workspace bind does not match local folder ${e.project.source.path}.`),{statusCode:409,code:"INSTANCE_WORKSPACE_MOUNT_IDENTITY_MISMATCH"})}}async validateOwnedVolume(e,t,n=!1){let i;try{i=await this.runCommand("docker",["volume","inspect","--format","{{json .}}",t.name])}catch(e){throw cr("INSTANCE_VOLUME_INSPECT_FAILED",`Could not inspect managed volume ${t.name}.`,e)}try{const r=JSON.parse(i.stdout||"{}"),o=r.Labels&&"object"==typeof r.Labels&&!Array.isArray(r.Labels)?r.Labels:{},s=r.Name===t.name&&"task-handoff"===o["task-handoff.owner"]&&o["task-handoff.instance-id"]===e&&o["task-handoff.volume-role"]===t.role,a=n&&r.Name===t.name&&0===Object.keys(o).length;if(!s&&!a)throw new Error("volume name or ownership labels do not match")}catch(n){throw Object.assign(new Error(`Managed volume ${t.name} identity does not match instance ${e}.`,{cause:n}),{statusCode:409,code:"INSTANCE_VOLUME_IDENTITY_MISMATCH"})}}async runningResult(e,t,n){const i=await this.publishedEndpoint(t),r=e.node?.id||"node_unset",o=e.runtime?.id||"runtime_local_docker";return{status:"registering",health:"unknown",connectionStatus:"online",agentStatus:"unknown",targetStatus:"unknown",uiAccessStatus:"unknown",target:{strategy:"direct-port",status:"reachable",...i},workspace:{mode:e.project.workspacePolicy.mode,status:"pending",path:e.project.workspacePolicy.path},runtime:{...e.instance.runtime,kind:"docker",containerName:t,...n?{containerId:n}:{},labels:{...e.instance.runtime.labels,"task-handoff.instance-id":e.instance.id,"task-handoff.project-id":e.project.id,"task-handoff.node-id":r,"task-handoff.runtime-id":o,"task-handoff.image-id":e.image.id}}}}async resumedContainerResult(e,t,n){const i=this.bootstrapResult(e,t,n);return{...i,target:{...i.target,...await this.publishedEndpoint(t)}}}async publishedEndpoint(e){const t=`http://127.0.0.1:${await this.containerPort(e,"8080/tcp")}`;return{web:t,api:`${t}/api`}}bootstrapResult(e,t,n,i){return{status:"starting",health:"unknown",connectionStatus:"unknown",agentStatus:"unknown",targetStatus:"unknown",uiAccessStatus:"unknown",target:{strategy:"direct-port",status:"unknown"},workspace:{mode:e.project.workspacePolicy.mode,status:"pending",path:e.project.workspacePolicy.path},runtime:{...e.instance.runtime,kind:"docker",containerName:t,...n?{containerId:n}:{},labels:{...e.instance.runtime.labels,"task-handoff.bootstrap-abi":"1",...i?{"task-handoff.bootstrap-backup":i}:{}}}}}async stop(e){const t=e.instance.runtime.containerName||pr(e.instance.id);try{await this.runCommand("docker",["stop",t])}catch(e){if(!lr(e))throw cr("RUNTIME_EXECUTOR_FAILED",`Could not stop Docker container ${t}.`,e)}return{status:"stopped",health:"unknown",connectionStatus:"offline",target:{...e.instance.target,status:"unknown"},runtime:e.instance.runtime}}async restart(e,t){fr(e);const n=e.instance.runtime.containerName||pr(e.instance.id),i=await this.inspectContainerId(n);if(!i)throw cr("INSTANCE_RUNTIME_RESTART_FAILED",`Docker container ${n} does not exist.`);ur(n,i,t,"before restart","INSTANCE_RUNTIME_RESTART_FAILED"),await this.runCommand("docker",["restart",n]);const r=await this.inspectContainerId(n);if(!r||r!==i)throw cr("INSTANCE_RUNTIME_RESTART_FAILED",`Docker container identity changed while restarting ${n}.`);return ur(n,r,t,"after restart","INSTANCE_RUNTIME_RESTART_FAILED"),this.runningResult(e,n,r)}async delete(e,t){const n=e.instance.runtime.containerName||pr(e.instance.id),i=await this.inspectContainerForStart(n),r=new Set;if(i){ur(n,i.id,e.instance.runtime.containerId,"before delete","RUNTIME_EXECUTOR_FAILED");const t=i.labels["task-handoff.instance-id"];if(t!==e.instance.id)throw cr("RUNTIME_EXECUTOR_FAILED",`Docker container ${n} belongs to ${t||"an unknown instance"}, not ${e.instance.id}.`);for(const t of Xi(e))i.mounts.some(e=>"volume"===e.type&&e.name===t.name&&e.destination===t.mountPath)&&r.add(t.name);try{await this.runCommand("docker",["rm","-f",i.id])}catch(e){if(!lr(e))throw cr("RUNTIME_EXECUTOR_FAILED",`Could not delete Docker container ${n}.`,e)}}const o=[];for(const n of Xi(e))if(t.deleteVolumes)try{const t=await this.inspectVolumeForDelete(n.name);if(!t){o.push({role:n.role,name:n.name,mountPath:n.mountPath,status:"missing"});continue}const i=t.name===n.name&&"task-handoff"===t.labels["task-handoff.owner"]&&t.labels["task-handoff.instance-id"]===e.instance.id&&t.labels["task-handoff.volume-role"]===n.role,s=r.has(n.name)&&t.name===n.name&&0===Object.keys(t.labels).length;if(!i&&!s)throw Object.assign(new Error(`Managed volume ${n.name} ownership does not match instance ${e.instance.id}.`),{code:"INSTANCE_VOLUME_IDENTITY_MISMATCH"});await this.runCommand("docker",["volume","rm",n.name]),o.push({role:n.role,name:n.name,mountPath:n.mountPath,status:"deleted"})}catch(e){o.push({role:n.role,name:n.name,mountPath:n.mountPath,status:"failed",error:{code:"object"==typeof e&&e&&"code"in e&&"string"==typeof e.code?e.code:"INSTANCE_VOLUME_DELETE_FAILED",message:e instanceof Error?e.message:String(e)}})}else o.push({role:n.role,name:n.name,mountPath:n.mountPath,status:"retained"});return await this.deleteRuntimeVolume(e),Kt.parse({instanceId:e.instance.id,containerDeleted:!0,completed:o.every(e=>"failed"!==e.status),deletedVolumes:o.filter(e=>"deleted"===e.status||"missing"===e.status),retainedVolumes:o.filter(e=>"retained"===e.status),volumeResults:o})}async deleteRuntimeVolume(e){const t=Yi(e.instance.id,e.node?.id||"node_unset"),n=await this.inspectVolumeForDelete(t.name);if(n){if(n.name!==t.name||"task-handoff"!==n.labels["task-handoff.owner"]||n.labels["task-handoff.instance-id"]!==e.instance.id||"runtime"!==n.labels["task-handoff.volume-role"])throw cr("INSTANCE_VOLUME_IDENTITY_MISMATCH",`Runtime volume ${t.name} ownership does not match instance ${e.instance.id}.`);try{await this.runCommand("docker",["volume","rm",t.name])}catch(e){throw cr("INSTANCE_VOLUME_DELETE_FAILED",`Could not delete runtime volume ${t.name}.`,e)}}}async inspectVolumeForDelete(e){try{const t=await this.runCommand("docker",["volume","inspect","--format","{{json .}}",e]),n=JSON.parse(t.stdout||"{}");return{name:"string"==typeof n.Name?n.Name:"",labels:n.Labels&&"object"==typeof n.Labels&&!Array.isArray(n.Labels)?Object.fromEntries(Object.entries(n.Labels).filter(e=>"string"==typeof e[1])):{}}}catch(t){if(function(e){const t=dr(e)?.toLowerCase()||"";return t.includes("no such volume")||t.includes("no such object")}(t))return;throw cr("INSTANCE_VOLUME_INSPECT_FAILED",`Could not inspect managed volume ${e}.`,t)}}async installRuntime(e){const t=await this.installRuntimeRelease(e);ur(e.containerName,t,e.expectedContainerId,"before runtime restart","INSTANCE_RUNTIME_RESTART_FAILED");try{await this.runCommand("docker",["restart",t])}catch(t){throw cr("INSTANCE_RUNTIME_RESTART_FAILED",`Could not restart Docker container ${e.containerName}.`,t)}const n=await this.inspectContainerId(e.containerName);if(!n||n!==t)throw cr("INSTANCE_RUNTIME_RESTART_FAILED",`Docker container identity changed while updating ${e.containerName}.`);return ur(e.containerName,n,e.expectedContainerId,"after runtime restart","INSTANCE_RUNTIME_RESTART_FAILED"),this.inspectRuntimeVersion(e.containerName)}async installRuntimeRelease(e){const t=await this.inspectContainerId(e.containerName);if(!t)throw cr("INSTANCE_RUNTIME_INSTALL_FAILED",`Docker container ${e.containerName} does not exist.`);ur(e.containerName,t,e.expectedContainerId,"before runtime install","INSTANCE_RUNTIME_INSTALL_FAILED");const n=`/opt/task-handoff/instance-runtime/incoming/task-handoff-runtime-${i=e.identity.version,i.replace(/[^0-9A-Za-z.+_-]/g,"-")}-${e.identity.sha256.slice(0,12)}.tar.gz`;var i;await this.runCommand("docker",["exec","--user","0",t,"install","-d","-o","root","-g","root","-m","0755","/opt/task-handoff/instance-runtime/incoming"]),await this.runCommand("docker",["cp",e.artifactPath,`${t}:${n}`]);try{await this.runCommand("docker",["exec","--user","0",t,"node",Ji,"install","--artifact",n,"--version",e.identity.version,"--sha256",e.identity.sha256,"--platform",e.identity.platform,"--arch",e.identity.arch,"--launcher-abi",String(e.identity.launcherAbi)])}catch(t){throw cr("INSTANCE_RUNTIME_INSTALL_FAILED",`Could not install controlled-instance ${e.identity.version} in ${e.containerName}.`,t)}finally{await this.runCommand("docker",["exec","--user","0",t,"rm","-f",n]).catch(()=>({stdout:"",stderr:""}))}const r=await this.inspectContainerId(e.containerName);if(!r||r!==t)throw cr("INSTANCE_RUNTIME_INSTALL_FAILED",`Docker container identity changed while installing ${e.containerName}.`);return ur(e.containerName,r,e.expectedContainerId,"after runtime install","INSTANCE_RUNTIME_INSTALL_FAILED"),t}async inspectRuntimeVersion(e){const t=await this.inspectContainerId(e);if(!t)return{};const n=await this.runCommand("docker",["exec","--user","agent",e,"node",Ji,"verify-active"]).catch(()=>{});if(!n?.stdout)return{containerId:t};try{const e=Mi(yn,JSON.parse(n.stdout));return e.success?{containerId:t,...e.data}:{containerId:t}}catch{return{containerId:t}}}async removeBootstrapBackup(e,t){const n=await this.inspectContainerForStart(e);if(n){if(n.labels["task-handoff.instance-id"]!==t)throw cr("RUNTIME_EXECUTOR_FAILED",`Docker bootstrap backup ${e} does not belong to ${t}.`);await this.runCommand("docker",["rm","-f",e])}}async inspectRuntimeTarget(e){let t,n;if(e){const i=await this.runCommand("docker",["inspect","--format","{{json .}}",e]).then(e=>JSON.parse(e.stdout.trim()||"{}")).catch(()=>{});if(t=i?.Platform,"string"==typeof i?.Image&&i.Image){const e=await this.runCommand("docker",["image","inspect","--format","{{json .}}",i.Image]).then(e=>JSON.parse(e.stdout.trim()||"{}")).catch(()=>{});t=e?.Os||t,n=e?.Architecture}}if(!t||!n){const e=await this.runCommand("docker",["info","--format","{{json .}}"]).then(e=>JSON.parse(e.stdout.trim()||"{}")).catch(e=>{throw cr("INSTANCE_BASE_RUNTIME_INCOMPATIBLE","Could not inspect the Docker runtime target.",e)});t||=e.OSType,n||=e.Architecture}const i=rr(t),r=or(n);if(!i||!r)throw cr("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Docker reported an unsupported runtime target ${String(t||"unknown")}/${String(n||"unknown")}.`);return{platform:i,arch:r,launcherAbi:1}}async installRuntimeReleaseWithRecovery(e){const t=e.containerName,i=await this.inspectContainerForStart(t);if(!i)throw cr("INSTANCE_RUNTIME_INSTALL_FAILED",`Docker container ${t} does not exist.`);if(ur(t,i.id,e.expectedContainerId,"before runtime install recovery","INSTANCE_RUNTIME_INSTALL_FAILED"),i.running)return await this.installRuntimeLauncher(t,i.id),void await this.installRuntimeRelease({...e,expectedContainerId:i.id});if(!i.image)throw cr("INSTANCE_RUNTIME_INSTALL_FAILED",`Docker container ${t} does not expose its immutable image identity.`);const r="/run/task-handoff/runtime-rescue-artifact.tar.gz",o=[`test -r ${Ki}`,`test -r ${Bi}/instance-launcher.sh`,`test -r ${Ji}`,`install -d -o root -g root -m 0755 ${Wi} ${Wi}/releases ${Wi}/staging ${Wi}/incoming`,`chown -R root:root ${Wi}`,`chmod -R go-w ${Wi}`,`node ${Ji} install --artifact "$1" --version "$2" --sha256 "$3" --platform "$4" --arch "$5" --launcher-abi "$6"`].join("; ");try{await this.runCommand("docker",["run","--rm","--user","0:0","--volumes-from",i.id,"--mount",`type=bind,source=${n.resolve(e.artifactPath)},target=${r},readonly`,"--entrypoint",Gi,i.image,"-ceu",o,"task-handoff-runtime-rescue",r,e.identity.version,e.identity.sha256,e.identity.platform,e.identity.arch,String(e.identity.launcherAbi)])}catch(n){throw cr("INSTANCE_RUNTIME_INSTALL_FAILED",`Could not rescue controlled-instance ${e.identity.version} in stopped container ${t}.`,n)}const s=await this.inspectContainerForStart(t);if(!s)throw cr("INSTANCE_RUNTIME_INSTALL_FAILED",`Docker container ${t} disappeared during runtime install recovery.`);if(ur(t,s.id,i.id,"after runtime install recovery","INSTANCE_RUNTIME_INSTALL_FAILED"),s.running)throw cr("INSTANCE_RUNTIME_INSTALL_FAILED",`Stopped Docker container ${t} changed lifecycle state during runtime install recovery.`)}async installRuntimeLauncher(e,t){const n=await this.inspectContainerId(e);if(!n)throw cr("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Docker container ${e} does not exist.`);ur(e,n,t,"before runtime launcher install","INSTANCE_BASE_RUNTIME_INCOMPATIBLE");try{await this.runCommand("docker",["exec","--user","0",n,"bash","-ceu",`test -r ${Ki}; test -r ${Bi}/instance-launcher.sh; test -r ${Ji}; install -d -o root -g root -m 0755 /opt/task-handoff/instance-runtime /opt/task-handoff/instance-runtime/releases /opt/task-handoff/instance-runtime/staging /opt/task-handoff/instance-runtime/incoming; chown -R root:root /opt/task-handoff/instance-runtime; chmod -R go-w /opt/task-handoff/instance-runtime`])}catch(t){throw cr("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Could not install the runtime launcher in ${e}.`,t)}const i=await this.inspectContainerId(e);if(i!==n)throw cr("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Docker container identity changed while installing the runtime launcher in ${e}.`);ur(e,i,t,"after runtime launcher install","INSTANCE_BASE_RUNTIME_INCOMPATIBLE")}async inspectContainerId(e){try{return(await this.runCommand("docker",["inspect","--format","{{.Id}}",e])).stdout.trim()||void 0}catch(t){if(lr(t))return;throw cr("RUNTIME_EXECUTOR_FAILED",`Could not inspect Docker container ${e}.`,t)}}async inspectContainerForStart(e){let t;try{t=await this.runCommand("docker",["inspect","--format","{{json .}}",e])}catch(t){if(lr(t))return;throw cr("RUNTIME_EXECUTOR_FAILED",`Could not inspect Docker container ${e}.`,t)}try{const e=JSON.parse(t.stdout||"{}");if("string"!=typeof e.Id||!e.Id)throw new Error("Docker inspect did not return a container id.");const n=e.Config?.Labels&&"object"==typeof e.Config.Labels&&!Array.isArray(e.Config.Labels)?Object.fromEntries(Object.entries(e.Config.Labels).filter(e=>"string"==typeof e[1])):{},i=Array.isArray(e.Mounts)?e.Mounts.flatMap(e=>{if(!e||"object"!=typeof e||Array.isArray(e))return[];const t=e,n="volume"===t.Type||"bind"===t.Type?t.Type:void 0,i="string"==typeof t.Destination?t.Destination:void 0;return n&&i?[{type:n,destination:i,name:"string"==typeof t.Name?t.Name:void 0,source:"string"==typeof t.Source?t.Source:void 0}]:[]}):[],r=Array.isArray(e.Config?.Entrypoint)?e.Config.Entrypoint.filter(e=>"string"==typeof e):"string"==typeof e.Config?.Entrypoint?[e.Config.Entrypoint]:[],o=Array.isArray(e.Config?.Cmd)?e.Config.Cmd.filter(e=>"string"==typeof e):"string"==typeof e.Config?.Cmd?[e.Config.Cmd]:[];return{id:e.Id,image:"string"==typeof e.Image?e.Image:void 0,running:!0===e.State?.Running,entrypoint:r,command:o,labels:n,mounts:i}}catch(t){throw cr("RUNTIME_EXECUTOR_FAILED",`Docker returned invalid inspection data for ${e}.`,t)}}async containerPort(e,t){let n,i=!1;for(const r of this.portResolutionRetryDelaysMs){r>0&&await ir(r);try{const n=tr((await this.runCommand("docker",["port",e,t])).stdout);if(n)return n}catch(e){n=e}try{const n=nr((await this.runCommand("docker",["inspect","--format","{{json .NetworkSettings.Ports}}",e])).stdout,t);if(i=!0,n)return n}catch(e){n=e}}if(i)throw cr("RUNTIME_EXECUTOR_FAILED",`Docker container ${e} does not publish ${t}.`);throw cr("RUNTIME_EXECUTOR_FAILED",`Could not resolve the published port for Docker container ${e}.`,n)}}function tr(e){const t=e.split(/\r?\n/).find(Boolean);return t?.match(/:(\d+)$/)?.[1]}function nr(e,t){const n=JSON.parse(e||"null");if(!n||"object"!=typeof n||Array.isArray(n))return;const i=n[t];if(Array.isArray(i))for(const e of i){if(!e||"object"!=typeof e||Array.isArray(e))continue;const t=e.HostPort;if("string"==typeof t&&/^\d+$/.test(t))return t}}function ir(e){return new Promise(t=>setTimeout(t,e))}function rr(e){return"linux"===e||"darwin"===e?e:"windows"===e||"win32"===e?"win32":void 0}function or(e){return"amd64"===e||"x86_64"===e||"x64"===e?"x64":"arm64"===e||"aarch64"===e?"arm64":void 0}function sr(){const e=("undefined"==typeof document?require("url").pathToFileURL(__filename).href:b&&"SCRIPT"===b.tagName.toUpperCase()&&b.src||new URL("cli.js",document.baseURI).href)?n.dirname(r.fileURLToPath("undefined"==typeof document?require("url").pathToFileURL(__filename).href:b&&"SCRIPT"===b.tagName.toUpperCase()&&b.src||new URL("cli.js",document.baseURI).href)):__dirname,i=[n.resolve(e,"../../../../../docker"),n.resolve(e,"../docker"),n.resolve(e,"../../docker")];return i.find(e=>t.existsSync(n.join(e,"runtime-installer.mjs")))||i[0]}function ar(e){return`task-handoff/environment-image:${e.replace(/^sha256:/,"")}`}function cr(e,t,n){const i=dr(n),r=new Error(i?`${t} Cause: ${i}`:t,void 0===n?void 0:{cause:n});return Object.assign(r,{statusCode:502,code:e}),r}function dr(e){if(!e||"object"!=typeof e)return void 0===e?void 0:String(e);const t=e,n=t.details?.stderr||t.details?.stdout;return"string"==typeof n&&n.trim()?n.trim():"string"==typeof t.message&&t.message.trim()?t.message.trim():void 0}function lr(e){const t=dr(e)?.toLowerCase()||"";return t.includes("no such container")||t.includes("no such object")}function ur(e,t,n,i,r){if(n&&t!==n)throw cr(r,`Docker container ${e} identity mismatch ${i}: expected ${n}, got ${t}.`)}async function mr(e=Ui){return async function(e=Ui){return(await e("docker",["images","--digests","--format","{{json .}}"])).stdout.split(/\r?\n/).map(e=>e.trim()).filter(Boolean).map(e=>{const t=JSON.parse(e),n=t.Repository||"<none>",i=t.Tag||"<none>",r=t.ID||t.IDShort||"",o="<none>"!==n&&"<none>"!==i?`${n}:${i}`:r,s="<none>"!==n&&t.Digest&&"<none>"!==t.Digest?[`${n}@${t.Digest}`]:[];return{repository:n,tag:i,id:r,createdSince:t.CreatedSince,size:t.Size,sizeBytes:Hi(t.Size),reference:o,repoDigests:s}}).filter(e=>Boolean(e.reference))}(e)}function pr(e){return`task-handoff-${e.replace(/[^a-zA-Z0-9_.-]/g,"-")}`}function hr(e,t,n){e.push("-e",`${t}=${n}`)}function gr(e,t,i={}){const r=i.publishHost||"127.0.0.1",o=n.resolve(i.launcherAssetsDir||sr()),s=e.node?.id||"node_unset",a=e.runtime?.id||"runtime_local_docker",c=["run","-d","--name",t,"--user","0:0","--label",`task-handoff.instance-id=${e.instance.id}`,"--label",`task-handoff.project-id=${e.project.id}`,"--label",`task-handoff.node-id=${s}`,"--label",`task-handoff.runtime-id=${a}`,"--label",`task-handoff.image-id=${e.image.id}`,"--label","task-handoff.bootstrap-abi=1","--shm-size","1gb","--security-opt","seccomp=unconfined","--network","bridge","--no-healthcheck","--add-host","host.docker.internal:host-gateway","--tmpfs","/tmp:rw,mode=1777","-p",`${r}::8080`];if(!e.privateConfigPath)throw Object.assign(new Error(`Instance ${e.instance.id} private config was not materialized.`),{statusCode:409,code:"INSTANCE_PRIVATE_CONFIG_MISSING"});c.push("--mount",`type=bind,src=${e.privateConfigPath},dst=/run/task-handoff/instance-private-config.json,readonly`,"--mount",`type=bind,src=${o},dst=${Bi},readonly`,"--entrypoint",Gi);for(const t of Xi(e))c.push("--mount",`type=volume,src=${t.name},dst=${t.mountPath}`);const d=Yi(e.instance.id,e.node?.id||"node_unset");c.push("--mount",`type=volume,src=${d.name},dst=${d.mountPath}`);const l={TASK_HANDOFF_CONTROL_MODE:"controlled",TASK_HANDOFF_NODE_AGENT_URL:e.nodeAgentUrl||e.node?.endpoint||"",TASK_HANDOFF_INSTANCE_ID:e.instance.id,TASK_HANDOFF_INSTANCE_NAME:e.instance.name,TASK_HANDOFF_PROJECT_ID:e.project.id,TASK_HANDOFF_NODE_ID:s,TASK_HANDOFF_RUNTIME_ID:a,TASK_HANDOFF_IMAGE_ID:e.image.id,TASK_HANDOFF_INSTANCE_LAUNCHER:`${Bi}/instance-launcher.sh`,...e.image.tag?{TASK_HANDOFF_IMAGE_TAG:e.image.tag}:{},TASK_HANDOFF_CHAT_BRIDGES:"none",TASK_HANDOFF_WORKSPACE:e.project.workspacePolicy.path||"/workspace",TASK_HANDOFF_WORKSPACE_MODE:e.project.workspacePolicy.mode};for(const[e,t]of Object.entries(l))hr(c,e,t);"local-folder"===e.project.source.type?c.push("-v",`${e.project.source.path}:${e.project.workspacePolicy.path||"/workspace"}:${e.project.workspacePolicy.readOnly?"ro":"rw"}`):(hr(c,"TASK_HANDOFF_PROJECT_SOURCE",JSON.stringify(e.project.source)),hr(c,"TASK_HANDOFF_WORKSPACE_POLICY",JSON.stringify(e.project.workspacePolicy)),hr(c,"TASK_HANDOFF_GIT_URL",e.project.source.url),e.project.source.ref?.commit?hr(c,"TASK_HANDOFF_GIT_COMMIT",e.project.source.ref.commit):e.project.source.ref?.name&&hr(c,"TASK_HANDOFF_GIT_REF",e.project.source.ref.name),e.project.source.clone?.depth&&hr(c,"TASK_HANDOFF_GIT_DEPTH",String(e.project.source.clone.depth)),hr(c,"TASK_HANDOFF_GIT_SUBMODULES",e.project.source.clone?.submodules?"true":"false"),hr(c,"TASK_HANDOFF_GIT_LFS",e.project.source.clone?.lfs?"true":"false"),e.project.source.clone?.subdirectory&&hr(c,"TASK_HANDOFF_WORKSPACE_SUBDIRECTORY",e.project.source.clone.subdirectory));for(const[t,n]of Object.entries(e.image.defaultEnv))hr(c,t,n);return c.push(i.imageReference||e.instance.environmentTemplateOrigin?.imageId||e.image.resolvedReference||e.image.requestedReference,Ki,"task-handoff","web"),c}function fr(e){if("local-folder"===e.project.source.type&&e.project.source.ownerNodeId&&e.project.source.ownerNodeId!==e.node.id){const e=new Error("Local folder projects can only start on the node that owns the folder.");throw Object.assign(e,{statusCode:400,code:"LOCAL_FOLDER_REQUIRES_OWNER_NODE"}),e}if(!e.image.requestedReference?.trim()){const e=new Error("Image profile must reference a registered image.");throw Object.assign(e,{statusCode:400,code:"IMAGE_PROFILE_INVALID"}),e}}a.z.object({type:a.z.literal("snapshot"),data:a.z.string(),pendingEscape:a.z.string(),cols:a.z.number().int().positive(),rows:a.z.number().int().positive()}).passthrough();const yr=a.z.enum(["created","starting","running","stopping","stopped","exited","failed","closed","terminated","unknown"]),Ir=a.z.enum(["tty","vnc","web"]);a.z.object({mode:Ir,url:a.z.string().trim().min(1).max(4096),token:a.z.string().trim().min(1).max(512),expiresAt:a.z.string().datetime()}).strict(),a.z.object({revoked:a.z.boolean()}).strict();const Ar=a.z.object({type:a.z.enum(["app-session","provider-session","adapter-key"]),id:a.z.string().trim().min(1).max(240),agent:a.z.string().trim().min(1).max(80).optional(),adapter:a.z.string().trim().min(1).max(80).optional(),key:a.z.string().trim().min(1).max(240).optional()}).strict(),br=a.z.record(a.z.string(),a.z.unknown()).and(a.z.object({id:a.z.string().trim().min(1).max(160),appId:a.z.string().trim().min(1).max(160).optional(),title:a.z.string().trim().max(240).optional(),kind:a.z.string().trim().max(80).optional(),status:yr.default("unknown"),bindings:a.z.array(Ar).max(40).default([]),workspace:a.z.object({cwd:a.z.string().trim().max(4096).optional()}).strict().optional(),createdAt:a.z.string().datetime().optional(),updatedAt:a.z.string().datetime().optional()})),wr=a.z.object({runningCount:a.z.number().int().min(0).default(0),problemCount:a.z.number().int().min(0).default(0),sessions:a.z.array(br).default([]),updatedAt:a.z.string().datetime()}).strict();a.z.object({streamId:a.z.string().trim().min(1).max(240),revision:a.z.number().int().min(0),lastEventAt:a.z.string().datetime(),snapshot:wr}).strict(),wr.pick({runningCount:!0,problemCount:!0,updatedAt:!0}).extend({revision:a.z.number().int().min(0).optional()});const vr=a.z.enum(["app-session-created","app-session-updated","app-session-deleted","app-session-recovered","control-action","heartbeat-sync","startup"]),Er=a.z.object({streamId:a.z.string().trim().min(1).max(240),instanceId:a.z.string().trim().min(1).max(160),nodeId:a.z.string().trim().min(1).max(160).optional(),revision:a.z.number().int().min(0),previousRevision:a.z.number().int().min(0).optional(),traceId:a.z.string().trim().min(1).max(160),generatedAt:a.z.string().datetime(),reason:vr}).strict(),Nr=a.z.object({meta:Er,snapshot:wr}).strict(),Sr=a.z.object({meta:Er,session:br}).strict(),Tr=a.z.object({meta:Er,sessionId:a.z.string().trim().min(1).max(160),tombstone:br.optional(),expiresAt:a.z.string().datetime().optional()}).strict();function zr(e){return e.startsWith("ai-session.")||e.startsWith("ai.session.")?"ai.sessions":e.startsWith("app-session.")?"app.sessions":e.startsWith("app.management")?"apps":e.startsWith("trigger.")?"triggers":e.startsWith("instance.")?"instances":e.startsWith("node.")?"nodes":e.startsWith("project.")?"projects":e.startsWith("model.")?"models":e.startsWith("image.")?"images":e.startsWith("market.")?"market":"system"}a.z.object({streamId:a.z.string().trim().min(1).max(240),instanceId:a.z.string().trim().min(1).max(160),sinceRevision:a.z.number().int().min(0),latestRevision:a.z.number().int().min(0),earliestRetainedRevision:a.z.number().int().min(0),syncRequired:a.z.boolean().default(!1),events:a.z.array(a.z.discriminatedUnion("type",[a.z.object({type:a.z.literal("app-session.snapshot"),payload:Nr}).strict(),a.z.object({type:a.z.literal("app-session.patch"),payload:Sr}).strict(),a.z.object({type:a.z.literal("app-session.removed"),payload:Tr}).strict()])).default([])}).strict();const _r=a.z.enum(["ai.sessions","app.sessions"]),Cr=a.z.object({topic:_r,instanceId:a.z.string().trim().min(1).max(160),streamId:a.z.string().trim().min(1).max(240),latestRevision:a.z.number().int().min(0),earliestRetainedRevision:a.z.number().int().min(0)}).strict(),kr=a.z.object({protocolVersion:a.z.literal(1),streams:a.z.array(Cr)}).strict();class Or{attempt=0;timer;get pending(){return Boolean(this.timer)}get attempts(){return this.attempt}schedule(e,t={}){if(this.timer)return;const n=function(e,t=Math.random){const n=Math.min(3e4,1e3*2**Math.max(0,e));return Math.min(3e4,Math.round(n*(.75+.5*t())))}(this.attempt,t.random);this.attempt+=1;const i=t.setTimeoutFn||setTimeout;return this.timer=i(()=>{this.timer=void 0,e()},n),{attempt:this.attempt,delay:n}}reset(e=clearTimeout){this.timer&&e(this.timer),this.timer=void 0,this.attempt=0}cancel(e=clearTimeout){this.timer&&e(this.timer),this.timer=void 0}}function Rr(e,t=6e4){const n=[];for(let i=0;i<e.length;i+=t)n.push(e.slice(i,i+t));return n}class xr{sockets=new Map;socketUrls=new Map;retries=new Map;outputs=new Set;imagePullTerminalByInstance=new Map;state;token;logger;safetyIntervalMs;lastAiSessionEventByInstance=new Map;lastAppSessionEventByInstance=new Map;timer;reconnectAttempts=0;safetyReconciliations=0;localSequence=0;createSocket;setIntervalFn;clearIntervalFn;constructor(e,t,n={}){var i;this.state=e,this.token=t,this.logger=n.logger,this.safetyIntervalMs=(i=n.safetyIntervalMs,Math.min(6e4,Math.max(3e4,i??45e3))),this.createSocket=n.createSocket||((e,t)=>new m(e,t)),this.setIntervalFn=n.setIntervalFn||setInterval,this.clearIntervalFn=n.clearIntervalFn||clearInterval}start(){this.sync(),this.timer=this.setIntervalFn(()=>{this.safetyReconciliations+=1,this.sync()},this.safetyIntervalMs)}stop(){this.timer&&(this.clearIntervalFn(this.timer),this.timer=void 0);for(const e of this.sockets.values())e.close();this.sockets.clear(),this.socketUrls.clear();for(const e of this.retries.values())e.timer.cancel();this.retries.clear(),this.outputs.clear()}addOutput(e){this.outputs.add(e),e.on("close",()=>this.outputs.delete(e)),e.on("error",()=>this.outputs.delete(e));for(const t of this.state.listInstances()){const n=Dr(t);n?this.sendForwarded(e,this.createEvent(Ti,n,{instanceId:t.id})):this.logger?.warn?.({instanceId:t.id},"instance.lifecycle.snapshot.invalid")}for(const[t,n]of this.imagePullTerminalByInstance)Rr(n.tail).forEach((i,r)=>this.sendForwarded(e,this.createEvent(si,{...n.output,sequence:n.output.sequence+r,data:i,...0===r?{replay:!0}:{}},{instanceId:t}))),n.finished&&this.sendForwarded(e,this.createEvent(ai,n.finished,{instanceId:t}));return this.syncNow(),()=>{this.outputs.delete(e)}}publish(e,t,n={}){this.rememberImagePullTerminal(e,t);const i=this.createEvent(e,t,n);for(const e of this.outputs)this.sendForwarded(e,i)}rememberImagePullTerminal(e,t){if(e===si){const e=Mi(di,t);if(!e.success)return;const n=e.data,i=this.imagePullTerminalByInstance.get(n.instanceId);if(i&&n.generation<i.output.generation)return;const r=i?.output.generation===n.generation,o=n.replay||!r?n.data:`${i.tail}${n.data}`.slice(-262144);return void this.imagePullTerminalByInstance.set(n.instanceId,{output:n,tail:o})}if(e===ai){const e=Mi(li,t);if(!e.success)return;const n=e.data,i=this.imagePullTerminalByInstance.get(n.instanceId);i?.output.generation===n.generation&&(i.finished=n)}}publishInstanceLifecycle(e){this.publish(Ti,function(e){return zi.parse(Pr(e))}(e),{instanceId:e.id});const t=this.imagePullTerminalByInstance.get(e.id);"ready"===e.imageProvisioning?.phase&&"succeeded"===t?.finished?.outcome&&this.imagePullTerminalByInstance.delete(e.id)}createEvent(e,t,n){const i=++this.localSequence;return{v:1,id:`node_evt_${Date.now().toString(36)}_${i.toString(36)}`,seq:i,type:e,topic:zr(e),createdAt:(new Date).toISOString(),payload:t,scope:n}}sendForwarded(e,t){const n=JSON.stringify({type:"node-agent.event.forwarded",event:t});e.readyState===m.OPEN&&e.send(n)}syncNow(){this.sync()}diagnostics(){return{reconnectAttempts:this.reconnectAttempts,safetyReconciliations:this.safetyReconciliations,activeConnections:this.sockets.size,pendingRetries:[...this.retries.values()].filter(e=>e.timer.pending).length,safetyIntervalMs:this.safetyIntervalMs}}sync(){const e=new Set(this.state.listInstances().map(e=>e.id));for(const t of this.imagePullTerminalByInstance.keys())e.has(t)||this.imagePullTerminalByInstance.delete(t);if(!this.outputs.size){for(const e of this.sockets.values())e.close();this.sockets.clear(),this.socketUrls.clear();for(const e of this.retries.values())e.timer.cancel();return void this.retries.clear()}const t=new Set;for(const e of this.state.listInstances()){const n=Lr(e);if(!n)continue;t.add(e.id);const i=this.retries.get(e.id);i?.timer.pending&&i.url!==n&&(i.timer.cancel(),this.retries.delete(e.id)),this.socketUrls.get(e.id)!==n&&this.sockets.has(e.id)&&(this.sockets.get(e.id)?.close(),this.sockets.delete(e.id)),this.sockets.has(e.id)||this.retries.get(e.id)?.timer.pending||this.connect(e.id,n)}for(const[e,n]of this.sockets)if(!t.has(e)){n.close(),this.sockets.delete(e),this.socketUrls.delete(e);const t=this.retries.get(e);t?.timer.cancel(),this.retries.delete(e)}for(const[e,n]of this.retries)t.has(e)||(n.timer.cancel(),this.retries.delete(e),this.socketUrls.delete(e))}connect(e,t){const n=this.token?{authorization:`Bearer ${this.token}`}:void 0,i=this.createSocket(t,{headers:n});this.sockets.set(e,i),this.socketUrls.set(e,t),i.on("open",()=>{const n=this.retries.get(e);n?.timer.reset(),this.retries.set(e,{timer:n?.timer||new Or,url:t}),i.readyState===m.OPEN&&(i.send(JSON.stringify({v:1,type:"subscribe",topics:[J,"app.sessions","apps","instances"]})),this.logger?.info?.({instanceId:e,url:t},"ai-session.event.forward.connect"),this.logger?.info?.({instanceId:e,url:t},"app-session.event.forward.connect"))}),i.on("message",t=>{const n=function(e,t){try{const n=JSON.parse(String(e));if(!n||"object"!=typeof n||Array.isArray(n))return;const i=n,r="string"==typeof i.type?i.type:"";if(!r||"events.connected"===r)return;const o=i.scope&&"object"==typeof i.scope&&!Array.isArray(i.scope)?i.scope:{};return{v:1,id:"string"==typeof i.id?i.id:`evt_${Date.now().toString(36)}`,seq:Number(i.seq)||0,type:r,topic:"string"==typeof i.topic?i.topic:zr(r),createdAt:"string"==typeof i.createdAt?i.createdAt:(new Date).toISOString(),payload:"payload"in i?i.payload:{},scope:{...o,instanceId:t}}}catch{return}}(t,e);if(!n)return;if("streams.hello"===n.type){const t=Mi(kr,n.payload);if(!t.success)return this.logger?.warn?.({instanceId:e,issues:t.error.issues},"session-stream.handshake.invalid"),void i.close(1002,"Incompatible session stream handshake.");const r=JSON.stringify({type:"node-agent.streams.hello",instanceId:e,payload:t.data});for(const e of this.outputs)e.readyState===m.OPEN&&e.send(r);return}this.recordAiSessionEvent(e,n),this.recordAppSessionEvent(e,n);const r=JSON.stringify({type:"node-agent.event.forwarded",event:n});for(const e of this.outputs)e.readyState===m.OPEN&&e.send(r)}),i.on("close",()=>{this.sockets.get(e)===i&&(this.sockets.delete(e),this.socketUrls.delete(e),this.scheduleReconnect(e))}),i.on("error",()=>{this.logger?.warn?.({instanceId:e,url:t},"ai-session.event.forward.error"),this.logger?.warn?.({instanceId:e,url:t},"app-session.event.forward.error"),i.close()})}scheduleReconnect(e){const t=this.state.listInstances().find(t=>t.id===e),n=t&&Lr(t);if(!n||!this.outputs.size)return;const i=this.retries.get(e)??{timer:new Or};if(i.timer.pending)return;i.url=n;const r=i.timer.schedule(()=>{this.sockets.has(e)||this.connect(e,n)});r&&(this.reconnectAttempts+=1,this.logger?.info?.({instanceId:e,url:n,attempt:r.attempt,delay:r.delay,reconnectAttempts:this.reconnectAttempts},"session-stream.connection.reconnect-scheduled")),this.retries.set(e,i)}recordAiSessionEvent(e,t){if(t.topic!==J)return;if("ai-session.message-delta"===t.type)return;const n=Mr(t.payload),i=this.lastAiSessionEventByInstance.get(e);i?.streamId===n.streamId&&void 0!==i.revision&&void 0!==n.revision&&n.revision>i.revision+1&&this.logger?.warn?.({instanceId:e,traceId:n.traceId,streamId:n.streamId,previousRevision:i.revision,revision:n.revision},"ai-session.event.forward.gap"),this.lastAiSessionEventByInstance.set(e,{streamId:n.streamId??i?.streamId,revision:n.revision??i?.revision}),this.logger?.info?.({instanceId:e,traceId:n.traceId,eventType:t.type,streamId:n.streamId,revision:n.revision},"ai-session.event.forward.message")}recordAppSessionEvent(e,t){if("app.sessions"!==t.topic)return;const n=Mr(t.payload),i=this.lastAppSessionEventByInstance.get(e);i?.streamId===n.streamId&&void 0!==i.revision&&void 0!==n.revision&&n.revision>i.revision+1&&this.logger?.warn?.({instanceId:e,traceId:n.traceId,streamId:n.streamId,previousRevision:i.revision,revision:n.revision},"app-session.event.forward.gap"),this.lastAppSessionEventByInstance.set(e,{streamId:n.streamId??i?.streamId,revision:n.revision??i?.revision}),this.logger?.info?.({instanceId:e,traceId:n.traceId,eventType:t.type,streamId:n.streamId,revision:n.revision},"app-session.event.forward.message")}}function Dr(e){const t=zi.safeParse(Pr(e));return t.success?t.data:void 0}function Pr(e){return{instanceId:e.id,revision:e.stateRevision,updatedAt:e.updatedAt,status:e.status,health:e.health,connectionStatus:e.connectionStatus,accessStatus:"online"===e.connectionStatus||"online"===e.agentStatus?"reachable":"endpoint-unreachable",imageProvisioning:e.imageProvisioning,workspace:e.workspace,runtime:e.runtime,runtimeVersion:e.runtimeVersion,ready:e.ready,lastHeartbeatAt:e.lastHeartbeatAt}}function Mr(e){const t=e&&"object"==typeof e&&!Array.isArray(e)?e:{},n=t.meta&&"object"==typeof t.meta&&!Array.isArray(t.meta)?t.meta:{};return{streamId:"string"==typeof n.streamId?n.streamId:void 0,revision:"number"==typeof n.revision?n.revision:void 0,traceId:"string"==typeof n.traceId?n.traceId:void 0}}function Lr(e){if(!function(e){return!1!==e.ready&&(!e.runtimeVersion||["matched","failed"].includes(e.runtimeVersion.phase))}(e))return;const t=e.target?.api||e.target?.web;if(t)try{const e=new URL("/api/events",t);return e.protocol="https:"===e.protocol?"wss:":"ws:",e.toString()}catch{return}}const jr=new Set(["provisioning","starting","registering","registered","running","unhealthy"]),$r=JSON.stringify({id:"{{.ID}}",name:"{{.Name}}",cpu:"{{.CPUPerc}}",memory:"{{.MemUsage}}",memoryPercent:"{{.MemPerc}}",network:"{{.NetIO}}",blockIo:"{{.BlockIO}}",pids:"{{.PIDs}}"});class Fr{snapshots=new Map;runCommand;targets;publish;intervalMs;timer;inFlight;pendingTargets=new Map;collectingTargets=new Map;constructor(e,t,n,i=3e3){this.runCommand=e,this.targets=t,this.publish=n,this.intervalMs=i}start(){this.collect().catch(()=>{}),this.timer=setInterval(()=>{this.collect().catch(()=>{})},this.intervalMs)}stop(){this.timer&&clearInterval(this.timer),this.timer=void 0}async snapshot(e){const t=this.targets().find(t=>t.id===e);if(!t)return;if(!jr.has(t.status))return Kr(t.id);const n=this.snapshots.get(e);return n&&Date.now()-Date.parse(n.sampledAt)<=this.intervalMs?n:(await this.collect([t]),this.snapshots.get(e))}async collect(e){const t=e||this.targets();if(!e){const e=new Set(t.map(e=>e.id));for(const t of this.snapshots.keys())e.has(t)||this.snapshots.delete(t)}for(const e of t){const t=Ur(e);this.collectingTargets.get(e.id)!==t&&this.pendingTargets.set(e.id,e)}this.inFlight||(this.inFlight=this.drain().finally(()=>{this.inFlight=void 0})),await this.inFlight}async drain(){for(;this.pendingTargets.size;){const e=[...this.pendingTargets.values()];this.pendingTargets.clear();for(const t of e)this.collectingTargets.set(t.id,Ur(t));try{await this.collectOnce(e)}finally{for(const t of e)this.collectingTargets.delete(t.id)}}}async collectOnce(e){const t=e.filter(e=>jr.has(e.status)&&(e.runtime.containerId||e.runtime.containerName));for(const t of e.filter(e=>jr.has(e.status)&&!e.runtime.containerId&&!e.runtime.containerName))this.update(Gr(t.id));for(const t of e.filter(e=>!jr.has(e.status)))this.update(Kr(t.id));if(!t.length)return;const n=t.map(e=>e.runtime.containerId||e.runtime.containerName),i=(new Date).toISOString();try{const e=await this.runCommand("docker",["stats","--no-stream","--format",$r,...n],{timeoutMs:5e3});this.applyDockerOutput(t,e.stdout,i)}catch(e){if(1===t.length)return void this.update(Jr(t[0].id,i,e instanceof Error?e.message:String(e)));await Promise.all(t.map(async e=>{const t=e.runtime.containerId||e.runtime.containerName;try{const n=await this.runCommand("docker",["stats","--no-stream","--format",$r,t],{timeoutMs:5e3});this.applyDockerOutput([e],n.stdout,i)}catch(t){this.update(Jr(e.id,i,t instanceof Error?t.message:String(t)))}}))}}applyDockerOutput(e,t,n){const i=function(e,t=(new Date).toISOString()){const n=new Map;for(const i of e.split(/\r?\n/).filter(Boolean)){let e;try{e=JSON.parse(i)}catch{continue}const r=Br(e.id),o=Br(e.name),s=r||o;if(!s)continue;const a=Vr(Br(e.memory)),c=Vr(Br(e.network)),d=Vr(Br(e.blockIo)),l=gi.parse({instanceId:s,runtimeKind:"docker",state:"available",sampledAt:t,cpu:qr(e.cpu,"usagePercent"),memory:a?{usageBytes:a[0],...void 0!==a[1]?{limitBytes:a[1]}:{},...qr(e.memoryPercent,"usagePercent")}:void 0,network:c?{rxBytes:c[0],txBytes:c[1]||0}:void 0,blockIo:d?{readBytes:d[0],writeBytes:d[1]||0}:void 0,pids:Hr(e.pids)});r&&n.set(r,l),o&&n.set(o,l)}return n}(t,n);for(const t of e){const e=[t.runtime.containerId,t.runtime.containerName].filter(Boolean),r=[...i.entries()].find(([t])=>e.some(e=>e===t||e.startsWith(t)||t.startsWith(e)))?.[1];this.update(r?{...r,instanceId:t.id}:Jr(t.id,n,"Container metrics were not returned by Docker."))}}update(e){const t=gi.parse(e);this.snapshots.set(t.instanceId,t),this.publish?.(t)}}function Ur(e){return[e.status,e.runtime.containerId||"",e.runtime.containerName||""].join("\0")}function Vr(e){if(!e)return;const[t,n]=e.split("/").map(e=>function(e){const t=e.trim().match(/^([0-9]+(?:\.[0-9]+)?)\s*([kmgtpe]?i?b)$/i);if(!t)return;const n=Number(t[1]),i=t[2].toLowerCase(),r=i.includes("i"),o="b"===i[0]?"":i[0],s=o?"kmgtpe".indexOf(o)+1:0;return Math.round(n*(r?1024:1e3)**s)}(e||""));return void 0===t?void 0:[t,n]}function qr(e,t){const n=Number(Br(e).replace(/%$/,""));return Number.isFinite(n)&&n>=0?{[t]:n}:void 0}function Hr(e){const t=Number(Br(e));return Number.isFinite(t)&&t>=0?t:void 0}function Br(e){return"string"==typeof e||"number"==typeof e?String(e).trim():""}function Kr(e){return{instanceId:e,runtimeKind:"docker",state:"stopped",sampledAt:(new Date).toISOString()}}function Gr(e){return{instanceId:e,runtimeKind:"docker",state:"pending",sampledAt:(new Date).toISOString()}}function Jr(e,t,n){return{instanceId:e,runtimeKind:"docker",state:"unavailable",sampledAt:t,error:n.slice(0,2048)}}function Wr(e){try{return t.statSync(e).isDirectory()}catch{return!1}}function Yr(e,i){let r;try{r=t.statSync(e)}catch{return}if(!r.isDirectory())return;const o=n.resolve(e),s=n.basename(o)||o;let a=[];try{a=i>0?t.readdirSync(o,{withFileTypes:!0}):[]}catch{a=[]}const c=i>0?a.filter(e=>e.isDirectory()||e.isSymbolicLink()&&Wr(n.join(o,e.name))).sort((e,t)=>e.name.localeCompare(t.name)).slice(0,80).flatMap(e=>{const t=Yr(n.join(o,e.name),i-1);return t?[t]:[]}):[];return{name:s,path:o,children:c}}function Xr(e){return(e.path?[e.path]:function(){if("win32"!==process.platform)return[n.parse(n.resolve(process.cwd())).root];const e=n.parse(n.resolve(process.cwd())).root,t=Array.from({length:26},(e,t)=>`${String.fromCharCode(65+t)}:\\`);return[...new Set([e,...t])].filter(Wr)}()).flatMap(t=>{const n=Yr(t,e.depth);return n?[n]:[]})}function Qr(){return process.env.TASK_HANDOFF_NODE_AGENT_DATA_DIR||n.join(c.homedir(),".config","task-handoff","node-agent")}function Zr(e=Qr()){const t=n.resolve(e);return{dataDir:t,identityPath:n.join(t,"identity.json"),settingsPath:n.join(t,"runtime-settings.json"),localFoldersDir:n.join(t,"local-folders"),nodeRuntimesDir:n.join(t,"node-runtimes"),controlledInstancesDir:n.join(t,"controlled-instances"),environmentTemplatesDir:n.join(t,"environment-templates"),instancePrivateConfigsDir:n.join(t,"instance-private-configs"),nodeModelsDir:n.join(t,"models"),modelAssignmentsDir:n.join(t,"model-assignments"),modelEnvironmentsDir:n.join(t,"model-environments"),updatesDir:n.join(t,"updates"),logsDir:n.join(t,"logs")}}function eo(e,t){const i=n.extname(e);return`${i?e.slice(0,-i.length):e}.${t}${i}`}function to(e,n=10485760,i=2){if(!t.existsSync(e))return!1;const r=t.lstatSync(e);if(!r.isFile()||r.isSymbolicLink()||r.size<=n)return!1;if(i>0){!function(e,n){if(!(n<=0)){t.rmSync(eo(e,n),{force:!0});for(let i=n-1;i>=1;i-=1){const n=eo(e,i);t.existsSync(n)&&t.renameSync(n,eo(e,i+1))}}}(e,i);const r=function(e,n){const i=t.statSync(e),r=Math.min(i.size,n),o=Buffer.allocUnsafe(r),s=t.openSync(e,"r");let a=0;try{for(;a<r;){const e=t.readSync(s,o,a,r-a,i.size-r+a);if(0===e)break;a+=e}}finally{t.closeSync(s)}return a===r?o:o.subarray(0,a)}(e,n);t.writeFileSync(eo(e,1),r,{mode:384})}return t.truncateSync(e,0),t.chmodSync(e,384),!0}class no{localInstancesRoot;localInstancesTrashRoot;options;constructor(e,t={}){this.options=t,this.localInstancesRoot=n.join(e.dataDir,"local-instances"),this.localInstancesTrashRoot=n.join(e.dataDir,"local-instances-trash")}run(e){const n=new Set(e);if(t.existsSync(this.localInstancesRoot)){K(this.localInstancesRoot);for(const e of t.readdirSync(this.localInstancesRoot,{withFileTypes:!0}))e.isDirectory()&&!e.isSymbolicLink()&&(n.has(e.name)?this.capControlledInstanceLogs(e.name):this.retire(e.name))}return function(e){if(!t.existsSync(e.trashRoot))return[];const n=e.nowMs??Date.now(),i=e.retentionMs??H,r=[];for(const o of t.readdirSync(e.trashRoot,{withFileTypes:!0})){const s=B(e.trashRoot,o.name);try{const e=Number(o.name.split("-",1)[0]);if(!Number.isFinite(e)||e+i>n)continue;const a=t.lstatSync(s);a.isSymbolicLink()?t.unlinkSync(s):a.isDirectory()?t.rmSync(s,{recursive:!0,force:!0}):t.unlinkSync(s),r.push(s)}catch(t){e.logger?.("retired persistence entry cleanup failed",{path:s,error:t instanceof Error?t.message:String(t)})}}return r}({trashRoot:this.localInstancesTrashRoot,retentionMs:this.options.retentionMs??H,nowMs:this.now(),logger:this.options.logger})}capActiveInstanceLogs(e){for(const t of e)this.capControlledInstanceLogs(t)}capControlledInstanceLogs(e){const t=n.resolve(this.localInstancesRoot,e);if(n.dirname(t)!==n.resolve(this.localInstancesRoot))return[];const i=n.join(t,"logs"),r=[];for(const t of["controlled-instance.out.log","controlled-instance.err.log"]){const o=n.join(i,t);try{to(o)&&r.push(o)}catch(t){this.options.logger?.("controlled instance log rotation failed",{instanceId:e,filePath:o,error:t instanceof Error?t.message:String(t)})}}return r}retire(e){try{return function(e){const n=B(e.sourceRoot,e.entryName);if(!t.existsSync(n))return;const i=t.lstatSync(n);if(!i.isDirectory()||i.isSymbolicLink())throw new Error(`Retention source must be a real directory: ${n}`);K(e.trashRoot);const r=e.nowMs??Date.now();let o=0,s=`${r}-${e.entryName}`;for(;t.existsSync(B(e.trashRoot,s));)o+=1,s=`${r}-${o}-${e.entryName}`;const a=B(e.trashRoot,s);return t.renameSync(n,a),a}({sourceRoot:this.localInstancesRoot,entryName:e,trashRoot:this.localInstancesTrashRoot,nowMs:this.now()})}catch(t){return void this.options.logger?.("local instance persistence retirement failed",{instanceId:e,error:t instanceof Error?t.message:String(t)})}}now(){return this.options.now?.()??Date.now()}}function io(e,t=process.platform){const i=n.resolve(e),r=d.createHash("sha256").update(i).digest("hex").slice(0,16);return"win32"===t?`\\\\.\\pipe\\task-handoff-node-agent-${r}`:n.join("/tmp",`task-handoff-node-agent-${process.getuid?.()??"user"}`,`${r}.sock`)}const ro="runtime-manifest.json";class oo extends Error{code;retryable;constructor(e,t,n){super(t,void 0===n?.cause?void 0:{cause:n.cause}),this.name="RuntimeArtifactError",this.code=e,this.retryable=n?.retryable??!1}}async function so(e,t=""){const i=[],r=await g.readdir(n.join(e,t),{withFileTypes:!0});for(const o of r){const r=t?n.posix.join(t,o.name):o.name;if(!t&&r===ro)continue;const s=n.join(e,...r.split("/"));if(o.isDirectory()){i.push(...await so(e,r));continue}if(o.isSymbolicLink()){const t=await g.readlink(s);if(n.isAbsolute(t))throw new oo("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload symlink is absolute: ${r}`);const o=n.resolve(n.dirname(s),t),a=n.relative(n.resolve(e),o);if(!a||".."===a||a.startsWith(`..${n.sep}`)||n.isAbsolute(a))throw new oo("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload symlink escapes the artifact: ${r}`);if(!await g.lstat(o).catch(()=>{}))throw new oo("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload symlink is broken: ${r}`);i.push({absolutePath:s,relativePath:r,kind:"symlink",target:t,size:Buffer.byteLength(t)});continue}if(!o.isFile())throw new oo("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload contains unsupported entry: ${r}`);const a=await g.lstat(s);i.push({absolutePath:s,relativePath:r,kind:"file",size:a.size})}return i}async function ao(e){const n=(await so(e)).sort((e,t)=>function(e,t){return Buffer.compare(Buffer.from(e,"utf8"),Buffer.from(t,"utf8"))}(e.relativePath,t.relativePath)),i=d.createHash("sha256");for(const e of n){if(i.update("file"===e.kind?"F":"L","ascii"),i.update(Buffer.from(e.relativePath,"utf8")),i.update(Buffer.from([0])),i.update(Buffer.from(String(e.size),"ascii")),i.update(Buffer.from([0])),"file"===e.kind)for await(const n of t.createReadStream(e.absolutePath))i.update(n);else i.update(Buffer.from(e.target,"utf8"));i.update(Buffer.from([0]))}return i.digest("hex")}function co(e){for(const[t,n]of[["version",e.version],["platform",e.platform],["arch",e.arch]])if(!/^[0-9A-Za-z._-]+$/.test(n))throw new oo("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Invalid runtime artifact ${t}: ${n}`);return`${e.version}-${e.platform}-${e.arch}`}function lo(e,t){return`${co(e)}-${e.sha256}-${t}`}async function uo(e){const n=d.createHash("sha256");for await(const i of t.createReadStream(e))n.update(i);return n.digest("hex")}class mo{#e;#t;#n=new Map;constructor(e){this.#e=e.cacheDir,this.#t=e.fetchImpl??fetch}resolve(e,t){const n=yn.parse(e);if(!/^[a-f0-9]{64}$/.test(t.archiveSha256))throw new oo("INSTANCE_RUNTIME_ARTIFACT_INVALID","Runtime archive SHA-256 is invalid.");if((t.archiveUrl?1:0)+(t.archivePath?1:0)!=1)throw new oo("INSTANCE_RUNTIME_ARTIFACT_INVALID","Runtime artifact source must specify exactly one archive location.");const i=lo(n,t.archiveSha256),r=this.#n.get(i);if(r)return r;const o=this.#i(n,t).finally(()=>this.#n.delete(i));return this.#n.set(i,o),o}async#i(e,i){if(!/^[a-f0-9]{64}$/.test(i.archiveSha256))throw new oo("INSTANCE_RUNTIME_ARTIFACT_INVALID","Runtime archive SHA-256 is invalid.");const r=lo(e,i.archiveSha256),o=n.join(this.#e,"archives"),s=n.join(o,`${r}.tar.gz`);if(await g.mkdir(o,{recursive:!0}),await this.#r(s,e,i.archiveSha256))return{identity:e,archivePath:s,cacheHit:!0};await g.rm(s,{force:!0});const a=n.join(o,`.${r}.${d.randomUUID()}.part`);try{const n=await g.open(a,"wx");if(i.archivePath)await f.pipeline(t.createReadStream(i.archivePath),n.createWriteStream());else{const e=await this.#t(i.archiveUrl);if(!e.ok||!e.body)throw await n.close(),new oo("INSTANCE_RUNTIME_ARTIFACT_UNAVAILABLE",`Runtime artifact download failed with HTTP ${e.status}.`,{retryable:e.status>=500});await f.pipeline(e.body,n.createWriteStream())}if(await uo(a)!==i.archiveSha256)throw new oo("INSTANCE_RUNTIME_ARTIFACT_INVALID","Downloaded runtime archive SHA-256 does not match release metadata.");return await this.#o(a,e),await g.rename(a,s),{identity:e,archivePath:s,cacheHit:!1}}catch(e){if(e instanceof oo)throw e;throw new oo("INSTANCE_RUNTIME_ARTIFACT_UNAVAILABLE","Could not download runtime artifact.",{cause:e,retryable:!0})}finally{await g.rm(a,{force:!0})}}async#r(e,t,n){try{return await uo(e)===n&&(await this.#o(e,t),!0)}catch{return!1}}async#o(e,t){const i=n.join(this.#e,"validation",`${co(t)}-${d.randomUUID()}`);try{await async function(e,t){await g.mkdir(t,{recursive:!0});try{await y.extract({file:e,cwd:t,strict:!0,preservePaths:!1,filter:(e,t)=>{const i=n.posix.normalize(e.replace(/^\.\//,""));if(!i||".."===i||i.startsWith("../")||n.posix.isAbsolute(i))throw new oo("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime archive entry escapes the artifact root: ${e}`);const r=t.type;if("File"!==r&&"OldFile"!==r&&"Directory"!==r&&"SymbolicLink"!==r)throw new oo("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime archive contains unsupported entry type ${r??"unknown"}: ${e}`);return!0}})}catch(e){throw new oo("INSTANCE_RUNTIME_ARTIFACT_INVALID","Could not extract runtime artifact safely.",{cause:e})}}(e,i),await async function(e,t,i){const r=await async function(e){let t;try{t=JSON.parse(await g.readFile(n.join(e,ro),"utf8"))}catch(e){throw new oo("INSTANCE_RUNTIME_ARTIFACT_INVALID","Runtime artifact manifest is missing or invalid JSON.",{cause:e})}const i=Mi(yn,t);if(!i.success)throw new oo("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime artifact manifest is invalid: ${i.error.message}`);return i.data}(e);if(function(e,t){for(const n of["packageName","version","platform","arch","formatVersion","launcherAbi","entrypoint","sha256"])if(e[n]!==t[n])throw new oo("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime artifact ${"sha256"===n?"SHA-256":n} mismatch: expected ${t[n]}, got ${e[n]}.`)}(r,t),1!==r.formatVersion)throw new oo("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Unsupported runtime artifact format ${r.formatVersion}.`);if(i?.platform&&"universal"!==r.platform&&r.platform!==i.platform)throw new oo("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime artifact platform ${r.platform} does not match ${i.platform}.`);if(i?.arch&&"universal"!==r.arch&&r.arch!==i.arch)throw new oo("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime artifact architecture ${r.arch} does not match ${i.arch}.`);if(void 0!==i?.launcherAbi&&r.launcherAbi>i.launcherAbi)throw new oo("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Runtime requires launcher ABI ${r.launcherAbi}, but the base runtime provides ${i.launcherAbi}.`);const o=function(e,t){if(!e||e.includes("\\")||n.posix.isAbsolute(e))throw new oo("INSTANCE_RUNTIME_ARTIFACT_INVALID",`${t} must be a non-empty POSIX relative path.`);const i=n.posix.normalize(e);if("."===i||".."===i||i.startsWith("../"))throw new oo("INSTANCE_RUNTIME_ARTIFACT_INVALID",`${t} escapes the runtime root.`);return i}(r.entrypoint,"Runtime entrypoint"),s=await g.lstat(n.join(e,...o.split("/"))).catch(()=>{});if(!s?.isFile())throw new oo("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime entrypoint is missing: ${o}`);const a=await ao(e);if(a!==r.sha256)throw new oo("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload SHA-256 mismatch: expected ${r.sha256}, got ${a}.`);return r}(i,t,{platform:t.platform,arch:t.arch})}finally{await g.rm(i,{recursive:!0,force:!0})}}}async function po(e,t,i,r=fetch){if("linux"!==t||!["x64","arm64"].includes(i))throw new oo("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Managed controlled-instance updates require a Linux x64 or arm64 target, received ${t}/${i}.`);const o=await async function(e){const t=`controlled-instance-runtime-${e}-linux-universal`,i=function(){const e=process.env.TASK_HANDOFF_BUNDLED_RUNTIME_DIR?.trim();return n.resolve(e||n.join(n.dirname(process.argv[1]||process.cwd()),"..","runtime-artifacts"))}();try{const[r,o]=await Promise.all([g.readFile(n.join(i,`${t}.manifest.json`),"utf8"),g.readFile(n.join(i,`${t}.tar.gz.sha256`),"utf8")]),s=Mi(yn,JSON.parse(r));if(!s.success||s.data.version!==e||"linux"!==s.data.platform||"universal"!==s.data.arch)throw new oo("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Bundled controlled-instance ${e} has an invalid Linux manifest.`);const a=o.trim().split(/\s+/)[0]?.toLowerCase();if(!a||!/^[a-f0-9]{64}$/.test(a))throw new oo("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Bundled controlled-instance ${e} has an invalid archive checksum.`);return{identity:s.data,source:{archivePath:n.join(i,`${t}.tar.gz`),archiveSha256:a}}}catch(t){if("ENOENT"===t.code)return;if(t instanceof oo)throw t;throw new oo("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Could not read bundled controlled-instance ${e}.`,{cause:t})}}(e);if(o)return o;const s=`controlled-instance-runtime-${e}-linux-universal`,a=function(e){const t=process.env.TASK_HANDOFF_RUNTIME_RELEASE_BASE_URL?.trim();return t?t.replaceAll("{version}",e).replace(/\/$/,""):`https://github.com/edgestorage/task-handoff/releases/download/v${e}`}(e),c=`${a}/${s}.manifest.json`,d=`${a}/${s}.tar.gz`,l=`${a}/${s}.tar.gz.sha256`,[u,m]=await Promise.all([r(c),r(l)]).catch(t=>{throw new oo("INSTANCE_RUNTIME_ARTIFACT_UNAVAILABLE",`Could not read release metadata for controlled-instance ${e}.`,{cause:t,retryable:!0})});if(!u.ok||!m.ok)throw new oo("INSTANCE_RUNTIME_ARTIFACT_UNAVAILABLE",`Release metadata for controlled-instance ${e} is unavailable (manifest HTTP ${u.status}, checksum HTTP ${m.status}).`,{retryable:u.status>=500||m.status>=500});let p;try{p=await u.json()}catch(t){throw new oo("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Release manifest for controlled-instance ${e} is not valid JSON.`,{cause:t})}const h=Mi(yn,p);if(!h.success)throw new oo("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Release manifest for controlled-instance ${e} is invalid: ${h.error.message}`);if(h.data.version!==e||"linux"!==h.data.platform||"universal"!==h.data.arch)throw new oo("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Release identity mismatch: requested ${e}-linux-universal, received ${h.data.version}-${h.data.platform}-${h.data.arch}.`);const f=(await m.text()).trim().split(/\s+/)[0]?.toLowerCase();if(!f||!/^[a-f0-9]{64}$/.test(f))throw new oo("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Release checksum for controlled-instance ${e} is invalid.`);return{identity:h.data,source:{archiveUrl:d,archiveSha256:f}}}class ho{store;desiredVersion;hooks;inFlight=new Map;requests=new Map;cancelled=new Set;now;delay;drainTimeoutMs;verificationTimeoutMs;pollIntervalMs;maxAttempts;retryBaseDelayMs;retryMaxDelayMs;constructor(e,t,n,i={}){this.store=e,this.desiredVersion=t,this.hooks=n,this.now=i.now||(()=>new Date),this.delay=i.delay||(e=>new Promise(t=>setTimeout(t,e))),this.drainTimeoutMs=i.drainTimeoutMs??3e5,this.verificationTimeoutMs=i.verificationTimeoutMs??6e4,this.pollIntervalMs=i.pollIntervalMs??250,this.maxAttempts=function(e){if(!Number.isInteger(e)||e<=0)throw new TypeError("maxAttempts must be a positive integer.");return e}(i.maxAttempts??3),this.retryBaseDelayMs=vo(i.retryBaseDelayMs??1e3,"retryBaseDelayMs"),this.retryMaxDelayMs=vo(i.retryMaxDelayMs??3e4,"retryMaxDelayMs")}schedule(e,t={}){const n=this.requests.get(e)||{startRequested:!1,resumeCancelled:!1};n.startRequested||=!0===t.startRequested,n.resumeCancelled||=!0===t.resumeCancelled||!0===t.startRequested,n.resumeCancelled&&this.cancelled.delete(e),this.requests.set(e,n);const i=this.inFlight.get(e);if(i)return i;const r=Promise.resolve().then(()=>this.reconcile(e,n)).finally(()=>{this.inFlight.delete(e),this.requests.delete(e)});return this.inFlight.set(e,r),r}isRunning(e){return this.inFlight.has(e)}cancel(e){return this.cancelled.add(e),this.inFlight.get(e)}async reconcile(e,t){let n=this.requireInstance(e);const i=this.desiredVersion();if(this.cancelled.has(e)&&!t.resumeCancelled)return this.storePhase(n,"pending");const r=n.runtimeVersion?.desiredVersion!==i||t.startRequested||yo(n)?0:this.remainingRetryDelayMs(n.runtimeVersion);if(r>0&&(await this.delay(r),n=this.requireInstance(e),this.cancelled.has(e)))return this.storePhase(n,"pending");const o=go(n),s=o===i&&(await(this.hooks.isInstalled?.(n,i))??!0);if(this.cancelled.has(e))return this.storePhase(this.requireInstance(e),"pending");if(o===i&&s)return this.storeState(n,{desiredVersion:i,actualVersion:o,phase:"matched",attempt:n.runtimeVersion?.attempt||0,matchedAt:this.timestamp()},!yo(n)&&"failed"!==n.health);if(n=this.storeState(n,function(e,t,n,i=!1){const r=e.runtimeVersion,o=r?.desiredVersion===t&&"matched"!==r.phase;return{desiredVersion:t,...n?{actualVersion:n}:{},phase:"pending",attempt:o?r.attempt:0,error:(o?r.error:void 0)||(n!==t||i?Io(t,n):Ao("INSTANCE_RUNTIME_VERIFICATION_FAILED",`Controlled-instance ${t} is running, but the active runtime artifact does not match the desired release identity.`,t,n,!0))}}(n,i,o,s)),yo(n)&&!t.startRequested)return n;let a=!1,c=0;try{for(;c<this.maxAttempts;){if(this.cancelled.has(e))return this.storePhase(this.requireInstance(e),"pending");let r;try{if(n=this.storePhase(n,"draining"),await(this.hooks.beginDrain?.(n)),a=!0,n=this.requireInstance(e),fo(n)){const t=await this.waitUntil(e,this.drainTimeoutMs,e=>!fo(e));if(n=this.requireInstance(e),!t){if(this.cancelled.has(e))return this.storePhase(n,"pending");await(this.hooks.onForcedDrain?.(n))}}if(n=this.storePhase(this.requireInstance(e),"installing",!0),c+=1,await this.hooks.install(n,i),this.cancelled.has(e)||yo(this.requireInstance(e))&&!t.startRequested)return this.storePhase(this.requireInstance(e),"pending");if(n=this.storePhase(this.requireInstance(e),"restarting"),await this.hooks.restart(n),this.cancelled.has(e))return this.storePhase(this.requireInstance(e),"pending");n=this.storePhase(this.requireInstance(e),"verifying");const r=await this.waitUntil(e,this.verificationTimeoutMs,e=>go(e)===i);if(this.cancelled.has(e))return this.storePhase(this.requireInstance(e),"pending");if(!r)throw Ao("INSTANCE_RUNTIME_VERIFICATION_FAILED",`Instance ${e} did not register controlled-instance ${i} after restart.`,i,go(this.requireInstance(e)),!0);const o=this.requireInstance(e);if(this.hooks.isInstalled&&!await this.hooks.isInstalled(o,i))throw Ao("INSTANCE_RUNTIME_VERIFICATION_FAILED",`Instance ${e} reported controlled-instance ${i}, but its active runtime release is missing.`,i,go(o),!0);return this.storeState(o,{desiredVersion:i,actualVersion:i,phase:"matched",attempt:o.runtimeVersion?.attempt||1,matchedAt:this.timestamp()},!yo(o)&&"failed"!==o.health)}catch(t){if(this.cancelled.has(e))return this.storePhase(this.requireInstance(e),"pending");r=bo(t,i,go(this.store.get(e)))}n=this.requireInstance(e);const o=n.runtimeVersion?.attempt||1;if(!r.retryable||c>=this.maxAttempts)return this.storeBatchFailure(n,i,o>=this.maxAttempts&&r.retryable?wo(i,go(n),this.maxAttempts,r):r);n=this.storeState(n,{desiredVersion:i,...go(n)?{actualVersion:go(n)}:{},phase:"pending",attempt:o,lastAttemptAt:this.timestamp(),error:r}),await this.delay(this.retryDelayMs(o))}return this.storeBatchFailure(n,i,wo(i,go(n),this.maxAttempts,n.runtimeVersion?.error))}finally{a&&await(this.hooks.endDrain?.(this.requireInstance(e)))}}storeBatchFailure(e,t,n){const i=go(e);return this.storeState(e,{desiredVersion:t,...i?{actualVersion:i}:{},phase:"pending",attempt:e.runtimeVersion?.attempt||0,lastAttemptAt:this.timestamp(),error:n})}retryDelayMs(e){return Math.min(this.retryMaxDelayMs,this.retryBaseDelayMs*2**Math.max(0,e-1))}remainingRetryDelayMs(e){if(!e?.error||!e.lastAttemptAt)return 0;const t=Date.parse(e.lastAttemptAt);return Number.isFinite(t)?Math.max(0,t+this.retryDelayMs(e.attempt||1)-this.now().getTime()):0}storePhase(e,t,n=!1){const i=this.desiredVersion(),r=go(e),o=e.runtimeVersion?.desiredVersion===i?e.runtimeVersion.error:void 0;return this.storeState(e,{desiredVersion:i,...r?{actualVersion:r}:{},phase:t,attempt:(e.runtimeVersion?.attempt||0)+(n?1:0),lastAttemptAt:this.timestamp(),...o?{error:o}:"pending"===t?{error:Io(i,r)}:{}},"restarting"!==t&&void 0)}storeState(e,t,n){const i=this.store.get(e.id)||e;return this.store.put(Si.parse({...i,runtimeVersion:t,...void 0===n?{}:{ready:n},updatedAt:this.timestamp()}))}async waitUntil(e,t,n){const i=this.now().getTime()+t;for(;;){const t=this.store.get(e);if(t&&n(t))return!0;if(this.cancelled.has(e))return!1;if(this.now().getTime()>=i)return!1;await this.delay(Math.min(this.pollIntervalMs,Math.max(0,i-this.now().getTime())))}}requireInstance(e){const t=this.store.get(e);if(!t)throw new Error(`Instance ${e} was removed during runtime reconciliation.`);return t}timestamp(){return this.now().toISOString()}}function go(e){return e?.build?.packageVersion||e?.instanceVersion}function fo(e){return e.apps.runningCount>0||e.aiSessions.runningCount>0}function yo(e){return["created","stopped","failed"].includes(e.status)}function Io(e,t){return Ao("INSTANCE_RUNTIME_VERSION_MISMATCH",`Expected controlled-instance ${e}, received ${t||"an unknown version"}.`,e,t,!0)}function Ao(e,t,n,i,r){return{code:e,message:t,expectedVersion:n,...i?{actualVersion:i}:{},retryable:r}}function bo(e,t,n){if(e&&"object"==typeof e&&"code"in e&&"message"in e){const i=e,r=In.shape.code.safeParse(i.code);if(r.success&&"string"==typeof i.message)return Ao(r.data,i.message,t,n,"boolean"!=typeof i.retryable||i.retryable)}return Ao("INSTANCE_RUNTIME_INSTALL_FAILED",e instanceof Error?e.message:String(e),t,n,!0)}function wo(e,t,n,i){const r=i?.message?` Last error: ${i.message}`:"";return Ao(i?.code||"INSTANCE_RUNTIME_INSTALL_FAILED",`Runtime convergence paused after ${n} attempts and will retry.${r}`,e,t,!0)}function vo(e,t){if(!Number.isFinite(e)||e<0)throw new TypeError(`${t} must be a nonnegative finite number.`);return e}function Eo(e,n=448){t.mkdirSync(e,{recursive:!0,mode:n}),t.chmodSync(e,n)}function No(e,i,r={}){const o=r.directoryMode??448,s=r.fileMode??384;Eo(n.dirname(e),o),I.sync(e,`${JSON.stringify(i,null,2)}\n`,{encoding:"utf8",mode:s}),t.chmodSync(e,s)}function So(e,t){console.warn(JSON.stringify({message:e,...t}))}function To(e){return e&&"object"==typeof e&&"issues"in e?{issues:e.issues}:{error:e instanceof Error?e.message:String(e)}}function zo(e,n){const i=n.logger||So;let r;try{r=JSON.parse(t.readFileSync(e,"utf8"))}catch(t){return void i("stored JSON could not be read",{filePath:e,...To(t)})}if(!n.schema)return r;const o=n.sanitize?n.sanitize(r):r,s=n.schema.safeParse(o);if(s.success)return s.data;const a="strip"in n.schema&&"function"==typeof n.schema.strip?n.schema.strip().safeParse(o):void 0;if(a?.success)return i("unknown stored fields were ignored",{filePath:e,issues:s.error.issues}),a.data;i("stored record failed validation and was isolated",{filePath:e,issues:s.error.issues})}function _o(e){return`${e}_${d.randomUUID().replace(/-/g,"").slice(0,20)}`}function Co(){return d.randomBytes(24).toString("base64url")}class ko{directory;options;permissionsInitialized=!1;constructor(e,t={}){this.directory=e,this.options=t}init(){if(this.permissionsInitialized&&t.existsSync(this.directory))return;Eo(this.directory,this.options.directoryMode??448);const e=this.options.fileMode??384;for(const i of t.readdirSync(this.directory).filter(e=>e.endsWith(".json")))t.chmodSync(n.join(this.directory,i),e);this.permissionsInitialized=!0}filePath(e){return n.join(this.directory,`${e}.json`)}list(){return this.init(),t.readdirSync(this.directory).filter(e=>e.endsWith(".json")).sort().flatMap(e=>{const t=zo(n.join(this.directory,e),this.options);return t?[t]:[]})}get(e){this.init();const n=this.filePath(e);return t.existsSync(n)?zo(n,this.options):void 0}put(e){const t=this.options.sanitize?this.options.sanitize(e):e,n=this.options.schema?this.options.schema.parse(t):t;return No(this.filePath(n.id),n,this.options),n}patch(e,t){const n=this.get(e);if(!n)return;const i={...n,...t,id:n.id,createdAt:n.createdAt,updatedAt:(new Date).toISOString()};return this.put(i)}delete(e){const n=this.filePath(e);return!!t.existsSync(n)&&(t.unlinkSync(n),!0)}}class Oo{filePathValue;defaults;options;constructor(e,t,n={}){this.filePathValue=e,this.defaults=t,this.options=n}init(){Eo(n.dirname(this.filePathValue),this.options.directoryMode??448),t.existsSync(this.filePathValue)?t.chmodSync(this.filePathValue,this.options.fileMode??384):this.put(this.defaults())}get(){return this.init(),t.existsSync(this.filePathValue)?zo(this.filePathValue,this.options)??this.defaults():this.defaults()}put(e){const t=this.options.sanitize?this.options.sanitize(e):e,n=this.options.schema?this.options.schema.parse(t):t;return No(this.filePathValue,n,this.options),n}}const Ro=a.z.record(a.z.string(),a.z.string()),xo=new Set(["OPENAI_API_KEY","OPENAI_BASE_URL","CODEX_MODEL","TASK_HANDOFF_CODEX_BASE_URL","TASK_HANDOFF_CODEX_MODEL","TASK_HANDOFF_CODEX_MODEL_ID","ANTHROPIC_API_KEY","ANTHROPIC_BASE_URL","CLAUDE_MODEL","TASK_HANDOFF_CLAUDE_MODEL","TASK_HANDOFF_CLAUDE_MODEL_ID"]);class Do{directory;constructor(e){this.directory=e}get(e){try{return Ro.parse(JSON.parse(t.readFileSync(this.filePath(e),"utf8")))}catch(t){if(t&&"object"==typeof t&&"code"in t&&"ENOENT"===t.code)return{};throw new Error(`Stored model environment for instance ${e} is invalid: ${t instanceof Error?t.message:String(t)}`)}}has(e){return t.existsSync(this.filePath(e))}listInstanceIds(){return t.existsSync(this.directory)?t.readdirSync(this.directory).filter(e=>e.endsWith(".json")).map(e=>e.slice(0,-5)).sort():[]}put(e,n){const i=Ro.parse(n);t.mkdirSync(this.directory,{recursive:!0,mode:448});const r=this.filePath(e);return I.sync(r,`${JSON.stringify(i,null,2)}\n`,{encoding:"utf8",mode:384}),t.chmodSync(r,384),i}delete(e){t.rmSync(this.filePath(e),{force:!0})}filePath(e){return n.join(this.directory,`${e}.json`)}}class Po{directory;nodeId;constructor(e,t){this.directory=e,this.nodeId=t}init(){t.mkdirSync(this.directory,{recursive:!0,mode:448}),t.chmodSync(this.directory,448)}list(){return this.init(),t.readdirSync(this.directory).filter(e=>e.endsWith(".json")).sort().flatMap(e=>{const t=this.read(n.join(this.directory,e));return t?[t]:[]})}get(e){const n=this.filePath(e);return t.existsSync(n)?this.read(n):void 0}put(e){const n=Pn.parse(e);this.init();const i=this.filePath(n.id);return I.sync(i,`${JSON.stringify(n,null,2)}\n`,{encoding:"utf8",mode:384}),t.chmodSync(i,384),n}delete(e){const n=this.filePath(e);return!!t.existsSync(n)&&(t.unlinkSync(n),!0)}read(e){try{const i=JSON.parse(t.readFileSync(e,"utf8")),r=n.basename(e,".json"),o=Pn.safeParse(i);if(o.success&&o.data.id===r&&Kn(o.data)===o.data.id)return o.data;const s=Pn.strip().safeParse(i);return s.success&&s.data.id===r&&Kn(s.data)===s.data.id?(console.warn(JSON.stringify({message:"unknown stored node model fields were ignored",nodeId:this.nodeId,filePath:e})),s.data):void console.warn(JSON.stringify({message:"stored node model failed validation and was isolated",nodeId:this.nodeId,filePath:e}))}catch(t){return void console.warn(JSON.stringify({message:"stored node model could not be read",nodeId:this.nodeId,filePath:e,error:t instanceof Error?t.message:String(t)}))}}filePath(e){return n.join(this.directory,`${e}.json`)}}class Mo{directory;constructor(e){this.directory=e}init(){t.mkdirSync(this.directory,{recursive:!0,mode:448}),t.chmodSync(this.directory,448)}get(e){const n=this.filePath(e);if(t.existsSync(n))try{const i=JSON.parse(t.readFileSync(n,"utf8")),r=jn.safeParse(i);if(r.success)return r.data;const o=jn.strip().safeParse(i);if(o.success)return console.warn(JSON.stringify({message:"unknown stored model assignment fields were ignored",instanceId:e,filePath:n})),o.data;throw r.error}catch(t){throw Object.assign(new Error(`Stored model assignment for instance ${e} is invalid.`),{statusCode:409,code:"NODE_MODEL_ASSIGNMENT_INVALID",cause:t})}}put(e){const n=jn.parse(e);this.init();const i=this.filePath(n.instanceId);return I.sync(i,`${JSON.stringify(n,null,2)}\n`,{encoding:"utf8",mode:384}),t.chmodSync(i,384),n}delete(e){t.rmSync(this.filePath(e),{force:!0})}filePath(e){return n.join(this.directory,`${e}.json`)}}function Lo(){return(new Date).toISOString()}class jo{models;assignments;legacyEnvironments;nodeId;instances;constructor(e,t,n){this.nodeId=t,this.instances=n,this.models=new Po(e.nodeModelsDir,t),this.assignments=new Mo(e.modelAssignmentsDir),this.legacyEnvironments=new Do(e.modelEnvironmentsDir)}init(){this.models.init(),this.assignments.init(),this.migrateLegacyEnvironments()}list(){const e=new Map;for(const t of this.instances.list()){const n=this.assignments.get(t.id);for(const t of[n?.codexModelHash,n?.claudeModelHash])t&&e.set(t,(e.get(t)||0)+1)}return this.models.list().map(t=>this.toPublic(t,e.get(t.id)||0))}create(e){const t=Lo(),n=Kn(e),i=this.models.get(n),r=Pn.parse({...e,id:n,enabled:e.enabled??!0,order:e.order??this.nextOrder(),labels:e.labels||{},createdAt:i?.createdAt||t,updatedAt:t});return this.toPublic(this.models.put(r),this.referenceIds(n).length)}deploy(e){const t=Kn(e);if(e.id!==t)throw Object.assign(new Error(`Model content hash ${t} does not match ${e.id}.`),{statusCode:400,code:"NODE_MODEL_HASH_MISMATCH"});const n=this.models.get(e.id)||this.models.put(Pn.parse(e));return this.toPublic(n,this.referenceIds(n.id).length)}update(e,t){const n=this.requireModel(e),i=Pn.parse({...n,...t,key:t.key?.trim()?t.key:n.key,createdAt:n.createdAt,updatedAt:Lo()}),r=Kn(i),o=this.models.put(Pn.parse({...i,id:r}));return this.toPublic(o,this.referenceIds(r).length)}delete(e){this.requireModel(e);const t=this.referenceIds(e);if(t.length)throw Object.assign(new Error(`Model ${e} is assigned to ${t.length} instance${1===t.length?"":"s"}.`),{statusCode:409,code:"NODE_MODEL_IN_USE",instanceIds:t});return this.models.delete(e)}assign(e,t){const n=this.instances.require(e);if(this.validateRef("codex",t.codexModelHash),this.validateRef("claude",t.claudeModelHash),void 0!==t.modelSelection.codexModelHash&&(t.modelSelection.codexModelHash??void 0)!==t.codexModelHash)throw Object.assign(new Error("Codex model selection does not match its node assignment."),{statusCode:400,code:"NODE_MODEL_SELECTION_MISMATCH"});if(void 0!==t.modelSelection.claudeModelHash&&(t.modelSelection.claudeModelHash??void 0)!==t.claudeModelHash)throw Object.assign(new Error("Claude model selection does not match its node assignment."),{statusCode:400,code:"NODE_MODEL_SELECTION_MISMATCH"});const i=this.assignments.get(e),r=jn.parse({instanceId:e,codexModelHash:t.codexModelHash,claudeModelHash:t.claudeModelHash,updatedAt:Lo()});this.assignments.put(r);try{return{assignment:r,instance:this.instances.put(Si.parse({...n,modelSelection:t.modelSelection,updatedAt:Lo()}))}}catch(t){throw i?this.assignments.put(i):this.assignments.delete(e),t}}resolvedEnvironment(e){const t=this.assignments.get(e);if(!t){if(this.legacyEnvironments.has(e))throw Object.assign(new Error(`Legacy model environment for instance ${e} requires manual migration.`),{statusCode:409,code:"NODE_MODEL_MIGRATION_REQUIRED"});return{}}return{...this.environmentForRef("codex",t.codexModelHash),...this.environmentForRef("claude",t.claudeModelHash)}}deleteInstanceMetadata(e){this.assignments.delete(e),this.legacyEnvironments.delete(e)}validateRef(e,t){if(!t)return;const n=this.requireModel(t);if(n.app!==e)throw Object.assign(new Error(`Model ${n.id} belongs to ${n.app}, not ${e}.`),{statusCode:400,code:"NODE_MODEL_APP_MISMATCH"});if(!n.enabled)throw Object.assign(new Error(`Model ${n.id} is disabled.`),{statusCode:409,code:"NODE_MODEL_DISABLED"})}environmentForRef(e,t){if(!t)return{};this.validateRef(e,t);const n=this.requireModel(t);return"codex"===e?{OPENAI_API_KEY:n.key,OPENAI_BASE_URL:n.endpoint,TASK_HANDOFF_CODEX_BASE_URL:n.endpoint,TASK_HANDOFF_CODEX_MODEL:n.model}:{ANTHROPIC_API_KEY:n.key,ANTHROPIC_BASE_URL:n.endpoint,TASK_HANDOFF_CLAUDE_MODEL:n.model}}requireModel(e){const t=this.models.get(e);if(!t)throw Object.assign(new Error(`Model ${e} was not found on node ${this.nodeId}.`),{statusCode:404,code:"NODE_MODEL_NOT_FOUND"});if(Kn(t)!==t.id)throw Object.assign(new Error(`Stored model ${e} does not match its content hash.`),{statusCode:409,code:"NODE_MODEL_HASH_INVALID"});return t}referenceIds(e){return this.instances.list().filter(t=>{const n=this.assignments.get(t.id);return n?.codexModelHash===e||n?.claudeModelHash===e}).map(e=>e.id)}toPublic(e,t){const{key:n,...i}=e;return Ln.parse({...i,keyPreview:n.length<=8?"set":`${n.slice(0,4)}...${n.slice(-4)}`,keySet:!0,referenceCount:t})}nextOrder(){return this.models.list().reduce((e,t)=>Math.max(e,t.order),0)+100}migrateLegacyEnvironments(){for(const e of this.legacyEnvironments.listInstanceIds()){if(!this.instances.has(e)){this.warnMigration(e,"instance-not-found");continue}if(this.assignments.get(e)){try{this.resolvedEnvironment(e),this.legacyEnvironments.delete(e)}catch{this.warnMigration(e,"existing-assignment-invalid")}continue}let t;try{t=this.legacyEnvironments.get(e)}catch{this.warnMigration(e,"sidecar-invalid");continue}if(!Object.keys(t).length){this.legacyEnvironments.delete(e);continue}if(Object.keys(t).some(e=>!xo.has(e))){this.warnMigration(e,"unknown-fields");continue}const n=[];try{const i=this.migrateApp(t,"codex",n),r=this.migrateApp(t,"claude",n);if(!i&&!r)throw new Error("no complete model configuration");const o={...i?{codexModelHash:i}:{},...r?{claudeModelHash:r}:{}};this.assign(e,{modelSelection:o,codexModelHash:i,claudeModelHash:r}),this.resolvedEnvironment(e),this.legacyEnvironments.delete(e)}catch{this.assignments.delete(e);for(const e of n)this.models.delete(e);this.warnMigration(e,"mapping-failed")}}}migrateApp(e,t,n){const i=e["codex"===t?"OPENAI_API_KEY":"ANTHROPIC_API_KEY"],r="codex"===t?e.TASK_HANDOFF_CODEX_BASE_URL||e.OPENAI_BASE_URL:e.ANTHROPIC_BASE_URL,o="codex"===t?e.TASK_HANDOFF_CODEX_MODEL||e.CODEX_MODEL:e.TASK_HANDOFF_CLAUDE_MODEL||e.CLAUDE_MODEL;if(!i&&!r&&!o)return;if(!i||!r||!o)throw new Error("model configuration incomplete");const s=Kn({app:t,endpoint:r,key:i,model:o}),a=this.models.get(s);if(a){if(a.app!==t||a.key!==i||a.endpoint!==r||a.model!==o||!a.enabled)throw new Error("existing model conflicts with legacy environment");return s}const c=Lo();return this.models.put(Pn.parse({id:s,name:`Migrated ${"codex"===t?"Codex":"Claude"} model`,endpoint:r,key:i,model:o,app:t,enabled:!0,order:this.nextOrder(),labels:{migratedFrom:"instance-model-environment"},createdAt:c,updatedAt:c})),n.push(s),s}warnMigration(e,t){console.warn(JSON.stringify({message:"legacy model environment was preserved because it could not be migrated",nodeId:this.nodeId,instanceId:e,reason:t}))}}function $o(){return(new Date).toISOString()}function Fo(e,t){if(!e)return!0;const n=A.valid(e),i=A.valid(t);return n&&i?A.gt(i,n):e!==t}function Uo(){return process.env.TASK_HANDOFF_NPM_COMMAND||"npm"}function Vo(e,i){const r=n.join(e,...i.split("/"),"package.json");try{const e=JSON.parse(t.readFileSync(r,"utf8"));if(e.name!==i||"string"!=typeof e.version||!e.version.trim())throw new Error(`Installed package manifest is invalid: ${r}`);return{name:i,version:e.version.trim()}}catch(e){if("ENOENT"===e.code)return;throw e}}async function qo(e){const t=(await e(Uo(),["root","--global"])).stdout.trim();if(!t)throw new Error("npm did not return its global module root.");const n=Vo(t,"@task-handoff/server"),i=Vo(t,"@task-handoff/node-agent");return n?{packageName:"@task-handoff/server",currentVersion:n.version,relatedCurrentVersions:i?[i.version]:[]}:{packageName:"@task-handoff/node-agent",currentVersion:i?.version,relatedCurrentVersions:[]}}function Ho(e){if(!e||"object"!=typeof e||Array.isArray(e))return e;const t=e,n="string"==typeof t.updatedAt?t.updatedAt:$o(),i=t.target&&"object"==typeof t.target&&!Array.isArray(t.target)?t.target:void 0,r="controlled-instance"===i?.component,o={updating:"updating-node",downloading:"updating-node",installing:"updating-node",restarting:"restarting-node",completed:"succeeded",success:"succeeded",error:"failed"},s=new Set(["queued","updating-node","restarting-node","converging-instances","succeeded","degraded","failed"]),a="string"==typeof t.status?t.status:"queued",c=r?"failed":s.has(a)?a:o[a]||"failed",d="string"==typeof t.toVersion&&t.toVersion?t.toVersion:"unknown",l=bn.strip().safeParse(t.impact).success?bn.strip().parse(t.impact):{runningInstanceCount:0,stoppedInstanceCount:0,activeInstanceCount:0,restartInstanceCount:0,runningInstanceIds:[],stoppedInstanceIds:[],activeInstanceIds:[]},u=r?{code:"LEGACY_INSTANCE_UPDATE_RETIRED",message:"Independent controlled-instance update jobs were retired in favor of Node reconciliation.",retryable:!1}:"failed"!==c||t.error||s.has(a)||a in o?"string"==typeof t.error?{code:"NODE_UPDATE_FAILED",message:t.error,retryable:!1}:In.strip().safeParse(t.error).success?In.strip().parse(t.error):t.error&&"object"==typeof t.error?{code:"NODE_UPDATE_FAILED",message:"string"==typeof t.error.message?t.error.message:"Stored update job contained an unknown error.",retryable:!1}:void 0:{code:"NODE_UPDATE_FAILED",message:`Stored update job used an unknown status: ${a}.`,retryable:!1},{target:m,error:p,...h}=t,g={phase:"succeeded"===c?"succeeded":"failed"===c?"failed":c||"queued",desiredVersion:d,expectedInstanceIds:[],expectedInstanceCount:0,matchedInstanceCount:0,pendingInstanceCount:0,failedInstanceCount:r||"failed"===c?1:0,deferredInstanceCount:0},f=wn.strip().safeParse(t.rollout);return{...h,source:"npm",status:c,impact:l,runtimeArtifacts:Array.isArray(t.runtimeArtifacts)?t.runtimeArtifacts.flatMap(e=>{const t=yn.strip().safeParse(e);return t.success?[t.data]:[]}):[],rollout:f.success?f.data:g,...u?{error:u}:{},...r?{completedAt:t.completedAt||n}:{}}}class Bo{records;constructor(e){this.records=new ko(e.updatesDir,{schema:Nn,sanitize:Ho})}init(){this.records.init()}list(){return this.records.list().sort((e,t)=>t.createdAt.localeCompare(e.createdAt))}create(e,t){const n=$o();return this.records.put(Nn.parse({id:_o("update"),nodeId:e,source:t.source,channel:t.channel,fromVersion:t.currentVersion,toVersion:t.availableVersion,artifactRef:t.artifactRef,runtimeArtifacts:t.runtimeArtifacts,impact:t.impact,status:"queued",rollout:{phase:"queued",desiredVersion:t.availableVersion,expectedInstanceIds:t.impact.runningInstanceIds,expectedInstanceCount:t.impact.runningInstanceCount,matchedInstanceCount:0,pendingInstanceCount:t.impact.runningInstanceCount,failedInstanceCount:0,deferredInstanceCount:t.impact.stoppedInstanceCount},createdAt:n,updatedAt:n}))}patch(e,t){const n=this.records.get(e);if(!n)throw Object.assign(new Error(`Update job ${e} was not found.`),{statusCode:404,code:"UPDATE_JOB_NOT_FOUND"});return this.records.put(Nn.parse({...n,...t,id:e,createdAt:n.createdAt,updatedAt:$o()}))}reconcileRollouts(e,t,n={}){const i=new Map(e.map(e=>[e.id,e]));for(const e of this.list().filter(e=>["updating-node","restarting-node","converging-instances"].includes(e.status))){if(n.processStarted&&"restarting-node"===e.status&&t!==e.toVersion){this.patch(e.id,{status:"failed",rollout:{...e.rollout,phase:"failed",nodeVersion:t},error:{code:"NODE_UPDATE_FAILED",message:`Node agent restarted with version ${t}, expected ${e.toVersion}.`,retryable:!1},completedAt:$o()});continue}const r="converging-instances"!==e.status&&t===e.toVersion?this.patch(e.id,{status:"converging-instances",rollout:{...e.rollout,phase:"converging-instances",nodeVersion:t}}):e;if("converging-instances"!==r.status)continue;const o=r.rollout.expectedInstanceIds,s=o.map(e=>i.get(e)),a=s.filter(e=>e?.ready&&"matched"===e.runtimeVersion?.phase&&e.runtimeVersion.actualVersion===r.toVersion).length,c=s.filter(e=>e&&["created","stopped","failed"].includes(e.status||"")&&"failed"!==e.runtimeVersion?.phase).length,d=s.filter(e=>!e||"failed"===e.runtimeVersion?.phase).length,l=Math.max(0,o.length-a-d-c),u=d>0?"degraded":0===l?"succeeded":"converging-instances";this.patch(r.id,{status:u,rollout:{...r.rollout,phase:u,nodeVersion:t,expectedInstanceCount:o.length,matchedInstanceCount:a,pendingInstanceCount:l,failedInstanceCount:d,deferredInstanceCount:r.impact.stoppedInstanceCount+c},..."succeeded"===u||"degraded"===u?{completedAt:$o()}:{}})}}run(e,t){(async()=>{this.patch(e.id,{status:"updating-node",rollout:{...e.rollout,phase:"updating-node"},startedAt:$o(),error:void 0});try{await t(e),this.patch(e.id,{status:"succeeded",completedAt:$o()})}catch(t){this.patch(e.id,{status:"failed",rollout:{...e.rollout,phase:"failed"},error:{code:"NODE_UPDATE_FAILED",message:t instanceof Error?t.message:String(t),retryable:!1},completedAt:$o()})}})()}}function Ko(){return(new Date).toISOString()}class Go{records;constructor(e){this.records=new ko(e.environmentTemplatesDir,{schema:Zt,sanitize:e=>function(e,t){if(!e||"object"!=typeof e||Array.isArray(e))return e;const n=e,i=new Set(["id","name","sourceInstanceId","nodeId","imageId","internalTag","platform","architecture","sizeBytes","status","error","createdAt","updatedAt"]),r="string"==typeof n.id?n.id:void 0;for(const e of Object.keys(n))i.has(e)||t?.({templateId:r,field:e});const o=Ri(n,[...i]);if(n.error&&"object"==typeof n.error&&!Array.isArray(n.error)){const e=n.error;for(const n of Object.keys(e))["code","message","phase"].includes(n)||t?.({templateId:r,field:`error.${n}`});o.error=Ri(e,["code","message","phase"])}return o}(e,e=>{console.warn(JSON.stringify({message:"unknown stored environment template field was ignored",...e}))})})}init(){this.records.init();for(const e of this.records.list())"creating"===e.status&&this.records.put(Zt.parse({...e,status:"failed",error:{code:"ENVIRONMENT_TEMPLATE_CREATION_INTERRUPTED",message:"Environment template creation was interrupted by a node-agent restart.",phase:"recovery"},updatedAt:Ko()}))}list(){return this.records.list()}get(e){return this.records.get(e)}put(e){return this.records.put(Zt.parse(e))}patch(e,t){return this.records.patch(e,t)}delete(e){return this.records.delete(e)}}const Jo=a.z.record(a.z.string().regex(/^[A-Za-z_][A-Za-z0-9_]*$/),a.z.string()),Wo=a.z.object({version:a.z.literal(1),instanceId:a.z.string().trim().min(1).max(120),instanceCredential:a.z.string().trim().min(1).max(240),environment:Jo,updatedAt:a.z.string().datetime()}).strict();class Yo{directory;constructor(e){this.directory=e.instancePrivateConfigsDir}init(){t.mkdirSync(this.directory,{recursive:!0,mode:448}),t.chmodSync(this.directory,448);for(const e of t.readdirSync(this.directory).filter(e=>e.endsWith(".json")))t.chmodSync(n.join(this.directory,e),384)}filePath(e){return n.join(this.directory,`${e}.json`)}get(e){const n=this.filePath(e);if(!t.existsSync(n))return;const i=JSON.parse(t.readFileSync(n,"utf8")),r=i&&"object"==typeof i&&!Array.isArray(i)?i:{},o=Wo.parse({version:r.version,instanceId:r.instanceId,instanceCredential:r.instanceCredential??r.registrationToken,environment:r.environment,updatedAt:r.updatedAt});if(o.instanceId!==e)throw Object.assign(new Error(`Private config identity mismatch for instance ${e}.`),{statusCode:409,code:"INSTANCE_PRIVATE_CONFIG_IDENTITY_MISMATCH"});return void 0===r.instanceCredential&&void 0!==r.registrationToken&&this.put(o),o}put(e){const n=Wo.parse(e);this.init();const i=this.filePath(n.instanceId);return I.sync(i,`${JSON.stringify(n,null,2)}\n`,{encoding:"utf8",mode:384}),t.chmodSync(i,384),n}materialize(e,t,n){if(!t)throw Object.assign(new Error(`Instance ${e} does not have a long-lived credential.`),{statusCode:409,code:"INSTANCE_PRIVATE_CONFIG_CREDENTIAL_MISSING"});return this.put({version:1,instanceId:e,instanceCredential:t,environment:n,updatedAt:(new Date).toISOString()})}delete(e){t.rmSync(this.filePath(e),{force:!0})}}const Xo=function(e,t=process.env,n=e){let i;return()=>{const r=t.TASK_HANDOFF_VERSION?.trim();return r||(i||=E(e,t,n),i)}}("@task-handoff/node-agent",process.env,"@task-handoff/control-plane");function Qo(){return Xo()}function Zo(e,t){return{code:"INSTANCE_RUNTIME_VERSION_MISMATCH",message:`Expected controlled-instance ${e}, received ${t||"an unknown version"}.`,expectedVersion:e,...t?{actualVersion:t}:{},retryable:!0}}function es(e){const t=Qo();return e===t?{desiredVersion:t,actualVersion:e,phase:"matched",attempt:0,matchedAt:(new Date).toISOString()}:{desiredVersion:t,...e?{actualVersion:e}:{},phase:"pending",attempt:0,error:Zo(t,e)}}function ts(e,t,n=!0){if(!n)return es(t);const i=Qo(),r=e.runtimeVersion;if(!r||r.desiredVersion!==i)return es(t);const o="INSTANCE_RUNTIME_VERSION_MISMATCH"!==r.error?.code?r.error:t===i?void 0:Zo(i,t);return An.parse({...r,desiredVersion:i,...t?{actualVersion:t}:{actualVersion:void 0},..."pending"===r.phase?{error:o||(t!==i?Zo(i,t):void 0)}:{}})}const ns="runtime_local_host",is="task-handoff.node-agent.builtin";function rs(){return(new Date).toISOString()}function os(e){const t={...e};return delete t[is],t}function ss(e){return"local-folder"===e.type?On.parse({mode:"local-bind",path:"/workspace",readOnly:!1}):On.parse({mode:"git-clone",path:"/workspace",readOnly:!1})}function as(e){const t=kn.parse(e.source),n=e.projectId||("local-folder"===t.type?t.localFolderId:void 0)||("git-repository"===t.type?t.repositoryId:void 0)||("git-template"===t.type?t.templateId:void 0)||`project_${e.id}`;return xn.parse({id:n,name:"string"==typeof e.sourceSnapshot.name?e.sourceSnapshot.name:e.name,source:t,defaultImageSelection:e.imageSelection,defaultNodeId:e.nodeId,defaultRuntimeId:e.runtimeId,workspacePolicy:ss(t),labels:{},createdAt:e.createdAt,updatedAt:e.updatedAt})}function cs(e,t){throw Object.assign(new Error(t),{statusCode:403,code:e})}function ds(e,t){e!==It&&console.warn(JSON.stringify({message:"protocol version mismatch",peer:t,expectedProtocolVersion:It,actualProtocolVersion:e||"missing",errorCode:"PROTOCOL_VERSION_MISMATCH"}))}function ls(e){return"none"!==e.capabilities.artifactKind}function us(e={}){return{...e,requiresImage:!1,supportsControlledInstanceApi:!0,supportsContainerLifecycle:!1,supportsAppSessions:!0,supportsHostSessions:!0,artifactKind:"none",isolation:"none"}}class ms extends ko{onStored;privateConfigs;constructor(e,t,n){super(e,t),this.privateConfigs=n}setOnStored(e){this.onStored=e}put(e){const t=super.get(e.id)?.stateRevision||0,n=this.privateConfigs.get(e.id),i=e.registrationToken||n?.instanceCredential;i&&this.privateConfigs.materialize(e.id,i,n?.environment||{});const{registrationToken:r,...o}=e,s=super.put(Si.parse({...o,stateRevision:Math.max(e.stateRevision||0,t)+1})),a=this.hydrate(s);return this.onStored?.(a),a}get(e){const t=super.get(e);return t?this.hydrate(t):void 0}list(){return super.list().map(e=>this.hydrate(e))}hydrate(e){const t=this.privateConfigs.get(e.id)?.instanceCredential||e.registrationToken;return Si.parse({...e,registrationToken:t})}}class ps{nodeId;paths;localFolders;nodeRuntimes;controlledInstances;environmentTemplates;instancePrivateConfigs;modelRegistry;updateJobs;node;listenerPort;containerUrlOverride;platform;constructor(e,t,n,i,r,o){this.paths=e,this.nodeId=t,this.localFolders=new ko(e.localFoldersDir,{schema:Cn,sanitize:Wt}),this.nodeRuntimes=new ko(e.nodeRuntimesDir,{schema:hi}),this.instancePrivateConfigs=new Yo(e),this.controlledInstances=new ms(e.controlledInstancesDir,{schema:Si,sanitize:e=>Ci(e,e=>{console.warn(JSON.stringify({message:"legacy controlled instance field was ignored",...e}))})},this.instancePrivateConfigs),this.environmentTemplates=new Go(e),this.modelRegistry=new jo(e,t,{has:e=>Boolean(this.controlledInstances.get(e)),list:()=>this.listInstances(),require:e=>this.requireInstance(e),put:e=>this.controlledInstances.put(e)}),this.updateJobs=new Bo(e),this.listenerPort=r,this.platform=o,this.containerUrlOverride=i;const s=rs();this.node=pi.parse({id:t,name:t,connectionMode:"direct-http",endpoint:n,controlEndpoint:n,containerEndpoint:this.containerUrl,publicWebBase:n?n.replace(/:\d+$/,""):void 0,status:"online",health:"ok",capabilities:{},labels:{},createdAt:s,updatedAt:s})}init(){this.localFolders.init();for(const e of this.localFolders.list())this.localFolders.put(e);if(this.nodeRuntimes.init(),this.instancePrivateConfigs.init(),this.controlledInstances.init(),this.environmentTemplates.init(),this.modelRegistry.init(),this.updateJobs.init(),this.updateJobs.reconcileRollouts(this.controlledInstances.list(),Qo(),{processStarted:!0}),!this.nodeRuntimes.get("runtime_local_docker")){const e=rs();this.nodeRuntimes.put(hi.parse({id:"runtime_local_docker",nodeId:this.nodeId,name:"Local Docker",type:"docker",status:"unknown",accessStrategy:"direct-port",capabilities:{},labels:{},createdAt:e,updatedAt:e}))}if("win32"!==this.platform){const e=this.nodeRuntimes.get(ns),t=rs();this.nodeRuntimes.put(hi.parse({id:ns,nodeId:this.nodeId,name:"Local Runtime",type:"local",status:e?.status||"unknown",accessStrategy:"node-proxy",capabilities:us(e?.capabilities),labels:{...e?.labels,[is]:"true"},createdAt:e?.createdAt||t,updatedAt:e?.updatedAt||t}))}for(const e of this.nodeRuntimes.list())e.nodeId!==this.nodeId&&this.nodeRuntimes.put(hi.parse({...e,nodeId:this.nodeId,updatedAt:rs()}));for(const e of this.localFolders.list())e.nodeId!==this.nodeId&&this.localFolders.put(Cn.parse({...e,nodeId:this.nodeId,updatedAt:rs()}));this.normalizeInstanceRuntimeVersions()}normalizeInstanceRuntimeVersions(){for(const e of this.controlledInstances.list()){const t=es(e.build?.packageVersion||e.instanceVersion),n=ls(this.requireRuntime(e.runtimeId)),i=["created","stopped","failed"].includes(e.status),r=n&&e.runtimeVersion?.desiredVersion===t.desiredVersion?e.runtimeVersion:void 0,o=n?"matched"===t.phase?i?t:{...t,phase:"verifying",matchedAt:void 0}:{...t,phase:"pending",attempt:r?.attempt||0,lastAttemptAt:r?.lastAttemptAt,error:r?.error||t.error}:t;this.controlledInstances.put(Si.parse({...e,ready:!1,runtimeVersion:o,updatedAt:rs()}))}}get localNodeAgentUrl(){return`http://127.0.0.1:${this.listenerPort}`}get currentListenerPort(){return this.listenerPort}get containerUrl(){return this.containerUrlOverride||`http://host.docker.internal:${this.listenerPort}`}setListenerPort(e){this.listenerPort=e,this.node.containerEndpoint=this.containerUrl,this.node.updatedAt=rs()}runningInstanceCount(){const e=new Set(["created","stopped","failed"]);return this.listInstances().filter(t=>!e.has(t.status)).length}createLocalFolder(e){const t=rs(),n=Cn.parse({...e,id:e.id||_o("folder"),nodeId:this.nodeId,labels:e.labels||{},createdAt:t,updatedAt:t});return this.localFolders.put(n)}createRuntime(e){if("local"===e.type){const e="win32"===this.platform,t=new Error(e?"Local Runtime is not supported on Windows.":"Local Runtime is built in and cannot be added manually.");throw Object.assign(t,{statusCode:e?400:409,code:e?"LOCAL_RUNTIME_UNSUPPORTED":"LOCAL_RUNTIME_BUILTIN"}),t}const t=rs(),n=hi.parse({...e,id:e.id||_o("runtime"),nodeId:this.nodeId,accessStrategy:e.accessStrategy||(i=e.type,"docker"===i?"direct-port":"node-proxy"),capabilities:e.capabilities||{},labels:os(e.labels),createdAt:t,updatedAt:t});var i;return this.nodeRuntimes.put(n)}updateRuntime(e,t){const n=this.requireRuntime(e);if("true"===n.labels[is]){const t=new Error(`Built-in runtime ${e} cannot be modified.`);throw Object.assign(t,{statusCode:400,code:"NODE_RUNTIME_BUILTIN"}),t}if("local"===n.type||"local"===t.type){const e="win32"===this.platform,t=new Error(e?"Local Runtime is not supported on Windows.":"Local Runtime is built in and cannot be configured manually.");throw Object.assign(t,{statusCode:e?400:409,code:e?"LOCAL_RUNTIME_UNSUPPORTED":"LOCAL_RUNTIME_BUILTIN"}),t}const i=hi.parse({...n,...t,id:n.id,nodeId:this.nodeId,accessStrategy:t.accessStrategy||n.accessStrategy,capabilities:t.capabilities||n.capabilities,labels:t.labels?os(t.labels):n.labels,createdAt:n.createdAt,updatedAt:rs()});return this.nodeRuntimes.put(i)}deleteRuntime(e){if("true"===this.requireRuntime(e).labels[is]){const t=new Error(`Built-in runtime ${e} cannot be deleted.`);throw Object.assign(t,{statusCode:400,code:"NODE_RUNTIME_BUILTIN"}),t}const t=this.listInstances().filter(t=>t.runtimeId===e);if(t.length){const n=new Error(`Runtime ${e} is used by ${t.length} instance${1===t.length?"":"s"}.`);throw Object.assign(n,{statusCode:409,code:"NODE_RUNTIME_IN_USE"}),n}return this.nodeRuntimes.delete(e)}checkRuntime(e,t){const n=this.requireRuntime(e);return t.check?t.check(n).then(e=>{const t=hi.parse({...n,...e,id:n.id,nodeId:this.nodeId,createdAt:n.createdAt,updatedAt:rs()});return this.nodeRuntimes.put(t)}):this.nodeRuntimes.put(hi.parse({...n,status:"unknown",updatedAt:rs()}))}requireRuntime(e){const t=this.nodeRuntimes.get(e);if(!t){const t=new Error(`Node runtime ${e} was not found.`);throw Object.assign(t,{statusCode:404,code:"NODE_RUNTIME_NOT_FOUND"}),t}return t}requireInstance(e){const t=this.controlledInstances.get(e);if(!t){const t=new Error(`Instance ${e} was not found on node ${this.nodeId}.`);throw Object.assign(t,{statusCode:404,code:"NODE_INSTANCE_NOT_FOUND"}),t}const n=_i(t);if(!n.success)throw function(e,t){const n=t.map(e=>`${e.path.join(".")||"body"}: ${e.message}`).join("; ");return Object.assign(new Error(`Stored instance ${e} is not compatible with protocol ${It}: ${n}`),{statusCode:409,code:"NODE_INSTANCE_PAYLOAD_INVALID"})}(e,n.error.issues);return n.data}applyInstanceLifecycle(e,t){return this.controlledInstances.put(function(e,t,n=(new Date).toISOString()){switch(t.type){case"start-requested":return Si.parse({...e,status:"starting",ready:!1,updatedAt:n});case"stop-requested":return Si.parse({...e,status:"stopping",ready:!1,updatedAt:n});case"stop-failed":return"stopping"!==e.status?e:Si.parse({...e,status:t.baseline.status,health:t.baseline.health,connectionStatus:t.baseline.connectionStatus,agentStatus:t.baseline.agentStatus,targetStatus:t.baseline.targetStatus,uiAccessStatus:t.baseline.uiAccessStatus,ready:t.baseline.ready,target:{...e.target,status:t.baseline.target.status},updatedAt:n});case"convergence-restart-requested":return Si.parse({...e,build:void 0,instanceVersion:void 0,ready:!1,updatedAt:n});case"runtime-lifecycle-completed":return function(e,t,n,i){if(t.stateRevision>e.stateRevision&&["failed","stopping","stopped","deleting"].includes(t.status))return t;const r=t.stateRevision>e.stateRevision&&t.lastHeartbeatAt!==e.lastHeartbeatAt&&"online"===t.agentStatus;return Si.parse({...t,...n,...r?{status:t.status,health:t.health,connectionStatus:t.connectionStatus,agentStatus:t.agentStatus,targetStatus:t.targetStatus,uiAccessStatus:t.uiAccessStatus}:{},ready:!!r&&t.ready,target:n.target?r?{...n.target,...t.target}:{...t.target,...n.target}:t.target,workspace:n.workspace?r?{...n.workspace,...t.workspace}:{...t.workspace,...n.workspace}:t.workspace,runtime:n.runtime?{...t.runtime,...n.runtime}:t.runtime,updatedAt:i})}(t.baseline,e,t.observation,n);case"stop-completed":return Si.parse({...e,status:"stopped",health:"unknown",connectionStatus:"offline",ready:!1,agentStatus:"offline",targetStatus:"unknown",uiAccessStatus:"unknown",target:{...e.target,status:"unknown"},updatedAt:n});case"runtime-exited":case"start-failed":return Si.parse({...e,status:"failed",ready:!1,health:"failed",connectionStatus:"offline",agentStatus:"offline",targetStatus:"unknown",uiAccessStatus:"unknown",workspace:{...e.workspace,error:(i=t.error,i instanceof Error?i.message:String(i))},updatedAt:n})}var i}(this.requireInstance(e),t))}listInstances(){return this.controlledInstances.list().flatMap(e=>{const t=_i(e);return t.success?[t.data]:[]})}resolvedAssignedModelEnvironment(e){return this.modelRegistry.resolvedEnvironment(e)}createInstance(e){const t=this.requireRuntime(e.runtimeId),i=rs(),r=e.id||_o("inst"),o=kn.parse(e.source),s=e.environmentSource||(e.imageSelection?{type:"image",imageSelection:e.imageSelection}:void 0);if("template"===s?.type&&"docker"!==t.type){const e=new Error(`Runtime ${t.name} does not support environment templates.`);throw Object.assign(e,{statusCode:409,code:"ENVIRONMENT_TEMPLATE_RUNTIME_UNSUPPORTED"}),e}const a="template"===s?.type?this.environmentTemplates.get(s.environmentTemplateId):void 0;if("template"===s?.type&&(!a||"ready"!==a.status)){const e=new Error(`Environment template ${s.environmentTemplateId} is not ready on node ${this.nodeId}.`);throw Object.assign(e,{statusCode:a?409:404,code:a?"ENVIRONMENT_TEMPLATE_NOT_READY":"ENVIRONMENT_TEMPLATE_NOT_FOUND"}),e}if(a&&a.nodeId!==this.nodeId){const e=new Error(`Environment template ${a.id} belongs to node ${a.nodeId}, not ${this.nodeId}.`);throw Object.assign(e,{statusCode:409,code:"ENVIRONMENT_TEMPLATE_NODE_MISMATCH"}),e}if(function(e){return"boolean"==typeof e.capabilities.requiresImage?e.capabilities.requiresImage:"local"!==e.type}(t)&&(!s||"image"===s.type&&!e.image)){const e=new Error(`Runtime ${t.name} requires an image.`);throw Object.assign(e,{statusCode:400,code:"NODE_RUNTIME_IMAGE_REQUIRED"}),e}if("local"===t.type&&"local-folder"!==o.type){const e=new Error("Localhost runtime currently supports local folder sources only.");throw Object.assign(e,{statusCode:400,code:"LOCAL_RUNTIME_REQUIRES_LOCAL_FOLDER"}),e}if("local"===t.type&&this.listInstances().some(e=>"local"===this.requireRuntime(e.runtimeId).type)){const e=new Error("A localhost instance already exists on this node.");throw Object.assign(e,{statusCode:409,code:"LOCAL_RUNTIME_INSTANCE_EXISTS"}),e}const c=a?ri.parse({id:a.id,origin:"custom",name:a.name,repository:"task-handoff/environment-template",tag:a.id.toLowerCase().replace(/[^a-z0-9_.-]/g,"-"),requestedReference:a.internalTag,resolvedDigest:a.imageId,resolvedReference:a.internalTag,downloadSizeBytes:a.sizeBytes||void 0,pullPolicy:"if-not-present",capabilities:[],optionalApps:[],defaultEnv:{},labels:{},createdAt:a.createdAt,updatedAt:a.updatedAt}):e.image?ri.parse(e.image):void 0,d="local"===t.type&&"local-folder"===o.type?n.resolve(o.path):void 0,l=Si.parse({id:r,name:e.name||`instance-${r.replace(/^inst_?/,"").slice(0,6)}`,source:o,sourceSnapshot:e.sourceSnapshot||{},modelSelection:e.modelSelection,projectId:e.projectId,nodeId:this.nodeId,runtimeId:t.id,imageSelection:"image"===s?.type?s.imageSelection:void 0,environmentSource:s,environmentTemplateOrigin:a?{templateId:a.id,nodeId:a.nodeId,imageId:a.imageId,name:a.name,platform:a.platform,architecture:a.architecture}:void 0,imageSnapshot:c,imageProvisioning:c&&"docker"===t.type&&"template"!==s?.type?{phase:"checking-image",requestedReference:c.requestedReference,generation:0,startedAt:i,updatedAt:i}:void 0,status:c&&"docker"===t.type&&"template"!==s?.type?"provisioning":"created",health:"unknown",connectionStatus:"unknown",agentStatus:"unknown",targetStatus:"unknown",uiAccessStatus:"unknown",controlMode:"controlled",ready:!1,runtimeVersion:es(),capabilities:{},config:{autoImportAgentConfigs:e.config?.autoImportAgentConfigs??!0,defaultCodexPermissionMode:e.config?.defaultCodexPermissionMode??("docker"===t.type?"full-access":"ask")},workspace:"local"===t.type?{mode:"local-bind",status:"unknown",path:d}:{status:"unknown"},target:{strategy:"node-proxy",status:"unknown"},runtime:"local"===t.type?{kind:"local",workspacePath:d,labels:{"task-handoff.runtime-kind":"local"}}:{labels:{}},registrationToken:Co(),createdAt:i,updatedAt:i}),u=this.controlledInstances.put(l);return this.instancePrivateConfigs.materialize(u.id,u.registrationToken,this.resolvedAssignedModelEnvironment(u.id)),u}registerInstance(e,t,n){const i=xi.parse(t),r=rs(),o=this.controlledInstances.get(e);if(!o){const t=new Error(`Instance ${e} was not found on node ${this.nodeId}.`);throw Object.assign(t,{statusCode:404,code:"NODE_INSTANCE_NOT_FOUND"}),t}if(this.validateInstanceReport(o,i,n),i.processIncarnationId&&i.processIncarnationId===o.processIncarnationId)return o;ds(i.protocolVersion,`Instance ${e}`);const s=i.build?.packageVersion||i.instanceVersion,a=ls(this.requireRuntime(o.runtimeId)),c=ts(o,s,a),d=Si.parse({...o,status:"registered",health:s===Qo()?"ok":"degraded",ready:!a&&s===Qo(),connectionStatus:"online",agentStatus:"online",targetStatus:"endpoint-unreachable"===i.target.status?"endpoint-unreachable":"reachable"===i.target.status?"reachable":o.targetStatus,uiAccessStatus:"endpoint-unreachable"===i.target.status?"endpoint-unreachable":o.uiAccessStatus,controlMode:i.controlMode,protocolVersion:i.protocolVersion,instanceVersion:i.instanceVersion,build:i.build,runtimeVersion:c,processIncarnationId:i.processIncarnationId||o.processIncarnationId,capabilities:i.capabilities,appInventory:i.appInventory,workspace:i.workspace,target:{...o.target,...i.target},registrationToken:o.registrationToken||i.registrationToken,lastHeartbeatAt:r,updatedAt:r});return this.controlledInstances.put(d)}heartbeatInstance(e,t,n){const i=this.requireInstance(e);this.validateInstanceToken(i,n);const r=Di.parse(t);i.processIncarnationId&&r.processIncarnationId&&r.processIncarnationId!==i.processIncarnationId&&function(e,t){throw Object.assign(new Error(t),{statusCode:409,code:"INSTANCE_PROCESS_INCARNATION_MISMATCH"})}(0,`Instance ${e} report belongs to an obsolete controlled-instance process.`),ds(r.protocolVersion,`Instance ${e}`);const o=rs(),s=r.target?{...i.target,...r.target}:i.target,a={...s,status:"unknown"===s.status&&(s.web||s.api)?"reachable":s.status},c="endpoint-unreachable"===a.status?"endpoint-unreachable":"reachable"===a.status?"reachable":i.targetStatus,d=ts(i,r.build?.packageVersion||i.build?.packageVersion||i.instanceVersion,ls(this.requireRuntime(i.runtimeId))),l=r.health||i.health,u="running"===(r.status||i.status)&&"failed"!==l,m=Si.parse({...i,...r,target:a,ready:u,health:l,runtimeVersion:d,processIncarnationId:r.processIncarnationId||i.processIncarnationId,agentStatus:"online",targetStatus:c,uiAccessStatus:c,connectionStatus:"online",build:r.build||i.build,lastHeartbeatAt:o,updatedAt:o});return this.controlledInstances.put(m)}validateInstanceReport(e,t,n){this.validateInstanceToken(e,n||t.registrationToken),t.instanceId&&t.instanceId!==e.id&&cs("INSTANCE_ID_MISMATCH",`Instance ${t.instanceId} cannot register as ${e.id}.`),t.nodeId&&t.nodeId!==this.nodeId&&cs("INSTANCE_NODE_MISMATCH",`Instance ${e.id} belongs to node ${this.nodeId}.`),t.runtimeId&&t.runtimeId!==e.runtimeId&&cs("INSTANCE_RUNTIME_MISMATCH",`Instance ${e.id} belongs to runtime ${e.runtimeId}.`),t.imageSelection&&t.imageSelection.imageId!==e.imageSelection?.imageId&&cs("INSTANCE_IMAGE_MISMATCH",`Instance ${e.id} belongs to image ${e.imageSelection?.imageId}.`)}validateInstanceToken(e,t){e.registrationToken&&t===e.registrationToken||cs("INSTANCE_REGISTRATION_TOKEN_INVALID",`Invalid registration token for instance ${e.id}.`)}context(e,t=this.resolvedAssignedModelEnvironment(e.id)){const n=e.imageSnapshot||ri.parse({id:"img_localhost",origin:"custom",name:"Localhost",repository:"localhost",tag:"local",requestedReference:"localhost:local",pullPolicy:"if-not-present",capabilities:[],optionalApps:[],defaultEnv:{},labels:{},createdAt:e.createdAt,updatedAt:e.updatedAt}),i=this.instancePrivateConfigs.materialize(e.id,e.registrationToken,t);return{project:as(e),image:n,node:this.node,runtime:this.requireRuntime(e.runtimeId),instance:e,nodeAgentUrl:this.containerUrl,modelEnv:t,privateConfigPath:this.instancePrivateConfigs.filePath(i.instanceId)}}}const hs=a.z.object({path:a.z.string().trim().min(1).max(2048),method:a.z.string().trim().min(1).max(20).default("GET"),headers:a.z.record(a.z.string(),a.z.string()).default({}),body:a.z.string().optional(),bodyBase64:a.z.string().optional()}).strict(),gs=a.z.object({id:a.z.string().trim().min(1).max(120).optional(),name:a.z.string().trim().min(1).max(160),path:a.z.string().trim().min(1).max(4096),defaultImageSelection:Mt.optional(),labels:a.z.record(a.z.string(),a.z.string()).default({})}).strict(),fs=a.z.object({path:a.z.string().trim().min(1).max(4096).optional(),depth:a.z.coerce.number().int().min(0).max(1).default(0)}).strict(),ys=a.z.object({id:a.z.string().trim().min(1).max(120).optional(),name:a.z.string().trim().min(1).max(160).optional(),runtimeId:a.z.string().trim().min(1).max(120),imageSelection:Mt.optional(),environmentSource:Lt.optional(),projectId:a.z.string().trim().min(1).max(120).optional(),image:ri.optional(),source:kn,sourceSnapshot:a.z.record(a.z.string(),a.z.unknown()).default({}),config:a.z.object({autoImportAgentConfigs:a.z.boolean().optional(),defaultCodexPermissionMode:me.optional()}).strict().optional(),modelSelection:Si.shape.modelSelection}).strict().superRefine((e,t)=>{e.environmentSource&&e.imageSelection&&t.addIssue({code:"custom",path:["environmentSource"],message:"environmentSource and imageSelection are mutually exclusive."}),"template"===e.environmentSource?.type&&e.image&&t.addIssue({code:"custom",path:["image"],message:"Template environment source is resolved by the node-agent and cannot include an image snapshot."})}),Is=a.z.object({name:a.z.string().trim().min(1).max(160).optional(),config:a.z.object({autoImportAgentConfigs:a.z.boolean().optional(),defaultCodexPermissionMode:me.optional()}).strict().optional(),modelSelection:Si.shape.modelSelection.optional()}).strict(),As=a.z.object({id:a.z.string().trim().min(1).max(120).optional(),name:a.z.string().trim().min(1).max(160),type:a.z.enum(["docker","kubernetes","local"]),status:a.z.enum(["unknown","online","offline","degraded"]).default("unknown"),accessStrategy:a.z.enum(["node-proxy","direct-port","kubernetes-ingress","kubernetes-port-forward"]).optional(),capabilities:a.z.record(a.z.string(),a.z.unknown()).default({}),labels:a.z.record(a.z.string(),a.z.string()).default({})}).strict(),bs=As.omit({id:!0}).partial().strict();function ws(e){const t=e.authorization;return"string"==typeof t&&t.startsWith("Bearer ")?t.slice(7).trim():void 0}class vs{operations=new Map;intents=new Map;intent(e){const t=this.intents.get(e);if(t)return t;const n={};return this.intents.set(e,n),n}invalidate(e){const t={};return this.intents.set(e,t),t}isIntentCurrent(e,t){return this.intents.get(e)===t}clearIntent(e){this.intents.delete(e)}async run(e,t){const n=this.operations.get(e)||Promise.resolve();let i;const r=new Promise(e=>{i=e});this.operations.set(e,r),await n;try{return await t()}finally{i(),this.operations.get(e)===r&&this.operations.delete(e)}}}const Es=a.z.object({}).strict().default({});function Ns(){return(new Date).toISOString()}function Ss(){return(new Date).toISOString()}class Ts{state;images;options;inFlight=new Map;abortController=new AbortController;stopped=!1;constructor(e,t,n){this.state=e,this.images=t,this.options=n}retry(e){const t=this.state.requireInstance(e);if("docker"!==this.state.requireRuntime(t.runtimeId).type||!t.imageSnapshot)throw Object.assign(new Error(`Instance ${e} does not use a Docker image.`),{statusCode:400,code:"INSTANCE_IMAGE_PROVISIONING_UNSUPPORTED"});if("failed"!==t.status||"failed"!==t.imageProvisioning?.phase)throw Object.assign(new Error(`Instance ${e} does not have failed image provisioning to retry.`),{statusCode:409,code:"INSTANCE_IMAGE_PROVISIONING_NOT_FAILED"});const n=Ss();return this.state.controlledInstances.put(Si.parse({...t,status:"provisioning",health:"unknown",imageProvisioning:{phase:"checking-image",requestedReference:t.imageSnapshot.requestedReference,generation:(t.imageProvisioning?.generation||0)+1,startedAt:n,updatedAt:n},updatedAt:n}))}provision(e,t){if(this.stopped)return Promise.resolve();const n=e.imageProvisioning?.generation;if(void 0===n)return Promise.resolve();const i=`${e.id}:${n}`,r=this.inFlight.get(i);if(r)return r;const o=this.provisionGeneration(e,n,t).finally(()=>{this.inFlight.get(i)===o&&this.inFlight.delete(i)});return this.inFlight.set(i,o),o}async stop(){this.stopped=!0,this.abortController.abort(),await Promise.allSettled([...this.inFlight.values()])}async provisionGeneration(e,t,n){const i=this.currentGeneration(e.id,t,!0,e.createdAt);if(!i)return;let r,o=0,s=!1,a=Promise.resolve();try{const c=await this.images.ensure(i.imageSnapshot.requestedReference,n=>{a=a.then(async()=>{if(!r)try{await this.updatePhase(e.id,t,n,e.createdAt)}catch(e){r={error:e}}})},n=>{this.stopped||(s=!0,o=n.sequence,this.publishTerminalOutput(e,t,n))},this.abortController.signal);if(await a,r)throw r.error;if(this.stopped)return;s&&this.publishFinished(e,t,o+1,"succeeded");const d=async()=>{if(this.stopped)return;const i=this.currentGeneration(e.id,t,!0,e.createdAt);if(!i)return;const r=this.state.controlledInstances.put(Si.parse({...i,status:"provisioning"===i.status?"created":i.status,health:"unknown",imageSnapshot:{...i.imageSnapshot,requestedReference:c.requestedReference,resolvedDigest:c.resolvedDigest,resolvedReference:c.resolvedReference},imageProvisioning:{...i.imageProvisioning,phase:"ready",error:void 0,updatedAt:Ss()},updatedAt:Ss()}));this.options.sync(),this.options.diagnostic({instanceId:e.id,action:"image.provision",reference:c.requestedReference,digest:c.resolvedDigest,pulled:c.pulled},"node instance image provisioning completed"),"starting"===r.status&&await(n?.())};await(this.options.runInstanceOperation?.(e.id,d)??d())}catch(n){if(await a,r&&(n=r.error),this.stopped)return;s&&this.publishFinished(e,t,o+1,"failed");const i=n instanceof Error?n.message:String(n),c=async()=>{if(this.stopped)return;const n=this.currentGeneration(e.id,t,!1,e.createdAt);n?.imageProvisioning&&["provisioning","starting"].includes(n.status)&&(this.state.controlledInstances.put(Si.parse({...n,status:"failed",health:"failed",imageProvisioning:{...n.imageProvisioning,phase:"failed",error:i,updatedAt:Ss()},updatedAt:Ss()})),this.options.sync(),this.options.warn({instanceId:e.id,action:"image.provision",reference:n.imageProvisioning.requestedReference,error:i},"node instance image provisioning failed"))};await(this.options.runInstanceOperation?.(e.id,c)??c())}}currentGeneration(e,t,n=!0,i){const r=this.state.controlledInstances.get(e);if(!(!r||i&&r.createdAt!==i||r.imageProvisioning?.generation!==t||n&&!r.imageSnapshot))return r}async updatePhase(e,t,n,i){if(this.stopped)return;const r=async()=>{if(this.stopped)return;const r=this.currentGeneration(e,t,!0,i);r&&["provisioning","starting"].includes(r.status)&&(this.state.controlledInstances.put(Si.parse({...r,status:"starting"===r.status?"starting":"provisioning",imageProvisioning:{...r.imageProvisioning,phase:n,error:void 0,updatedAt:Ss()},updatedAt:Ss()})),this.options.sync())};await(this.options.runInstanceOperation?.(e,r)??r())}eventBase(e,t){return{instanceId:e.id,generation:t,requestedReference:e.imageProvisioning.requestedReference,observedAt:Ss()}}publishTerminalOutput(e,t,n){for(const[i,r]of function(e,t=6e4){const n=[];for(let i=0;i<e.length;i+=t)n.push(e.slice(i,i+t));return n}(n.data).entries())this.options.publish(si,{...this.eventBase(e,t),sequence:1e3*n.sequence+i,data:r,...n.replay?{replay:!0}:{}},e.id)}publishFinished(e,t,n,i){this.options.publish(ai,{...this.eventBase(e,t),sequence:1e3*n,outcome:i},e.id)}}const zs=a.z.object({name:a.z.string().trim().min(1).max(160)}).strict();function _s(){return(new Date).toISOString()}function Cs(e,t,n){return{code:"object"==typeof e&&e&&"code"in e&&"string"==typeof e.code?e.code:t,message:e instanceof Error?e.message:String(e),phase:n}}class ks{templateOperations=new vs;store;privateConfigs;docker;requireInstanceValue;requireRuntimeValue;runInstanceOperationValue;isImageReferencedValue;constructor(e,t,n,i,r,o,s=()=>!1){this.store=e,this.privateConfigs=t,this.docker=n,this.requireInstanceValue=i,this.requireRuntimeValue=r,this.runInstanceOperationValue=o,this.isImageReferencedValue=s}list(){return this.store.list()}require(e){const t=this.store.get(e);if(!t)throw Object.assign(new Error(`Environment template ${e} was not found.`),{statusCode:404,code:"ENVIRONMENT_TEMPLATE_NOT_FOUND"});return t}runTemplateOperation(e,t){return this.templateOperations.run(e,async()=>t())}async create(e,t){const n=zs.parse(t),i=this.requireInstanceValue(e),r=this.requireRuntimeValue(i.runtimeId);if("docker"!==r.type)throw Object.assign(new Error(`Runtime ${r.name} does not support environment templates.`),{statusCode:409,code:"ENVIRONMENT_TEMPLATE_RUNTIME_UNSUPPORTED"});if(!i.runtime.containerName)throw Object.assign(new Error(`Instance ${i.id} does not have a Docker container.`),{statusCode:409,code:"ENVIRONMENT_TEMPLATE_CONTAINER_NOT_FOUND"});const o=_s(),s=_o("envtpl"),a=`task-handoff/environment-template:${s.toLowerCase().replace(/[^a-z0-9_.-]/g,"-")}`;return this.store.put(Zt.parse({id:s,name:n.name,sourceInstanceId:i.id,nodeId:i.nodeId,internalTag:a,status:"creating",createdAt:o,updatedAt:o})),this.runInstanceOperationValue(i.id,async()=>{let e,t=!1;try{const n=this.requireInstanceValue(i.id);if("docker"!==this.requireRuntimeValue(n.runtimeId).type||!n.runtime.containerName)throw Object.assign(new Error(`Instance ${i.id} is no longer a valid Docker template source.`),{code:"ENVIRONMENT_TEMPLATE_SOURCE_CHANGED"});const r=this.privateConfigs.get(i.id);if(!r)throw Object.assign(new Error(`Instance ${i.id} private configuration is missing.`),{code:"INSTANCE_PRIVATE_CONFIG_MISSING"});const o=[r.instanceCredential,...Object.values(r.environment)];await this.docker.inspectContainerConfigSecurity(n.runtime.containerName,o),e=await this.docker.commitEnvironmentTemplate(n.runtime.containerName,n.runtime.containerId,a),t=!0;const c=await this.docker.inspectEnvironmentTemplateImage(a);return await this.docker.inspectImageConfigSecurity(a,o),this.store.put(Zt.parse({...this.require(s),...c,status:"ready",error:void 0,updatedAt:_s()}))}catch(n){return t&&(await this.docker.untagEnvironmentTemplate(a,e).catch(()=>!1),e&&await this.docker.garbageCollectEnvironmentTemplateImage(e).catch(()=>!1)),this.store.put(Zt.parse({...this.require(s),status:"failed",error:Cs(n,"ENVIRONMENT_TEMPLATE_CREATE_FAILED","commit"),updatedAt:_s()}))}})}async delete(e){return this.runTemplateOperation(e,async()=>{const t=this.require(e);this.store.put(Zt.parse({...t,status:"deleting",error:void 0,updatedAt:_s()}));try{const n=t.internalTag?await this.docker.untagEnvironmentTemplate(t.internalTag,t.imageId):void 0,i=t.imageId||n;return i&&!this.isImageReferencedValue(i)&&await this.docker.garbageCollectEnvironmentTemplateImage(i),this.store.delete(e),{deleted:!0,templateId:e}}catch(e){throw this.store.put(Zt.parse({...t,status:"failed",error:Cs(e,"ENVIRONMENT_TEMPLATE_DELETE_FAILED","delete"),updatedAt:_s()})),e}})}async releaseUnusedImage(e){return!this.store.list().some(t=>t.imageId===e)&&!this.isImageReferencedValue(e)&&this.docker.garbageCollectEnvironmentTemplateImage(e)}}const Os=new Set(["DELETE","GET","HEAD","PATCH","POST","PUT","OPTIONS"]);function Rs(e){return"string"==typeof e&&Os.has(e.toUpperCase())?e.toUpperCase():"GET"}const xs=new Set(["content-encoding","content-length","transfer-encoding"]),Ds=67108864;function Ps(e){return Object.fromEntries([...e.entries()].filter(([e])=>!xs.has(e.toLowerCase())))}function Ms(e){return e.bodyBase64?Buffer.from(e.bodyBase64,"base64"):e.body}function Ls(){const e=Number(process.env.TASK_HANDOFF_INSTANCE_PROXY_MAX_RESPONSE_BYTES);return Number.isSafeInteger(e)&&e>0?e:67108864}function js(e){return e.startsWith("/")?e:`/${e}`}function $s(e,t){return e.code(502).send({error:{code:"INSTANCE_PROXY_RESPONSE_TOO_LARGE",message:`Instance response exceeds ${t} bytes.`}})}const Fs=a.z.object({version:a.z.literal(1),externalListener:fi}).strict();function Us(e){return"all-ipv4"===e?"0.0.0.0":"127.0.0.1"}function Vs(e){if(!e||"object"!=typeof e||Array.isArray(e))return e;const t=e,n=t.externalListener&&"object"==typeof t.externalListener&&!Array.isArray(t.externalListener)?t.externalListener:{},i=Object.keys(t).filter(e=>"version"!==e&&"externalListener"!==e),r=Object.keys(n).filter(e=>"bindScope"!==e&&"port"!==e);return(i.length||r.length)&&console.warn(JSON.stringify({message:"unknown stored node agent runtime setting fields were ignored",filePath:"runtime-settings.json",fields:[...i,...r.map(e=>`externalListener.${e}`)]})),{version:t.version,externalListener:{bindScope:n.bindScope,port:n.port}}}async function qs(e){const t=Us(e.bindScope);return!await new Promise(t=>{const n=p.createConnection({host:"127.0.0.1",port:e.port}),i=e=>{n.removeAllListeners(),n.destroy(),t(e)};n.once("connect",()=>i(!0)),n.once("error",()=>i(!1)),n.setTimeout(250,()=>i(!1))})&&new Promise(n=>{const i=p.createServer();i.once("error",()=>n(!1)),i.listen({host:t,port:e.port,exclusive:!0},()=>i.close(()=>n(!0)))})}class Hs{app;state;settings;sockets=new Set;config;source;status="error";error;onActiveListener;updateQueue=Promise.resolve();constructor(e){this.app=e.app,this.state=e.state,this.settings=e.settings,this.config=e.config,this.source=e.source,this.onActiveListener=e.onActiveListener,this.app.server.on("connection",e=>{this.sockets.add(e),e.once("close",()=>this.sockets.delete(e))})}current(){return yi.parse({...this.config,host:Us(this.config.bindScope),status:this.status,source:this.source,...this.error?{error:this.error}:{}})}async start(){try{await this.listen(this.config),this.status="listening",this.error=void 0,this.state.setListenerPort(this.config.port)}catch(e){throw this.status="error",this.error=e instanceof Error?e.message:String(e),this.app.log.error({host:Us(this.config.bindScope),port:this.config.port,error:this.error},"node agent TCP listener failed to start"),Object.assign(new Error(`Failed to bind node agent TCP listener at ${Us(this.config.bindScope)}:${this.config.port}: ${this.error}`),{statusCode:409,code:"NODE_AGENT_LISTENER_BIND_FAILED"})}const e=this.current();return this.onActiveListener?.(e),e}update(e){const t=this.updateQueue.then(()=>this.updateOnce(e));return this.updateQueue=t.then(()=>{},()=>{}),t}async updateOnce(e){const t=Ii.parse(e);if(t.bindScope===this.config.bindScope&&t.port===this.config.port)return this.current();if(t.port!==this.config.port){const e=this.state.runningInstanceCount();if(e>0)throw Object.assign(new Error(`Cannot change the node agent port while ${e} controlled instance(s) are running.`),{statusCode:409,code:"NODE_AGENT_LISTENER_PORT_IN_USE_BY_INSTANCES",blockingInstanceCount:e})}const n=this.snapshot();await this.stop();try{await this.listen(t)}catch(e){throw await this.restore(n),Object.assign(new Error(`Failed to bind node agent TCP listener at ${Us(t.bindScope)}:${t.port}: ${e instanceof Error?e.message:String(e)}`),{statusCode:409,code:"NODE_AGENT_LISTENER_BIND_FAILED"})}try{this.settings.put({version:1,externalListener:t})}catch(e){throw await this.stop(),await this.restore(n),Object.assign(new Error(`Failed to persist node agent TCP listener: ${e instanceof Error?e.message:String(e)}`),{statusCode:500,code:"NODE_AGENT_LISTENER_PERSIST_FAILED"})}this.config=t,this.source="persisted",this.status="listening",this.error=void 0,this.state.setListenerPort(t.port);const i=this.current();return this.onActiveListener?.(i),i}async shutdown(){await this.updateQueue,await this.stop()}snapshot(){return{config:this.config,source:this.source,status:this.status,error:this.error}}async restore(e){if(this.config=e.config,this.source=e.source,this.status=e.status,this.error=e.error,"listening"===e.status)try{await this.listen(e.config)}catch(e){this.status="error",this.error=`Failed to restore previous listener: ${e instanceof Error?e.message:String(e)}`,this.app.log.error({error:this.error},"node agent TCP listener rollback failed")}this.state.setListenerPort(e.config.port),"listening"===this.status&&this.onActiveListener?.(this.current())}async listen(e){await new Promise((t,n)=>{const i=e=>{this.app.server.off("listening",r),n(e)},r=()=>{this.app.server.off("error",i),t()};this.app.server.once("error",i),this.app.server.once("listening",r),this.app.server.listen({host:Us(e.bindScope),port:e.port})})}async stop(){this.app.server.listening&&await new Promise((e,t)=>{this.app.server.close(n=>n?t(n):e());for(const e of this.sockets)e.destroy()})}}const Bs="TASK_HANDOFF_NODE_AGENT_V1",Ks="/api/node-tunnel";function Gs(e=""){return d.createHash("sha256").update(e).digest("hex")}function Js(e,t){return d.createHmac("sha256",e).update(function(e){return[Bs,e.keyId,e.method.toUpperCase(),e.pathWithQuery,e.timestamp,e.nonce,e.bodySha256].join("\n")}(t)).digest("hex")}function Ws(e){const t=e.timestamp||(new Date).toISOString(),n=e.nonce||d.randomBytes(18).toString("base64url"),i=Gs(e.body||""),r=Js(e.secret,{keyId:e.keyId,method:e.method,pathWithQuery:e.pathWithQuery,timestamp:t,nonce:n,bodySha256:i});return{"x-taskhandoff-node-id":e.nodeId,"x-taskhandoff-key-id":e.keyId,"x-taskhandoff-timestamp":t,"x-taskhandoff-nonce":n,"x-taskhandoff-body-sha256":i,"x-taskhandoff-signature":r}}class Ys{usedNonces=new Map;identity;nodeId;overrideSecret;overrideKeyId;nowMs;constructor(e,t,n,i,r=Date.now){this.identity=e,this.nodeId=t,this.overrideSecret=n,this.overrideKeyId=i,this.nowMs=r}hasRemoteSecrets(){return this.identity.remoteSecrets(this.overrideSecret,this.overrideKeyId).length>0}verify(e){const t=function(e){const t=new Map;for(const[n,i]of Object.entries(e)){const e=Array.isArray(i)?i.join(","):"string"==typeof i?i:void 0===i?"":String(i);t.set(n.toLowerCase(),e)}return{nodeId:t.get("x-taskhandoff-node-id")||"",keyId:t.get("x-taskhandoff-key-id")||"",timestamp:t.get("x-taskhandoff-timestamp")||"",nonce:t.get("x-taskhandoff-nonce")||"",bodySha256:t.get("x-taskhandoff-body-sha256")||"",signature:t.get("x-taskhandoff-signature")||""}}(e.headers);if(!t.nodeId&&!t.signature)return!1;const n="DELETE"===e.method&&"/api/node-agent/pairing/current"===e.url.split("?")[0],i=this.identity.remoteSecrets(this.overrideSecret,this.overrideKeyId,n);if(!i.length)return!1;if(t.nodeId!==this.nodeId)throw Object.assign(new Error("Invalid node agent HMAC node id."),{statusCode:401,code:"NODE_AGENT_HMAC_NODE_MISMATCH"});if(!t.keyId)throw Object.assign(new Error("Node agent HMAC key id is missing."),{statusCode:401,code:"NODE_AGENT_HMAC_KEY_MISSING"});const r=i.filter(e=>t.keyId===e.keyId);if(!r.length)throw Object.assign(new Error("Invalid node agent HMAC key id."),{statusCode:401,code:"NODE_AGENT_HMAC_KEY_INVALID"});const o=Date.parse(t.timestamp);if(!Number.isFinite(o)||Math.abs(this.nowMs()-o)>6e4)throw Object.assign(new Error("Node agent HMAC timestamp is outside the allowed window."),{statusCode:401,code:"NODE_AGENT_HMAC_TIMESTAMP_INVALID"});if(!t.nonce)throw Object.assign(new Error("Node agent HMAC nonce is missing."),{statusCode:401,code:"NODE_AGENT_HMAC_NONCE_MISSING"});this.pruneNonces();const s=`${t.nodeId}:${t.keyId}:${t.nonce}`;if(this.usedNonces.has(s))throw Object.assign(new Error("Node agent HMAC nonce was already used."),{statusCode:401,code:"NODE_AGENT_HMAC_NONCE_REPLAY"});const a=Gs(null==(c=e.body)?"":"string"==typeof c||Buffer.isBuffer(c)?c:JSON.stringify(c));var c;if(t.bodySha256!==a)throw Object.assign(new Error("Node agent HMAC body hash mismatch."),{statusCode:401,code:"NODE_AGENT_HMAC_BODY_HASH_INVALID"});if(!r.some(n=>function(e,t){const n=Buffer.from(e,"hex"),i=Buffer.from(t,"hex");return n.length===i.length&&d.timingSafeEqual(n,i)}(t.signature,Js(n.secret,{keyId:t.keyId,method:e.method,pathWithQuery:e.url,timestamp:t.timestamp,nonce:t.nonce,bodySha256:a}))))throw Object.assign(new Error("Invalid node agent HMAC signature."),{statusCode:401,code:"NODE_AGENT_HMAC_SIGNATURE_INVALID"});return this.usedNonces.set(s,o+6e4+1),t.keyId}pruneNonces(){const e=this.nowMs();for(const[t,n]of this.usedNonces)n<=e&&this.usedNonces.delete(t)}}const Xs=a.z.string().trim().min(1).max(160),Qs=a.z.string().datetime(),Zs=a.z.string().min(1).max(4096),ea=a.z.string().trim().url().max(2048),ta=a.z.object({id:Xs,keyId:Xs,name:a.z.string().trim().min(1).max(160).optional(),secret:Zs,pairedAt:Qs,revokedAt:Qs.optional(),updatedAt:Qs}).strip(),na=a.z.object({id:Xs,pairingKeyId:Xs,name:a.z.string().trim().min(1).max(160).optional(),url:ea,enabled:a.z.boolean().default(!0),createdAt:Qs,updatedAt:Qs}).strip(),ia=a.z.object({controlPlaneName:a.z.string().trim().min(1).max(160).optional(),controlPlaneUrl:a.z.string().trim().max(2048).optional(),expiresInMs:a.z.number().int().positive().max(36e5).optional()}).strict(),ra=a.z.object({joinToken:a.z.string().trim().min(1).max(4096),controlPlaneId:a.z.string().trim().min(1).max(160).optional(),controlPlaneName:a.z.string().trim().min(1).max(160).optional()}).strict(),oa=a.z.object({controlPlaneUrl:a.z.string().trim().url().max(2048),joinToken:a.z.string().trim().min(1).max(4096),controlPlaneName:a.z.string().trim().min(1).max(160).optional(),activate:a.z.boolean().optional()}).strict();function sa(){return(new Date).toISOString()}const aa=new Set(["nodeId","createdAt","updatedAt","pairingInvites","controlPlanePairings","controlPlaneConnections","remoteControlPlanes"]),ca=new Set(["id","keyId","name","secret","pairedAt","revokedAt","updatedAt"]),da=new Set(["id","pairingKeyId","name","url","enabled","createdAt","updatedAt"]),la=new Set(["id","keyId","name","url","secret","pairedAt","updatedAt","active"]);function ua(e,t){console.warn(JSON.stringify({message:e,...t}))}function ma(e,t){return Object.assign(new Error(e,void 0===t?void 0:{cause:t}),{code:"NODE_AGENT_IDENTITY_INVALID"})}function pa(e,t){return Object.keys(e).filter(e=>!t.has(e))}function ha(e,t,n){const i=Qs.safeParse(e);return i.success?i.data:(n("invalid node agent identity timestamp was replaced",{field:t}),sa())}function ga(e,t){if(!e||"object"!=typeof e||Array.isArray(e))throw ma("Node agent identity must be a JSON object.");const n=e,i=Xs.safeParse(n.nodeId);if(!i.success)throw ma("Node agent identity has an invalid nodeId.",i.error);const r=i.data,o=pa(n,aa);o.length&&t("unknown node agent identity fields were ignored",{fields:o}),Array.isArray(n.pairingInvites)&&n.pairingInvites.length&&t("persisted node agent pairing invites were discarded",{count:n.pairingInvites.length});const s=Array.isArray(n.remoteControlPlanes)?n.remoteControlPlanes.flatMap(e=>{if(!e||"object"!=typeof e||Array.isArray(e))return[];const n=e,i=pa(n,la);i.length&&t("unknown legacy node agent remote control-plane fields were ignored",{fields:i});const r=ta.safeParse(n);if(!r.success)return t("invalid legacy node agent control-plane pairing was ignored",{issues:r.error.issues}),[];const o=n.url?na.safeParse({id:`connection_${r.data.keyId}`,pairingKeyId:r.data.keyId,name:n.name,url:n.url,enabled:!1!==n.active,createdAt:r.data.pairedAt,updatedAt:r.data.updatedAt}):void 0;return[{pairing:r.data,...o?.success?{connection:o.data}:{}}]}):[],a=(e,n,i,r)=>Array.isArray(e)?e.flatMap(e=>{if(!e||"object"!=typeof e||Array.isArray(e))return t(`invalid node agent ${r} was ignored`,{}),[];const o=pa(e,n);o.length&&t(`unknown node agent ${r} fields were ignored`,{fields:o});const s=i.safeParse(e);return s.success?[s.data]:(t(`invalid node agent ${r} was ignored`,{issues:s.error.issues}),[])}):[];return{nodeId:r,createdAt:ha(n.createdAt,"createdAt",t),updatedAt:ha(n.updatedAt,"updatedAt",t),controlPlanePairings:n.controlPlanePairings?a(n.controlPlanePairings,ca,ta,"control-plane pairing"):s.map(e=>e.pairing),controlPlaneConnections:n.controlPlaneConnections?a(n.controlPlaneConnections,da,na,"control-plane connection"):s.flatMap(e=>e.connection?[e.connection]:[])}}class fa{paths;logger;constructor(e,t={}){this.paths=e,this.logger=t.logger||ua}read(){let e,n;try{e=t.readFileSync(this.paths.identityPath,"utf8")}catch(e){if("ENOENT"===e.code)return;throw Object.assign(new Error(`Node agent identity could not be read: ${this.paths.identityPath}`,{cause:e}),{code:"NODE_AGENT_IDENTITY_READ_FAILED"})}try{n=JSON.parse(e)}catch(e){throw ma(`Node agent identity contains invalid JSON: ${this.paths.identityPath}`,e)}return ga(n,this.logger)}init(){const e=this.read();if(!e)return;const n=JSON.parse(t.readFileSync(this.paths.identityPath,"utf8"));("pairingInvites"in n||"remoteControlPlanes"in n)&&this.write(e)}write(e){t.mkdirSync(n.dirname(this.paths.identityPath),{recursive:!0});const i=ga({...e,updatedAt:sa()},this.logger);I.sync(this.paths.identityPath,`${JSON.stringify(i,null,2)}\n`,{encoding:"utf8",mode:384})}}class ya{values=new Map;put(e,t){this.prune(),this.values.set(e,t)}take(e){this.prune();const t=this.values.get(e);return t&&this.values.delete(e),t}prune(e=Date.now()){for(const[t,n]of this.values)Date.parse(n.expiresAt)<=e&&this.values.delete(t)}}function Ia(){return(new Date).toISOString()}class Aa{store;pairingInvites=new ya;controlPlaneConnectionOperations=new Map;constructor(e){this.store=new fa(e),this.store.init()}async runControlPlaneConnectionOperation(e,t){const n=e.replace(/\/$/,""),i=this.controlPlaneConnectionOperations.get(n)||Promise.resolve();let r;const o=new Promise(e=>{r=e});this.controlPlaneConnectionOperations.set(n,o),await i;try{return await t()}finally{r(),this.controlPlaneConnectionOperations.get(n)===o&&this.controlPlaneConnectionOperations.delete(n)}}resolveNodeId(e){if(e?.trim())return this.writeNodeId(e.trim()),e.trim();const t=this.store.read();if(t?.nodeId)return t.nodeId;const n=_o("node");return this.writeNodeId(n),n}createPairingInvite(e){const t=Ia(),n=new Date(Date.now()+(e.expiresInMs||6e5)).toISOString(),i=Co(),r={tokenHash:Gs(i),createdAt:t,expiresAt:n,...e.controlPlaneName?{controlPlaneName:e.controlPlaneName}:{}};return this.pairingInvites.put(r.tokenHash,r),{...r,token:i}}completePairingInvite(e){const t=this.store.read()||this.newIdentity(),n=Gs(e.joinToken),i=this.pairingInvites.take(n);if(!i){const e=new Error("Node agent pairing invite is invalid or expired.");throw Object.assign(e,{statusCode:401,code:"NODE_AGENT_PAIRING_INVITE_INVALID"}),e}const r=Ia(),o={id:e.controlPlaneId||_o("cp"),keyId:_o("key"),...e.controlPlaneName||i.controlPlaneName?{name:e.controlPlaneName||i.controlPlaneName}:{},secret:Co(),pairedAt:r,updatedAt:r};return this.store.write({...t,controlPlanePairings:[...(t.controlPlanePairings||[]).filter(e=>e.id!==o.id),o]}),o}stageControlPlaneConnection(e){const{pairing:t,connection:n}=this.createControlPlaneConnection(e),i=this.store.read()||this.newIdentity(),r=n.url.replace(/\/$/,""),o=(i.controlPlaneConnections||[]).filter(e=>e.id===n.id||e.url.replace(/\/$/,"")===r);return this.store.write({...i,controlPlanePairings:[...(i.controlPlanePairings||[]).filter(e=>e.keyId!==t.keyId),t],controlPlaneConnections:[...(i.controlPlaneConnections||[]).filter(e=>e.id!==n.id&&e.url.replace(/\/$/,"")!==r),n]}),{pairing:t,connection:n,replacedConnections:o}}commitControlPlaneConnection(e,t={}){const n=this.store.read()||this.newIdentity(),i={...e.pairing,...t.name?{name:t.name}:{}},r={...e.connection,...t.name?{name:t.name}:{}},o=new Set((n.controlPlaneConnections||[]).map(e=>e.pairingKeyId)),s=new Set(e.replacedConnections.map(e=>e.pairingKeyId));return this.store.write({...n,controlPlanePairings:[...(n.controlPlanePairings||[]).filter(e=>e.keyId!==i.keyId&&(!s.has(e.keyId)||o.has(e.keyId))),i],controlPlaneConnections:[...(n.controlPlaneConnections||[]).filter(e=>e.id!==r.id),r]}),{pairing:i,connection:r}}rollbackControlPlaneConnection(e){const t=this.store.read();if(!t)return;const n=new Set(e.replacedConnections.map(e=>e.id));this.store.write({...t,controlPlanePairings:(t.controlPlanePairings||[]).filter(t=>t.keyId!==e.pairing.keyId),controlPlaneConnections:[...(t.controlPlaneConnections||[]).filter(t=>t.id!==e.connection.id&&!n.has(t.id)),...e.replacedConnections]})}createControlPlaneConnection(e){const t=Ia(),n={id:_o("cp"),keyId:_o("key"),...e.name?{name:e.name}:{},secret:Co(),pairedAt:t,updatedAt:t};return{pairing:n,connection:{id:_o("connection"),pairingKeyId:n.keyId,...e.name?{name:e.name}:{},url:e.url,enabled:!1!==e.enabled,createdAt:t,updatedAt:t}}}resolvedControlPlaneAccess(){const e=this.store.read(),t=new Map((e?.controlPlanePairings||[]).filter(e=>!e.revokedAt).map(e=>[e.keyId,e])),n=e?.controlPlaneConnections||[];return{hasPersistedAccess:n.length>0||t.size>0,connections:n.map(e=>({connection:e,pairing:t.get(e.pairingKeyId)}))}}listControlPlanePairings(e=""){return(this.store.read()?.controlPlanePairings||[]).filter(e=>!e.revokedAt).map(({secret:t,...n})=>({...n,current:Boolean(e&&n.keyId===e)})).sort((e,t)=>Number(t.current)-Number(e.current)||t.updatedAt.localeCompare(e.updatedAt))}listControlPlaneConnections(){return[...this.store.read()?.controlPlaneConnections||[]].sort((e,t)=>t.updatedAt.localeCompare(e.updatedAt))}deleteControlPlanePairing(e,t=""){if(t&&e===t){const e=new Error("Cannot delete the pairing used to authenticate the current request.");throw Object.assign(e,{statusCode:409,code:"NODE_AGENT_PAIRING_CURRENT_REQUEST"}),e}const n=this.store.read();if(!n)return!1;if((n.controlPlaneConnections||[]).some(t=>t.pairingKeyId===e))throw Object.assign(new Error("Cannot delete a pairing used by a configured control-plane connection."),{statusCode:409,code:"NODE_AGENT_PAIRING_IN_USE"});const i=(n.controlPlanePairings||[]).filter(t=>t.keyId!==e);return i.length!==(n.controlPlanePairings||[]).length&&(this.store.write({...n,controlPlanePairings:i}),!0)}revokeCurrentControlPlanePairing(e){if(!e)throw Object.assign(new Error("Current paired-HMAC authentication is required to revoke this pairing."),{statusCode:403,code:"NODE_AGENT_PAIRING_SELF_REVOKE_HMAC_REQUIRED"});const t=this.store.read(),n=t?.controlPlanePairings?.find(t=>t.keyId===e);if(!t||!n)throw Object.assign(new Error("The current control-plane pairing no longer exists."),{statusCode:404,code:"NODE_AGENT_PAIRING_NOT_FOUND"});if(n.revokedAt)return{keyId:e,revoked:!0,revokedAt:n.revokedAt};if((t.controlPlaneConnections||[]).some(t=>t.pairingKeyId===e))throw Object.assign(new Error("Cannot revoke a pairing used by a configured control-plane connection."),{statusCode:409,code:"NODE_AGENT_PAIRING_IN_USE"});const i=Ia();return this.store.write({...t,controlPlanePairings:t.controlPlanePairings.map(t=>t.keyId===e?{...t,revokedAt:i,updatedAt:i}:t)}),{keyId:e,revoked:!0,revokedAt:i}}deleteControlPlaneConnection(e){const t=this.store.read();if(!t)return!1;const n=(t.controlPlaneConnections||[]).filter(t=>t.id!==e);return n.length!==(t.controlPlaneConnections||[]).length&&(this.store.write({...t,controlPlaneConnections:n}),!0)}remoteSecrets(e,t,n=!1){return[...(this.store.read()?.controlPlanePairings||[]).filter(e=>n||!e.revokedAt).map(e=>({keyId:e.keyId,secret:e.secret})),...e&&t?[{keyId:t,secret:e}]:[]]}isRevokedPairing(e){return Boolean(this.store.read()?.controlPlanePairings?.some(t=>t.keyId===e&&t.revokedAt))}reverseTunnelSecret(e,t,n){if(t&&n)return{keyId:n,secret:t};const i=this.store.read(),r=(i?.controlPlanePairings||[]).filter(e=>!e.revokedAt);if(!r.length)return;if(e){const t=e.replace(/\/$/,""),n=(i?.controlPlaneConnections||[]).find(e=>e.url.replace(/\/$/,"")===t),o=n&&r.find(e=>e.keyId===n.pairingKeyId);if(o)return{keyId:o.keyId,secret:o.secret}}const o=[...r].sort((e,t)=>t.updatedAt.localeCompare(e.updatedAt))[0];return o?{keyId:o.keyId,secret:o.secret}:void 0}newIdentity(){return{nodeId:this.resolveNodeId(),createdAt:Ia(),updatedAt:Ia(),controlPlanePairings:[],controlPlaneConnections:[]}}writeNodeId(e){const t=this.store.read();this.store.write({...t||{createdAt:Ia()},nodeId:e,updatedAt:Ia(),controlPlanePairings:t?.controlPlanePairings||[],controlPlaneConnections:t?.controlPlaneConnections||[]})}}const ba=a.z.string().trim().min(1).max(160);const wa=Sn.strict();function va(e){const t=e.filter(e=>!["created","stopped","failed"].includes(e.status)),n=new Set(t.map(e=>e.id)),i=t.filter(e=>e.apps.runningCount>0||e.aiSessions.runningCount>0);return{runningInstanceCount:t.length,stoppedInstanceCount:e.length-t.length,activeInstanceCount:i.length,restartInstanceCount:t.length,runningInstanceIds:t.map(e=>e.id).sort(),stoppedInstanceIds:e.filter(e=>!n.has(e.id)).map(e=>e.id).sort(),activeInstanceIds:i.map(e=>e.id).sort()}}class Ea{preflights=new Map;options;constructor(e){this.options=e}async check(e){const t=vn.parse(e),n=va(this.options.listInstances()),i=await qo(this.options.runCommand),r=this.options.currentRuntimeVersion(),o="@task-handoff/server"===i.packageName?[...new Set([...i.relatedCurrentVersions,r])]:i.relatedCurrentVersions,s=await async function(e){const t=e.packageName||"@task-handoff/node-agent",n=await async function(e,t,n){const i=function(e){return"stable"===e?"latest":e}(n),r=await e(Uo(),["view",`${t}@${i}`,"version","--json"]).catch(e=>{if(!function(e){if(!e||"object"!=typeof e)return!1;const t=e,n=[t.message,t.details?.stdout,t.details?.stderr].filter(e=>"string"==typeof e).join("\n");return/\bE404\b/i.test(n)}(e))throw e});if(!r)return;const o=JSON.parse(r.stdout);if("string"!=typeof o)throw new Error(`npm did not resolve ${t}@${i} to one version.`);return o}(e.runCommand,t,e.channel);if(!n)return function(e){return En.parse({source:"npm",channel:e.channel,currentVersion:e.currentVersion,availableVersion:e.currentVersion||"unavailable",impact:e.impact||{runningInstanceCount:0,stoppedInstanceCount:0,activeInstanceCount:0,restartInstanceCount:0,runningInstanceIds:[],stoppedInstanceIds:[],activeInstanceIds:[]},updateAvailable:!1,reason:`No ${e.channel} release is currently published.`,checkedAt:$o()})}({channel:e.channel,currentVersion:e.currentVersion,impact:e.impact});const i=Fo(e.currentVersion,n)||(e.relatedCurrentVersions||[]).some(e=>Fo(e,n)),r=i?await async function(e,t,n){const i=await e(Uo(),["view",`${t}@${n}`,"dist.integrity","--json"]),r=JSON.parse(i.stdout);if("string"!=typeof r||!/^sha(?:256|384|512)-[A-Za-z0-9+/=]+$/.test(r))throw Object.assign(new Error(`npm did not return immutable integrity metadata for ${t}@${n}.`),{statusCode:502,code:"NODE_UPDATE_PREFLIGHT_FAILED",retryable:!0});return r}(e.runCommand,t,n):void 0;return En.parse({source:"npm",channel:e.channel,currentVersion:e.currentVersion,availableVersion:n,...r?{artifactRef:`npm:${t}@${n}#${r}`}:{},runtimeArtifacts:e.runtimeArtifacts||[],impact:e.impact||{runningInstanceCount:0,stoppedInstanceCount:0,activeInstanceCount:0,restartInstanceCount:0,runningInstanceIds:[],stoppedInstanceIds:[],activeInstanceIds:[]},updateAvailable:i,checkedAt:$o()})}({channel:t.channel,currentVersion:i.currentVersion||r,runCommand:this.options.runCommand,packageName:i.packageName,relatedCurrentVersions:o,impact:n});if(!s.updateAvailable)return s;const a={...s,runtimeArtifacts:await this.options.resolveRuntimeArtifacts(s.availableVersion),preflightToken:Co()};return this.preflights.set(a.preflightToken,{result:a,expiresAt:Date.now()+6e5}),a}async apply(e){const i=wa.parse(e),r=await this.consumePreflight(i);if(!r.supported)throw Object.assign(new Error(r.reason||"The requested update is not supported."),{statusCode:400,code:"UPDATE_UNSUPPORTED"});if(!r.updateAvailable)throw Object.assign(new Error(r.reason||"No update is available for the selected channel."),{statusCode:409,code:"UPDATE_NOT_AVAILABLE"});const o=this.options.jobs.create(this.options.nodeId,r),{worker:s,packaged:a,expectedWorker:c}=function(e,i=t.existsSync){const r=[n.resolve(e,"..","bin","task-handoff-node-update-worker"),n.resolve(e,"..","..","bin","task-handoff-node-update-worker")],o=r.find(i),s=n.resolve(e,"..","..","..","..","scripts","node-update-worker.cts");return o?{worker:o,packaged:!0,expectedWorker:r[0]}:i(s)?{worker:s,packaged:!1,expectedWorker:r[0]}:{worker:void 0,packaged:!1,expectedWorker:r[0]}}(this.options.moduleDir);if(!s)throw this.options.jobs.patch(o.id,{status:"failed",rollout:{...o.rollout,phase:"failed"},error:{code:"NODE_UPDATE_FAILED",message:`Update worker was not found: ${c}`,retryable:!1},completedAt:(new Date).toISOString()}),Object.assign(new Error(`Node agent update worker was not found: ${c}`),{statusCode:500,code:"UPDATE_WORKER_NOT_FOUND"});const d=process.env.TASK_HANDOFF_CONTROL_PLANE_HEALTH_URL?.trim();try{await this.options.runCommand("systemd-run",["--unit",`task-handoff-update-${o.id}`,"--collect","--property=Type=exec",...a?[s]:[process.execPath,s],"--job-file",this.options.jobs.records.filePath(o.id),"--target-version",o.toVersion,"--npm-command",Uo(),...d?["--control-plane-health-url",d]:[]])}catch(e){const t=e instanceof Error?e.message:String(e);throw this.options.jobs.patch(o.id,{status:"failed",rollout:{...o.rollout,phase:"failed"},error:{code:"NODE_UPDATE_FAILED",message:`Failed to launch the node update worker: ${t}`,retryable:!0},completedAt:(new Date).toISOString()}),Object.assign(new Error(`Failed to launch the node update worker: ${t}`),{statusCode:500,code:"NODE_UPDATE_WORKER_LAUNCH_FAILED",cause:e})}return o}async consumePreflight(e){const t=this.preflights.get(e.preflightToken);if(this.preflights.delete(e.preflightToken),!t||t.expiresAt<=Date.now())throw Object.assign(new Error("The update preflight is missing or expired. Check for updates again."),{statusCode:409,code:"UPDATE_PREFLIGHT_EXPIRED"});const n=t.result,i=await qo(this.options.runCommand);n.channel===e.channel&&n.availableVersion===e.targetVersion&&n.currentVersion===(i.currentVersion||this.options.currentRuntimeVersion())&&!0===n.artifactRef?.startsWith(`npm:${i.packageName}@`)&&JSON.stringify(n.impact)===JSON.stringify(va(this.options.listInstances()))||this.throwStale();const r=await this.options.resolveRuntimeArtifacts(n.availableVersion);return JSON.stringify(n.runtimeArtifacts)!==JSON.stringify(r)&&this.throwStale(),n}throwStale(){throw Object.assign(new Error("The update target or affected instances changed after preflight. Check for updates again."),{statusCode:409,code:"UPDATE_PREFLIGHT_STALE"})}}const Na=new Set(["provisioning","starting","registering","registered","running"]);function Sa(e){return Si.parse({...e,health:"unknown",connectionStatus:"offline",agentStatus:"offline",targetStatus:"unknown",uiAccessStatus:"unknown",target:{...e.target,status:"unknown"},updatedAt:(new Date).toISOString()})}class Ta{options;restoredInstances=new Set;restoreErrors=new Map;unexpectedExitRetries=new Map;suppressedInstances=new Set;pendingUnexpectedExits=new Map;activeRestores=new Map;timer;activeCycle;cycleRequested=!1;cycleRequestDelayMs;started=!1;stopped=!1;constructor(e){this.options=e}markRestored(e){const t=this.options.state.requireInstance(e).status;return!["failed","stopping","stopped"].includes(t)&&(this.restoredInstances.add(e),this.restoreErrors.delete(e),!0)}allowRecovery(e){this.suppressedInstances.delete(e);const t=this.pendingUnexpectedExits.get(e);void 0!==t&&(this.pendingUnexpectedExits.delete(e),this.applyUnexpectedLocalExit(e,t))}completeSuppressedOperation(e){this.pendingUnexpectedExits.delete(e),this.restoredInstances.delete(e),this.restoreErrors.delete(e),this.unexpectedExitRetries.delete(e)}forgetInstance(e){this.restoredInstances.delete(e),this.restoreErrors.delete(e),this.unexpectedExitRetries.delete(e),this.suppressedInstances.delete(e),this.activeRestores.delete(e),this.pendingUnexpectedExits.delete(e)}async suppressRecovery(e){this.suppressedInstances.add(e),await(this.activeRestores.get(e)?.catch(()=>{}))}handleUnexpectedLocalExit(e,t){this.stopped||(this.suppressedInstances.has(e)?this.pendingUnexpectedExits.set(e,t):this.applyUnexpectedLocalExit(e,t))}applyUnexpectedLocalExit(e,t){const n=this.options.state.requireInstance(e);if("local"!==this.options.state.requireRuntime(n.runtimeId).type)return;this.restoredInstances.delete(e);const i=this.options.nowMs?.()??Date.now(),r=this.unexpectedExitRetries.get(e),o=this.options.crashStableWindowMs??3e4,s=r&&i-r.lastExitAt<o?r.attempt+1:1;this.unexpectedExitRetries.set(e,{attempt:s,lastExitAt:i});const a=this.options.retryBaseDelayMs??1e3,c=1===s?0:Math.min(this.options.retryMaxDelayMs??3e4,a*2**Math.min(s-2,10)),d=t instanceof Error?t.message:String(t);this.restoreErrors.set(e,{message:d,attempt:s,nextAttemptAt:i+c}),this.options.state.applyInstanceLifecycle(e,{type:"runtime-exited",error:t}),this.requestCycle(c)}async restoreManagedInstances(){if(this.stopped)return;const{state:e}=this.options;for(const t of e.listInstances()){if(this.stopped)return;"docker"===e.requireRuntime(t.runtimeId).type&&["provisioning","starting"].includes(t.status)&&"ready"!==t.imageProvisioning?.phase&&this.options.provisionImage(t)}const t=e.listInstances().filter(t=>{if(this.restoredInstances.has(t.id))return!1;if(this.suppressedInstances.has(t.id))return!1;const n=e.requireRuntime(t.runtimeId);if("local"===n.type){const e=this.restoreErrors.get(t.id);return(Na.has(t.status)||"failed"===t.status)&&(!e||e.nextAttemptAt<=(this.options.nowMs?.()??Date.now()))}return"docker"===n.type&&(Na.has(t.status)||"provisioning"===t.status&&"ready"===t.imageProvisioning?.phase)});await Promise.all(t.map(async t=>{if(this.stopped)return;const n=async()=>{if(this.stopped)return;const n=e.listInstances().find(e=>e.id===t.id);if(!n)return;if(!this.isRestoreCandidate(n))return;const i=this.restoreErrors.get(n.id);try{const t=this.options.restoreInstance(n.id);this.activeRestores.set(n.id,t);try{await t}finally{this.activeRestores.get(n.id)===t&&this.activeRestores.delete(n.id)}if(this.stopped||this.suppressedInstances.has(n.id))return;if(await this.options.autoImport(e.requireInstance(n.id)),this.stopped||this.suppressedInstances.has(n.id))return;if(this.restoreErrors.get(n.id)!==i)return;if(!this.markRestored(n.id))throw new Error(`Restored instance ${n.id} did not reach a recoverable running state.`)}catch(t){if(this.stopped||this.suppressedInstances.has(n.id))return;"local"===e.requireRuntime(n.runtimeId).type&&e.applyInstanceLifecycle(n.id,{type:"start-failed",error:t});const i=t instanceof Error?t.message:String(t),r=this.restoreErrors.get(n.id),o=(r?.attempt??0)+1,s=this.options.retryBaseDelayMs??1e3,a=Math.min(this.options.retryMaxDelayMs??3e4,s*2**Math.min(o-1,10)),c=(this.options.nowMs?.()??Date.now())+a;this.restoreErrors.set(n.id,{message:i,attempt:o,nextAttemptAt:c}),r?.message===i&&r.attempt===o||this.options.warn({instanceId:n.id,action:"restore",runtimeId:n.runtimeId,error:i,attempt:o,nextAttemptAt:new Date(c).toISOString()},"node instance restore failed; recovery will retry")}};await(this.options.runInstanceOperation?.(t.id,n)??n())}))}isRestoreCandidate(e){if(this.restoredInstances.has(e.id)||this.suppressedInstances.has(e.id))return!1;const t=this.options.state.requireRuntime(e.runtimeId);if("local"===t.type){const t=this.restoreErrors.get(e.id);return(Na.has(e.status)||"failed"===e.status)&&(!t||t.nextAttemptAt<=(this.options.nowMs?.()??Date.now()))}return"docker"===t.type&&(Na.has(e.status)||"provisioning"===e.status&&"ready"===e.imageProvisioning?.phase)}async recoverManagedInstances(){if(this.stopped)return;const{state:e,convergence:t}=this.options,n=e.listInstances().filter(e=>this.options.usesManagedArtifact(e)&&!t.isRunning(e.id)&&(this.restoredInstances.has(e.id)||"unknown"!==e.target.status)&&(!e.ready||"matched"!==e.runtimeVersion?.phase)&&!["created","stopped","failed","provisioning","stopping"].includes(e.status));await Promise.all(n.map(async e=>{if(!this.stopped)try{await t.schedule(e.id)}catch(t){this.options.error({instanceId:e.id,error:t},"runtime convergence recovery failed")}}))}start(){this.started||this.stopped||(this.started=!0,this.runAndContinue())}async stop(){this.stopped=!0,this.timer&&clearTimeout(this.timer),this.timer=void 0;const e=this.options.stopImageProvisioning(),t=this.options.state.listInstances().map(e=>this.options.convergence.cancel(e.id));await Promise.all(t),await this.activeCycle,await e,await this.options.runtimeAdapters.stopAll();for(const e of this.options.state.listInstances())"local"===this.options.state.requireRuntime(e.runtimeId).type&&this.options.state.controlledInstances.put(Sa(e))}async runCycle(){await this.restoreManagedInstances(),this.stopped||await this.recoverManagedInstances()}runAndContinue(){if(this.stopped)return;const e=this.runCycle().catch(e=>this.options.error({error:e},"node agent startup recovery cycle failed"));this.activeCycle=e,e.finally(()=>{this.activeCycle===e&&(this.activeCycle=void 0),this.cycleRequested?(this.cycleRequested=!1,this.cycleRequestDelayMs=void 0,this.scheduleNext()):this.scheduleNext()})}scheduleNext(){if(this.stopped)return;const e=this.options.nowMs?.()??Date.now(),t=new Map(this.options.state.listInstances().map(e=>[e.id,e])),n=[...this.restoreErrors.entries()].reduce((e,[n,i])=>{const r=t.get(n);return!r||this.restoredInstances.has(n)||this.suppressedInstances.has(n)||"local"!==this.options.state.requireRuntime(r.runtimeId).type?e:Na.has(r.status)||"failed"===r.status?Math.min(e,i.nextAttemptAt):e},Number.POSITIVE_INFINITY),i=Math.min(this.options.intervalMs??1e4,Math.max(0,n-e));this.timer=setTimeout(()=>{this.timer=void 0,this.runAndContinue()},i),this.timer.unref?.()}requestCycle(e=0){if(this.started&&!this.stopped){if(this.activeCycle)return this.cycleRequested=!0,void(this.cycleRequestDelayMs=void 0===this.cycleRequestDelayMs?e:Math.min(this.cycleRequestDelayMs,e));this.timer&&clearTimeout(this.timer),this.timer=setTimeout(()=>{this.timer=void 0,this.runAndContinue()},e),this.timer.unref?.()}}}function za(e){return e.readyState===(e.OPEN??1)}function _a(e){const t=Buffer.isBuffer(e)?e.toString("utf8"):"string"==typeof e?e:"";if(Buffer.byteLength(t,"utf8")<=123)return t;let n="";for(const e of t){const t=`${n}${e}`;if(Buffer.byteLength(t,"utf8")>123)break;n=t}return n}function Ca(e){if("number"==typeof e&&Number.isInteger(e))return e>=3e3&&e<=4999||e>=1e3&&e<=1014&&1004!==e&&1005!==e&&1006!==e?e:void 0}function ka(e,t,n){e.close(Ca(t),_a(n)||void 0)}function Oa(e,t,n,i){if(za(e))for(const e of t.splice(0))if(i(e),!n(e))return}function Ra(e,t){const n=new URL(t.tunnelUrl);n.searchParams.set("nodeId",t.nodeId);const i=t.secret?Ws({nodeId:t.nodeId,keyId:t.keyId,secret:t.secret,method:"GET",pathWithQuery:`${n.pathname}${n.search}`}):{},r=new m(n,{headers:i}),o=new Map,s=new Map,a=new Map;let c;r.on("error",i=>{e.log.warn({nodeId:t.nodeId,tunnelUrl:`${n.origin}${n.pathname}`,error:i instanceof Error?i.message:String(i)},"node agent reverse tunnel connection failed")});const d=e=>{const n=e.startsWith("/")?e:`/${e}`,i="function"==typeof t.port?t.port():t.port,r=new URL(`/api/node-agent${n}`,`http://127.0.0.1:${i}`);return r.protocol="ws:",r},l=(e,n,i,r={})=>{const o=e.startsWith("/")?e:`/${e}`;return{...r,...t.secret&&t.keyId?Ws({nodeId:t.nodeId,keyId:t.keyId,secret:t.secret,method:n,pathWithQuery:`/api/node-agent${o}`,body:i}):t.token?{authorization:`Bearer ${t.token}`}:{}}},u=e=>t.secret?Ws({nodeId:t.nodeId,keyId:t.keyId,secret:t.secret,method:"GET",pathWithQuery:`${e.pathname}${e.search}`}):{},p=(e,t,n)=>{const i=o.get(e);o.delete(e),i?.upstream&&ka(i.upstream,t,n),i?.tunnel&&ka(i.tunnel,t,n)},h=(e,t,n=!1)=>new Promise((i,r)=>{e.send(t,{binary:n},e=>e?r(e):i())});r.on("open",()=>{r.send(JSON.stringify({type:"node-agent.identify",nodeId:t.nodeId,serverTime:(new Date).toISOString()})),c=e.nodeAgentEventForwarder?.addOutput(r)}),r.on("close",()=>{for(const e of o.keys())p(e,1001,"Reverse tunnel disconnected.");for(const[e,t]of s)s.delete(e),t.controller.abort(),ka(t.tunnel,1001,"Reverse tunnel disconnected.");for(const[e,t]of a)a.delete(e),t.abort();c?.(),c=void 0});return r.on("message",i=>{(async i=>{let c;try{c=JSON.parse(String(i))}catch{return void r.send(JSON.stringify({type:"node-agent.error",code:"INVALID_JSON"}))}const g=c&&"object"==typeof c?c:{};if("control-plane.http.open"===g.type){const i="string"==typeof g.streamId?g.streamId:"",o="string"==typeof g.route&&g.route.startsWith("/")?g.route:"/health",a=g.init&&"object"==typeof g.init?g.init:{},c=a.headers&&"object"==typeof a.headers?a.headers:{},d=Rs(a.method);let p;try{p=Tt(a.body)}catch(n){return e.log.warn({nodeId:t.nodeId,messageType:g.type,streamId:i,error:n instanceof Error?n.message:String(n)},"node agent reverse tunnel request body rejected"),void r.send(JSON.stringify({type:"node-agent.error",code:"NODE_TUNNEL_REQUEST_BODY_INVALID",streamId:i}))}const f=new AbortController,y=(e=>{const t=new URL(n);return t.pathname=`${t.pathname.replace(/\/$/,"")}/http-streams/${encodeURIComponent(e)}`,t})(i),I=new m(y,{headers:u(y)});return s.set(i,{tunnel:I,controller:f}),I.on("open",async()=>{try{const e=await fetch((e=>{const n=e.startsWith("/")?e:`/${e}`,i="function"==typeof t.port?t.port():t.port;return new URL(`/api/node-agent${n}`,`http://127.0.0.1:${i}`)})(o),{method:d,headers:l(o,d,p,c),body:Buffer.isBuffer(p)?new Uint8Array(p):p,signal:f.signal});if(await h(I,JSON.stringify({type:"node-agent.http.head",streamId:i,status:e.status,headers:Object.fromEntries(e.headers.entries())})),e.body){const t=e.body.getReader();for(;;){const{done:e,value:n}=await t.read();if(e)break;await h(I,Buffer.from(n),!0)}}await h(I,JSON.stringify({type:"node-agent.http.end",streamId:i})),I.close(1e3,"HTTP stream completed.")}catch(e){I.readyState===m.OPEN&&(await h(I,JSON.stringify({type:"node-agent.http.error",streamId:i,message:e instanceof Error?e.message:String(e)})).catch(()=>{}),I.close(1011,"HTTP stream failed."))}finally{s.delete(i)}}),I.on("close",()=>{f.abort(),s.delete(i)}),void I.on("error",()=>f.abort())}if("control-plane.http.cancel"===g.type){const e="string"==typeof g.streamId?g.streamId:"",t=s.get(e);if(!t)return;return s.delete(e),t.controller.abort(),void ka(t.tunnel,1e3,"string"==typeof g.reason?g.reason:"HTTP stream canceled.")}if("control-plane.websocket.open"===g.type){const e="string"==typeof g.streamId?g.streamId:"",t="string"==typeof g.route?g.route:"",i=Array.isArray(g.protocols)?g.protocols.filter(e=>"string"==typeof e):void 0;try{const s=l(t,"GET",void 0),a=i?.length?new m(d(t),i,{headers:s}):new m(d(t),{headers:s}),c=(e=>{const t=new URL(n);return t.pathname=`${t.pathname.replace(/\/$/,"")}/streams/${encodeURIComponent(e)}`,t})(e),p=new m(c,{headers:u(c)});o.set(e,{upstream:a,tunnel:p,close:(e=1e3,t="")=>{ka(a,e,t),ka(p,e,t)}}),a.on("open",()=>{r.send(JSON.stringify({type:"node-agent.websocket.open",streamId:e,protocol:a.protocol}))}),function(e,t,n={}){const i=n.pendingFrameLimit??256,r=n.maxFrameBytes??8388608,o=n.maxTotalBytes??1073741824,s=n.maxBufferedBytes??16777216;let a=!1,c=za(t);const d=[],l=[];let u,m=0,p=0,h=0;const g=e=>Buffer.isBuffer(e)||e instanceof ArrayBuffer||ArrayBuffer.isView(e)?e.byteLength:Buffer.byteLength("string"==typeof e?e:String(e),"utf8"),f=(i,s)=>{const a=g(s);return h+=a,n.onFrame?.(i,a),!(a>r||h>o)||(ka(e,1009,"WebSocket bridge traffic limit exceeded."),ka(t,1009,"WebSocket bridge traffic limit exceeded."),!1)},y=()=>{u&&(clearTimeout(u),u=void 0)},I=(n,i)=>{const r=i.bytes;if((n.bufferedAmount??0)+r>s)return ka(e,1013,"WebSocket bridge consumer is too slow."),ka(t,1013,"WebSocket bridge consumer is too slow."),!1;try{return function(e,t){e.send(t.data,{binary:t.isBinary})}(n,i),!0}catch{return ka(e,1011,"WebSocket bridge send failed."),ka(t,1011,"WebSocket bridge send failed."),!1}},A=(n,r,o)=>{if(r.length>=i)return ka(e,1011,"WebSocket bridge pending frame limit exceeded."),void ka(t,1011,"WebSocket bridge pending frame limit exceeded.");const a="upstream"===n?m:p;if((("upstream"===n?t:e).bufferedAmount??0)+a+o.bytes>s)return ka(e,1013,"WebSocket bridge consumer is too slow."),void ka(t,1013,"WebSocket bridge consumer is too slow.");r.push(o),"upstream"===n?m+=o.bytes:p+=o.bytes};n.upstreamOpenTimeoutMs&&!c&&(u=setTimeout(()=>{c||a||(ka(e,1011,"Upstream websocket did not open."),ka(t))},n.upstreamOpenTimeoutMs)),e.on("open",()=>Oa(e,l,t=>I(e,t),e=>{p-=e.bytes})),t.on("open",()=>{y(),c=!0,n.onUpstreamOpen?.(),Oa(t,d,e=>I(t,e),e=>{m-=e.bytes})}),e.on("message",(e,n=!1)=>{if(!f("client-to-upstream",e))return;const i={data:e,isBinary:Boolean(n),bytes:g(e)};za(t)?I(t,i):A("upstream",d,i)}),t.on("message",(t,n=!1)=>{if(!f("upstream-to-client",t))return;const i={data:t,isBinary:Boolean(n),bytes:g(t)};za(e)?I(e,i):A("client",l,i)}),t.on("close",(t,i)=>{y(),n.onUpstreamClose?.(t,i),(c||a||!n.onUpstreamCloseBeforeOpen?.())&&ka(e,t,i)}),t.on("error",t=>{n.onUpstreamError?.(t),(c||a||!n.onUpstreamErrorBeforeOpen?.(t))&&ka(e)}),e.on("close",(e,i)=>{y(),a=!0,n.onClientClose?.(e,i),ka(t,e,i)}),e.on("error",e=>{y(),a=!0,n.onClientError?.(e),ka(t,1011,"WebSocket bridge client failed.")})}(p,a,{pendingFrameLimit:256,upstreamOpenTimeoutMs:1e4,onClientClose:()=>{o.delete(e)},onClientError:t=>{o.delete(e),r.send(JSON.stringify({type:"node-agent.websocket.error",streamId:e,message:t instanceof Error?t.message:String(t)}))},onUpstreamClose:(t,n)=>{o.delete(e);const i=Ca(t),s=_a(n);r.send(JSON.stringify({type:"node-agent.websocket.close",streamId:e,...void 0===i?{}:{code:i},...s?{reason:s}:{}}))},onUpstreamError:t=>{o.delete(e),r.send(JSON.stringify({type:"node-agent.websocket.error",streamId:e,message:t instanceof Error?t.message:String(t)}))}})}catch(t){r.send(JSON.stringify({type:"node-agent.websocket.error",streamId:e,message:t instanceof Error?t.message:String(t)}))}return}if("control-plane.websocket.close"===g.type){const e="string"==typeof g.streamId?g.streamId:"";return void p(e,"number"==typeof g.code?g.code:1e3,"string"==typeof g.reason?g.reason:"")}if("control-plane.request.cancel"===g.type){const e="string"==typeof g.requestId?g.requestId:"";return a.get(e)?.abort(),void a.delete(e)}if("control-plane.request"===g.type){const n="string"==typeof g.requestId?g.requestId:"",i=g.init&&"object"==typeof g.init?g.init:{},o="string"==typeof g.route&&g.route.startsWith("/")?g.route:"/health",s=i.headers&&"object"==typeof i.headers?i.headers:{},c=Rs(i.method);let d;try{d=Tt(i.body)}catch(i){return e.log.warn({nodeId:t.nodeId,messageType:g.type,requestId:n,error:i instanceof Error?i.message:String(i)},"node agent reverse tunnel request body rejected"),void r.send(JSON.stringify({type:"node-agent.response",requestId:n,status:400,error:{code:"NODE_TUNNEL_REQUEST_BODY_INVALID",message:"Reverse tunnel request body does not match the negotiated protocol."}}))}const u=new AbortController;a.set(n,u);try{const t=await e.inject({method:c,url:`/api/node-agent${o}`,headers:l(o,c,d,s),payload:d,signal:u.signal});if(u.signal.aborted)return;r.send(JSON.stringify({type:"node-agent.response",requestId:n,status:t.statusCode,headers:t.headers,body:t.body}))}catch(e){if(u.signal.aborted)return;r.send(JSON.stringify({type:"node-agent.response",requestId:n,status:502,error:{code:"NODE_AGENT_REVERSE_INJECT_FAILED",message:e instanceof Error?e.message:String(e)}}))}finally{a.delete(n)}}})(i).catch(n=>{e.log.warn({nodeId:t.nodeId,error:n instanceof Error?n.message:String(n)},"node agent reverse tunnel message rejected");try{r.send(JSON.stringify({type:"node-agent.error",code:"INVALID_TUNNEL_MESSAGE"}))}catch{}})}),r}function xa(e,t){return Number.isFinite(e)&&Number(e)>0?Number(e):t}function Da(e){return e.unref?.(),e}class Pa{connectTimeoutMs;handshakeTimeoutMs;heartbeatIntervalMs;heartbeatTimeoutMs;stableThresholdMs;now;setTimeoutFn;clearTimeoutFn;ping;onTimeout;onStable;onPhase;connectTimer;handshakeTimer;heartbeatTimer;stableTimer;awaitingPongSince;stable=!1;stopped=!1;currentPhase="connecting";lastActivityAt;lastPongAt;constructor(e){this.connectTimeoutMs=xa(e.connectTimeoutMs,1e4),this.handshakeTimeoutMs=xa(e.handshakeTimeoutMs,1e4),this.heartbeatIntervalMs=xa(e.heartbeatIntervalMs,25e3),this.heartbeatTimeoutMs=xa(e.heartbeatTimeoutMs,1e4),this.stableThresholdMs=xa(e.stableThresholdMs,6e4),this.now=e.now||Date.now,this.setTimeoutFn=e.setTimeoutFn||setTimeout,this.clearTimeoutFn=e.clearTimeoutFn||clearTimeout,this.ping=e.ping,this.onTimeout=e.onTimeout,this.onStable=e.onStable,this.onPhase=e.onPhase}get phase(){return this.currentPhase}start(){this.stopped=!1,this.setPhase("connecting"),this.clearTimer("connectTimer"),this.connectTimer=Da(this.setTimeoutFn(()=>this.timeout("connect"),this.connectTimeoutMs))}opened(){this.stopped||(this.clearTimer("connectTimer"),this.setPhase("handshaking"),this.handshakeTimer=Da(this.setTimeoutFn(()=>this.timeout("handshake"),this.handshakeTimeoutMs)),this.scheduleHeartbeat(this.heartbeatIntervalMs))}healthy(){this.stopped||(this.clearTimer("handshakeTimer"),this.activity(),this.setPhase("healthy"),this.stable||this.stableTimer||(this.stableTimer=Da(this.setTimeoutFn(()=>{this.stableTimer=void 0,this.stopped||"healthy"!==this.currentPhase||(this.stable=!0,this.onStable?.())},this.stableThresholdMs))))}activity(){this.stopped||(this.lastActivityAt=this.now())}pong(){if(this.stopped)return;const e=this.now();this.awaitingPongSince=void 0,this.lastPongAt=e,this.lastActivityAt=e,this.scheduleHeartbeat(this.heartbeatIntervalMs)}close(){this.stopped||(this.stopped=!0,this.clearTimers(),this.awaitingPongSince=void 0,this.setPhase("closed"))}diagnostics(){return{phase:this.currentPhase,stable:this.stable,...void 0===this.lastActivityAt?{}:{lastActivityAt:new Date(this.lastActivityAt).toISOString()},...void 0===this.lastPongAt?{}:{lastPongAt:new Date(this.lastPongAt).toISOString()}}}scheduleHeartbeat(e){this.stopped||(this.clearTimer("heartbeatTimer"),this.heartbeatTimer=Da(this.setTimeoutFn(()=>{if(this.heartbeatTimer=void 0,!this.stopped){if(void 0!==this.awaitingPongSince){const e=Math.max(0,this.now()-this.awaitingPongSince);return e>=this.heartbeatTimeoutMs?void this.timeout("heartbeat"):void this.scheduleHeartbeat(this.heartbeatTimeoutMs-e)}this.awaitingPongSince=this.now();try{this.ping()}catch{return void this.timeout("heartbeat")}this.scheduleHeartbeat(this.heartbeatTimeoutMs)}},e)))}timeout(e){this.stopped||(this.clearTimers(),this.setPhase("failed"),this.onTimeout(e))}setPhase(e){this.currentPhase!==e&&(this.currentPhase=e,this.onPhase?.(e))}clearTimers(){this.clearTimer("connectTimer"),this.clearTimer("handshakeTimer"),this.clearTimer("heartbeatTimer"),this.clearTimer("stableTimer")}clearTimer(e){const t=this[e];t&&this.clearTimeoutFn(t),this[e]=void 0}}function Ma(e){const t=new URL(Ks,e);return t.protocol="https:"===t.protocol?"wss:":"ws:",t.toString()}const La=new Set(["linux","darwin","win32","freebsd","openbsd","aix","sunos"]);function ja(e){return La.has(e)?e:"unknown"}function $a(e){return!0===e.managedArtifacts}class Fa{managedArtifacts=!0;executor;runCommand;platform;arch;constructor(e,t,n,i){this.executor=e,this.runCommand=t,this.platform=n,this.arch=i}artifactTarget(e){return this.executor.inspectRuntimeTarget(e?.instance.runtime.containerName)}async installRuntime(e,t){const n=e.instance.runtime.containerName;if(!n)throw Object.assign(new Error(`Instance ${e.instance.id} does not have a Docker container.`),{code:"INSTANCE_RUNTIME_INSTALL_FAILED"});await this.executor.installRuntimeReleaseWithRecovery({containerName:n,expectedContainerId:e.instance.runtime.containerId,artifactPath:t.archivePath,identity:t.identity})}async inspectRuntime(e,t){const n=e.instance.runtime.containerName;if(!n)return!1;const i=function(e,t){return e.packageName===t.packageName&&e.version===t.version&&e.platform===t.platform&&e.arch===t.arch&&e.formatVersion===t.formatVersion&&e.launcherAbi===t.launcherAbi&&e.entrypoint===t.entrypoint&&e.sha256===t.sha256}(await this.executor.inspectRuntimeVersion(n),t),r=e.instance.runtime.labels["task-handoff.bootstrap-backup"];return i&&r&&await this.executor.removeBootstrapBackup(r,e.instance.id),i}start(e){return this.executor.start(e)}stop(e){return this.executor.stop(e)}restart(e){return this.executor.restart(e,e.instance.runtime.containerId)}delete(e,t){return this.executor.delete(e,t)}async check(e){try{const t=(await this.runCommand("docker",["version","--format","{{.Server.Version}}"],{timeoutMs:5e3})).stdout.trim();return{status:"online",capabilities:{...e.capabilities,daemon:{status:"online",hostPlatform:ja(this.platform),...t?{serverVersion:t}:{}}}}}catch(t){return{status:"offline",capabilities:{...e.capabilities,daemon:{status:"offline",hostPlatform:ja(this.platform),error:t instanceof Error?t.message:String(t)}}}}}}class Ua{docker;local;constructor(e,t){this.docker=e,this.local=t}forRuntime(e){if("docker"===e.type)return this.docker;if("local"===e.type)return this.local;throw Object.assign(new Error(`Runtime type ${e.type} is not supported by this node agent.`),{statusCode:400,code:"NODE_RUNTIME_TYPE_UNSUPPORTED"})}managedAdapters(){return[this.docker,this.local].filter($a)}async stopAll(){await(this.local.stopAll?.())}}const Va="task-handoff.local-process-nonce",qa=1e3,Ha=1e4,Ba=2e3;function Ka(e,t){try{e?.(t)}catch{}}function Ga(e){return e.runtime.port?`http://127.0.0.1:${e.runtime.port}`:e.target.web}async function Ja(e,t){try{const n=await fetch(`${e}/api/internal/node-agent/process-identity`,{headers:{authorization:`Bearer ${t}`},signal:AbortSignal.timeout(qa)});if(!n.ok)return;const i=(await n.json()).data;if("string"!=typeof i?.instanceId||"number"!=typeof i.pid||"string"!=typeof i.processNonce)return;return{instanceId:i.instanceId,pid:i.pid,processNonce:i.processNonce,startIdentity:"string"==typeof i.startIdentity?i.startIdentity:void 0}}catch{return}}async function Wa(e,t){if(C(e)!==t)return!1;try{process.kill(e,"SIGTERM")}catch{return!0}const n=Date.now()+Ha;for(;Date.now()<n;){try{process.kill(e,0)}catch{return!0}await new Promise(e=>setTimeout(e,50))}try{process.kill(e,"SIGKILL")}catch{}const i=Date.now()+Ba;for(;Date.now()<i;){try{process.kill(e,0)}catch{return!0}await new Promise(e=>setTimeout(e,50))}return!1}function Ya(e,t){return Object.assign(new Error(t),{statusCode:503,code:"LOCAL_INSTANCE_STOP_UNCONFIRMED",instanceId:e.id})}async function Xa(e){return!await function(e){return new Promise(t=>{const n=p.createConnection({host:"127.0.0.1",port:e}),i=e=>{n.removeAllListeners(),n.destroy(),t(e)};n.once("connect",()=>i(!0)),n.once("error",()=>i(!1)),n.setTimeout(250,()=>i(!1))})}(e)&&new Promise(t=>{const n=p.createServer();n.once("error",()=>t(!1)),n.listen({host:"127.0.0.1",port:e,exclusive:!0},()=>n.close(()=>t(!0)))})}const Qa=Xa;function Za(e,t){return null!==e.exitCode||null!==e.signalCode?Promise.resolve(!0):new Promise(n=>{const i=setTimeout(()=>{e.off("exit",r),n(null!==e.exitCode||null!==e.signalCode)},t);i.unref();const r=()=>{clearTimeout(i),n(!0)};e.once("exit",r)})}async function ec(e,t=1e4,n=2e3,i){if(await Za(e,t))return;Ka(i,{stage:"graceful-timeout",pid:e.pid,timeoutMs:t});let r=!1;if(null===e.exitCode&&null===e.signalCode&&(e.kill("SIGKILL"),r=!0,Ka(i,{stage:"force-signal-sent",pid:e.pid,signal:"SIGKILL"})),!await Za(e,n))throw Ka(i,{stage:"force-exit-unconfirmed",pid:e.pid,signal:"SIGKILL",timeoutMs:n}),Object.assign(new Error(`Controlled instance process pid=${e.pid??"unknown"} did not exit after SIGKILL.`),{statusCode:503,code:"LOCAL_INSTANCE_PROCESS_EXIT_UNCONFIRMED",pid:e.pid});r&&Ka(i,{stage:"force-exit-confirmed",pid:e.pid,signal:"SIGKILL"})}class tc{children=new Map;readyChildren=new WeakSet;expectedExits=new WeakSet;lifecycleReporters=new WeakMap;lockPath;onUnexpectedExit;onUnexpectedExitError;constructor(e,t,n){this.lockPath=e,this.onUnexpectedExit=t,this.onUnexpectedExitError=n}track(e,t,n){this.children.set(e,t),n&&this.lifecycleReporters.set(t,n),t.once("exit",(n,i)=>{if(this.release(e,t),this.readyChildren.has(t)&&!this.expectedExits.has(t)){const r={instanceId:e,pid:t.pid,code:n,signal:i},o=e=>{try{this.onUnexpectedExitError?.(e,r)}catch{}};try{Promise.resolve(this.onUnexpectedExit?.(r)).catch(o)}catch(e){o(e)}}})}markReady(e,t){return this.children.get(e)===t&&null===t.exitCode&&null===t.signalCode&&(this.readyChildren.add(t),!0)}release(e,t){this.children.get(e)===t&&this.children.delete(e)}async stop(e){const t=this.children.get(e.id);if(t){this.expectedExits.add(t);const n=this.lifecycleReporters.get(t);return t.killed||(t.kill("SIGTERM"),Ka(n,{stage:"graceful-signal-sent",pid:t.pid,signal:"SIGTERM"})),this.children.delete(e.id),void await ec(t,Ha,Ba,n)}const i=await async function(e){const t=Ga(e),n=e.runtime.labels?.[Va];if(!t||!n||!e.registrationToken)return;const i=await Ja(t,e.registrationToken);if(i&&i.instanceId===e.id&&i.processNonce===n)try{return(await fetch(`${t}/api/internal/node-agent/shutdown`,{method:"POST",headers:{authorization:`Bearer ${e.registrationToken}`},signal:AbortSignal.timeout(qa)})).ok?i:void 0}catch{return}}(e);if(i){const t=Ga(e),n=Date.now()+Ha;for(;t&&Date.now()<n;){if(!await Ja(t,e.registrationToken))return;await new Promise(e=>setTimeout(e,50))}const r=t?await Ja(t,e.registrationToken):void 0;if(r&&r.instanceId===i.instanceId&&r.pid===i.pid&&r.processNonce===i.processNonce&&r.startIdentity===i.startIdentity&&r.startIdentity&&await Wa(r.pid,r.startIdentity))return;throw Ya(e,`Controlled instance ${e.id} accepted shutdown but its exit could not be confirmed.`)}const r=function(e=function(){const e="win32"===process.platform?c.tmpdir():"/tmp";return n.join(e,`task-handoff-local-controlled-instance-${function(){const e=process.getuid?.();return void 0!==e?String(e):c.userInfo().username.replace(/[^a-zA-Z0-9_.-]/g,"_")}()}.lock`)}()){return k(e)}(this.lockPath),o=await async function(e){const t=Ga(e);if(t)try{const[n,i]=await Promise.all([fetch(`${t}/api/instance/status`,{signal:AbortSignal.timeout(qa)}),fetch(`${t}/api/diagnostics`,{signal:AbortSignal.timeout(qa)})]);if(!n.ok||!i.ok)return;const r=await n.json(),o=await i.json(),s=o.data?.runtime?.pid;if(r.data?.id!==e.id||"controlled"!==r.data.controlMode||"number"!=typeof s||!Number.isInteger(s)||s<=0)return;const a=C(s);return a?{pid:s,startIdentity:a}:void 0}catch{return}}(e);if(o){if(await Wa(o.pid,o.startIdentity))return;throw Ya(e,`Legacy controlled instance ${e.id} did not exit after termination.`)}if(r?.instanceId===e.id&&x(r))throw Ya(e,`Local controlled instance ${e.id} is still owned by pid ${r.pid}, but its process identity could not be verified.`)}async waitUntilHealthy(e,t,n,i,r=function(e=process.env.TASK_HANDOFF_LOCAL_PROCESS_READY_TIMEOUT_MS){const t=Number(e);return Number.isFinite(t)&&t>0?t:3e4}()){const o=Date.now()+r;for(;Date.now()<o;){if(null!==n.exitCode||null!==n.signalCode)return!1;const r=await Ja(e,i);if(r&&r.instanceId===t.instanceId&&r.pid===t.pid&&r.processNonce===t.processNonce&&r.startIdentity===t.startIdentity)return!0;await new Promise(e=>setTimeout(e,100))}return!1}async stopAll(){const e=Array.from(this.children.values());for(const t of e){this.expectedExits.add(t);const e=this.lifecycleReporters.get(t);t.killed||(t.kill("SIGTERM"),Ka(e,{stage:"graceful-signal-sent",pid:t.pid,signal:"SIGTERM"}))}this.children.clear(),await Promise.all(e.map(e=>ec(e,Ha,Ba,this.lifecycleReporters.get(e))))}}async function nc(e,t){try{const n=await e(t,["--version"]);return{available:!0,command:t,version:(n.stdout||n.stderr).split(/\r?\n/)[0]?.trim()||void 0}}catch{return{available:!1}}}class ic{runCommand;paths;nodeAgentUrl;processSupervisor;commandOverride;lockPath;constructor(e,t,n,i,r,o,s){this.runCommand=e,this.paths=t,this.nodeAgentUrl=n,this.commandOverride=i,this.lockPath=r,this.processSupervisor=new tc(r,o,s)}async start(e){await this.processSupervisor.stop(e.instance);const i=function(e){if("local-folder"!==e.source.type){const e=new Error("Localhost runtime currently supports local folder sources only.");throw Object.assign(e,{statusCode:400,code:"LOCAL_RUNTIME_REQUIRES_LOCAL_FOLDER"}),e}return n.resolve(e.source.path)}(e.instance),r=e.instance.runtime.port,o=!!r&&await Xa(r),s="allocate"===process.env.TASK_HANDOFF_LOCAL_INSTANCE_PORT_CONFLICT;if(r&&!o&&!s)throw Object.assign(new Error(`Local controlled instance port 127.0.0.1:${r} is already in use.`),{statusCode:409,code:"LOCAL_INSTANCE_PORT_IN_USE"});const a=r&&o?r:await async function(){const e=Number(process.env.TASK_HANDOFF_LOCAL_INSTANCE_PORT_START||19e3),t=Number.isInteger(e)&&e>0?e:19e3;for(let e=t;e<t+1e3&&e<=65535;e+=1)if(await Qa(e))return e;throw Object.assign(new Error(`No free localhost port found in range ${t}-${Math.min(t+999,65535)}.`),{statusCode:503,code:"LOCAL_INSTANCE_PORT_UNAVAILABLE"})}(),c=n.join(this.paths.dataDir,"local-instances",e.instance.id),u=n.join(c,"logs");t.mkdirSync(u,{recursive:!0,mode:448}),t.chmodSync(c,448),t.chmodSync(u,448);const[m,...p]=function(e){if(e)return e;const i=n.resolve(process.cwd(),"bin","task-handoff.js");if(t.existsSync(i))return[process.execPath,i,"web"];throw Object.assign(new Error("The bundled controlled-instance command is unavailable."),{statusCode:500,code:"LOCAL_CONTROLLED_COMMAND_MISSING"})}(this.commandOverride),h=[...p,"--host","127.0.0.1","--port",String(a)],g=d.randomUUID(),f=n.join(u,"controlled-instance.out.log"),y=n.join(u,"controlled-instance.err.log");to(f),to(y);const I=t.openSync(f,"a",384),A=t.openSync(y,"a",384),b=l.spawn(m,h,{cwd:i,detached:!1,stdio:["ignore",I,A],env:{...process.env,TASK_HANDOFF_CONTROL_MODE:"controlled",TASK_HANDOFF_RUNTIME_KIND:"local",TASK_HANDOFF_CONTROLLED_INSTANCE_VERSION:Qo(),...this.lockPath?{TASK_HANDOFF_LOCAL_CONTROLLED_INSTANCE_LOCK_PATH:this.lockPath}:{},TASK_HANDOFF_NODE_AGENT_URL:this.nodeAgentUrl(),TASK_HANDOFF_INSTANCE_ID:e.instance.id,TASK_HANDOFF_INSTANCE_NAME:e.instance.name,TASK_HANDOFF_REGISTRATION_TOKEN:e.instance.registrationToken||"",TASK_HANDOFF_PROJECT_ID:e.project.id,TASK_HANDOFF_NODE_ID:e.node.id,TASK_HANDOFF_RUNTIME_ID:e.runtime.id,TASK_HANDOFF_LOCAL_PROCESS_NONCE:g,TASK_HANDOFF_WORKSPACE:i,TASK_HANDOFF_WORKSPACE_MODE:"local-bind",TASK_HANDOFF_DATA_DIR:c,TASK_HANDOFF_LOG_DIR:u,TASK_HANDOFF_APP_SESSION_PERSIST:"1",TASK_HANDOFF_CODEX_APP_SERVER:process.env.TASK_HANDOFF_CODEX_APP_SERVER||"1",TASK_HANDOFF_WEB_PORT:String(a),TASK_HANDOFF_WEB_HOST:"127.0.0.1",...e.modelEnv||{}}});t.closeSync(I),t.closeSync(A);try{await function(e){return new Promise((t,n)=>{const i=()=>{e.off("error",r),t()},r=t=>{e.off("spawn",i),n(t)};e.once("spawn",i),e.once("error",r)})}(b)}catch(e){const r=e instanceof Error?e.message:String(e);try{t.appendFileSync(n.join(u,"controlled-instance.lifecycle.log"),`[${(new Date).toISOString()}] spawn failed command=${m} cwd=${i} error=${r}\n`)}catch{}throw Object.assign(new Error(`Controlled instance process could not start with command ${m} in ${i}: ${r}`),{statusCode:500,code:"LOCAL_INSTANCE_PROCESS_SPAWN_FAILED"})}const w=n.join(u,"controlled-instance.lifecycle.log");this.processSupervisor.track(e.instance.id,b,e=>{t.appendFileSync(w,`[${(new Date).toISOString()}] shutdown stage=${e.stage} pid=${e.pid??""} signal=${e.signal??""} timeoutMs=${e.timeoutMs??""}\n`)}),b.on("error",e=>{try{t.appendFileSync(w,`[${(new Date).toISOString()}] process error pid=${b.pid??""} error=${e.message}\n`)}catch{}}),b.once("exit",(e,n)=>{try{t.appendFileSync(w,`[${(new Date).toISOString()}] exited pid=${b.pid??""} code=${e??""} signal=${n??""}\n`)}catch{}});const v=`http://127.0.0.1:${a}`,E=b.pid?C(b.pid):void 0;if(!(b.pid&&e.instance.registrationToken&&await this.processSupervisor.waitUntilHealthy(v,{instanceId:e.instance.id,pid:b.pid,processNonce:g,startIdentity:E},b,e.instance.registrationToken)&&this.processSupervisor.markReady(e.instance.id,b)))throw this.processSupervisor.release(e.instance.id,b),null===b.exitCode&&null===b.signalCode&&b.kill("SIGTERM"),await ec(b),Object.assign(new Error(`Controlled instance process did not become ready for instance ${e.instance.id} on ${v}.`),{statusCode:503,code:"LOCAL_INSTANCE_PROCESS_NOT_READY"});return{status:"registering",health:"unknown",connectionStatus:"online",agentStatus:"unknown",targetStatus:"unknown",uiAccessStatus:"unknown",target:{strategy:"direct-port",status:"unknown",web:v,api:`${v}/api`},workspace:{mode:"local-bind",status:"pending",path:i},runtime:{kind:"local",workspacePath:i,pid:b.pid,port:a,labels:{...e.instance.runtime.labels,"task-handoff.runtime-kind":"local",[Va]:g}}}}async stop(e){return await this.processSupervisor.stop(e.instance),{status:"stopped",health:"unknown",connectionStatus:"offline",agentStatus:"offline",targetStatus:"unknown",uiAccessStatus:"unknown",target:{...e.instance.target,status:"unknown"},runtime:e.instance.runtime}}async restart(e){return this.start(e)}async delete(e,t){return await this.stop(e),Kt.parse({instanceId:e.instance.id,containerDeleted:!0,completed:!0,deletedVolumes:[],retainedVolumes:[],volumeResults:[]})}async check(e){const[t,n]=await Promise.all([nc(this.runCommand,"codex"),nc(this.runCommand,"claude")]);return{status:"online",capabilities:us({...e.capabilities,apps:{terminal:!0,codex:t,claude:n}})}}async stopAll(){await this.processSupervisor.stopAll()}}const rc=["codex","claude"],oc=5e3,sc=C(process.pid);function ac(e){const t=process.env[e]?.trim();return t||void 0}function cc(e){const t=e.authorization;return"string"==typeof t&&t.startsWith("Bearer ")?t.slice(7).trim():void 0}function dc(e){if("string"!=typeof e)return!1;const t=e.trim().toLowerCase();return"localhost"===t||"127.0.0.1"===t||"::1"===t||"::ffff:127.0.0.1"===t}function lc(e){return!e.ip&&!e.socket.remoteAddress&&!e.socket.remoteFamily}function uc(){return(new Date).toISOString()}async function mc(e,t){if(!t.target.web)return"unknown";const n=new AbortController,i=setTimeout(()=>n.abort(),2e3);try{return(await e(`${fc(t)}/api/health`,{signal:n.signal})).ok?"reachable":"endpoint-unreachable"}catch{return"endpoint-unreachable"}finally{clearTimeout(i)}}async function pc(e,t,n,i){const r=new AbortController,o=setTimeout(()=>r.abort(),i);try{return await e(t,{...n,signal:r.signal})}finally{clearTimeout(o)}}async function hc(e,t,n,i){if(!t.config.autoImportAgentConfigs)return void i.diagnostic({instanceId:t.id,action:n},"node instance config auto-import skipped");if("reachable"!==t.targetStatus)return;const r=fc(t),o=Number(process.env.TASK_HANDOFF_CONFIG_AUTO_IMPORT_TIMEOUT_MS||oc);for(const s of rc)try{const a=await pc(e,`${r}/api/config-sync/import/${encodeURIComponent(s)}`,{method:"POST"},Number.isFinite(o)&&o>0?o:oc);if(!a.ok){i.warn({instanceId:t.id,action:n,preset:s,statusCode:a.status},"node instance config auto-import failed");continue}i.diagnostic({instanceId:t.id,action:n,preset:s},"node instance config auto-import completed")}catch(e){i.warn({instanceId:t.id,action:n,preset:s,error:e instanceof Error?e.message:String(e)},"node instance config auto-import failed")}}async function gc(e,t,n,i){const r=t.requireInstance(n);if(t.instancePrivateConfigs.materialize(r.id,r.registrationToken,t.resolvedAssignedModelEnvironment(n)),"reachable"!==r.targetStatus||!r.target.web)return!1;let o;try{o=await pc(e,`${fc(r)}/api/internal/model-environment`,{method:"PUT",headers:{"content-type":"application/json",authorization:`Bearer ${r.registrationToken}`},body:JSON.stringify(t.resolvedAssignedModelEnvironment(n))},oc)}catch(e){return i?.({instanceId:n,targetWeb:r.target.web,error:e instanceof Error?e.message:String(e)},"node instance model environment live sync deferred"),!1}return!!o.ok||(i?.({instanceId:n,targetWeb:r.target.web,statusCode:o.status},"node instance model environment live sync deferred"),!1)}function fc(e){const t=e.target.web;if(!t){const t=new Error(`Instance ${e.id} does not have a web endpoint.`);throw Object.assign(t,{statusCode:409,code:"NODE_INSTANCE_WEB_ENDPOINT_MISSING"}),t}if("direct-port"!==e.target.strategy)return t.replace(/\/$/,"");try{const e=new URL(t);return e.port?(e.hostname=process.env.TASK_HANDOFF_NODE_AGENT_PROXY_HOST||"127.0.0.1",e.toString().replace(/\/$/,"")):t.replace(/\/$/,"")}catch{return t.replace(/\/$/,"")}}async function yc(e,t,n,i,r,o="request"){const s=e.requireInstance(i);if(s.imageProvisioning&&"ready"!==s.imageProvisioning.phase&&"docker"===e.requireRuntime(s.runtimeId).type)return r.diagnostic({instanceId:i,action:"start",reason:o,runtimeId:s.runtimeId,imageId:s.imageSelection?.imageId,imagePhase:s.imageProvisioning.phase},"node instance start queued until image provisioning completes"),e.controlledInstances.put(Si.parse({...s,status:"starting",updatedAt:uc()}));r.diagnostic({instanceId:i,action:"start",reason:o,runtimeId:s.runtimeId,imageId:s.imageSelection?.imageId},"node instance start requested");const a=e.applyInstanceLifecycle(i,{type:"start-requested"}),c=t.forRuntime(e.requireRuntime(a.runtimeId)),d=await c.start(e.context(a)),l=await mc(n,Si.parse({...a,...d,target:d.target?{...a.target,...d.target}:a.target,workspace:d.workspace?{...a.workspace,error:void 0,...d.workspace}:a.workspace,runtime:d.runtime?{...a.runtime,...d.runtime}:a.runtime,updatedAt:uc()})),u=e.applyInstanceLifecycle(i,{type:"runtime-lifecycle-completed",baseline:a,observation:{...d,target:d.target?{...d.target,status:l}:void 0,workspace:d.workspace?{error:void 0,...d.workspace}:void 0,targetStatus:l,uiAccessStatus:l}});return r.diagnostic({instanceId:i,action:"start",reason:o,status:u.status,connectionStatus:u.connectionStatus,targetStatus:u.targetStatus,targetWeb:u.target.web,containerName:u.runtime.containerName},"node instance start completed"),u}async function Ic(e={}){const t=e.token||process.env.TASK_HANDOFF_NODE_AGENT_TOKEN,i=Number(e.port||process.env.TASK_HANDOFF_NODE_AGENT_PORT||"8091"),c=`http://127.0.0.1:${i}`,d=e.containerUrl||process.env.TASK_HANDOFF_NODE_AGENT_CONTAINER_URL,l=Zr(e.dataDir),u=e.remoteSecret||process.env.TASK_HANDOFF_NODE_AGENT_REMOTE_SECRET,p=e.remoteKeyId||process.env.TASK_HANDOFF_NODE_AGENT_REMOTE_KEY_ID,g=new Aa(l),f=g.resolveNodeId(e.nodeId||process.env.TASK_HANDOFF_NODE_ID),y=e.connectionMode||("local-ipc"===process.env.TASK_HANDOFF_NODE_AGENT_CONNECTION_MODE?"local-ipc":"local-loopback"),I=e.ipcPath||process.env.TASK_HANDOFF_NODE_AGENT_IPC_PATH||io(l.dataDir),A="local-ipc"===y?`ipc://${encodeURIComponent(I)}`:c,w=e.platform||process.platform,v=e.arch||process.arch,E=new ps(l,f,c,d,i,w);E.node.connectionMode=y,E.node.controlEndpoint=A,E.node.endpoint=A,E.init();const N=e.dockerCommandRunner||Ui,S=new qi(N,e.dockerTerminalCommandRunner),T=new er(N,{publishHost:"127.0.0.1",imageService:S});let z;const _=new Ua(new Fa(T,N,w,v),new ic(e.dockerCommandRunner||Ui,l,()=>E.localNodeAgentUrl,function(){const e=process.env.TASK_HANDOFF_LOCAL_CONTROLLED_COMMAND_ARGV?.trim();if(!e){const e=process.env.TASK_HANDOFF_LOCAL_CONTROLLED_COMMAND?.trim();return e?e.split(/\s+/):void 0}let t;try{t=JSON.parse(e)}catch{throw Object.assign(new Error("TASK_HANDOFF_LOCAL_CONTROLLED_COMMAND_ARGV must be valid JSON."),{code:"LOCAL_CONTROLLED_COMMAND_INVALID"})}if(!Array.isArray(t)||!t.length||t.some(e=>"string"!=typeof e||!e))throw Object.assign(new Error("TASK_HANDOFF_LOCAL_CONTROLLED_COMMAND_ARGV must be a non-empty string array."),{code:"LOCAL_CONTROLLED_COMMAND_INVALID"});return t}(),e.localControlledInstanceLockPath||process.env.TASK_HANDOFF_LOCAL_CONTROLLED_INSTANCE_LOCK_PATH,e=>z.handleUnexpectedLocalExit(e.instanceId,new Error(`Local controlled instance exited unexpectedly (pid=${e.pid??"unknown"}, code=${e.code??"none"}, signal=${e.signal??"none"}).`)),(e,t)=>$.log.error({error:e,instanceId:t.instanceId,pid:t.pid},"local controlled instance exit recovery failed"))),C=e.updateCommandRunner||e.dockerCommandRunner||Ui,k=e.fetchImpl||fetch,O=new mo({cacheDir:n.join(l.dataDir,"runtime-artifacts"),fetchImpl:k}),R=e.resolveRuntimeArtifactRelease||((e,t,n)=>po(e,t,n,k)),x=async(t,n,i)=>{const r=await n.artifactTarget(i);if(e.resolveRuntimeArtifact)return e.resolveRuntimeArtifact(t,r.platform,r.arch);const o=await R(t,r.platform,r.arch);if(o.identity.launcherAbi>r.launcherAbi)throw Object.assign(new Error(`Runtime requires launcher ABI ${o.identity.launcherAbi}, but ${r.platform}-${r.arch} provides ABI ${r.launcherAbi}.`),{code:"INSTANCE_BASE_RUNTIME_INCOMPATIBLE",retryable:!1});return O.resolve(o.identity,o.source)},D=e=>_.forRuntime(E.requireRuntime(e.runtimeId)),P=e=>{const t=D(e);return $a(t)?t:void 0},M=e=>{const t=P(e);if(t)return t;throw Object.assign(new Error(`Runtime for instance ${e.id} does not use managed artifacts.`),{code:"INSTANCE_RUNTIME_ARTIFACT_UNMANAGED",retryable:!1})},L=e=>Boolean(P(e)),j=(e,t)=>{const n=E.context(e);return x(t,M(e),n)},$=o({logger:e.logger??!0}),F=new no(l,{logger:(e,t)=>$.log.warn(t,e)}),U=()=>E.listInstances().map(e=>e.id),V=()=>{try{F.run(U())}catch(e){$.log.warn({error:e},"node-agent persistence maintenance failed")}};V();const q=setInterval(()=>{V()},216e5);q.unref();const H=setInterval(()=>{(()=>{try{F.capActiveInstanceLogs(U())}catch(e){$.log.warn({error:e},"node-agent active log maintenance failed")}})()},6e4);H.unref();const B={requests:0,active:0,completed:0,aborted:0,limitRejected:0,responseBytes:0,totalDurationMs:0,maxResponseBytes:Ls()};$.decorate("nodeAgentState",E),await $.register(s);const K=new xr(E,t,{logger:$.log,safetyIntervalMs:Number(process.env.TASK_HANDOFF_EVENT_CONNECTION_SAFETY_INTERVAL_MS)||void 0}),G=new ho(E.controlledInstances,Qo,{isInstalled:async(e,t)=>{const n=await j(e,t),i=await M(e).inspectRuntime(E.context(e),n.identity);if(i&&e.runtime.labels["task-handoff.bootstrap-backup"]){const t=E.requireInstance(e.id),n={...t.runtime.labels};delete n["task-handoff.bootstrap-backup"],E.controlledInstances.put(Si.parse({...t,runtime:{...t.runtime,labels:n},updatedAt:uc()}))}return i},beginDrain:async e=>{try{const t=await async function(e,t){const n=fc(t);if(t.registrationToken&&(await pc(e,`${n}/api/internal/node-agent/drain`,{method:"POST",headers:{authorization:`Bearer ${t.registrationToken}`}},1e4)).ok)return{requested:t.apps.runningCount,failures:[]};const i=await pc(e,`${n}/api/apps/sessions`,{method:"GET",headers:{"cache-control":"no-cache"}},5e3);if(!i.ok)throw new Error(`Could not list app sessions for runtime drain (HTTP ${i.status}).`);const r=function(e){if(!e||"object"!=typeof e||Array.isArray(e))return[];const t=e.data;if(Array.isArray(t))return t;if(!t||"object"!=typeof t||Array.isArray(t))return[];const n=t.snapshot,i=(n&&"object"==typeof n&&!Array.isArray(n)?n:t).sessions;return Array.isArray(i)?i:[]}(await i.json()).flatMap(e=>{if(!e||"object"!=typeof e||Array.isArray(e))return[];const t=e;return"running"===t.status&&"string"==typeof t.id&&t.id?[t.id]:[]}),o=await Promise.all(r.map(async t=>{try{const i=await pc(e,`${n}/api/apps/sessions/${encodeURIComponent(t)}/stop`,{method:"POST"},5e3);return i.ok?void 0:{sessionId:t,error:`HTTP ${i.status}`}}catch(e){return{sessionId:t,error:e instanceof Error?e.message:String(e)}}}));return{requested:r.length,failures:o.filter(e=>Boolean(e))}}(k,e);t.failures.length?$.log.warn({instanceId:e.id,requested:t.requested,failures:t.failures},"runtime convergence could not stop every app session"):$.log.info({instanceId:e.id,requested:t.requested},"runtime convergence requested app session drain")}catch(t){$.log.warn({instanceId:e.id,error:t instanceof Error?t.message:String(t)},"runtime convergence could not request app session drain")}},endDrain:async e=>{try{await async function(e,t){return!!t.registrationToken&&(await pc(e,`${fc(t)}/api/internal/node-agent/resume`,{method:"POST",headers:{authorization:`Bearer ${t.registrationToken}`}},5e3)).ok}(k,e)&&$.log.info({instanceId:e.id},"runtime convergence released app session drain")}catch(t){$.log.warn({instanceId:e.id,error:t instanceof Error?t.message:String(t)},"runtime convergence could not release app session drain")}},install:async(e,t)=>{const n=M(e);await n.installRuntime(E.context(e),await j(e,t))},restart:async e=>{const t=D(e),n=E.applyInstanceLifecycle(e.id,{type:"convergence-restart-requested"}),i=await t.restart(E.context(n));E.applyInstanceLifecycle(e.id,{type:"runtime-lifecycle-completed",baseline:n,observation:i})},onForcedDrain:e=>$.log.warn({instanceId:e.id},"runtime convergence drain deadline reached; restarting instance")},{drainTimeoutMs:Number(process.env.TASK_HANDOFF_RUNTIME_DRAIN_TIMEOUT_MS)||void 0,verificationTimeoutMs:Number(process.env.TASK_HANDOFF_RUNTIME_VERIFY_TIMEOUT_MS)||void 0,maxAttempts:Number(process.env.TASK_HANDOFF_RUNTIME_MAX_ATTEMPTS)||void 0});E.controlledInstances.setOnStored(e=>{K.publishInstanceLifecycle(e),E.updateJobs.reconcileRollouts(E.listInstances(),Qo())}),K.start(),$.decorate("nodeAgentEventForwarder",K);const J=new Fr(N,()=>E.listInstances().filter(e=>"docker"===E.requireRuntime(e.runtimeId).type),e=>K.publish("instance.metrics.snapshot",e,{instanceId:e.instanceId}));J.start(),$.decorate("nodeAgentRuntimeMetrics",J);const W=(re=process.env.TASK_HANDOFF_DIAGNOSTIC_LOGS,["1","true","yes","on"].includes(String(re||"").trim().toLowerCase())),Y=new Ys(g,f,u,p),X=(e,t)=>{W&&$.log.info(e,t)},Q={diagnostic:X,warn:(e,t)=>$.log.warn(e,t)},Z=new vs,ee=new ks(E.environmentTemplates,E.instancePrivateConfigs,T,e=>E.requireInstance(e),e=>E.requireRuntime(e),(e,t)=>Z.run(e,t),e=>E.listInstances().some(t=>t.environmentTemplateOrigin?.imageId===e)),te=async(e,t,n=()=>!0)=>{try{if(!n())return E.requireInstance(e);let i=E.requireInstance(e);"failed"===i.runtimeVersion?.phase&&L(i)&&(i=E.controlledInstances.put(Si.parse({...i,ready:!1,runtimeVersion:es(go(i)),updatedAt:uc()})));const r=E.requireRuntime(i.runtimeId);await yc(E,_,k,e,Q);const o=E.requireInstance(e);if("docker"===r.type&&o.imageProvisioning&&"ready"!==o.imageProvisioning.phase)return K.syncNow(),o;if(!n())return E.requireInstance(e);z.markRestored(e);let s=E.requireInstance(e);if(L(s)){try{s=await G.schedule(e,{startRequested:!0})}catch(n){s=E.requireInstance(e),Q.warn({instanceId:e,action:"runtime.converge",reason:t,error:n instanceof Error?n.message:String(n)},"node instance runtime convergence failed after start")}"matched"!==s.runtimeVersion?.phase&&s.runtimeVersion?.error&&Q.warn({instanceId:e,action:"runtime.converge",reason:t,error:s.runtimeVersion.error},"node instance started with pending runtime convergence")}return n()?(await hc(k,s,"start",Q),K.syncNow(),s):E.requireInstance(e)}catch(n){throw E.applyInstanceLifecycle(e,{type:"start-failed",error:n}),K.syncNow(),Q.warn({instanceId:e,action:"start",reason:t,error:n instanceof Error?n.message:String(n)},"node instance start failed"),n}},ne=new Ts(E,S,{sync:()=>K.syncNow(),diagnostic:Q.diagnostic,warn:Q.warn,publish:(e,t,n)=>K.publish(e,t,{instanceId:n}),runInstanceOperation:(e,t)=>Z.run(e,t)}),ie=e=>{const t=Z.intent(e.id);ne.provision(e,async()=>{await te(e.id,"image-ready",()=>Z.isIntentCurrent(e.id,t)).catch(()=>{})})};var re;z=new Ta({state:E,runtimeAdapters:_,convergence:G,restoreInstance:e=>yc(E,_,k,e,Q,"restore"),autoImport:e=>hc(k,e,"start",Q),provisionImage:ie,stopImageProvisioning:()=>ne.stop(),usesManagedArtifact:L,warn:Q.warn,error:(e,t)=>$.log.error(e,t),runInstanceOperation:(e,t)=>Z.run(e,t)});const oe=new Ea({nodeId:f,jobs:E.updateJobs,runCommand:C,currentRuntimeVersion:Qo,listInstances:()=>E.listInstances(),resolveRuntimeArtifacts:async e=>(await(async e=>{const t=new Map;for(const e of _.managedAdapters()){const n=await e.artifactTarget();t.set(`${n.platform}-${n.arch}`,{adapter:e})}for(const e of E.listInstances()){const n=P(e);if(!n)continue;const i=E.context(e),r=await n.artifactTarget(i);t.set(`${r.platform}-${r.arch}`,{adapter:n,context:i})}return(await Promise.all([...t.values()].map(({adapter:t,context:n})=>x(e,t,n)))).sort((e,t)=>`${e.identity.platform}/${e.identity.arch}`.localeCompare(`${t.identity.platform}/${t.identity.arch}`))})(e)).map(e=>e.identity),moduleDir:("undefined"==typeof document?require("url").pathToFileURL(__filename).href:b&&"SCRIPT"===b.tagName.toUpperCase()&&b.src||new URL("cli.js",document.baseURI).href)?n.dirname(r.fileURLToPath("undefined"==typeof document?require("url").pathToFileURL(__filename).href:b&&"SCRIPT"===b.tagName.toUpperCase()&&b.src||new URL("cli.js",document.baseURI).href)):__dirname});return $.setErrorHandler((e,t,n)=>{const i=function(e){if(e instanceof a.z.ZodError)return{statusCode:400,code:"VALIDATION_ERROR",message:e.issues.map(e=>`${e.path.join(".")||"body"}: ${e.message}`).join("; "),details:{issues:e.issues.map(e=>({path:e.path.map(String),code:e.code,message:e.message}))}};const t=e&&"object"==typeof e?e:{};return{statusCode:"number"==typeof t.statusCode?t.statusCode:500,code:"string"==typeof t.code?t.code:"NODE_AGENT_ERROR",message:e instanceof Error?e.message:String(e),...t.details&&"object"==typeof t.details&&!Array.isArray(t.details)?{details:t.details}:{},..."boolean"==typeof t.retryable?{retryable:t.retryable}:{}}}(e);(W||i.statusCode>=500)&&(i.statusCode>=500?$.log.error.bind($.log):$.log.warn.bind($.log))({method:t.method,url:t.url,statusCode:i.statusCode,errorCode:i.code,error:i.message},"node agent request failed"),n.code(i.statusCode).send({error:{code:i.code,message:i.message,...e&&"object"==typeof e&&"string"==typeof e.expectedVersion?{expectedVersion:e.expectedVersion}:{},...e&&"object"==typeof e&&"string"==typeof e.actualVersion?{actualVersion:e.actualVersion}:{},...e&&"object"==typeof e&&"string"==typeof e.phase?{phase:e.phase}:{},...e&&"object"==typeof e&&"boolean"==typeof e.retryable?{retryable:e.retryable}:{},...e&&"object"==typeof e&&"number"==typeof e.blockingInstanceCount?{blockingInstanceCount:e.blockingInstanceCount}:{}}})}),$.addHook("preHandler",async e=>{const n=Y.verify(e);if(n){if(g.isRevokedPairing(n)&&"/api/node-agent/pairing/current"!==e.url.split("?")[0]){const e=new Error("The node agent pairing used for this request has been revoked.");throw Object.assign(e,{statusCode:401,code:"NODE_AGENT_HMAC_KEY_REVOKED"}),e}e.nodeAgentAuthKeyId=n}else if(lc(e)){if(t&&cc(e.headers)!==t){const e=new Error("Invalid node agent token.");throw Object.assign(e,{statusCode:401,code:"NODE_AGENT_UNAUTHORIZED"}),e}}else if("/api/node-agent/pairing/complete"!==e.url.split("?")[0]&&!function(e){const t=e.split("?")[0];return/^\/api\/node-agent\/instances\/[^/]+\/(register|heartbeat)$/.test(t)}(e.url)){if(Y.hasRemoteSecrets()){const e=new Error("Node agent HMAC signature is required.");throw Object.assign(e,{statusCode:401,code:"NODE_AGENT_HMAC_SIGNATURE_REQUIRED"}),e}if(!function(e){return dc(e.ip)||dc(e.socket.remoteAddress)||!e.ip&&!e.socket.remoteAddress&&!e.socket.remoteFamily}(e)){const e=new Error("Local node agent access is only accepted from loopback or local IPC connections.");throw Object.assign(e,{statusCode:401,code:"NODE_AGENT_LOCAL_TOKEN_REQUIRES_LOOPBACK"}),e}if(t&&cc(e.headers)!==t){const e=new Error("Invalid node agent token.");throw Object.assign(e,{statusCode:401,code:"NODE_AGENT_UNAUTHORIZED"}),e}}}),$.addHook("onClose",async()=>{clearInterval(q),clearInterval(H),J.stop(),K.stop(),await z.stop()}),$.decorate("nodeAgentRestoreManagedInstances",()=>z.restoreManagedInstances()),$.decorate("nodeAgentRecoverManagedInstances",()=>z.recoverManagedInstances()),$.decorate("nodeAgentStartRecoverySupervisor",()=>z.start()),$.get("/api/node-agent/health",async()=>{return{data:{ok:!0,role:"node-agent",process:{pid:process.pid,...sc?{startIdentity:sc}:{}},listener:{host:"127.0.0.1",port:E.currentListenerPort},nodeId:f,platform:ja(w),arch:process.arch,protocolVersion:It,build:(e="node-agent",{component:e,packageName:"@task-handoff/node-agent",packageVersion:Qo(),protocolVersion:It,buildId:ac("TASK_HANDOFF_BUILD_ID"),builtAt:ac("TASK_HANDOFF_BUILT_AT"),gitCommit:ac("TASK_HANDOFF_GIT_COMMIT"),imageRef:ac("TASK_HANDOFF_IMAGE_REF"),imageDigest:ac("TASK_HANDOFF_IMAGE_DIGEST")}),instanceProxy:{...B},serverTime:(new Date).toISOString()}};var e}),function(e,t){e.get("/api/node-agent/settings/external-listener",async e=>({data:t(e).current()})),e.patch("/api/node-agent/settings/external-listener",async e=>({data:await t(e).update(e.body)}))}($,e=>{if(!lc(e)){const e=new Error("Node agent TCP listener settings are available only over local Unix IPC.");throw Object.assign(e,{statusCode:403,code:"NODE_AGENT_LISTENER_LOCAL_IPC_ONLY"}),e}if(!$.nodeAgentListenerManager){const e=new Error("Node agent TCP listener manager is not initialized.");throw Object.assign(e,{statusCode:503,code:"NODE_AGENT_LISTENER_UNAVAILABLE"}),e}return $.nodeAgentListenerManager}),function(e,t,n){e.get("/api/node-agent/updates/jobs",async()=>({data:n.list()})),e.post("/api/node-agent/updates/check",async e=>({data:await t.check(e.body)})),e.post("/api/node-agent/updates/apply",async(e,n)=>n.code(202).send({data:await t.apply(e.body)}))}($,oe,E.updateJobs),function(e,t){const{identity:n,nodeId:i,fetchImpl:r}=t;e.post("/api/node-agent/pairing/invites",async(e,t)=>{const r=n.createPairingInvite(ia.parse(e.body||{}));return t.code(201).send({data:{nodeId:i,joinToken:r.token,expiresAt:r.expiresAt}})}),e.post("/api/node-agent/pairing/complete",async(e,t)=>{const r=n.completePairingInvite(ra.parse(e.body));return t.code(201).send({data:{nodeId:i,keyId:r.keyId,secret:r.secret,pairedAt:r.pairedAt}})}),e.get("/api/node-agent/control-plane-pairings",async e=>({data:n.listControlPlanePairings(e.nodeAgentAuthKeyId)})),e.delete("/api/node-agent/control-plane-pairings/:keyId",async e=>{const t=ba.parse(e.params.keyId);return{data:{deleted:n.deleteControlPlanePairing(t,e.nodeAgentAuthKeyId)}}}),e.delete("/api/node-agent/pairing/current",async e=>({data:n.revokeCurrentControlPlanePairing(e.nodeAgentAuthKeyId||"")})),e.get("/api/node-agent/control-plane-connections",async()=>({data:n.listControlPlaneConnections().map(e=>({...e,...t.reverseTunnels()?.state(e.id)||{status:e.enabled?"connecting":"disabled"}}))})),e.delete("/api/node-agent/control-plane-connections/:connectionId",async e=>{const i=ba.parse(e.params.connectionId),r=n.deleteControlPlaneConnection(i);return r&&t.reverseTunnels()?.connectConfigured(),{data:{deleted:r}}}),e.post("/api/node-agent/control-plane-connections",async(e,o)=>{const s=oa.parse(e.body),a=function(e){const t=new URL(e);if("http:"!==t.protocol&&"https:"!==t.protocol){const e=new Error("Control-plane URL must use http or https.");throw Object.assign(e,{statusCode:400,code:"NODE_AGENT_REMOTE_CONTROL_PLANE_URL_INVALID"}),e}return t.toString().replace(/\/$/,"")}(s.controlPlaneUrl);return n.runControlPlaneConnectionOperation(a,async()=>{const e=n.stageControlPlaneConnection({url:a,...s.controlPlaneName?{name:s.controlPlaneName}:{},enabled:!1!==s.activate});let c;try{c=await async function(e,t,n){const i=await e(new URL("/api/node-join/complete",t).toString(),{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(n)}),r=await i.json().catch(()=>({}));if(!i.ok){const e=new Error(r.error?.message||`Control-plane node join failed with HTTP ${i.status}.`);throw Object.assign(e,{statusCode:i.status,code:r.error?.code||"NODE_AGENT_REMOTE_JOIN_FAILED"}),e}return r.data||{}}(r,a,{joinToken:s.joinToken,nodeId:i,nodeName:t.nodeName(),keyId:e.pairing.keyId,secret:e.pairing.secret,pairedAt:e.pairing.pairedAt})}catch(t){throw n.rollbackControlPlaneConnection(e),t}const d=n.commitControlPlaneConnection(e,{name:s.controlPlaneName||("string"==typeof c.name&&c.name?c.name:void 0)});let l,u=d.connection.enabled?"saved":"disabled";const m=t.reverseTunnels();if(m)try{m.connectConfigured(),d.connection.enabled&&(u="connecting")}catch(e){u="failed",l=e instanceof Error?e.message:String(e)}return o.code(201).send({data:{pairing:n.listControlPlanePairings().find(e=>e.keyId===d.pairing.keyId),connection:d.connection,tunnel:{status:u,...l?{error:l}:{}}}})})})}($,{identity:g,nodeId:f,nodeName:()=>E.node.name,fetchImpl:k,reverseTunnels:()=>$.nodeAgentReverseTunnels}),function(e,t){e.get("/api/node-agent/runtimes",async()=>({data:t.listRuntimes()})),e.post("/api/node-agent/runtimes",async(e,n)=>n.code(201).send({data:t.createRuntime(As.parse(e.body))})),e.patch("/api/node-agent/runtimes/:id",async e=>({data:t.updateRuntime(e.params.id,bs.parse(e.body))})),e.delete("/api/node-agent/runtimes/:id",async e=>({data:{deleted:t.deleteRuntime(e.params.id)}})),e.post("/api/node-agent/runtimes/:id/check",async e=>({data:await t.checkRuntime(e.params.id)})),e.get("/api/node-agent/local-folders",async()=>({data:t.listLocalFolders()})),e.get("/api/node-agent/folders/tree",async e=>({data:t.listFolderTree(fs.parse(e.query))})),e.post("/api/node-agent/local-folders",async(e,n)=>n.code(201).send({data:t.createLocalFolder(gs.parse(e.body))})),e.delete("/api/node-agent/local-folders/:id",async e=>({data:{deleted:t.deleteLocalFolder(e.params.id)}}))}($,{listRuntimes:()=>E.nodeRuntimes.list(),createRuntime:e=>E.createRuntime(e),updateRuntime:(e,t)=>E.updateRuntime(e,t),deleteRuntime:e=>E.deleteRuntime(e),checkRuntime:async e=>{const t=E.requireRuntime(e);return E.checkRuntime(e,_.forRuntime(t))},listLocalFolders:()=>E.localFolders.list(),listFolderTree:Xr,createLocalFolder:e=>E.createLocalFolder(e),deleteLocalFolder:e=>E.localFolders.delete(e)}),function(e,t){e.get("/api/node-agent/models",async()=>({data:t.list()})),e.post("/api/node-agent/models",async(e,n)=>n.code(201).send({data:t.create(Vn.parse(e.body))})),e.put("/api/node-agent/models/:id/deploy",async e=>{const n=e.params.id,i=Hn.parse(e.body);if(i.id!==n)throw Object.assign(new Error(`Model payload id ${i.id} does not match route id ${n}.`),{statusCode:400,code:"NODE_MODEL_ID_MISMATCH"});return{data:t.deploy(i)}}),e.patch("/api/node-agent/models/:id",async e=>({data:t.update(e.params.id,qn.parse(e.body))})),e.delete("/api/node-agent/models/:id",async e=>({data:{deleted:t.delete(e.params.id)}})),e.put("/api/node-agent/instances/:id/model-assignment",async e=>{const n=e.params.id,i=t.assign(n,Bn.parse(e.body));return await(e=>gc(k,E,e,Q.warn))(n),{data:i}})}($,E.modelRegistry),function(e,t){e.get("/api/node-agent/environment-templates",async()=>({data:t.list()})),e.get("/api/node-agent/environment-templates/:id",async e=>({data:Zt.parse(t.require(e.params.id))})),e.post("/api/node-agent/instances/:id/environment-templates",async(e,n)=>{const i=await t.create(e.params.id,e.body);return n.code(201).send({data:i})}),e.delete("/api/node-agent/environment-templates/:id",async e=>({data:await t.delete(e.params.id)}))}($,ee),function(e,t){e.get("/api/node-agent/instances",async()=>({data:t.list()})),e.post("/api/node-agent/instances",async(e,n)=>{const i=await t.create(ys.parse(e.body));return t.afterCreate(i),n.code(201).send({data:i})}),e.post("/api/node-agent/instances/:id/image-provisioning/retry",async e=>{const n=t.retryImageProvisioning(e.params.id);return t.afterImageRetry(n),{data:n}}),e.patch("/api/node-agent/instances/:id",async e=>{const n=t.update(e.params.id,Is.parse(e.body));return t.afterUpdate(n),{data:n}}),e.post("/api/node-agent/instances/:id/register",async(e,n)=>{const i=e.params.id,r=t.sanitizeReport(i,"register",e.body),o=t.register(i,xi.parse(r),ws(e.headers));return t.afterReport(o,"register"),n.code(201).send({data:o})}),e.post("/api/node-agent/instances/:id/heartbeat",async e=>{const n=e.params.id,i=t.sanitizeReport(n,"heartbeat",e.body),r=t.heartbeat(n,Di.parse(i),ws(e.headers));return t.afterReport(r,"heartbeat"),{data:r}})}($,{list:()=>E.listInstances(),create:e=>"template"===e.environmentSource?.type?ee.runTemplateOperation(e.environmentSource.environmentTemplateId,()=>E.createInstance(e)):E.createInstance(e),retryImageProvisioning:e=>ne.retry(e),update:(e,t)=>{const n=E.requireInstance(e);return E.controlledInstances.put(Si.parse({...n,...t,...t.config?{config:{...n.config,...t.config}}:{},updatedAt:uc()}))},register:(e,t,n)=>E.registerInstance(e,t,n),heartbeat:(e,t,n)=>E.heartbeatInstance(e,t,n),sanitizeReport:(e,t,n)=>{const i=n&&"object"==typeof n&&!Array.isArray(n)?n.protocolVersion:void 0;if("string"!=typeof i||i===It)return n;const r=({field:n,action:r})=>$.log.warn({instanceId:e,report:t,protocolVersion:i,expectedProtocolVersion:It,field:n,action:r},"cross-version controlled instance report sanitized");return"register"===t?function(e,t){if(!e||"object"!=typeof e||Array.isArray(e))return e;const n=e,i=["instanceId","projectId","source","nodeId","runtimeId","imageSelection","instanceVersion","protocolVersion","build","controlMode","capabilities","appInventory","target","workspace","registrationToken","processIncarnationId"],r=new Set([...i,"imageId"]);for(const e of Object.keys(n))r.has(e)||t?.({field:e,action:"ignored"});return Object.prototype.hasOwnProperty.call(n,"imageId")&&t?.({field:"imageId",action:"migrated"}),{...Ri(n,i),imageSelection:Jt(n.imageSelection,n.imageId)}}(n,r):function(e,t){if(!e||"object"!=typeof e||Array.isArray(e))return e;const n=["status","health","protocolVersion","build","capabilities","appInventory","apps","aiSessions","triggers","workspace","target","processIncarnationId"],i=new Set(n);for(const n of Object.keys(e))i.has(n)||t?.({field:n,action:"ignored"});return Ri(e,n)}(n,r)},afterCreate:e=>{K.syncNow(),e.imageProvisioning&&ie(e)},afterImageRetry:e=>{K.syncNow(),ie(e)},afterUpdate:()=>K.syncNow(),afterReport:(e,t)=>{K.syncNow(),"register"===t?X({instanceId:e.id,action:t,protocolVersion:e.protocolVersion,build:e.build,targetStatus:e.targetStatus,targetStrategy:e.target.strategy},"node instance registered"):X({instanceId:e.id,action:t,status:e.status,health:e.health,protocolVersion:e.protocolVersion,build:e.build,targetStatus:e.targetStatus,apps:e.apps.runningCount},"node instance heartbeat accepted"),!L(e)||e.ready&&"matched"===e.runtimeVersion?.phase||G.schedule(e.id).catch(n=>$.log.error({instanceId:e.id,error:n},`runtime convergence after ${t} failed`))}}),$.get("/api/node-agent/events",{websocket:!0},e=>{const t=e;t.send(JSON.stringify({type:"node-agent.events.connected",nodeId:f,serverTime:(new Date).toISOString()}));const n=K.addOutput(t);t.on("close",n),t.on("error",n)}),$.get("/api/node-agent/docker/images",async()=>({data:await mr(e.dockerCommandRunner)})),$.get("/api/node-agent/instances/:id/metrics",async e=>{const t=e.params.id,n=E.requireInstance(t);if("docker"!==E.requireRuntime(n.runtimeId).type){const e=new Error(`Runtime type ${E.requireRuntime(n.runtimeId).type} does not provide resource metrics.`);throw Object.assign(e,{statusCode:409,code:"INSTANCE_METRICS_UNSUPPORTED"}),e}return{data:await J.snapshot(t)}}),function(e,t,n,i,r,o=new vs){const s=e=>o.intent(e),a=e=>Promise.resolve(i.cancel(e)).then(()=>({ok:!0}),e=>({ok:!1,error:e})),c=(e,t)=>{if(!o.isIntentCurrent(e,t))throw Object.assign(new Error(`Instance operation for ${e} was superseded by stop or delete.`),{statusCode:409,code:"INSTANCE_OPERATION_SUPERSEDED"})};e.post("/api/node-agent/instances/:id/start",async e=>{Es.parse(e.body);const t=e.params.id,n=s(t);return o.run(t,async()=>(c(t,n),r.allowRecovery(t),{data:await r.start(t,()=>o.isIntentCurrent(t,n))}))}),e.post("/api/node-agent/instances/:id/runtime/reconcile",async e=>{const n=e.params.id;Es.parse(e.body);const a=s(n);return o.run(n,async()=>{c(n,a);const e=t.requireInstance(n);t.putInstance(Si.parse({...e,ready:!1,runtimeVersion:es(go(e)),updatedAt:Ns()})),c(n,a);const o=await i.schedule(n,{startRequested:!["created","stopped"].includes(e.status),resumeCancelled:!0});return c(n,a),r.sync(),{data:o}})}),e.post("/api/node-agent/instances/:id/stop",async e=>{const i=e.params.id;t.requireInstance(i),o.invalidate(i);const s=a(i);return o.run(i,async()=>{const e=t.requireInstance(i);t.applyLifecycle(i,{type:"stop-requested"});try{await r.suppressRecovery(i);const e=await s;if("error"in e)throw e.error;const o=t.requireInstance(i);r.diagnostic({instanceId:i,action:"stop",runtimeId:o.runtimeId,containerName:o.runtime.containerName},"node instance stop requested"),await n.forRuntime(t.requireRuntime(o.runtimeId)).stop(t.context(o))}catch(n){try{t.applyLifecycle(i,{type:"stop-failed",baseline:e}),r.sync()}finally{r.allowRecovery(i)}throw n}const o=t.applyLifecycle(i,{type:"stop-completed"});return r.completeSuppressedRecovery(i),r.sync(),r.diagnostic({instanceId:i,action:"stop",status:o.status,connectionStatus:o.connectionStatus,containerName:o.runtime.containerName},"node instance stop completed"),{data:o}})}),e.post("/api/node-agent/instances/:id/restart",async e=>{const a=e.params.id;Es.parse(e.body);const d=s(a);return o.run(a,async()=>{c(a,d),r.allowRecovery(a);let e=t.requireInstance(a);if(r.isManaged(e)&&(!e.ready||"matched"!==e.runtimeVersion?.phase)){"failed"===e.runtimeVersion?.phase&&(e=t.putInstance(Si.parse({...e,runtimeVersion:es(go(e)),updatedAt:Ns()}))),c(a,d);const n=await i.schedule(a,{startRequested:!0});return c(a,d),r.sync(),{data:n}}r.diagnostic({instanceId:a,action:"restart",runtimeId:e.runtimeId,imageId:e.imageSelection?.imageId,containerName:e.runtime.containerName},"node instance restart requested");const o=await n.forRuntime(t.requireRuntime(e.runtimeId)).restart(t.context(e));let s=t.applyLifecycle(a,{type:"runtime-lifecycle-completed",baseline:e,observation:{...o,target:o.target?{...e.target,...o.target}:void 0}});r.markRestarted(a),c(a,d);const l=Si.parse({...s,updatedAt:Ns()}),u=await r.probe(l);return c(a,d),s=t.applyLifecycle(a,{type:"runtime-lifecycle-completed",baseline:s,observation:{target:{...s.target,status:u},targetStatus:u,uiAccessStatus:u}}),await r.autoImport(s),r.sync(),r.diagnostic({instanceId:a,action:"restart",status:s.status,connectionStatus:s.connectionStatus,targetStatus:s.targetStatus,targetWeb:s.target.web,containerName:s.runtime.containerName},"node instance restart completed"),{data:s}})}),e.post("/api/node-agent/instances/:id/delete",async e=>{const i=e.params.id,s=Ht.parse(e.body);t.requireInstance(i),o.invalidate(i);const c=a(i);return o.run(i,async()=>{const e=t.requireInstance(i);"deleting"!==e.status&&t.applyLifecycle(i,{type:"stop-requested"});try{await r.suppressRecovery(i);const e=await c;if("error"in e)throw e.error;const a=t.requireInstance(i);t.putInstance(Si.parse({...a,status:"deleting",ready:!1,updatedAt:Ns()})),r.diagnostic({instanceId:i,action:"delete",runtimeId:a.runtimeId,containerName:a.runtime.containerName},"node instance delete requested");const d=await n.forRuntime(t.requireRuntime(a.runtimeId)).delete(t.context(a,{}),s);if(!d.completed)return r.diagnostic({instanceId:i,action:"delete",volumeResults:d.volumeResults},"node instance delete requires retry"),r.sync(),{data:d};r.diagnostic({instanceId:i,action:"delete"},"node instance delete completed");const l=t.deleteInstance(i);return l&&(r.forgetRecovery(i),o.clearIntent(i)),r.deleteMetadata(i),l&&r.retireInstanceData(i),l&&a.environmentTemplateOrigin?.imageId&&r.releaseEnvironmentImage&&await r.releaseEnvironmentImage(a.environmentTemplateOrigin.imageId).catch(e=>{r.diagnostic({instanceId:i,action:"release-environment-image",error:e instanceof Error?e.message:String(e)},"environment image cleanup deferred after instance deletion")}),r.sync(),{data:d}}catch(n){try{t.putInstance(Si.parse({...e,updatedAt:Ns()})),r.sync()}finally{r.allowRecovery(i)}throw n}})})}($,{requireInstance:e=>E.requireInstance(e),requireRuntime:e=>E.requireRuntime(e),putInstance:e=>E.controlledInstances.put(e),deleteInstance:e=>E.controlledInstances.delete(e),applyLifecycle:(e,t)=>E.applyInstanceLifecycle(e,t),context:(e,t)=>E.context(e,t)},_,G,{start:(e,t)=>te(e,"request",t),sync:()=>K.syncNow(),isManaged:L,probe:e=>mc(k,e),autoImport:e=>hc(k,e,"restart",Q),markRestarted:e=>z.markRestored(e),allowRecovery:e=>z.allowRecovery(e),suppressRecovery:e=>z.suppressRecovery(e),forgetRecovery:e=>z.forgetInstance(e),completeSuppressedRecovery:e=>z.completeSuppressedOperation(e),deleteMetadata:e=>{E.modelRegistry.deleteInstanceMetadata(e),E.instancePrivateConfigs.delete(e)},retireInstanceData:e=>{F.retire(e)},releaseEnvironmentImage:e=>ee.releaseUnusedImage(e),diagnostic:X},Z),function(e,t){const{fetchImpl:n,metrics:i,diagnostic:r}=t;e.post("/api/node-agent/instances/:id/proxy",async(e,i)=>{const o=e.params.id,s=hs.parse(e.body),a=t.instanceBase(o),c=js(s.path);"POST"===s.method&&"/api/apps/sessions"===c&&await t.syncModelEnvironment(o),r({instanceId:o,action:"proxy",method:s.method,path:c,instanceBase:a},"node instance proxy requested");const d=await n(`${a}${c}`,{method:s.method,headers:{...s.headers},body:Ms(s)}),l=d.headers.get("content-type")||"application/octet-stream",u=await d.text();r({instanceId:o,action:"proxy",method:s.method,path:c,statusCode:d.status,contentType:l},"node instance proxy completed"),i.code(d.status).type(l).send(u)}),e.post("/api/node-agent/instances/:id/proxy/stream",{bodyLimit:Ds},async(e,o)=>{const s=Date.now();i.requests+=1,i.active+=1;const a=new AbortController;let c=0,d=!1,l=!1;const u=e=>{l||(l=!0,i.active-=1,i.totalDurationMs+=Date.now()-s,i.responseBytes+=c,i[e]+=1)},m=()=>{a.abort(),d&&u("aborted")};e.raw.once("aborted",m),o.raw.once("close",m);try{const s=e.params.id,l=hs.parse(e.body),m=t.instanceBase(s),p=js(l.path);r({instanceId:s,action:"proxy.stream",method:l.method,path:p,instanceBase:m},"node instance streaming proxy requested");const g=await n(`${m}${p}`,{method:l.method,headers:{...l.headers},body:Ms(l),signal:a.signal}),f=Number(g.headers.get("content-length"));if(Number.isFinite(f)&&f>i.maxResponseBytes)return i.limitRejected+=1,a.abort(),$s(o,i.maxResponseBytes);o.code(g.status);for(const[e,t]of Object.entries(Ps(g.headers)))o.header(e,t);if(!g.body||"HEAD"===l.method)return u("completed"),o.send();const y=new h.Transform({transform(e,t,n){if(c+=e.length,c>i.maxResponseBytes)return i.limitRejected+=1,a.abort(),void n(Object.assign(new Error("Instance proxy response limit exceeded."),{code:"INSTANCE_PROXY_RESPONSE_TOO_LARGE"}));n(null,e)}});return d=!0,y.once("end",()=>u("completed")),y.once("error",()=>u("aborted")),o.send(h.Readable.fromWeb(g.body).pipe(y))}catch(e){throw u("aborted"),e}finally{e.raw.off("aborted",m),d||u("completed")}}),e.post("/api/node-agent/instances/:id/proxy/raw",{bodyLimit:Ds},async(e,o)=>{const s=e.params.id,a=hs.parse(e.body),c=t.instanceBase(s),d=js(a.path);r({instanceId:s,action:"proxy.raw",method:a.method,path:d,instanceBase:c},"node instance raw proxy requested");const l=await n(`${c}${d}`,{method:a.method,headers:{...a.headers},body:Ms(a)}),u=Number(l.headers.get("content-length"));if(Number.isFinite(u)&&u>i.maxResponseBytes)return i.limitRejected+=1,await(l.body?.cancel("Instance proxy response limit exceeded.").catch(()=>{})),$s(o,i.maxResponseBytes);let m;try{m=await async function(e,t){if(!e.body)return Buffer.alloc(0);const n=[];let i=0;const r=e.body.getReader();for(;;){const{done:e,value:o}=await r.read();if(e)break;if(i+=o.byteLength,i>t)throw await r.cancel("Instance proxy response limit exceeded.").catch(()=>{}),Object.assign(new Error("Instance proxy response limit exceeded."),{code:"INSTANCE_PROXY_RESPONSE_TOO_LARGE"});n.push(Buffer.from(o))}return Buffer.concat(n,i)}(l,i.maxResponseBytes)}catch(e){if(!(e instanceof Error)||"INSTANCE_PROXY_RESPONSE_TOO_LARGE"!==e.code)throw e;return i.limitRejected+=1,$s(o,i.maxResponseBytes)}return r({instanceId:s,action:"proxy.raw",method:a.method,path:d,statusCode:l.status,byteLength:m.length},"node instance raw proxy completed"),{data:{status:l.status,headers:Ps(l.headers),bodyBase64:m.toString("base64")}}}),e.get("/api/node-agent/instances/:id/proxy/ws/*",{websocket:!0},(e,n)=>{const i=n.params.id,o=n.params["*"]||"",s=n.url.indexOf("?"),a=s>=0?n.url.slice(s):"";let c;try{const s=t.instanceBase(i),d=new URL(`/${o}${a}`,`${s}/`);d.protocol="https:"===d.protocol?"wss:":"ws:";const l=function(e){const t=e["sec-websocket-protocol"],n=(Array.isArray(t)?t.join(","):"string"==typeof t?t:"").split(",").map(e=>e.trim()).filter(Boolean);return n.length?n:void 0}(n.headers);r({instanceId:i,action:"proxy.ws",path:`/${o}${a}`,upstreamUrl:d.toString(),protocols:l||[]},"node instance websocket proxy opening"),c=l?new m(d,l):new m(d),c.on("open",()=>{r({instanceId:i,action:"proxy.ws",path:`/${o}${a}`},"node instance websocket proxy opened"),e.on("message",(e,t)=>c?.readyState===m.OPEN&&c.send(function(e,t){return t?e:e.toString()}(e,t))),e.on("close",()=>c?.close()),e.on("error",()=>c?.close())}),c.on("message",(t,n)=>e.readyState===m.OPEN&&e.send(n?t:t.toString())),c.on("close",()=>{r({instanceId:i,action:"proxy.ws",path:`/${o}${a}`},"node instance websocket proxy closed"),e.close()}),c.on("error",t=>{r({instanceId:i,action:"proxy.ws",path:`/${o}${a}`,error:t instanceof Error?t.message:String(t)},"node instance websocket proxy failed"),e.close(1011,"Instance websocket proxy failed.")})}catch(t){r({instanceId:i,action:"proxy.ws",path:`/${o}${a}`,error:t instanceof Error?t.message:String(t)},"node instance websocket endpoint unavailable"),c?.close(),e.close(1011,"Instance websocket endpoint is not reachable.")}})}($,{fetchImpl:k,metrics:B,instanceBase:e=>fc(E.requireInstance(e)),syncModelEnvironment:e=>gc(k,E,e,Q.warn),diagnostic:X}),$}async function Ac(e){const r=Zr(e.dataDir),o=function(e,i={}){return function(e,i={}){t.mkdirSync(n.dirname(e),{recursive:!0});const r=C(process.pid),o={pid:process.pid,hostname:c.hostname(),command:process.argv.join(" "),acquiredAt:(new Date).toISOString(),token:d.randomUUID(),...void 0!==i.component?{component:i.component}:{},...r?{startIdentity:r}:{},...void 0!==i.dataDir?{dataDir:i.dataDir}:{},...void 0!==i.host?{host:i.host}:{},...void 0!==i.port?{port:i.port}:{},...void 0!==i.instanceId?{instanceId:i.instanceId}:{}};for(let n=0;n<5;n+=1)try{return t.mkdirSync(e),t.writeFileSync(T(e),`${JSON.stringify({token:o.token,pid:o.pid,startIdentity:o.startIdentity,startedAt:(new Date).toISOString()})}\n`,{encoding:"utf8",mode:384,flag:"wx"}),D(e,o),{lockPath:e,owner:o,updateDetails:t=>P(e,o,t),release(){const n=O(e);n?.token===o.token&&t.rmSync(e,{recursive:!0,force:!0})}}}catch(r){if("EEXIST"!==r.code)throw r;const o=O(e);if(x(o))throw new N(e,o,i.error);if(!o&&(L(e)||F(e)<(i.incompleteLockStaleMs??2e3))){if(n+1<5){$();continue}throw new N(e,void 0,i.error)}const s=d.randomUUID();if(!U(e,s)){if(n+1<5){$();continue}throw new N(e,O(e),i.error)}const a=O(e);if(x(a))throw j(z(e)),new N(e,a,i.error);if(o?.token&&a?.token!==o.token){j(z(e));continue}if(!q(e,s))continue;t.rmSync(e,{recursive:!0,force:!0})}const s=O(e);throw new N(e,s,i.error)}(e,{...i,component:"node-agent",error:{label:"Node agent",code:"NODE_AGENT_ALREADY_RUNNING"}})}(function(){const e=process.env.TASK_HANDOFF_NODE_AGENT_LOCK_PATH?.trim();return e?n.resolve(e):n.join(c.tmpdir(),`task-handoff-node-agent-${process.getuid?.()??"user"}.lock`)}(),{dataDir:r.dataDir});try{const c=(s=e.host,a=e.port,fi.parse({bindScope:"0.0.0.0"===s.trim()?"all-ipv4":"loopback",port:a})),d=t.existsSync(r.settingsPath),l=function(e,t){return new Oo(e.settingsPath,()=>({version:1,externalListener:t}),{schema:Fs,sanitize:Vs})}(r,c);let u=l.get().externalListener;if("allocate"===process.env.TASK_HANDOFF_NODE_AGENT_PORT_CONFLICT){const e=await async function(e,t=20){for(let n=0;n<t&&e.port+n<=65535;n+=1){const t={...e,port:e.port+n};if(await qs(t))return t}throw Object.assign(new Error(`No available node-agent port found starting at ${e.port}.`),{statusCode:503,code:"NODE_AGENT_LISTENER_PORT_UNAVAILABLE"})}(u);e.port!==u.port&&(l.put({version:1,externalListener:e}),u=e)}const m=e=>{if(!o.updateDetails({dataDir:r.dataDir,host:e.host,port:e.port,instanceId:void 0}))throw new Error("Node agent singleton ownership changed while publishing listener state.")},p={...e,port:u.port},h=await Ic(p),g=h.nodeAgentState;if(!g)throw new Error("Node agent state was not initialized.");const f=new Aa(r).resolveNodeId(e.nodeId||process.env.TASK_HANDOFF_NODE_ID),y=function(e,t,n,i){const r=t.token||process.env.TASK_HANDOFF_NODE_AGENT_TOKEN,o=new Aa(n),s=new Map;let a=!1;const c=(t,n)=>{if(a||n.retry.pending||s.get(t)!==n)return;const r=n.retry.schedule(()=>{a||s.get(t)!==n||n.socket||d(t,n)});r&&(n.status="reconnecting",n.nextRetryAt=new Date(Date.now()+r.delay).toISOString(),e.log.info({nodeId:i,tunnelUrl:new URL(n.config.tunnelUrl).origin,attempt:r.attempt,delay:r.delay},"node agent reverse tunnel reconnect scheduled"))},d=(n,o)=>{let d;o.status=o.lastDisconnectedAt?"reconnecting":"connecting",o.error=void 0,o.nextRetryAt=void 0;try{d=Ra(e,{...o.config,nodeId:i,port:()=>e.nodeAgentState.currentListenerPort,token:r})}catch(e){return o.status="failed",o.lastDisconnectedAt=(new Date).toISOString(),o.error=e instanceof Error?e.message:String(e),void c(n,o)}o.socket=d;const l=new Pa({connectTimeoutMs:t.connectTimeoutMs,handshakeTimeoutMs:t.handshakeTimeoutMs,heartbeatIntervalMs:t.heartbeatIntervalMs,heartbeatTimeoutMs:t.heartbeatTimeoutMs,stableThresholdMs:t.stableThresholdMs,ping:()=>d.ping(),onTimeout:e=>{s.get(n)===o&&o.socket===d&&(o.status="failed",o.error=`Reverse tunnel ${e} timeout.`,d.terminate())},onStable:()=>o.retry.reset()});return o.supervisor=l,l.start(),d.on("open",()=>{s.get(n)===o&&o.socket===d&&(o.status="connecting",l.opened())}),d.on("message",t=>{if(s.get(n)!==o||o.socket!==d||"connected"===o.status)return;let r;try{r=JSON.parse(String(t))}catch{return}const a=r&&"object"==typeof r?r.type:void 0;"control-plane.hello"!==a&&"control-plane.identified"!==a||(l.activity(),l.healthy(),o.status="connected",o.lastConnectedAt=(new Date).toISOString(),o.nextRetryAt=void 0,o.error=void 0,e.log.info({nodeId:i,tunnelUrl:new URL(o.config.tunnelUrl).origin},"node agent reverse tunnel connected"))}),d.on("pong",()=>l.pong()),d.on("close",(t,r)=>{s.get(n)===o&&o.socket===d&&(l.close(),o.socket=void 0,o.lastDisconnectedAt=(new Date).toISOString(),o.error=`WebSocket closed${t?` (${t})`:""}${r?`: ${Buffer.isBuffer(r)?r.toString("utf8"):String(r)}`:""}`,a||(e.log.warn({nodeId:i,tunnelUrl:new URL(o.config.tunnelUrl).origin,code:t,reason:Buffer.isBuffer(r)?r.toString("utf8"):String(r||"")},"node agent reverse tunnel disconnected"),c(n,o)))}),d.on("error",e=>{s.get(n)===o&&o.socket===d&&(o.status="failed",o.error=e instanceof Error?e.message:String(e),d.terminate())}),d},l=(e,t)=>{const n=s.get(e);n?.retry.cancel(),n?.supervisor?.close();const i={config:t,retry:new Or,status:"connecting"};return s.set(e,i),n?.socket?.close(1e3,"Reverse tunnel reconnecting."),d(e,i)},u=(e,t)=>e.tunnelUrl===t.tunnelUrl&&e.keyId===t.keyId&&e.secret===t.secret;return{connectConfigured:()=>{a=!1;const n=new Map,r=o.resolvedControlPlaneAccess(),c=new Set;for(const{connection:t,pairing:o}of r.connections){if(!t.enabled)continue;if(!o){e.log.warn({nodeId:i,connectionId:t.id,pairingKeyId:t.pairingKeyId},"node agent control-plane connection has no pairing");continue}const r=Ma(t.url);n.set(t.id,{tunnelUrl:r,keyId:o.keyId,secret:o.secret}),c.add(r)}const d=function(e){const t=e.controlPlaneTunnelUrl||process.env.TASK_HANDOFF_CONTROL_PLANE_TUNNEL_URL;return t?new URL(t).toString():void 0}(t);if(d&&!c.has(d)){const e=o.reverseTunnelSecret(process.env.TASK_HANDOFF_CONTROL_PLANE_URL,t.remoteSecret||process.env.TASK_HANDOFF_NODE_AGENT_REMOTE_SECRET,t.remoteKeyId||process.env.TASK_HANDOFF_NODE_AGENT_REMOTE_KEY_ID);n.set(`explicit:${d}`,{tunnelUrl:d,keyId:e?.keyId,secret:e?.secret}),c.add(d)}const m=r.hasPersistedAccess?void 0:function(){const e=process.env.TASK_HANDOFF_CONTROL_PLANE_URL;if(!e)return;const t=new URL(Ks,e);return t.protocol="https:"===t.protocol?"wss:":"ws:",t.toString()}();if(m&&!c.has(m)){const e=o.reverseTunnelSecret(process.env.TASK_HANDOFF_CONTROL_PLANE_URL,t.remoteSecret||process.env.TASK_HANDOFF_NODE_AGENT_REMOTE_SECRET,t.remoteKeyId||process.env.TASK_HANDOFF_NODE_AGENT_REMOTE_KEY_ID);n.set(`bootstrap:${m}`,{tunnelUrl:m,keyId:e?.keyId,secret:e?.secret})}(e=>{for(const[t,n]of s)e.has(t)||(n.retry.cancel(),n.supervisor?.close(),s.delete(t),n.socket?.close(1e3,"Reverse tunnel configuration removed."));for(const[t,n]of e){const e=s.get(t);e&&u(e.config,n)||l(t,n)}})(n)},state:e=>{const t=s.get(e);if(t)return{status:t.status,connection:t.supervisor?.diagnostics(),...t.lastConnectedAt?{lastConnectedAt:t.lastConnectedAt}:{},...t.lastDisconnectedAt?{lastDisconnectedAt:t.lastDisconnectedAt}:{},...t.nextRetryAt?{nextRetryAt:t.nextRetryAt}:{},...t.error?{error:t.error}:{}}},closeAll:()=>{a=!0;for(const e of s.values())e.retry.cancel(),e.supervisor?.close(),e.socket?.close(1001,"Node agent shutting down.");s.clear()}}}({log:h.log,inject:e=>h.inject(e),nodeAgentEventForwarder:h.nodeAgentEventForwarder,nodeAgentState:g},p,r,f);h.decorate("nodeAgentReverseTunnels",y);const I=new Hs({app:h,state:g,settings:l,config:u,source:d?"persisted":"bootstrap",onActiveListener:m});let A;h.decorate("nodeAgentListenerManager",I),function(e){let t=!1;const n=async n=>{if(!t){t=!0,y.closeAll(),A?.close();try{await e.close()}finally{process.exitCode=n?0:process.exitCode}}},i=()=>{n("SIGINT")},r=()=>{n("SIGTERM")};process.once("SIGINT",i),process.once("SIGTERM",r),e.addHook("onClose",async()=>{process.off("SIGINT",i),process.off("SIGTERM",r)})}(h),h.addHook("onClose",async()=>{A?.close(),o.release()});try{await h.ready();const o=e.ipcPath||process.env.TASK_HANDOFF_NODE_AGENT_IPC_PATH||io(r.dataDir);A=await async function(e,r){!function(e,i=process.platform){if("win32"!==i){t.mkdirSync(n.dirname(e),{recursive:!0,mode:448});try{t.chmodSync(n.dirname(e),448)}catch{}try{t.unlinkSync(e)}catch(e){if("ENOENT"!==e.code)throw e}}}(r);const o=i.createServer((t,n)=>{e.server.emit("request",t,n)});return o.on("upgrade",(t,n,i)=>{e.server.emit("upgrade",t,n,i)}),await new Promise((e,t)=>{o.once("error",t),o.listen(r,()=>{o.off("error",t),e()})}),o}(h,o),await I.start(),y.connectConfigured(),h.nodeAgentStartRecoverySupervisor?.()}catch(e){throw await h.close(),e}}catch(e){throw o.release(),e}var s,a}function bc(e){const t=Number(e);if(!Number.isInteger(t)||t<=0||t>65535)throw new Error("Port must be a valid TCP port.");return t}function wc(e){if("local-ipc"!==e&&"local-loopback"!==e)throw new Error("Connection mode must be local-ipc or local-loopback.");return e}function vc(e){const t=Number(e);if(!Number.isInteger(t)||t<=0)throw new Error("Expiry must be a positive integer.");return t}(async function(){const t=new e.Command;t.name("task-handoff-node-agent").description("Run a TaskHandoff node agent.").version(E("@task-handoff/cli")).option("--host <host>","Node agent host",process.env.TASK_HANDOFF_NODE_AGENT_HOST||"127.0.0.1").option("-p, --port <port>","Node agent port",bc,Number(process.env.TASK_HANDOFF_NODE_AGENT_PORT)||8091).option("--data-dir <path>","Node agent data directory").option("--token <token>","Bearer token required by the control plane").option("--connection-mode <mode>","Local control connection mode",wc).option("--ipc-path <path>","Unix socket path used by local-ipc mode").option("--control-plane-tunnel-url <url>","Control plane reverse WebSocket tunnel URL").action(async e=>{await Ac({host:e.host,port:e.port,dataDir:e.dataDir,token:e.token,connectionMode:e.connectionMode,ipcPath:e.ipcPath,controlPlaneTunnelUrl:e.controlPlaneTunnelUrl})}),t.command("invite").description("Create a one-time token for pairing this node agent with a control plane.").option("--endpoint <url>","Use the node-agent HTTP endpoint instead of its local IPC socket").option("--ipc-path <path>","Local node-agent IPC socket path").option("--data-dir <path>","Node-agent data directory used to locate its IPC socket").option("--token <token>","Bearer token for local node-agent access",process.env.TASK_HANDOFF_NODE_AGENT_TOKEN).option("--expires-in-ms <ms>","Invite expiry in milliseconds",vc).option("--json","Print raw JSON output").action(async e=>{const n=t.opts(),r=e.ipcPath||n.ipcPath||process.env.TASK_HANDOFF_NODE_AGENT_IPC_PATH,o=e.dataDir||n.dataDir||process.env.TASK_HANDOFF_NODE_AGENT_DATA_DIR,s=e.endpoint?void 0:r||io(o||Qr()),a=await async function(e){const t={"content-type":"application/json",...e.token?{authorization:`Bearer ${e.token}`}:{}},n=JSON.stringify({...e.expiresInMs?{expiresInMs:e.expiresInMs}:{}}),r=e.endpoint?await fetch(`${e.endpoint.replace(/\/$/,"")}/api/node-agent/pairing/invites`,{method:"POST",headers:t,body:n}):await async function(e,t,n={}){const r=n.method||"GET",o="string"==typeof n.body||n.body instanceof Buffer?n.body:void 0===n.body||null===n.body?void 0:String(n.body),s=new Headers(n.headers||{});return void 0===o||s.has("content-length")||s.set("content-length",String(Buffer.byteLength(o))),new Promise((a,c)=>{const d=i.request({socketPath:e,method:r,path:`/api/node-agent${t}`,headers:Object.fromEntries(s.entries())},e=>{const t=e.statusCode||500;a(new Response("HEAD"!==r&&204!==t&&205!==t&&304!==t?h.Readable.toWeb(e):null,{status:t,headers:e.headers}))});d.on("error",c);const l=()=>d.destroy(new DOMException("The operation was aborted.","AbortError"));n.signal?.aborted?l():n.signal?.addEventListener("abort",l,{once:!0}),d.once("close",()=>n.signal?.removeEventListener("abort",l)),void 0!==o&&d.write(o),d.end()})}(e.ipcPath,"/pairing/invites",{method:"POST",headers:t,body:n}),o=await r.json().catch(()=>({}));if(!r.ok)throw new Error(o.error?.message||`Node agent pairing invite failed with HTTP ${r.status}`);const s="string"==typeof o.data?.joinToken?o.data.joinToken:"";if(!s)throw new Error("Node agent pairing invite response did not include a join token.");return{nodeId:"string"==typeof o.data?.nodeId?o.data.nodeId:"",joinToken:s,expiresAt:"string"==typeof o.data?.expiresAt?o.data.expiresAt:""}}({endpoint:e.endpoint,ipcPath:s,token:e.token,expiresInMs:e.expiresInMs});e.json?console.log(JSON.stringify(a,null,2)):(a.nodeId&&console.log(`Node: ${a.nodeId}`),console.log(`Join token: ${a.joinToken}`),a.expiresAt&&console.log(`Expires: ${a.expiresAt}`))}),await t.parseAsync(process.argv)})().catch(e=>{console.error(e instanceof Error?e.message:String(e)),process.exitCode=1});