@task-handoff/node-agent 0.0.26 → 0.0.27

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"),s=require("node:url"),r=require("fastify"),o=require("@fastify/websocket"),a=require("zod"),c=require("node:os"),d=require("node:crypto"),l=require("node:child_process"),u=require("node-pty"),p=require("ws"),m=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=require("node:readline/promises"),v=require("node:process"),w="undefined"!=typeof document?document.currentScript:null;function S(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 E(e){if(e)try{return n.dirname(t.realpathSync(e))}catch{return}}function z(e,t=process.env,i=e){const s=t.TASK_HANDOFF_VERSION?.trim();if(s)return s;const r=i.split("/").at(-1),o=process.argv[1]?n.resolve(process.argv[1]):void 0,a=o?n.dirname(o):void 0,c=[E(o),a,process.cwd()].filter(e=>Boolean(e));for(const t of new Set(c)){let i=t;for(;;){const t=S(n.join(i,"package.json"),e);if(t)return t;const s=n.dirname(i);if(s===i)break;i=s}}let d;for(const e of new Set(c)){let t=e;for(;;){if(r){const e=S(n.join(t,"packages",r,"package.json"),i);if(e)return e}d||=S(n.join(t,"package.json"));const e=n.dirname(t);if(e===t)break;t=e}}return d||"unknown"}const N={perMessageDeflate:{threshold:256,serverNoContextTakeover:!0,clientNoContextTakeover:!0,concurrencyLimit:4,zlibDeflateOptions:{level:1}}};function T(e){return e.readyState===(e.OPEN??1)}function _(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 k(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 C(e,t,n){e.close(k(t),_(n)||void 0)}function O(e,t,n,i){if(T(e))for(const e of t.splice(0))if(i(e),!n(e))return}function x(e,t,n={}){const i=n.pendingFrameLimit??256,s=n.maxFrameBytes??8388608,r=n.maxTotalBytes??1073741824,o=n.maxBufferedBytes??16777216;let a=!1,c=T(t);const d=[],l=[];let u,p=0,m=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,o)=>{const a=g(o);return h+=a,n.onFrame?.(i,a),!(a>s||h>r)||(C(e,1009,"WebSocket bridge traffic limit exceeded."),C(t,1009,"WebSocket bridge traffic limit exceeded."),!1)},y=()=>{u&&(clearTimeout(u),u=void 0)},I=(n,i)=>{const s=i.bytes;if((n.bufferedAmount??0)+s>o)return C(e,1013,"WebSocket bridge consumer is too slow."),C(t,1013,"WebSocket bridge consumer is too slow."),!1;try{return function(e,t){e.send(t.data,{binary:t.isBinary,compress:!1})}(n,i),!0}catch{return C(e,1011,"WebSocket bridge send failed."),C(t,1011,"WebSocket bridge send failed."),!1}},A=(n,s,r)=>{if(s.length>=i)return C(e,1011,"WebSocket bridge pending frame limit exceeded."),void C(t,1011,"WebSocket bridge pending frame limit exceeded.");const a="upstream"===n?p:m;if((("upstream"===n?t:e).bufferedAmount??0)+a+r.bytes>o)return C(e,1013,"WebSocket bridge consumer is too slow."),void C(t,1013,"WebSocket bridge consumer is too slow.");s.push(r),"upstream"===n?p+=r.bytes:m+=r.bytes};return n.upstreamOpenTimeoutMs&&!c&&(u=setTimeout(()=>{c||a||(C(e,1011,"Upstream websocket did not open."),C(t))},n.upstreamOpenTimeoutMs)),e.on("open",()=>O(e,l,t=>I(e,t),e=>{m-=e.bytes})),t.on("open",()=>{y(),c=!0,n.onUpstreamOpen?.(),O(t,d,e=>I(t,e),e=>{p-=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)};T(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)};T(e)?I(e,i):A("client",l,i)}),t.on("close",(t,i)=>{y(),n.onUpstreamClose?.(t,i),(c||a||!n.onUpstreamCloseBeforeOpen?.())&&C(e,t,i)}),t.on("error",t=>{n.onUpstreamError?.(t),(c||a||!n.onUpstreamErrorBeforeOpen?.(t))&&C(e)}),e.on("close",(e,i)=>{y(),a=!0,n.onClientClose?.(e,i),C(t,e,i)}),e.on("error",e=>{y(),a=!0,n.onClientError?.(e),C(t,1011,"WebSocket bridge client failed.")}),{close:(n,i)=>{y(),C(t,n,i),C(e,n,i)}}}var R,P,D=function(){if(P)return R;P=1;const e=t,{spawnSync:n}=l;return R={processStartIdentity:function(t,i=process.platform){if(Number.isInteger(t)&&!(t<=0)){if("linux"===i)try{const n=e.readFileSync(`/proc/${t}/stat`,"utf8"),i=n.lastIndexOf(")");if(i<0)return;const s=n.slice(i+2).trim().split(/\s+/)[19];return s?`linux:${s}`:void 0}catch{return}if(["darwin","freebsd","openbsd","aix","sunos"].includes(i)){const e=n("ps",["-o","lstart=","-p",String(t)],{encoding:"utf8",timeout:1e3}),s=0===e.status?e.stdout.trim().replace(/\s+/g," "):"";return s?`${i}:${s}`:void 0}if("win32"===i){const e=n("powershell.exe",["-NoProfile","-NonInteractive","-Command",`(Get-Process -Id ${t} -ErrorAction Stop).StartTime.ToUniversalTime().Ticks`],{encoding:"utf8",timeout:2e3}),i=0===e.status?e.stdout.trim():"";return/^\d+$/.test(i)?`win32:${i}`:void 0}}}}}();class M 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 j(e){return n.join(e,"owner.json")}function L(e){return n.join(e,"initializing.json")}function F(e){return n.join(e,"recovering.json")}function $(e){return Number.isInteger(e)&&Number(e)>0}function U(e){try{const n=JSON.parse(t.readFileSync(j(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 V=U;function H(e){if(!$(e))return!1;try{return process.kill(Number(e),0),!0}catch(e){return"EPERM"===e.code}}function B(e){if(!e||!H(e.pid))return!1;if(!e.startIdentity)return!0;const t=D.processStartIdentity(e.pid);return void 0===t||t===e.startIdentity}function q(e,i){const s=n.join(e,`.owner-${i.token}.tmp`);t.writeFileSync(s,`${JSON.stringify(i,null,2)}\n`,{encoding:"utf8",mode:384,flag:"wx"});const r=G(e);if(r?.token!==i.token)throw J(s),new Error(`Process lock initialization was superseded: ${e}`);t.renameSync(s,j(e)),J(L(e))}function K(e,i,s){const r=V(e);if(r?.token!==i.token)return!1;const o={...i};for(const[e,t]of Object.entries(s))void 0===t?delete o[e]:Object.assign(o,{[e]:t});const a=n.join(e,`.owner-update-${i.token}-${d.randomUUID()}.tmp`);try{if(t.writeFileSync(a,`${JSON.stringify(o,null,2)}\n`,{encoding:"utf8",mode:384,flag:"wx"}),V(e)?.token!==i.token)return!1;t.renameSync(a,j(e));for(const e of Object.keys(i))delete i[e];return Object.assign(i,o),!0}catch(e){if("ENOENT"===e.code)return!1;throw e}finally{J(a)}}function G(e){try{return JSON.parse(t.readFileSync(L(e),"utf8"))}catch{return}}function W(e){const t=G(e);return $(t?.pid)&&B({pid:t.pid,startIdentity:t.startIdentity})}function J(e){try{t.unlinkSync(e)}catch(e){if("ENOENT"!==e.code)throw e}}function Y(){Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,20)}function X(e){try{const n=G(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 Q(e,i){try{return t.writeFileSync(F(e),`${JSON.stringify({token:i,pid:process.pid,startedAt:(new Date).toISOString()})}\n`,{encoding:"utf8",mode:384,flag:"wx"}),!0}catch(s){if("EEXIST"===s.code)return!!function(e){const i=F(e),s=Z(i),r=Date.parse(s?.startedAt||"");if(H(s?.pid)||Number.isFinite(r)&&Date.now()-r<2e3)return!1;const o=n.join(e,`.recovering-${d.randomUUID()}.stale`);try{t.renameSync(i,o)}catch(e){if(["ENOENT","EEXIST"].includes(e.code||""))return!1;throw e}const a=Z(o);if(a?.token===s?.token)return J(o),!0;try{t.linkSync(o,i)}catch(e){if("EEXIST"!==e.code)throw e}finally{J(o)}return!1}(e)&&Q(e,i);if("ENOENT"===s.code)return!1;throw s}}function Z(e){try{return JSON.parse(t.readFileSync(e,"utf8"))}catch{return}}function ee(e,t){return Z(F(e))?.token===t}function te(){return(new Date).toISOString()}const ne=6048e5;function ie(e,t){const i=n.resolve(e),s=n.resolve(i,t);if(n.dirname(s)!==i||n.basename(s)!==t)throw new Error(`Retention entry is not a direct child of its managed root: ${t}`);return s}function se(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 re=20971520,oe=512e3,ae=oe,ce=re,de=41943040,le="ai.sessions",ue="ai-session.snapshot",pe="ai-session.patch",me="ai-session.removed",he="ai-session.message-delta",ge="ai-session.timeline-item",fe=a.z.string().trim().min(1).max(80),ye=a.z.enum(["app-session","ai-session"]),Ie=a.z.enum(["image","file"]),Ae={scopeType:a.z.enum(["session","create-request"]),scopeId:a.z.string().trim().min(1).max(160),kind:Ie,name:a.z.string().trim().min(1).max(240),mime:a.z.string().trim().min(1).max(120)};a.z.object({...Ae,size:a.z.coerce.number().int().positive().max(re)}).strict();const be=a.z.string().regex(/^cia_[a-f0-9]{24}$/);a.z.object({attachmentId:be,...Ae,size:a.z.number().int().positive().max(re)}).strict(),a.z.object({offset:a.z.coerce.number().int().nonnegative()}).strict(),a.z.object({attachmentId:be,offset:a.z.number().int().nonnegative()}),a.z.object({id:be,kind:Ie,name:a.z.string().trim().min(1).max(240),mime:a.z.string().trim().min(1).max(120),size:a.z.number().int().positive().max(re),expiresAt:a.z.string().datetime()});const ve=a.z.object({id:a.z.string().trim().min(1).max(120),kind:Ie,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)}),we=a.z.enum(["available","expired","missing"]),Se=ve.extend({contentState:we.default("available")}).strict(),Ee=a.z.object({id:a.z.string().trim().min(1).max(240),text:a.z.string(),attachments:a.z.array(Se).max(6).default([])}).strict(),ze=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 Ne=a.z.enum(["thinking","tool","editing","approval","responding","unknown"]),Te=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(),_e=a.z.enum(["running","completed","failed","waiting"]),ke=a.z.object({id:a.z.string().trim().min(1).max(240),turnId:a.z.string().trim().min(1).max(240)}).strict(),Ce=ke.extend({type:a.z.literal("user-message"),text:a.z.string(),attachments:a.z.array(Se).max(6).optional()}).strict(),Oe=ke.extend({type:a.z.literal("ai-message"),text:a.z.string()}).strict(),xe=ke.extend({type:a.z.literal("activity"),activityKind:a.z.string().trim().min(1).max(120),title:a.z.string().trim().min(1).max(240),status:_e.optional(),summary:a.z.string().max(4e3).optional(),input:a.z.string().max(1e5).optional(),output:a.z.string().max(1e6).optional(),paths:a.z.array(a.z.string().trim().min(1).max(4096)).max(500).optional(),exitCode:a.z.number().int().optional(),durationMs:a.z.number().int().nonnegative().optional()}).strict(),Re=a.z.discriminatedUnion("type",[Ce,Oe,xe]);a.z.object({sessionId:a.z.string().trim().min(1).max(120),providerSessionId:a.z.string().trim().min(1).max(240),items:a.z.array(Re),generatedAt:a.z.string().datetime()}).strict(),a.z.object({sessionId:a.z.string().trim().min(1).max(120),turnId:a.z.string().trim().min(1).max(240),items:a.z.array(Re),generatedAt:a.z.string().datetime()}).strict();const Pe=a.z.enum(["pending-init","running","interrupted","completed","errored","shutdown","not-found"]),De=a.z.enum(["started","interacted","interrupted"]),Me=a.z.object({threadId:a.z.string().trim().min(1).max(240),path:a.z.string().trim().max(4096).optional(),status:Pe,activity:De.optional(),message:a.z.string().trim().max(1e3).optional(),updatedAt:a.z.string().datetime()}).strict(),je=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}),Le=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(),Fe=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(),$e=a.z.union([ve.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?re:oe;(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.`})}),ve.extend({source:a.z.object({type:a.z.literal("runtime-path"),path:a.z.string().trim().min(1).max(4096)}).strict()}).strict()]),Ue=ve.extend({sourceType:a.z.enum(["inline","runtime-path"])}).strict(),Ve=a.z.union([a.z.object({id:a.z.string().trim().min(1).max(120),kind:Ie.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:Ie,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()]),He=a.z.enum(["auto","queue","steer","immediate"]),Be=a.z.enum(["ask","auto-review","full-access"]),qe=a.z.enum(["review","rename","goal","compact"]);a.z.object({command:qe,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:qe,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 Ke=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",[Ke.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(),Ke.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(),Ke.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()]),We=a.z.array(Ge).max(20).default([]),Je=a.z.enum(["plugin","skill","file","directory","app"]),Ye=a.z.object({kind:Je,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."})}),Xe=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(Ye).max(1e3).default([]),diagnostics:a.z.array(Xe).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(Ye.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 Qe=a.z.object({message:a.z.string().trim().min(1).max(2e4),mode:He.optional(),permissionMode:Be.optional()}),Ze=Qe.extend({attachments:a.z.array($e).max(6).default([]),references:We}).strict().superRefine((e,t)=>{e.attachments.reduce((e,t)=>e+("inline"===t.source.type?t.size:0),0)>de&&t.addIssue({code:a.z.ZodIssueCode.custom,path:["attachments"],message:"Inline attachments must be 41943040 bytes or less in total."})}),et=Qe.extend({attachments:a.z.array(Ve).max(6).default([]),references:We}).strict(),tt=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(),nt=a.z.object({modelEntityId:a.z.string().trim().min(1).max(120),modelName:a.z.string().trim().min(1).max(240)}).strict(),it=a.z.enum(["none","minimal","low","medium","high","xhigh","max","ultra"]);Ze.extend({agent:fe,cwd:tt,cwdFolderId:a.z.string().trim().min(1).max(120).optional(),clientRequestId:a.z.string().trim().min(1).max(160),modelSelection:nt.optional(),reasoningEffort:it.optional()}).strict();const st=a.z.object({mode:a.z.enum(["current-folder","worktree"]),branch:a.z.string().trim().min(1).max(1024)}).strict();et.extend({agent:fe,cwdFolderId:a.z.string().trim().min(1).max(120).optional(),gitSelection:st.optional(),clientRequestId:a.z.string().trim().min(1).max(160),modelSelection:nt.optional(),reasoningEffort:it.optional()}).strict(),a.z.object({clientRequestId:a.z.string().trim().min(1).max(160),modelSelection:nt}).strict(),a.z.object({sessionId:a.z.string().trim().min(1).max(120),accepted:a.z.literal(!0)}).strict(),a.z.object({clientRequestId:a.z.string().trim().min(1).max(160),reasoningEffort:it}).strict(),a.z.object({sessionId:a.z.string().trim().min(1).max(120),accepted:a.z.literal(!0)}).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 rt=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:rt.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:ye}).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:ye}).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 ot=a.z.object({id:a.z.string().trim().min(1).max(120),messageId:a.z.string().trim().min(1).max(240).optional(),message:a.z.string().trim().min(1).max(2e4),attachments:a.z.array(Ue).max(6).default([]),references:We,permissionMode:Be.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(),at=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(ot).max(100).default([])}).strict().default({revision:0,pendingCount:0,items:[]}),ct=a.z.enum(["control","realtime","adapter-snapshot","transcript-tail","transcript-scan","process-scan","app-session"]),dt=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(),lt=a.z.object({id:a.z.string().trim().min(1).max(240),providerTurnId:a.z.string().trim().max(240).optional(),source:ct.optional(),userPrompt:a.z.string().trim().optional(),userMessages:a.z.array(Ee).max(100).optional(),status:a.z.enum(["queued","running","waiting","completed","failed"]).default("running"),phase:Ne.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(dt).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(),ut=lt.pick({id:!0,providerTurnId:!0,userPrompt:!0,userMessages:!0,status:!0,phase:!0,summary:!0,lastMessage:!0,contextCompactions:!0,startedAt:!0,updatedAt:!0,completedAt:!0}).strict(),pt=a.z.object({id:a.z.string().trim().min(1).max(120),agent:fe,creationSource:ye.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:Fe.optional(),providerMeta:a.z.record(a.z.string(),a.z.unknown()).optional(),modelSelection:nt.optional(),reasoningEffort:it.optional(),appBindingKeys:a.z.array(a.z.string().trim().min(1).max(240)).max(20).optional(),actions:Le.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(lt).max(50).optional(),status:ze.default("running"),phase:Ne.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:Te.optional(),toolCallsSinceLastMessage:a.z.number().int().min(0).default(0),subAgents:a.z.array(Me).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:je,queue:at}).strict(),mt=pt.pick({id:!0,appBindingKeys:!0,cwd:!0,error:!0,providerMeta:!0,modelSelection:!0,reasoningEffort:!0,queue:!0,subAgents:!0}).strict(),ht=lt.pick({id:!0,providerTurnId:!0,status:!0,phase:!0,revision:!0,startedAt:!0,updatedAt:!0,completedAt:!0}).extend({bodyRevision:a.z.string().trim().min(1).max(64)}).strict(),gt=a.z.object({sessionId:a.z.string().trim().min(1).max(120),revision:a.z.string().trim().min(1).max(64),turns:a.z.array(ht).max(50)}).strict(),ft=a.z.object({sessionId:a.z.string().trim().min(1).max(120),revision:a.z.string().trim().min(1).max(64),turn:lt}).strict(),yt=a.z.string().trim().min(1).max(64),It=a.z.object({kind:a.z.literal("not-modified"),revision:yt}).strict();a.z.discriminatedUnion("kind",[It,a.z.object({kind:a.z.literal("updated"),revision:yt,detail:mt}).strict()]),a.z.discriminatedUnion("kind",[It,a.z.object({kind:a.z.literal("updated"),revision:yt,index:gt}).strict()]),a.z.discriminatedUnion("kind",[It,a.z.object({kind:a.z.literal("updated"),revision:yt,body:ft}).strict()]);const At=a.z.object({session:pt,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(),bt=At.omit({session:!0}).extend({sessionId:a.z.string().trim().min(1).max(120),messageId:a.z.string().trim().min(1).max(240).optional()}).strict();a.z.object({sessionId:a.z.string().trim().min(1).max(120),queueRevision:a.z.number().int().min(0),action:a.z.enum(["retry","remove","edit","reorder"]),queueId:a.z.string().trim().min(1).max(120).optional()}).strict(),a.z.union([bt,At.transform(function(e){const t=e.session.turns?.at(-1),n=(e.queueId?e.session.queue?.items.find(t=>t.id===e.queueId)?.messageId:void 0)||("send"===e.action||"queue"===e.action||"steer"===e.action?t?.userMessages?.at(-1)?.id:void 0);return bt.parse({sessionId:e.session.id,provider:e.provider,action:e.action,...e.decision?{decision:e.decision}:{},...e.turnId||e.session.activeTurnId||t?.id?{turnId:e.turnId||e.session.activeTurnId||t?.id}:{},...e.providerTurnId||t?.providerTurnId?{providerTurnId:e.providerTurnId||t?.providerTurnId}:{},...e.queueId?{queueId:e.queueId}:{},...n?{messageId:n}:{}})})]);const vt=500,wt=a.z.object({id:a.z.string().trim().min(1).max(120),agent:fe,creationSource:ye,providerSessionId:a.z.string().trim().min(1).max(240),lineage:Fe.optional(),modelSelection:nt.optional(),reasoningEffort:it.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(wt).max(vt).default([])}).strict(),a.z.object({items:a.z.array(wt).max(vt).default([])}).strict(),a.z.object({item:wt,turns:a.z.array(ut).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:ye}).strict();const St=lt.omit({userMessages:!0}),Et=pt.pick({id:!0,agent:!0,creationSource:!0,appSessionId:!0,appId:!0,providerSessionId:!0,lineage:!0,providerMeta:!0,modelSelection:!0,reasoningEffort:!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}).extend({turns:a.z.array(St).max(50).optional(),detailRevision:a.z.string().trim().min(1).max(64).optional(),turnsRevision:a.z.string().trim().min(1).max(64).optional(),latestTurnRef:a.z.object({id:lt.shape.id,bodyRevision:a.z.string().trim().min(1).max(64)}).strict().optional(),turnCount:a.z.number().int().min(0).optional(),subAgentCount:a.z.number().int().min(0).optional(),lastUserMessageAt:a.z.string().datetime().optional()}).strict(),zt=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(Et).default([]),updatedAt:a.z.string().datetime()}).strict(),Nt=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:zt}).strict();zt.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 Tt=a.z.enum(["provider-event","app-session-created","app-session-updated","app-session-deleted","discovery-scan","control-action","heartbeat-sync","startup"]),_t=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:Tt}).strict(),kt=a.z.object({meta:_t,snapshot:zt}).strict(),Ct=a.z.object({meta:_t,upserted:a.z.array(Et).default([]),removed:a.z.array(a.z.string().trim().min(1).max(120)).default([])}).strict(),Ot=a.z.object({meta:_t,sessionIds:a.z.array(a.z.string().trim().min(1).max(120)).default([]),expiresAt:a.z.string().datetime()}).strict(),xt=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).optional(),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(),Rt=xt.omit({instanceId:!0,nodeId:!0,providerSessionId:!0}).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),item:Re,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(ue),payload:kt}).strict(),a.z.object({type:a.z.literal(pe),payload:Ct}).strict(),a.z.object({type:a.z.literal(me),payload:Ot}).strict()])).default([])}).strict();const Pt=a.z.object({source:ct,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(),Dt=Pt.extend({type:a.z.literal("snapshot"),agent:a.z.string().trim().min(1).max(80),creationSource:ye.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:Fe.optional(),providerMeta:a.z.record(a.z.string(),a.z.unknown()).optional(),modelSelection:nt.optional(),reasoningEffort:it.optional(),appBindingKeys:a.z.array(a.z.string().trim().min(1).max(240)).max(20).optional(),actions:Le.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(lt).max(50).optional(),status:ze.optional(),phase:Ne.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:Te.optional(),toolCallsSinceLastMessage:a.z.number().int().min(0).optional(),subAgents:a.z.array(Me).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(),Mt=Pt.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","model-selection","reasoning-effort"]),modelSelection:nt.optional(),reasoningEffort:it.optional(),activeTurnId:a.z.string().trim().max(240).optional(),providerTurnId:a.z.string().trim().max(240).optional(),userPrompt:a.z.string().trim().optional(),userMessage:Ee.optional(),text:a.z.string().optional(),itemId:a.z.string().trim().max(240).optional(),status:ze.optional(),phase:Ne.optional(),summary:a.z.string().trim().max(1e3).optional(),error:a.z.string().trim().max(4e3).optional(),currentTool:Te.nullable().optional(),toolCallsSinceLastMessage:a.z.number().int().min(0).optional(),subAgents:a.z.array(Me).max(50).optional(),contextCompaction:dt.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("model-selection"===e.kind?e.modelSelection||t.addIssue({code:"custom",path:["modelSelection"],message:"model-selection events require modelSelection"}):void 0!==e.modelSelection&&t.addIssue({code:"custom",path:["modelSelection"],message:"modelSelection is only valid for model-selection events"}),"reasoning-effort"===e.kind?e.reasoningEffort||t.addIssue({code:"custom",path:["reasoningEffort"],message:"reasoning-effort events require reasoningEffort"}):void 0!==e.reasoningEffort&&t.addIssue({code:"custom",path:["reasoningEffort"],message:"reasoningEffort is only valid for reasoning-effort events"}),"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"}),"send-ack"!==e.kind&&"user-message"!==e.kind&&void 0!==e.userMessage&&t.addIssue({code:"custom",path:["userMessage"],message:"userMessage is only valid for send-ack and user-message 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",[Dt,Mt]);const jt=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()]),Lt=a.z.union([jt,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()]),Ft=a.z.object({promptTemplate:a.z.string().trim().min(1).max(2e4)}).strict(),$t=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(),Ut=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:Lt,action:Ft,policy:$t.default({maxConcurrentRuns:1,whenBusy:"skip"}),createdAt:a.z.string().datetime(),updatedAt:a.z.string().datetime()}).strict(),Vt=a.z.object({type:a.z.literal("ai-session"),aiSessionId:a.z.string().trim().min(1).max(160)}).strict(),Ht=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:Vt,localName:a.z.string().trim().min(1).max(160).optional(),createdAt:a.z.string().datetime(),updatedAt:a.z.string().datetime()}).strict(),Bt=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(),qt=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:Vt,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(Ut).default([]),deployments:a.z.array(Ht).default([]),runtime:a.z.array(Bt).default([]),recentRuns:a.z.array(qt).default([])}).strict();const Kt=a.z.object({config:Ut,deployment:Ht,runtime:Bt.optional()}).strict();a.z.object({instanceId:a.z.string().trim().min(1).max(160),sessionId:a.z.string().trim().min(1).max(160),mutation:Kt.optional()}).strip(),a.z.object({instanceId:a.z.string().trim().min(1).max(160),sessionId:a.z.string().trim().min(1).max(160),configHash:Ut.shape.configHash}).strip();const Gt=a.z.object({instanceId:a.z.string().trim().min(1).max(160),instanceName:a.z.string().trim().min(1).max(160),deployment:Ht,runtime:Bt.optional()}).strip(),Wt=qt.extend({instanceName:a.z.string().trim().min(1).max(160).optional()}).strip(),Jt=a.z.object({configHash:a.z.string().trim().min(8).max(80),config:Ut,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(Gt),recentRuns:a.z.array(Wt)}).strip();a.z.object({updatedAt:a.z.string().datetime(),triggers:a.z.array(Jt)}).strip(),a.z.object({name:Ut.shape.name,description:Ut.shape.description,source:Lt,action:Ft,policy:$t.partial().optional()}).strict(),a.z.object({scope:a.z.enum(["node","instance"]),nodeId:a.z.string().trim().min(1).max(160).optional(),instanceId:a.z.string().trim().min(1).max(160).optional(),code:a.z.string().trim().min(1).max(160),message:a.z.string().trim().min(1).max(4e3)}).strip();const Yt=a.z.string().regex(/^\d{4}-\d{2}-\d{2}$/,"Proxy protocol version must use YYYY-MM-DD format."),Xt=a.z.string().trim().min(1).max(160).regex(/^[a-zA-Z0-9][a-zA-Z0-9_.:-]*$/),Qt=a.z.string().datetime(),Zt=a.z.string().trim().min(32).max(4096),en=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,s;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{s=new URL(t,"https://node-agent.invalid")}catch{throw new Error("Proxy route is invalid.")}if("https://node-agent.invalid"!==s.origin||s.username||s.password)throw new Error("Proxy route cannot select an absolute upstream URL.");return`${s.pathname}${s.search}`}(e)}catch(e){return t.addIssue({code:"custom",message:e instanceof Error?e.message:String(e)}),a.z.NEVER}});const tn=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"})),nn=a.z.object({code:tn,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(),sn=a.z.enum(["active","revoked"]),rn=a.z.object({id:Xt,targetNodeId:Xt,status:sn,createdBy:Xt,expiresAt:Qt,revokedAt:Qt.optional(),createdAt:Qt,updatedAt:Qt}).strict();a.z.object({targetNodeId:Xt,expiresInSeconds:a.z.number().int().min(60).max(3600).default(600)}).strict(),a.z.object({invite:rn,token:a.z.string().trim().min(24).max(512),proxyOrigin:en,protocolVersion:Yt}).strict();const on=a.z.enum(["active","revoked"]),an=a.z.object({id:Xt,claimId:Xt,sourceControlPlaneId:Xt,targetNodeId:Xt,bindingKeyId:Xt,status:on,revision:a.z.number().int().positive(),lastError:nn.optional(),revokedAt:Qt.optional(),createdAt:Qt,updatedAt:Qt}).strict();a.z.object({protocolVersion:Yt,inviteToken:a.z.string().trim().min(24).max(512).optional(),claimId:Xt,sourceControlPlaneId:Xt,targetNodeId:Xt.optional(),bindingKeyId:Xt,credential:Zt}).strict(),a.z.object({sourceControlPlaneId:Xt,bindingKeyId:Xt,credential:Zt}).strict();const cn=a.z.object({id:Xt,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:Qt.optional(),capabilities:a.z.record(a.z.string(),a.z.unknown()).default({})}).strict(),dn=a.z.object({protocolVersion:Yt,binding:an,streamId:Xt,revision:a.z.number().int().nonnegative(),observedAt:Qt,target:cn}).strict(),ln=a.z.object({type:a.z.literal("control-plane-proxy.event"),protocolVersion:Yt,streamId:Xt,bindingId:Xt,sourceControlPlaneId:Xt,targetNodeId:Xt,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:cn,event:a.z.object({type:a.z.string().trim().min(1).max(240),topic:a.z.string().trim().min(1).max(240),createdAt:Qt}).strict()}).strict(),un=a.z.object({type:a.z.literal("control-plane-proxy.events.ready"),protocolVersion:Yt,streamId:Xt,bindingId:Xt,sourceControlPlaneId:Xt,targetNodeId:Xt,latestRevision:a.z.number().int().nonnegative(),earliestRetainedRevision:a.z.number().int().nonnegative()}).strict(),pn=a.z.object({type:a.z.literal("control-plane-proxy.snapshot-required"),protocolVersion:Yt,streamId:Xt,bindingId:Xt,sourceControlPlaneId:Xt,targetNodeId:Xt,sinceRevision:a.z.number().int().nonnegative(),latestRevision:a.z.number().int().nonnegative(),earliestRetainedRevision:a.z.number().int().nonnegative(),error:nn}).strict();a.z.discriminatedUnion("type",[ln,un,pn]),a.z.object({protocolVersion:Yt,binding:an,target:dn.shape.target}).strict(),a.z.object({id:Xt,claimId:Xt,proxyOrigin:en,requestedName:a.z.string().trim().min(1).max(160).optional(),sourceControlPlaneId:Xt,targetNodeId:Xt.optional(),bindingKeyId:Xt,credential:Zt,status:a.z.enum(["pending","compensation-required"]),createdAt:Qt,updatedAt:Qt,expiresAt:Qt}).strict().omit({credential:!0}),a.z.object({id:Xt,nodeId:Xt,proxyOrigin:en,proxyBindingId:Xt,targetNodeId:Xt,sourceControlPlaneId:Xt,bindingKeyId:Xt,credential:Zt,createdAt:Qt,updatedAt:Qt}).strict();const mn=a.z.string().trim().min(1).max(120),hn=a.z.object({selectModelAtCreate:a.z.boolean().default(!1),selectProviderAtCreate:a.z.boolean().default(!1),switchModelWithinProvider:a.z.boolean().default(!1),switchProviderDuringSession:a.z.boolean().default(!1)}).strip().default({selectModelAtCreate:!1,selectProviderAtCreate:!1,switchModelWithinProvider:!1,switchProviderDuringSession:!1}),gn=a.z.object({selectAtCreate:a.z.boolean().default(!1),updateDuringSession:a.z.boolean().default(!1)}).strip().default({selectAtCreate:!1,updateDuringSession:!1}),fn=a.z.object({agent:mn,actions:a.z.object({create:a.z.boolean().default(!1),send:a.z.boolean().default(!1),queue:a.z.boolean().default(!1),steer:a.z.boolean().default(!1),interrupt:a.z.boolean().default(!1),archive:a.z.boolean().default(!1),delete:a.z.boolean().default(!1),fork:a.z.boolean().default(!1),approvalDecisions:a.z.array(a.z.enum(["allow","deny","skip"])).max(3).default([])}).passthrough(),timeline:a.z.object({sessionRead:a.z.boolean().default(!1),turnRead:a.z.boolean().default(!1),liveItems:a.z.boolean().default(!1)}).passthrough(),modelSelection:hn.optional(),reasoningEffort:gn.optional()}).passthrough(),yn=a.z.array(fn).max(100).default([]),In="2026-08-27",An=new Set(["2026-08-01","2026-08-16","2026-08-17","2026-08-20",In]),bn=a.z.string().regex(/^\d{4}-\d{2}-\d{2}$/,"Protocol version must use YYYY-MM-DD format."),vn=a.z.string().trim().min(1).max(120);function wn(){return{features:{appRuntime:!1,tty:!1,gui:!1,browser:!1,browserTunnel:!1,screenshots:!1,logs:!1,aiSessionWorkspaceSelection:!1,aiSessionPersistenceSettings:!1,privateModelCatalog:!1,gitCliCredentialBroker:!1,gitCredentialProxy:!1,aiSessionTimeline:{sessionReadAgents:[],turnReadAgents:[],liveItemAgents:[]},aiSessionConversationAttachments:{metadataAgents:[],contentAgents:[],uploadAgents:[],retentionSettings:!1,fileSizeLimitSettings:!1},aiSessionProviders:[]}}}const Sn=a.z.object({sessionReadAgents:a.z.array(vn).max(100).default([]),turnReadAgents:a.z.array(vn).max(100).default([]),liveItemAgents:a.z.array(vn).max(100).default([])}).passthrough(),En=a.z.object({metadataAgents:a.z.array(vn).max(100).default([]),contentAgents:a.z.array(vn).max(100).default([]),uploadAgents:a.z.array(vn).max(100).default([]),retentionSettings:a.z.boolean().default(!1),fileSizeLimitSettings:a.z.boolean().default(!1)}).passthrough(),zn=a.z.object({appRuntime:a.z.boolean().default(!1),tty:a.z.boolean().default(!1),gui:a.z.boolean().default(!1),browser:a.z.boolean().default(!1),browserTunnel:a.z.boolean().optional(),screenshots:a.z.boolean().default(!1),logs:a.z.boolean().default(!1),aiSessionWorkspaceSelection:a.z.boolean().default(!1),aiSessionPersistenceSettings:a.z.boolean().default(!1),privateModelCatalog:a.z.boolean().optional(),gitCliCredentialBroker:a.z.boolean().optional(),gitCredentialProxy:a.z.boolean().optional(),aiSessionTimeline:Sn.default(function(){return{sessionReadAgents:[],turnReadAgents:[],liveItemAgents:[]}}),aiSessionConversationAttachments:En.optional(),aiSessionProviders:yn.optional()}).passthrough(),Nn=a.z.object({features:zn.default(function(){return{appRuntime:!1,tty:!1,gui:!1,browser:!1,browserTunnel:!1,screenshots:!1,logs:!1,aiSessionWorkspaceSelection:!1,aiSessionPersistenceSettings:!1,privateModelCatalog:!1,gitCliCredentialBroker:!1,gitCredentialProxy:!1,aiSessionTimeline:{sessionReadAgents:[],turnReadAgents:[],liveItemAgents:[]},aiSessionConversationAttachments:{metadataAgents:[],contentAgents:[],uploadAgents:[],retentionSettings:!1,fileSizeLimitSettings:!1},aiSessionProviders:[]}})}).passthrough();function Tn(e){const t={features:{appRuntime:!1,tty:!1,gui:!1,browser:!1,browserTunnel:!1,screenshots:!1,logs:!1,aiSessionWorkspaceSelection:!1,aiSessionPersistenceSettings:!1,privateModelCatalog:!1,gitCliCredentialBroker:!1,gitCredentialProxy:!1,aiSessionTimeline:{sessionReadAgents:[],turnReadAgents:[],liveItemAgents:[]},aiSessionConversationAttachments:{metadataAgents:[],contentAgents:[],uploadAgents:[],retentionSettings:!1,fileSizeLimitSettings:!1},aiSessionProviders:[]}};if(!e||"object"!=typeof e||Array.isArray(e))return t;const n=e,i=n.features;if(!i||"object"!=typeof i||Array.isArray(i))return t;const s=i,r={appRuntime:!1,tty:!1,gui:!1,browser:!1,browserTunnel:!1,screenshots:!1,logs:!1,aiSessionWorkspaceSelection:!1,aiSessionPersistenceSettings:!1,privateModelCatalog:!1,gitCliCredentialBroker:!1,gitCredentialProxy:!1,aiSessionTimeline:{sessionReadAgents:[],turnReadAgents:[],liveItemAgents:[]},aiSessionConversationAttachments:{metadataAgents:[],contentAgents:[],uploadAgents:[],retentionSettings:!1,fileSizeLimitSettings:!1},aiSessionProviders:[]};for(const e of["appRuntime","tty","gui","browser","browserTunnel","screenshots","logs","aiSessionWorkspaceSelection","aiSessionPersistenceSettings","privateModelCatalog","gitCliCredentialBroker","gitCredentialProxy"]){const t=a.z.boolean().safeParse(s[e]);t.success&&(r[e]=t.data)}const o=Sn.safeParse(s.aiSessionTimeline);o.success&&(r.aiSessionTimeline=o.data);const c=En.safeParse(s.aiSessionConversationAttachments);c.success&&(r.aiSessionConversationAttachments=c.data);const d=yn.safeParse(s.aiSessionProviders);return d.success&&(r.aiSessionProviders=d.data),Nn.parse({...n,features:{...s,...r}})}function _n(e){return Tn(e).features.aiSessionConversationAttachments}const kn=a.z.string().trim().min(1).max(120).regex(/^[a-zA-Z0-9][a-zA-Z0-9_.:-]*$/),Cn=a.z.string().datetime(),On=a.z.record(a.z.string(),a.z.string()).default({}),xn=a.z.record(a.z.string(),a.z.string()).default({}),Rn=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 Pn(e){if(null==e)return;const t=Rn.parse(e);return"utf8"===t.encoding?t.data:Buffer.from(t.data,"base64")}const Dn=/^[A-Za-z0-9_][A-Za-z0-9_.-]{0,127}$/,Mn=/^sha256:([a-fA-F0-9]{64})$/,jn=/^(?:localhost|[a-z0-9](?:[a-z0-9.-]*[a-z0-9])?)(?::[1-9][0-9]{0,4})?$/,Ln=/^[a-z0-9]+(?:(?:[._]|__|-+)[a-z0-9]+)*$/;function Fn(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),s=-1===n?t:t.slice(0,n),r=i?Mn.exec(i):void 0;if(i&&!r)throw new Error("Docker image digest must use sha256 followed by 64 hexadecimal characters.");const o=s.lastIndexOf("/"),a=s.lastIndexOf(":"),c=a>o,d=c?s.slice(a+1):void 0,l=c?s.slice(0,a):s;if(d&&!Dn.test(d))throw new Error("Docker image tag is invalid.");if(!d&&!r)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 p=u.length>1&&(u[0].includes(".")||u[0].includes(":")||"localhost"===u[0]),m=p?u.slice(1):u;if(p&&!jn.test(u[0].toLowerCase()))throw new Error("Docker image registry host or port is invalid.");if(!m.length||m.some(e=>!Ln.test(e)))throw new Error("Docker image repository names must be lowercase and use valid separators.");const h=u.map((e,t)=>p&&0===t?e.toLowerCase():e).join("/"),g=r?`sha256:${r[1].toLowerCase()}`:void 0;return`${h}${d?`:${d}`:""}${g?`@${g}`:""}`}function $n(e){const t=Fn(e),n=t.indexOf("@"),i=-1===n?void 0:t.slice(n+1),s=-1===n?t:t.slice(0,n),r=s.lastIndexOf("/"),o=s.lastIndexOf(":"),a=o>r;return{reference:t,repository:a?s.slice(0,o):s,tag:a?s.slice(o+1):void 0,digest:i}}const Un=a.z.string().trim().min(1).max(512).transform((e,t)=>{try{return Fn(e)}catch(e){return t.addIssue({code:"custom",message:e instanceof Error?e.message:String(e)}),a.z.NEVER}}),Vn=a.z.string().trim().transform((e,t)=>{const n=Mn.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)}),Hn=a.z.object({modelEntityIds:a.z.array(kn).max(64).transform(e=>[...new Set(e)]).optional(),codexModelHash:kn.nullable().optional(),claudeModelHash:kn.nullable().optional(),opencodeModelHash:kn.nullable().optional()}).strict().default({}),Bn=a.z.object({imageId:kn,tag:a.z.string().trim().min(1).max(128).regex(Dn).optional()}).strict(),qn=a.z.discriminatedUnion("type",[a.z.object({type:a.z.literal("image"),imageSelection:Bn}).strict(),a.z.object({type:a.z.literal("template"),environmentTemplateId:kn}).strict()]),Kn=a.z.enum(["creating","ready","failed","deleting"]),Gn=a.z.enum(["linux","darwin","win32","freebsd","openbsd","aix","sunos","unknown"]),Wn=a.z.enum(["x64","arm64","arm","ia32","ppc64","s390x","riscv64","unknown"]),Jn=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(),Yn=a.z.object({templateId:kn,nodeId:kn,imageId:Vn,name:a.z.string().trim().min(1).max(160),platform:Gn,architecture:Wn}).strict(),Xn=a.z.enum(["data","agent-home","workspace"]),Qn=a.z.object({deleteVolumes:a.z.boolean()}).strict(),Zn=a.z.object({role:Xn,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(),ei=a.z.object({instanceId:kn,containerDeleted:a.z.boolean(),completed:a.z.boolean(),deletedVolumes:a.z.array(Zn),retainedVolumes:a.z.array(Zn),volumeResults:a.z.array(Zn)}).strict(),ti={img_default:"market_taskhandoff_browser",img_codex:"market_taskhandoff_codex",img_ai:"market_taskhandoff_ai"};function ni(e,t){if(e&&"object"==typeof e&&!Array.isArray(e)){const t=e;return{imageId:"string"==typeof t.imageId&&ti[t.imageId]||t.imageId,..."string"==typeof t.tag?{tag:t.tag}:{}}}if("string"==typeof t)return{imageId:ti[t]||t}}function ii(e){if(!e||"object"!=typeof e||Array.isArray(e))return e;const t=e,{defaultImageId:n,...i}=t;return{...i,defaultImageSelection:ni(t.defaultImageSelection,n)}}const si=a.z.object({id:kn,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(),ri=a.z.object({code:a.z.enum(["APP_CATALOG_INVALID"]),message:a.z.string().trim().min(1).max(500)}).strict(),oi=a.z.object({items:a.z.array(si).max(256),observedAt:Cn,issues:a.z.array(ri).max(32).default([])}).strict(),ai=a.z.object({id:kn,name:a.z.string().trim().min(1).max(160),sourceInstanceId:kn,nodeId:kn,imageId:Vn.optional(),internalTag:a.z.string().trim().min(1).max(512).optional(),platform:Gn.optional(),architecture:Wn.optional(),sizeBytes:a.z.number().int().nonnegative().optional(),status:Kn,error:Jn.optional(),createdAt:Cn,updatedAt:Cn}).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."})}),ci=a.z.enum(["apt","dnf","brew","npm"]),di=a.z.enum(["user","passwordless-sudo","root"]),li=a.z.object({platform:Gn,arch:Wn,installers:a.z.array(ci).max(8),privilege:di,installerAccess:a.z.object({npmGlobalWritable:a.z.boolean().optional()}).strict().optional()}).strict(),ui=a.z.enum(["installed","not-installed","broken","unsupported"]),pi=a.z.enum(["recipe","bundled","external","none"]),mi=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(),hi=a.z.object({id:kn,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:ui,managementSource:pi,version:a.z.string().trim().max(120).optional(),canInstall:a.z.boolean(),canUninstall:a.z.boolean(),installReason:mi.optional(),uninstallReason:mi.optional(),activeJobId:kn.optional()}).strict(),gi=a.z.enum(["install","uninstall"]),fi=a.z.enum(["queued","running","succeeded","failed","cancelled","interrupted"]),yi=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"]}),Ii=a.z.object({executable:a.z.string().trim().min(1).max(4096),args:a.z.array(a.z.string().max(4096)).max(128)}).strict(),Ai=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(kn).max(64).optional()}).strict(),bi=a.z.object({id:kn,requestId:kn.optional(),appId:kn,operation:gi,state:fi,phase:a.z.string().trim().min(1).max(120).optional(),progress:yi.optional(),command:Ii.optional(),logTail:a.z.string().max(32768).optional(),logTruncated:a.z.boolean().optional(),error:Ai.optional(),requestedAt:Cn,startedAt:Cn.optional(),finishedAt:Cn.optional(),updatedAt:Cn}).strict(),vi=a.z.object({streamId:kn,sequence:a.z.number().int().nonnegative(),capabilities:li,apps:a.z.array(hi).max(256),activeJobs:a.z.array(bi).max(256),recentJobs:a.z.array(bi).max(256),observedAt:Cn}).strict();a.z.object({requestId:kn.optional()}).strict(),a.z.object({job:bi}).strict(),a.z.object({type:a.z.literal("app-management"),streamId:kn,sequence:a.z.number().int().nonnegative(),observedAt:Cn,job:bi.optional(),snapshot:vi.optional()}).strict().refine(e=>void 0!==e.job||void 0!==e.snapshot,{message:"An app management event requires a job or snapshot."});const wi=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:bn.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:bn,build:wi.extend({component:a.z.literal("control-plane"),packageVersion:a.z.string().trim().min(1).max(80)}).loose(),serverTime:Cn}).loose()}).loose();const Si=a.z.enum(["stable","beta","alpha"]),Ei=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(),zi=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(),Ni=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:Cn.optional(),matchedAt:Cn.optional(),error:zi.optional()}).strict(),Ti=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(kn).max(1024).default([]),stoppedInstanceIds:a.z.array(kn).max(1024).default([]),activeInstanceIds:a.z.array(kn).max(1024).default([])}).strict(),_i=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(kn).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(),ki=a.z.object({channel:Si.default("stable")}).strict(),Ci=a.z.object({source:a.z.literal("npm"),channel:Si,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(Ei).default([]),impact:Ti,updateAvailable:a.z.boolean(),supported:a.z.boolean().default(!0),reason:a.z.string().trim().max(2048).optional(),checkedAt:Cn,preflightToken:a.z.string().trim().min(16).max(240).optional()}).strict(),Oi=a.z.object({id:kn,nodeId:kn,source:a.z.literal("npm"),channel:Si,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(Ei).default([]),impact:Ti,rollout:_i,status:a.z.enum(["queued","updating-node","restarting-node","converging-instances","succeeded","degraded","failed"]),error:zi.optional(),startedAt:Cn.optional(),completedAt:Cn.optional(),createdAt:Cn,updatedAt:Cn}).strict(),xi=a.z.object({channel:Si,targetVersion:a.z.string().trim().min(1).max(240),preflightToken:a.z.string().trim().min(16).max(240)}).strict(),Ri=a.z.object({type:a.z.enum(["branch","tag"]),name:a.z.string().trim().min(1).max(240)}).strict(),Pi=a.z.object({type:a.z.literal("commit"),commit:a.z.string().trim().regex(/^[0-9a-fA-F]{4,64}$/,"commit must be a hexadecimal Git object id")}).strict(),Di=a.z.discriminatedUnion("type",[Ri,Pi]),Mi=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(),ji=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).refine(e=>!e.startsWith("/")&&!e.split("/").some(e=>".."===e),"subdirectory must be a relative path within the repository").transform(e=>e.split("/").filter(e=>e&&"."!==e).join("/")).default("")}).strict();a.z.object({id:kn,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:Di.default({type:"branch",name:"main"}),auth:Mi.default({type:"none"}),clone:ji.default({submodules:!1,lfs:!1,subdirectory:""}),defaultImageSelection:Bn.optional(),labels:On,createdAt:Cn,updatedAt:Cn}).strict();const Li=a.z.object({id:kn,nodeId:kn,name:a.z.string().trim().min(1).max(160),path:a.z.string().trim().min(1).max(4096),defaultImageSelection:Bn.optional(),labels:On,createdAt:Cn,updatedAt:Cn}).strict(),Fi=a.z.discriminatedUnion("type",[a.z.object({type:a.z.literal("git-repository"),repositoryId:kn.optional(),url:a.z.string().trim().min(1).max(2048),provider:a.z.string().trim().max(80).optional(),ref:Di.default({type:"branch",name:"main"}),auth:Mi.default({type:"none"}),clone:ji.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:Di.default({type:"branch",name:"main"}),auth:Mi.default({type:"none"}),clone:ji.default({submodules:!1,lfs:!1,subdirectory:""})}).strict(),a.z.object({type:a.z.literal("local-folder"),localFolderId:kn.optional(),path:a.z.string().trim().min(1).max(4096),ownerNodeId:kn.optional()}).strict()]),$i=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(),Ui=a.z.enum(["codex","claude","opencode"]),Vi=a.z.enum(["openai-responses","openai-chat-completions","anthropic-messages"]),Hi=a.z.object({name:a.z.string().trim().min(1).max(240),order:a.z.number().int().min(0).max(1e6).default(0)}).strict(),Bi=a.z.object({id:kn,name:a.z.string().trim().min(1).max(160),source:Fi,defaultImageSelection:Bn.optional(),defaultNodeId:kn.optional(),workspacePolicy:$i,labels:On,createdAt:Cn,updatedAt:Cn}).strict(),qi=a.z.object({id:kn,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),modelNames:a.z.array(Hi).max(256).default([]),protocols:a.z.array(Vi).max(3).default([]),app:Ui,enabled:a.z.boolean().default(!0),order:a.z.number().int().min(0).max(1e6).default(0),labels:On,createdAt:Cn,updatedAt:Cn}).strict(),Ki=qi,Gi=qi.omit({key:!0}).extend({keyPreview:a.z.string().trim().min(1).max(160),keySet:a.z.boolean()}).strict(),Wi=Gi.extend({referenceCount:a.z.number().int().min(0)}).strict(),Ji=a.z.object({instanceId:kn,modelEntityIds:a.z.array(kn).max(64).transform(e=>[...new Set(e)]).optional(),codexModelHash:kn.optional(),claudeModelHash:kn.optional(),opencodeModelHash:kn.optional(),updatedAt:Cn}).strict().transform(e=>({...e,modelEntityIds:e.modelEntityIds?.length?e.modelEntityIds:[...new Set([e.codexModelHash,e.claudeModelHash,e.opencodeModelHash].filter(e=>Boolean(e)))]})),Yi=a.z.discriminatedUnion("type",[a.z.object({type:a.z.literal("control-plane"),name:qi.shape.name,enabled:qi.shape.enabled,order:qi.shape.order}).strict(),a.z.object({type:a.z.literal("node"),nodeId:kn,name:qi.shape.name,enabled:qi.shape.enabled,order:qi.shape.order,referenceCount:a.z.number().int().min(0)}).strict()]),Xi=a.z.object({id:kn,model:Gi,locations:a.z.array(Yi).min(1),referenceCount:a.z.number().int().min(0).default(0)}).strict(),Qi=a.z.object({nodeId:kn,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(Xi),nodeDiagnostics:a.z.array(Qi).default([]),updatedAt:Cn}).strict();const Zi=qi.omit({id:!0,createdAt:!0,updatedAt:!0}).strict(),es=Zi.partial().strict(),ts=qi,ns=a.z.object({modelSelection:Hn,modelEntityIds:a.z.array(kn).max(64).transform(e=>[...new Set(e)]).optional(),codexModelHash:kn.optional(),claudeModelHash:kn.optional(),opencodeModelHash:kn.optional()}).strict().transform(e=>({...e,modelEntityIds:e.modelEntityIds||e.modelSelection.modelEntityIds||[...new Set([e.codexModelHash,e.claudeModelHash,e.opencodeModelHash].filter(e=>Boolean(e)))]}));function is(e){const t={app:Ui.parse(e.app),endpoint:qi.shape.endpoint.parse(e.endpoint),key:qi.shape.key.parse(e.key),model:qi.shape.model.parse(e.model)};return`mdl_${d.createHash("sha256").update(JSON.stringify(t)).digest("hex")}`}const ss=a.z.enum(["market","custom"]),rs=a.z.enum(["active","deprecated","yanked"]),os=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:Vn.optional()}).strict()]),as=a.z.array(a.z.string().trim().min(1).max(80)).default([]),cs=a.z.array(a.z.string().trim().min(1).max(120)).default([]),ds=a.z.record(a.z.string().trim().min(2).max(35),a.z.string().trim().min(1).max(4096)),ls=a.z.object({os:a.z.string().trim().min(1).max(40),architecture:a.z.string().trim().min(1).max(40),digest:Vn.optional(),downloadSizeBytes:a.z.number().int().positive().optional(),unpackedSizeBytes:a.z.number().int().positive().optional()}).strict(),us=a.z.object({name:a.z.string().trim().min(1).max(128).regex(Dn),version:a.z.string().trim().min(1).max(160).optional(),reference:Un,manifestDigest:Vn.optional(),publishedAt:Cn.optional(),platforms:a.z.array(ls).default([]),status:rs.default("active")}).strict(),ps=a.z.object({id:kn,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:ds.optional(),cover:os.optional(),repository:a.z.string().trim().min(1).max(512),defaultTag:a.z.string().trim().min(1).max(128).regex(Dn),tags:a.z.array(us).min(1),capabilities:as,optionalApps:cs,defaultEnv:xn,labels:On,status:rs.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:bn,catalogId:kn,revision:a.z.string().trim().min(1).max(240),source:a.z.enum(["embedded","remote","cache"]),generatedAt:Cn,expiresAt:Cn.optional(),items:a.z.array(ps)}).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:Cn,error:a.z.string().trim().max(4096).optional()}).strict(),a.z.object({id:kn,origin:a.z.literal("custom"),name:a.z.string().trim().min(1).max(160),description:a.z.string().trim().max(4096).optional(),localizedDescriptions:ds.optional(),cover:os.optional(),reference:Un,repository:a.z.string().trim().min(1).max(512),tag:a.z.string().trim().min(1).max(128).regex(Dn).optional(),pullPolicy:a.z.literal("if-not-present").default("if-not-present"),capabilities:as,optionalApps:cs,defaultEnv:xn,labels:On,createdAt:Cn,updatedAt:Cn}).strict();const ms=a.z.object({name:a.z.string().trim().min(1).max(128).regex(Dn),version:a.z.string().trim().min(1).max(160).optional(),reference:Un,manifestDigest:Vn.optional(),status:rs}).strict(),hs=a.z.object({id:kn,origin:ss,name:a.z.string().trim().min(1).max(160),description:a.z.string().trim().max(4096).optional(),localizedDescriptions:ds.optional(),cover:os,repository:a.z.string().trim().min(1).max(512),tag:a.z.string().trim().min(1).max(128).regex(Dn).optional(),availableTags:a.z.array(ms),reference:Un,digest:Vn.optional(),downloadSizeBytes:a.z.number().int().positive().optional(),unpackedSizeBytes:a.z.number().int().positive().optional(),capabilities:as,optionalApps:cs,defaultEnv:xn,labels:On,readOnly:a.z.boolean(),lifecycleStatus:rs.optional(),market:a.z.object({catalogId:kn,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(),gs=a.z.object({id:kn,origin:ss,name:a.z.string().trim().min(1).max(160),description:a.z.string().trim().max(4096).optional(),localizedDescriptions:ds.optional(),cover:os.optional(),repository:a.z.string().trim().min(1).max(512),tag:a.z.string().trim().min(1).max(128).regex(Dn).optional(),requestedReference:Un,resolvedDigest:Vn.optional(),resolvedReference:Un.optional(),downloadSizeBytes:a.z.number().int().positive().optional(),pullPolicy:a.z.literal("if-not-present").default("if-not-present"),capabilities:as,optionalApps:cs,defaultEnv:xn,labels:On,market:a.z.object({catalogId:kn,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:Cn,updatedAt:Cn}).strict(),fs=a.z.object({phase:a.z.enum(["checking-image","pulling-image","resolving-image","ready","failed"]),requestedReference:Un,generation:a.z.number().int().nonnegative().default(0),error:a.z.string().trim().max(4096).optional(),startedAt:Cn,updatedAt:Cn}).strict(),ys="image.pull.terminal.output",Is="image.pull.terminal.finished",As=a.z.object({instanceId:kn,generation:a.z.number().int().nonnegative(),requestedReference:Un,sequence:a.z.number().int().nonnegative(),observedAt:Cn}).strict(),bs=As.extend({data:a.z.string().min(1).max(65536),replay:a.z.boolean().optional()}).strict(),vs=As.extend({outcome:a.z.enum(["succeeded","failed"])}).strict();As.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 ws=a.z.discriminatedUnion("kind",[a.z.object({kind:a.z.literal("direct")}).strict(),a.z.object({kind:a.z.literal("control-plane-proxy"),proxyId:kn,proxyBindingId:kn,targetNodeId:kn}).strict()]),Ss=a.z.object({pingRttMs:a.z.number().nonnegative().optional(),pingRttP95Ms:a.z.number().nonnegative().optional(),consecutiveReconnects:a.z.number().int().nonnegative(),nextRetryAt:Cn.optional()}).strict();a.z.object({nodeId:kn,inviteId:kn.optional()}).strict(),a.z.discriminatedUnion("status",[a.z.object({id:kn,status:a.z.literal("pending")}).strict(),a.z.object({id:kn,status:a.z.literal("completed"),nodeId:kn}).strict()]);const Es=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:Cn.optional(),target:cn.optional(),lastError:nn.optional(),updatedAt:Cn}).strict(),zs=a.z.object({id:kn,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:ws.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:kn.optional(),secret:a.z.string().trim().max(4096).optional(),pairedAt:Cn.optional(),pairing:a.z.object({status:a.z.enum(["pending","paired","expired"]).default("pending"),joinToken:a.z.string().trim().max(4096).optional(),expiresAt:Cn.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:Es.optional(),appInventory:oi.optional(),labels:On,lastSeenAt:Cn.optional(),createdAt:Cn,updatedAt:Cn}).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."})});a.z.object({nodeId:kn,status:a.z.enum(["unknown","online","offline","degraded"]),health:a.z.enum(["unknown","ok","degraded","failed"]),lastSeenAt:Cn.nullable(),connectionPhase:a.z.enum(["connecting","handshaking","healthy","reconnecting","suspect","offline"]).nullable(),connectionDiagnostics:Ss.nullable(),proxyState:Es.nullable()}).strict();const Ns=a.z.object({id:kn,nodeId:kn,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:On,createdAt:Cn,updatedAt:Cn}).strict(),Ts=a.z.object({instanceId:kn,runtimeKind:a.z.literal("docker"),state:a.z.enum(["pending","available","stopped","unavailable"]),sampledAt:Cn,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(),_s=a.z.object({registry:a.z.boolean().default(!1),runtimeBroker:a.z.boolean().default(!1),workspaceProvisioning:a.z.object({docker:a.z.boolean().default(!1),kubernetes:a.z.boolean().default(!1),local:a.z.boolean().default(!1)}).strip().default({docker:!1,kubernetes:!1,local:!1})}).strip(),ks=a.z.object({multiEntityAssignment:a.z.boolean().default(!1),privateModelCatalog:a.z.boolean().default(!1)}).strip(),Cs=a.z.object({modelEndpointProbe:a.z.boolean().optional(),aiSessionHistoryLimit:a.z.boolean().optional(),aiSessionAttachmentRetention:a.z.boolean().optional(),aiSessionFileAttachmentLimit:a.z.boolean().optional(),folderPlaces:a.z.boolean().optional(),localFolderNameUpdate:a.z.boolean().optional(),managedGitCredentials:_s.optional(),managedModels:ks.optional()}).strip(),Os=a.z.object({status:a.z.enum(["healthy","congested","recovering"]),activeOutputs:a.z.number().int().nonnegative(),bufferedBytes:a.z.number().int().nonnegative(),peakBufferedBytes:a.z.number().int().nonnegative(),coalescedEvents:a.z.number().int().nonnegative(),oversizedEvents:a.z.number().int().nonnegative().optional(),peakEventBytes:a.z.number().int().nonnegative().optional(),congestedSince:Cn.optional(),lastCongestedAt:Cn.optional()}).strip();a.z.object({ok:a.z.boolean().optional(),role:a.z.string().optional(),nodeId:kn.optional(),platform:Gn.optional(),arch:Wn.optional(),protocolVersion:bn.optional(),capabilities:Cs.optional(),build:wi.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(),eventTransport:Os.optional(),serverTime:Cn.optional()}).strip();const xs=a.z.object({bindScope:a.z.enum(["loopback","all-ipv4"]),port:a.z.number().int().min(1).max(65535)}).strict(),Rs=xs.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(),Ps=xs;a.z.object({nodeId:kn,joinToken:a.z.string().trim().min(1),expiresAt:Cn}).passthrough(),a.z.object({nodeId:kn,keyId:kn,secret:a.z.string().regex(/^[A-Za-z0-9_-]{32,128}$/),pairedAt:Cn}).strict();const Ds=a.z.object({id:kn,keyId:kn,name:a.z.string().trim().min(1).max(160).optional(),pairedAt:Cn,updatedAt:Cn,current:a.z.boolean()}).passthrough();a.z.object({keyId:kn,revoked:a.z.literal(!0),revokedAt:Cn}).strict(),a.z.object({id:kn,pairingKeyId:kn,url:a.z.string().trim().min(1).max(2048),name:a.z.string().trim().min(1).max(160).optional(),enabled:a.z.boolean(),createdAt:Cn,updatedAt:Cn,status:a.z.enum(["disabled","connecting","connected","reconnecting","failed"]),pingRttMs:a.z.number().nonnegative().optional(),pingRttP95Ms:a.z.number().nonnegative().optional(),consecutiveReconnects:a.z.number().int().nonnegative().optional(),nextRetryAt:Cn.optional(),lastConnectedAt:Cn.optional(),lastDisconnectedAt:Cn.optional(),error:a.z.string().optional()}).passthrough(),a.z.object({pairing:Ds,connection:a.z.object({id:kn,pairingKeyId:kn,url:a.z.string().trim().min(1).max(2048),name:a.z.string().trim().min(1).max(160).optional(),enabled:a.z.boolean(),createdAt:Cn,updatedAt:Cn}).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 Ms=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:hs,status:a.z.enum(["available","pull-required","unknown"]),localImage:Ms.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 js=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(js)}).passthrough());a.z.object({kind:a.z.enum(["home","root"]),name:a.z.string().trim().min(1),path:a.z.string().trim().min(1).max(4096)}).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 Ls=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(),Fs=a.z.object({...Ls.shape}).strict(),$s=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"}),Us=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(),Vs=a.z.object({id:kn,name:a.z.string().trim().min(1).max(160),projectId:kn.optional(),source:Fi,sourceSnapshot:a.z.record(a.z.string(),a.z.unknown()).default({}),modelSelection:Hn,nodeId:kn,runtimeId:kn,imageSelection:Bn.optional(),environmentSource:qn.optional(),environmentTemplateOrigin:Yn.optional(),imageSnapshot:gs.optional(),imageProvisioning:fs.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:bn.optional(),instanceVersion:a.z.string().trim().max(80).optional(),build:wi.optional(),runtimeVersion:Ni.optional(),ready:a.z.boolean().default(!1),capabilities:Nn.default(wn),appInventory:oi.optional(),config:a.z.object({autoImportAgentConfigs:a.z.boolean().default(!0),codexConfigEnabled:a.z.boolean().default(!0),codexHomeMode:a.z.enum(["default","taskhandoff"]).default("taskhandoff"),defaultCodexPermissionMode:Be.default("ask"),aiSessionHistoryLimit:a.z.number().int().min(1).max(vt).default(50),aiSessionAttachmentRetentionDays:a.z.number().int().min(0).max(365).default(30),aiSessionMaxFileAttachmentBytes:a.z.number().int().positive().max(ce).default(ae)}).strict().default({autoImportAgentConfigs:!0,codexConfigEnabled:!0,codexHomeMode:"taskhandoff",defaultCodexPermissionMode:"ask",aiSessionHistoryLimit:50,aiSessionAttachmentRetentionDays:30,aiSessionMaxFileAttachmentBytes:ae}),workspace:Us.default({status:"unknown"}),target:Ls.default({strategy:"direct-port",status:"unknown"}),access:$s,apps:a.z.object({runningCount:a.z.number().int().min(0).default(0),problemCount:a.z.number().int().min(0).default(0),updatedAt:Cn.optional(),revision:a.z.number().int().min(0).optional()}).strict().default({runningCount:0,problemCount:0}),aiSessions:zt.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:Ut,deployments:a.z.array(Ht).default([]),runtime:a.z.array(Bt).default([])}).strict()).default([]),recentRuns:a.z.array(qt).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:Cn.optional(),createdAt:Cn,updatedAt:Cn}).strict(),Hs=a.z.union([Vs.transform(e=>({instance:e,gitWorkspaceProvisioningOperationId:void 0})),a.z.object({instance:Vs,gitWorkspaceProvisioningOperationId:kn.optional()}).strict()]);a.z.preprocess(e=>{if(!e||"object"!=typeof e||Array.isArray(e))return e;const t=e;return t.instance&&"object"==typeof t.instance&&!Array.isArray(t.instance)?{instance:Gs(t.instance),..."string"==typeof t.gitWorkspaceProvisioningOperationId?{gitWorkspaceProvisioningOperationId:t.gitWorkspaceProvisioningOperationId}:{}}:Gs(t)},Hs);const Bs="instance.lifecycle.snapshot",qs=a.z.object({instanceId:Vs.shape.id,revision:a.z.number().int().min(0),updatedAt:Cn,status:Vs.shape.status.unwrap(),health:Vs.shape.health.unwrap(),connectionStatus:Vs.shape.connectionStatus.unwrap(),accessStatus:a.z.enum(["reachable","endpoint-unreachable"]),imageProvisioning:fs.optional(),workspace:Us,runtime:Vs.shape.runtime.unwrap(),runtimeVersion:Ni.optional(),ready:a.z.boolean(),lastHeartbeatAt:Cn.optional()}).strict();function Ks(e,t){return Vs.safeParse(Gs(e,t))}function Gs(e,t){if(!e||"object"!=typeof e||Array.isArray(e))return e;const n=e,i=new Set(Object.keys(Vs.shape)),s={};for(const[e,r]of Object.entries(n))i.has(e)?s[e]=r: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),s.capabilities=Tn(e)}else s.capabilities=Tn(void 0);s.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 s={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=Ys(e,["id","name","kind","source","availability","diagnosticCode"]);return!i||"object"!=typeof i||Array.isArray(i)?i:{...i,capabilities:Ys(e.capabilities,["automation","supportsCwdSelection"])}}):i.items,issues:Array.isArray(i.issues)?i.issues.map(e=>Ys(e,["code","message"])):i.issues},r=oi.safeParse(s);return r.success?r.data:void 0}(n.appInventory,t,"string"==typeof n.id?n.id:void 0),s.source=function(e,t,n){if(!e||"object"!=typeof e||Array.isArray(e))return e;const i=e,s=i.type,r=Fi.options.find(e=>e.shape.type.value===s);if(!r)return e;const o="local-folder"===s?["type","localFolderId","path","ownerNodeId"]:"git-template"===s?["type","url","templateId","ref","auth","clone"]:["type","repositoryId","url","provider","ref","auth","clone"],a=Ys(i,o);if("local-folder"!==s){const e=function(e,t,n){const i=e&&"object"==typeof e&&!Array.isArray(e)?e:void 0,s=Di.safeParse(Ys(i,["type","name","commit"]));if(s.success)return s.data;const r="string"==typeof i?.commit?i.commit.trim():"",o="string"==typeof i?.name?i.name.trim():"",a=r?Di.safeParse({type:"commit",commit:r}):o?Di.safeParse({type:"tag"===i?.type?"tag":"branch",name:o}):Di.safeParse({type:"branch",name:"main"});return a.success?(t?.({instanceId:n,field:"source.ref"}),a.data):void 0}(i.ref,t,n),s=Ws(Mi,Ys(i.auth,["type","secretId"]),"source.auth",t,n),r=Ws(ji,Ys(i.clone,["depth","submodules","lfs","subdirectory"]),"source.clone",t,n);e?a.ref=e:delete a.ref,s?a.auth=s:delete a.auth,r?a.clone=r:delete a.clone}const c=Ws(r,a,"source",t,n);return c?(Object.keys(i).some(e=>!o.includes(e))&&t?.({instanceId:n,field:"source"}),c):a}(n.source,t,"string"==typeof n.id?n.id:void 0),s.sourceSnapshot=n.sourceSnapshot&&"object"==typeof n.sourceSnapshot&&!Array.isArray(n.sourceSnapshot)?n.sourceSnapshot:{},s.build=Ws(wi,n.build,"build",t,"string"==typeof n.id?n.id:void 0),s.aiSessions=function(e,t,n){if(!e||"object"!=typeof e||Array.isArray(e))return;const i=e,s=Array.isArray(i.sessions)?i.sessions.flatMap((e,i)=>{const s=Ws(Et,e,`aiSessions.sessions.${i}`,t,n);return s?[s]:[]}):[],r={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:s,updatedAt:Cn.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"}),zt.parse(r)}(n.aiSessions,t,"string"==typeof n.id?n.id:void 0),s.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 s=(e,i,s)=>Array.isArray(e)?e.flatMap((e,r)=>{const o=Ws(i,e,`${s}.${r}`,t,n);return o?[o]:[]}):[],r=Array.isArray(i.configs)?i.configs.flatMap((e,i)=>{if(!e||"object"!=typeof e||Array.isArray(e))return[];const r=e;Object.keys(r).some(e=>!["configHash","config","deployments","runtime"].includes(e))&&t?.({instanceId:n,field:`triggers.configs.${i}`});const o=function(e,t,n,i){if(!e||"object"!=typeof e||Array.isArray(e))return;const s=e,r=Ys(s,["configHash","name","description","createdAt","updatedAt"]);if(s.source&&"object"==typeof s.source&&!Array.isArray(s.source)){const e=s.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"];r.source=Ys(e,t)}return r.action=Ys(s.action,["promptTemplate"]),r.policy=Ys(s.policy,["cooldownMs","maxConcurrentRuns","whenBusy"]),Ws(Ut,r,t,n,i)}(r.config,`triggers.configs.${i}.config`,t,n);return"string"==typeof r.configHash&&o?[{configHash:r.configHash,config:o,deployments:s(r.deployments,Ht,`triggers.configs.${i}.deployments`),runtime:s(r.runtime,Bt,`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:r,recentRuns:s(i.recentRuns,qt,"triggers.recentRuns")}}(n.triggers,t,"string"==typeof n.id?n.id:void 0),s.apps=Ws(Vs.shape.apps.unwrap(),Ys(n.apps,["runningCount","problemCount","updatedAt","revision"]),"apps",t,"string"==typeof n.id?n.id:void 0)||{runningCount:0,problemCount:0},s.config=Ws(Vs.shape.config.unwrap(),Ys(n.config,["autoImportAgentConfigs","codexConfigEnabled","codexHomeMode","defaultCodexPermissionMode","aiSessionHistoryLimit","aiSessionAttachmentRetentionDays","aiSessionMaxFileAttachmentBytes"]),"config",t,"string"==typeof n.id?n.id:void 0)||{autoImportAgentConfigs:!0,codexConfigEnabled:!0,codexHomeMode:"taskhandoff",defaultCodexPermissionMode:"ask",aiSessionHistoryLimit:50,aiSessionAttachmentRetentionDays:30,aiSessionMaxFileAttachmentBytes:ae},s.modelSelection=Ws(Hn.unwrap(),Ys(n.modelSelection,["modelEntityIds","codexModelHash","claudeModelHash","opencodeModelHash"]),"modelSelection",t,"string"==typeof n.id?n.id:void 0)||{},s.imageSnapshot=function(e,t,n,i){if(!e||"object"!=typeof e||Array.isArray(e))return e;const s=e,r=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 s,r="string"==typeof t.reference?t.reference:i;if(r)try{r=Fn(r)}catch{if(!r.includes("@")&&r.lastIndexOf(":")<=r.lastIndexOf("/"))try{r=Fn(`${r}:latest`)}catch{}}try{s=r?$n(r):void 0}catch{}return{id:t.id,origin:"custom",name:t.name,description:t.description,localizedDescriptions:t.localizedDescriptions,cover:Ys(t.cover,["kind","key","url","mediaType","digest"]),reference:s?.reference??r,repository:s?.repository??t.repository,tag:s?.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}}(s),{reference:o,...a}=r,c=s.requestedReference??o;let d;try{d="string"==typeof c?$n(c):void 0}catch{}const l={img_default:"market_taskhandoff_browser",img_codex:"market_taskhandoff_codex",img_ai:"market_taskhandoff_ai"},u="string"==typeof s.id?s.id:"string"==typeof t?t:void 0,p="market"===s.origin||u&&l[u]?"market":"custom";return void 0===s.image&&void 0===s.reference||n?.({instanceId:i,field:"imageSnapshot.reference"}),{...a,id:u&&l[u]?l[u]:u,origin:p,repository:d?.repository??s.repository,tag:d?.tag??s.tag,requestedReference:d?.reference??c,resolvedDigest:s.resolvedDigest,resolvedReference:s.resolvedReference,downloadSizeBytes:s.downloadSizeBytes,market:"market"===p?Ys(s.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 r="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,o=Ys(n.imageSelection,["imageId","tag"]);s.imageSelection=o||(r?{imageId:r,tag:s.imageSnapshot?.tag}:void 0),s.imageProvisioning=Ws(fs,Ys(n.imageProvisioning,["phase","requestedReference","generation","error","startedAt","updatedAt"]),"imageProvisioning",t,"string"==typeof n.id?n.id:void 0),s.runtimeVersion=function(e,t,n){if(!e||"object"!=typeof e||Array.isArray(e))return;const i=e,s=e=>{if("string"!=typeof e)return;const t=e.trim();return t&&t.length<=80?t:void 0},r=s(i.desiredVersion);if(!r)return void t?.({instanceId:n,field:"runtimeVersion.desiredVersion"});const o=new Set(Ni.shape.phase.options),a="string"==typeof i.phase?i.phase:"pending",c=o.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,r="string"==typeof e.message?e.message.trim().slice(0,4096):"";if(r){const i=new Set(zi.shape.code.options),o="string"==typeof e.code&&i.has(e.code)?e.code:"INSTANCE_RUNTIME_INSTALL_FAILED";o!==e.code&&t?.({instanceId:n,field:"runtimeVersion.error.code"});const a=s(e.expectedVersion),c=s(e.actualVersion);d={code:o,message:r,...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:r,...s(i.actualVersion)?{actualVersion:s(i.actualVersion)}:{},retryable:!1});const l=s(i.actualVersion),u=Cn.safeParse(i.lastAttemptAt),p=Cn.safeParse(i.matchedAt);return void 0===i.lastAttemptAt||u.success||t?.({instanceId:n,field:"runtimeVersion.lastAttemptAt"}),void 0===i.matchedAt||p.success||t?.({instanceId:n,field:"runtimeVersion.matchedAt"}),{desiredVersion:r,...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}:{},...p.success?{matchedAt:p.data}:{},...d?{error:d}:{}}}(n.runtimeVersion,t,"string"==typeof n.id?n.id:void 0),s.workspace=Ws(Us,n.workspace,"workspace",t,"string"==typeof n.id?n.id:void 0)||{status:"unknown"},s.environmentSource=Ws(qn,n.environmentSource,"environmentSource",t,"string"==typeof n.id?n.id:void 0),s.environmentTemplateOrigin=Ws(Yn,n.environmentTemplateOrigin,"environmentTemplateOrigin",t,"string"==typeof n.id?n.id:void 0),s.runtime=Ws(Vs.shape.runtime.unwrap(),n.runtime,"runtime",t,"string"==typeof n.id?n.id:void 0)||{labels:{}},s.target=Ws(Ls,Ys(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"},s.access=Ws($s,Ys(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(Vs.shape))Object.prototype.hasOwnProperty.call(s,e)&&!i.safeParse(s[e]).success&&i.safeParse(void 0).success&&(delete s[e],t?.({instanceId:"string"==typeof n.id?n.id:void 0,field:e}));return s}function Ws(e,t,n,i,s){if(!t||"object"!=typeof t||Array.isArray(t))return;let r=structuredClone(t),o=!1;for(let t=0;t<20;t+=1){const t=e.safeParse(r);if(t.success)return o&&i?.({instanceId:s,field:n}),t.data;let a=!1;for(const e of t.error.issues){if("unrecognized_keys"!==e.code)continue;const t=Js(r,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,o=!0)}if(!a){const o=structuredClone(r);let a=!1;for(const e of t.error.issues){if(!e.path.length||"string"!=typeof e.path.at(-1))continue;const t=Js(o,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(o);if(t.success)return i?.({instanceId:s,field:n}),t.data}break}}i?.({instanceId:s,field:n})}function Js(e,t){let n=e;for(const e of t){if(!n||"object"!=typeof n)return;n=n[e]}return n}function Ys(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 Xs=a.z.object({instanceId:kn.optional(),projectId:kn.optional(),source:Fi.optional(),nodeId:kn.optional(),runtimeId:kn.optional(),imageSelection:Bn.optional(),instanceVersion:a.z.string().trim().max(80).optional(),protocolVersion:bn,build:wi.optional(),controlMode:a.z.enum(["standalone","controlled"]).default("controlled"),capabilities:Nn.default(wn),appInventory:oi.optional(),target:Fs.optional(),workspace:Us.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)=>{An.has(e.protocolVersion)&&!e.appInventory&&t.addIssue({code:"custom",path:["appInventory"],message:"Current protocol register payload requires appInventory."})}),Qs=a.z.object({status:Vs.shape.status.optional(),health:Vs.shape.health.optional(),protocolVersion:bn,build:wi.optional(),capabilities:Vs.shape.capabilities.optional(),appInventory:oi.optional(),apps:Vs.shape.apps.optional(),aiSessions:Vs.shape.aiSessions.optional(),triggers:Vs.shape.triggers.optional(),workspace:Us.optional(),target:Fs.optional(),processIncarnationId:a.z.string().trim().min(1).max(120).optional()}).strict().superRefine((e,t)=>{An.has(e.protocolVersion)&&!e.appInventory&&t.addIssue({code:"custom",path:["appInventory"],message:"Current protocol heartbeat payload requires appInventory."})}),Zs=a.z.enum(["web","telegram","wechat","dingding","lark"]);function er(e,t){let n=sr(t);for(let t=0;t<100;t+=1){const t=e.safeParse(n);if(t.success)return t;const i=tr(t.error.issues);let s=!1;for(const e of i){const t=ir(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],s=!0)}if(!s)return t}return e.safeParse(n)}function tr(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 s=e.reduce((e,t)=>nr(t)<nr(e)?t:e);n.push(...tr(s,[...t,...i.path]))}return n}function nr(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(nr)):1)},0)}function ir(e,t){let n=e;for(const e of t){if(!n||"object"!=typeof n)return;n=n[e]}return n}function sr(e){return Array.isArray(e)?e.map(sr):e&&"object"==typeof e?Object.getPrototypeOf(e)!==Object.prototype&&null!==Object.getPrototypeOf(e)?e:Object.fromEntries(Object.entries(e).map(([e,t])=>[e,sr(t)])):e}function rr(e,t,n={}){return new Promise((i,s)=>{if(n.signal?.aborted)return void s(Object.assign(new Error(`${e} was aborted.`),{code:"RUNTIME_COMMAND_ABORTED"}));const r=l.spawn(e,t,{stdio:["ignore","pipe","pipe"]}),o=[],a=[];let c=!1;const d=n.timeoutMs?setTimeout(()=>{c=!0,r.kill("SIGKILL")},n.timeoutMs):void 0;let u=!1;const p=()=>{u=!0,r.kill("SIGKILL")},m=()=>{d&&clearTimeout(d),n.signal?.removeEventListener("abort",p)};n.signal?.addEventListener("abort",p,{once:!0}),d?.unref?.(),r.stdout.on("data",e=>o.push(Buffer.from(e))),r.stderr.on("data",e=>a.push(Buffer.from(e))),r.on("error",e=>{m(),s(e)}),r.on("close",t=>{m();const r={stdout:Buffer.concat(o).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:r}),void s(t)}if(u)return void s(Object.assign(new Error(`${e} was aborted.`),{code:"RUNTIME_COMMAND_ABORTED",details:r}));if(0===t)return void i(r);const d=new Error(r.stderr||`${e} exited with code ${t}`);Object.assign(d,{statusCode:502,code:"RUNTIME_EXECUTOR_FAILED",details:r}),s(d)})})}a.z.object({id:kn,channel:Zs,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:Cn,updatedAt:Cn}).strict(),a.z.object({id:kn,channel:Zs,bridgeId:kn.optional(),chatSessionId:a.z.string().trim().min(1).max(240),userId:a.z.string().trim().max(240).optional(),activeProjectId:kn.optional(),activeInstanceId:kn.optional(),activeAiSessionId:a.z.string().trim().min(1).max(120).optional(),lastUsedAt:Cn,createdAt:Cn,updatedAt:Cn}).strict(),a.z.object({source:a.z.object({type:a.z.literal("chat-gateway").default("chat-gateway"),channel:Zs,bridgeId:kn.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($e).max(6).default([])}).strict().superRefine((e,t)=>{e.attachments.reduce((e,t)=>e+("inline"===t.source.type?t.size:0),0)>de&&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:kn,aiSessionId:a.z.string().trim().min(1).max(120)}).strict().optional()}).strict(),a.z.object({id:kn,instanceId:kn,projectId:kn.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:Cn}).strict();const or=(e,t,n={})=>new Promise((i,s)=>{if(n.signal?.aborted)return void s(Object.assign(new Error(`${e} was aborted.`),{code:"RUNTIME_COMMAND_ABORTED"}));const r=[];let o,a=!1,c=!1;try{o=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 s(e)}const d=n.timeoutMs?setTimeout(()=>{a=!0,o.kill("SIGKILL")},n.timeoutMs):void 0,l=()=>{c=!0;try{o.kill("SIGKILL")}catch{}};n.signal?.addEventListener("abort",l,{once:!0}),d?.unref?.(),o.onData(e=>{r.push(e),n.onData?.(e)}),o.onExit(({exitCode:t})=>{d&&clearTimeout(d),n.signal?.removeEventListener("abort",l);const o={stdout:r.join(""),stderr:""};a?s(Object.assign(new Error(`${e} timed out after ${n.timeoutMs}ms`),{statusCode:504,code:"RUNTIME_COMMAND_TIMEOUT",details:o})):c?s(Object.assign(new Error(`${e} was aborted.`),{code:"RUNTIME_COMMAND_ABORTED",details:o})):0!==t?s(Object.assign(new Error(o.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:o})):i(o)})});class ar{inFlight=new Map;runCommand;runTerminalCommand;constructor(e=rr,t){this.runCommand=e,this.runTerminalCommand=t||function(e){return e===rr?or:async(t,n,i={})=>{const s=await e(t,n,{timeoutMs:i.timeoutMs,signal:i.signal});return s.stdout&&i.onData?.(s.stdout),s.stderr&&i.onData?.(s.stderr),s}}(e)}ensure(e,t,n,i){const s=Fn(e),r=this.inFlight.get(s);if(r)return t&&(r.phaseListeners.add(t),r.phase&&t(r.phase)),n&&(r.terminalListeners.add(n),r.terminalTail&&n({sequence:r.terminalSequence,data:r.terminalTail,replay:!0})),this.bindAbort(r,i),r.promise;const o=new Set,a=new Set;t&&o.add(t),n&&a.add(n);const c={promise:Promise.resolve(void 0),controller:new AbortController,abortDisposers:new Set,phaseListeners:o,terminalListeners:a,terminalSequence:0,terminalTail:""};return this.bindAbort(c,i),c.promise=this.ensureOnce(s,e=>{c.phase=e,o.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(s);for(const e of c.abortDisposers)e();c.abortDisposers.clear()}),this.inFlight.set(s,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 s=await this.inspect(e,i).catch(e=>{if(i.aborted)throw e}),r=!1;s||(t("pulling-image"),await this.runTerminalCommand("docker",["pull",e],{cols:120,rows:40,signal:i,onData:n}),r=!0,s=await this.inspect(e,i)),t("resolving-image");const o=(a=s,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=o?.split("@").at(-1)?.toLowerCase();return{requestedReference:e,...c?{resolvedDigest:c}:{},resolvedReference:o||e,pulled:r}}async inspect(e,t){const n=await this.runCommand("docker",["image","inspect",e,"--format","{{json .}}"],{signal:t});return JSON.parse(n.stdout.trim()||"{}")}}function cr(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 dr="/run/task-handoff/bootstrap",lr=`${dr}/entrypoint.sh`,ur="/bin/bash",pr=`${dr}/runtime-installer.mjs`,mr="/opt/task-handoff/instance-runtime";function hr(e,t){return{role:"runtime",name:`${xr(e)}-runtime`,mountPath:mr,labels:{"task-handoff.owner":"task-handoff","task-handoff.instance-id":e,"task-handoff.node-id":t,"task-handoff.volume-role":"runtime"}}}function gr(e){return function(e,t,n){const i=xr(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:s,mountPath:r})=>({role:n,name:`${i}-${s}`,mountPath:r,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 fr=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 yr(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,s=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),r=-1===n?"":e.slice(n+1);fr.has(i)&&s.add(`Config.Env.${i}`),t.some(e=>e&&r.includes(e))&&s.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))(fr.has(e)||"string"==typeof n&&t.some(e=>e&&n.includes(e)))&&s.add(`Config.Labels.${e}`);if(s.size)throw Object.assign(new Error(`Docker configuration contains instance-private values in ${[...s].sort().join(", ")}.`),{statusCode:409,code:"ENVIRONMENT_TEMPLATE_SECRET_IN_DOCKER_CONFIG",findings:[...s].sort()})}class Ir{runCommand;publishHost;images;launcherAssetsDir;portResolutionRetryDelaysMs;constructor(e=rr,t={}){this.runCommand=e,this.images=t.imageService||new ar(e),this.publishHost=t.publishHost||"127.0.0.1",this.launcherAssetsDir=t.launcherAssetsDir||Er(),this.portResolutionRetryDelaysMs=t.portResolutionRetryDelaysMs?.length?t.portResolutionRetryDelaysMs:[0,100,250,500,1e3]}async start(e){Dr(e);const t=e.instance.runtime.containerName||xr(e.instance.id),i=await this.inspectContainerForStart(t);if(i){Cr(t,i.id,e.instance.runtime.containerId,"before start","RUNTIME_EXECUTOR_FAILED");const s=i.labels["task-handoff.instance-id"];if(s!==e.instance.id)throw Nr("RUNTIME_EXECUTOR_FAILED",`Docker container ${t} belongs to ${s||"an unknown instance"}, not ${e.instance.id}.`);const r=i.mounts.find(e=>"bind"===e.type&&e.destination===dr);if("1"!==i.labels["task-handoff.bootstrap-abi"]||i.entrypoint[0]!==ur||i.command[0]!==lr||!r?.source||n.resolve(r.source)!==n.resolve(this.launcherAssetsDir)){const n=new Set(gr(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 Nr("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 s;await this.createPersistentVolumes(e),"local-folder"!==e.project.source.type&&await this.provisionGitWorkspace(e);try{s=await this.runCommand("docker",Pr(e,t,{publishHost:this.publishHost,launcherAssetsDir:this.launcherAssetsDir}))}catch(e){throw Nr("RUNTIME_EXECUTOR_FAILED",`Could not create Docker container ${t}.`,e)}return e.completeGitWorkspaceProvisioning?.(),this.bootstrapResult(e,t,s.stdout||void 0)}async provisionGitWorkspace(e){const i=e.gitWorkspaceProvisioning;if(!i)throw Nr("GIT_WORKSPACE_PROVISIONING_MISSING",`Git workspace provisioning input is missing for ${e.instance.id}.`);const s=`${xr(e.instance.id)}-git-provision`,r=t.mkdtempSync(n.join(c.tmpdir(),"task-handoff-git-auth-"));t.chmodSync(r,448);try{await this.runCommand("docker",["rm","-f",s],{timeoutMs:3e4}).catch(()=>({stdout:"",stderr:""})),this.materializeGitProvisioningAuth(r,i);const t=function(e,t,i,s={}){const r=e.gitWorkspaceProvisioning;if(!r||"local-folder"===e.project.source.type)throw Object.assign(new Error("Git provisioning requires a Git source and operation input."),{code:"GIT_WORKSPACE_PROVISIONING_INVALID",statusCode:400});const o=n.resolve(s.launcherAssetsDir||Er()),a=gr(e).find(e=>"workspace"===e.role);if(!a)throw Object.assign(new Error("Git workspace volume was not found."),{code:"GIT_WORKSPACE_VOLUME_MISSING",statusCode:409});const c=["run","--rm","--name",t,"--label","task-handoff.role=git-provisioning","--label",`task-handoff.instance-id=${e.instance.id}`,"--user","0:0","--network","bridge","--security-opt","no-new-privileges","--cap-drop","ALL","--cap-add","CHOWN","--cap-add","SETUID","--cap-add","SETGID","--cap-add","DAC_OVERRIDE","--mount",`type=volume,src=${a.name},dst=/workspace`,"--mount",`type=bind,src=${o},dst=${dr},readonly`,"--tmpfs","/run/task-handoff/git-runtime:rw,nosuid,nodev,exec,mode=0700"];r.credentials.length&&c.push("--mount",`type=bind,src=${n.resolve(i)},dst=/run/task-handoff/git-auth,readonly`);const d=(e,t)=>c.push("-e",`${e}=${t}`);return d("TASK_HANDOFF_GIT_URL",r.remoteUrl),d("TASK_HANDOFF_INSTANCE_ID",e.instance.id),"commit"===r.ref.type?d("TASK_HANDOFF_GIT_COMMIT",r.ref.commit):d("TASK_HANDOFF_GIT_REF",r.ref.name),r.clone.depth&&d("TASK_HANDOFF_GIT_DEPTH",String(r.clone.depth)),d("TASK_HANDOFF_GIT_SUBMODULES",r.clone.submodules?"true":"false"),d("TASK_HANDOFF_GIT_LFS",r.clone.lfs?"true":"false"),r.clone.subdirectory&&d("TASK_HANDOFF_WORKSPACE_SUBDIRECTORY",r.clone.subdirectory),c.push("--entrypoint","/bin/bash",e.instance.environmentTemplateOrigin?.imageId||e.image.resolvedReference||e.image.requestedReference,`${dr}/git-provision.sh`),c}(e,s,r,{launcherAssetsDir:this.launcherAssetsDir});await this.runCommand("docker",t,{timeoutMs:9e5,signal:e.signal})}catch(t){throw function(e,t){const n=t&&"object"==typeof t?t:void 0,i="string"==typeof n?.code?n.code:"";if("RUNTIME_COMMAND_TIMEOUT"===i)return Nr("GIT_WORKSPACE_PROVISIONING_TIMEOUT",`Git workspace provisioning timed out for ${e}.`);if("RUNTIME_COMMAND_ABORTED"===i)return Nr("GIT_WORKSPACE_PROVISIONING_CANCELLED",`Git workspace provisioning was cancelled for ${e}.`);const s=_r(t)||"",r=s.match(/TASK_HANDOFF_GIT_PROVISIONING_ERROR=([A-Z_]+)/)?.[1];return Nr(`GIT_WORKSPACE_PROVISIONING_${r&&Tr.has(r)?r:"FAILED"}`,`Could not provision Git workspace for ${e}.`)}(e.instance.id,t)}finally{await this.runCommand("docker",["rm","-f",s],{timeoutMs:3e4}).catch(()=>({stdout:"",stderr:""})),t.rmSync(r,{recursive:!0,force:!0})}}materializeGitProvisioningAuth(e,i){const s=(e,i,s)=>{const r=n.join(e,i);t.writeFileSync(r,s,{encoding:"utf8",mode:384}),t.chmodSync(r,384)};i.credentials.forEach((i,r)=>{const o=n.join(e,`credential-${r}`);if(t.mkdirSync(o,{recursive:!0,mode:448}),t.chmodSync(o,448),s(o,"scope.json",JSON.stringify(i.payload.credential.scope)),"https-token"===i.payload.secret.kind)return s(o,"username",i.payload.secret.username),void s(o,"token",i.payload.secret.token);s(o,"private-key",i.payload.secret.privateKey),s(o,"known_hosts",i.payload.secret.pinnedKnownHosts),i.payload.secret.passphrase&&s(o,"passphrase",i.payload.secret.passphrase),s(o,"ssh-askpass.sh",`#!/usr/bin/env bash\ncat /run/task-handoff/git-runtime/credential-${r}/passphrase 2>/dev/null || true\n`)})}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:""})),Nr("RUNTIME_EXECUTOR_FAILED",`Could not preserve Docker container ${t} before bootstrap migration.`,e)}try{const s=await this.runCommand("docker",Pr(e,t,{publishHost:this.publishHost,launcherAssetsDir:this.launcherAssetsDir,imageReference:n.image}));return this.bootstrapResult(e,t,s.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:""})),Nr("RUNTIME_EXECUTOR_FAILED",`Could not recreate Docker container ${t} with the node-agent bootstrap.`,e)}}async inspectContainerConfigSecurity(e,t){yr(await this.runCommand("docker",["inspect","--format","{{json .}}",e]).then(e=>JSON.parse(e.stdout||"{}")).catch(t=>{throw Nr("ENVIRONMENT_TEMPLATE_CONTAINER_INSPECT_FAILED",`Could not inspect Docker container ${e}.`,t)}),t)}async inspectImageConfigSecurity(e,t){yr(await this.runCommand("docker",["image","inspect","--format","{{json .}}",e]).then(e=>JSON.parse(e.stdout||"{}")).catch(e=>{throw Nr("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 Nr("ENVIRONMENT_TEMPLATE_CONTAINER_NOT_FOUND",`Docker container ${e} does not exist.`);Cr(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 Nr("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:"",s=wr(n.Os),r=Sr(n.Architecture),o="number"==typeof n.Size?n.Size:Number.NaN;if(!/^sha256:[a-f0-9]{64}$/.test(i)||!s||!r||!Number.isSafeInteger(o)||o<0)throw new Error("Docker image inspection did not return a valid immutable identity.");return{imageId:i,platform:s,architecture:r,sizeBytes:o}}catch(e){throw Nr("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,zr(n)]),await this.runCommand("docker",["image","rm",e]),n}catch(e){const t=_r(e)?.toLowerCase()||"";if(t.includes("no such image")||t.includes("no such object"))return;throw Nr("ENVIRONMENT_TEMPLATE_UNTAG_FAILED","Could not remove the environment template tag.",e)}}async garbageCollectEnvironmentTemplateImage(e){try{try{await this.runCommand("docker",["image","rm",zr(e)])}catch(e){const t=_r(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=_r(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 Nr("ENVIRONMENT_TEMPLATE_GC_FAILED","Could not garbage collect the environment template image.",e)}}async createPersistentVolumes(e,t=new Set){const n=hr(e.instance.id,e.node?.id||"node_unset");for(const i of[...gr(e),n])await this.createVolume(i),await this.validateOwnedVolume(e.instance.id,i,t.has(i.name))}async createRuntimeVolume(e){await this.createVolume(hr(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 Nr("INSTANCE_VOLUME_CREATE_FAILED",`Could not create managed volume ${e.name}.`,t)}}async validatePersistentVolumes(e,t){for(const n of gr(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=hr(e.instance.id,e.node?.id||"node_unset");await this.validateOwnedVolume(e.instance.id,i);const s=t.find(e=>"volume"===e.type&&e.destination===i.mountPath);if(!s||s.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 Nr("INSTANCE_VOLUME_INSPECT_FAILED",`Could not inspect managed volume ${t.name}.`,e)}try{const s=JSON.parse(i.stdout||"{}"),r=s.Labels&&"object"==typeof s.Labels&&!Array.isArray(s.Labels)?s.Labels:{},o=s.Name===t.name&&"task-handoff"===r["task-handoff.owner"]&&r["task-handoff.instance-id"]===e&&r["task-handoff.volume-role"]===t.role,a=n&&s.Name===t.name&&0===Object.keys(r).length;if(!o&&!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),s=e.node?.id||"node_unset",r=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":s,"task-handoff.runtime-id":r,"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`}}async resolveInstanceWeb(e){const t=e.instance.runtime.containerName||xr(e.instance.id),n=await this.inspectContainerId(t);if(!n)throw Nr("INSTANCE_RUNTIME_ENDPOINT_UNAVAILABLE",`Docker container ${t} does not exist.`);return Cr(t,n,e.instance.runtime.containerId,"while resolving its web endpoint","INSTANCE_RUNTIME_ENDPOINT_UNAVAILABLE"),(await this.publishedEndpoint(t)).web}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||xr(e.instance.id);try{await this.runCommand("docker",["stop",t])}catch(e){if(!kr(e))throw Nr("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){Dr(e);const n=e.instance.runtime.containerName||xr(e.instance.id),i=await this.inspectContainerId(n);if(!i)throw Nr("INSTANCE_RUNTIME_RESTART_FAILED",`Docker container ${n} does not exist.`);Cr(n,i,t,"before restart","INSTANCE_RUNTIME_RESTART_FAILED"),await this.runCommand("docker",["restart",n]);const s=await this.inspectContainerId(n);if(!s||s!==i)throw Nr("INSTANCE_RUNTIME_RESTART_FAILED",`Docker container identity changed while restarting ${n}.`);return Cr(n,s,t,"after restart","INSTANCE_RUNTIME_RESTART_FAILED"),this.runningResult(e,n,s)}async delete(e,t){const n=e.instance.runtime.containerName||xr(e.instance.id),i=await this.inspectContainerForStart(n),s=new Set;if(i){Cr(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 Nr("RUNTIME_EXECUTOR_FAILED",`Docker container ${n} belongs to ${t||"an unknown instance"}, not ${e.instance.id}.`);for(const t of gr(e))i.mounts.some(e=>"volume"===e.type&&e.name===t.name&&e.destination===t.mountPath)&&s.add(t.name);try{await this.runCommand("docker",["rm","-f",i.id])}catch(e){if(!kr(e))throw Nr("RUNTIME_EXECUTOR_FAILED",`Could not delete Docker container ${n}.`,e)}}const r=[];for(const n of gr(e))if(t.deleteVolumes)try{const t=await this.inspectVolumeForDelete(n.name);if(!t){r.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,o=s.has(n.name)&&t.name===n.name&&0===Object.keys(t.labels).length;if(!i&&!o)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]),r.push({role:n.role,name:n.name,mountPath:n.mountPath,status:"deleted"})}catch(e){r.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 r.push({role:n.role,name:n.name,mountPath:n.mountPath,status:"retained"});return await this.deleteRuntimeVolume(e),ei.parse({instanceId:e.instance.id,containerDeleted:!0,completed:r.every(e=>"failed"!==e.status),deletedVolumes:r.filter(e=>"deleted"===e.status||"missing"===e.status),retainedVolumes:r.filter(e=>"retained"===e.status),volumeResults:r})}async deleteRuntimeVolume(e){const t=hr(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 Nr("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 Nr("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=_r(e)?.toLowerCase()||"";return t.includes("no such volume")||t.includes("no such object")}(t))return;throw Nr("INSTANCE_VOLUME_INSPECT_FAILED",`Could not inspect managed volume ${e}.`,t)}}async installRuntime(e){const t=await this.installRuntimeRelease(e);Cr(e.containerName,t,e.expectedContainerId,"before runtime restart","INSTANCE_RUNTIME_RESTART_FAILED");try{await this.runCommand("docker",["restart",t])}catch(t){throw Nr("INSTANCE_RUNTIME_RESTART_FAILED",`Could not restart Docker container ${e.containerName}.`,t)}const n=await this.inspectContainerId(e.containerName);if(!n||n!==t)throw Nr("INSTANCE_RUNTIME_RESTART_FAILED",`Docker container identity changed while updating ${e.containerName}.`);return Cr(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 Nr("INSTANCE_RUNTIME_INSTALL_FAILED",`Docker container ${e.containerName} does not exist.`);Cr(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",pr,"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 Nr("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 s=await this.inspectContainerId(e.containerName);if(!s||s!==t)throw Nr("INSTANCE_RUNTIME_INSTALL_FAILED",`Docker container identity changed while installing ${e.containerName}.`);return Cr(e.containerName,s,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",pr,"verify-active"]).catch(()=>{});if(!n?.stdout)return{containerId:t};try{const e=er(Ei,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 Nr("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 Nr("INSTANCE_BASE_RUNTIME_INCOMPATIBLE","Could not inspect the Docker runtime target.",e)});t||=e.OSType,n||=e.Architecture}const i=wr(t),s=Sr(n);if(!i||!s)throw Nr("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Docker reported an unsupported runtime target ${String(t||"unknown")}/${String(n||"unknown")}.`);return{platform:i,arch:s,launcherAbi:1}}async installRuntimeReleaseWithRecovery(e){const t=e.containerName,i=await this.inspectContainerForStart(t);if(!i)throw Nr("INSTANCE_RUNTIME_INSTALL_FAILED",`Docker container ${t} does not exist.`);if(Cr(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 Nr("INSTANCE_RUNTIME_INSTALL_FAILED",`Docker container ${t} does not expose its immutable image identity.`);const s="/run/task-handoff/runtime-rescue-artifact.tar.gz",r=[`test -r ${lr}`,`test -r ${dr}/instance-launcher.sh`,`test -r ${pr}`,`install -d -o root -g root -m 0755 ${mr} ${mr}/releases ${mr}/staging ${mr}/incoming`,`chown -R root:root ${mr}`,`chmod -R go-w ${mr}`,`node ${pr} 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=${s},readonly`,"--entrypoint",ur,i.image,"-ceu",r,"task-handoff-runtime-rescue",s,e.identity.version,e.identity.sha256,e.identity.platform,e.identity.arch,String(e.identity.launcherAbi)])}catch(n){throw Nr("INSTANCE_RUNTIME_INSTALL_FAILED",`Could not rescue controlled-instance ${e.identity.version} in stopped container ${t}.`,n)}const o=await this.inspectContainerForStart(t);if(!o)throw Nr("INSTANCE_RUNTIME_INSTALL_FAILED",`Docker container ${t} disappeared during runtime install recovery.`);if(Cr(t,o.id,i.id,"after runtime install recovery","INSTANCE_RUNTIME_INSTALL_FAILED"),o.running)throw Nr("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 Nr("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Docker container ${e} does not exist.`);Cr(e,n,t,"before runtime launcher install","INSTANCE_BASE_RUNTIME_INCOMPATIBLE");try{await this.runCommand("docker",["exec","--user","0",n,"bash","-ceu",`test -r ${lr}; test -r ${dr}/instance-launcher.sh; test -r ${pr}; 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 Nr("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Could not install the runtime launcher in ${e}.`,t)}const i=await this.inspectContainerId(e);if(i!==n)throw Nr("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Docker container identity changed while installing the runtime launcher in ${e}.`);Cr(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(kr(t))return;throw Nr("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(kr(t))return;throw Nr("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}]:[]}):[],s=Array.isArray(e.Config?.Entrypoint)?e.Config.Entrypoint.filter(e=>"string"==typeof e):"string"==typeof e.Config?.Entrypoint?[e.Config.Entrypoint]:[],r=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:s,command:r,labels:n,mounts:i}}catch(t){throw Nr("RUNTIME_EXECUTOR_FAILED",`Docker returned invalid inspection data for ${e}.`,t)}}async containerPort(e,t){let n,i=!1;for(const s of this.portResolutionRetryDelaysMs){s>0&&await vr(s);try{const n=Ar((await this.runCommand("docker",["port",e,t])).stdout);if(n)return n}catch(e){n=e}try{const n=br((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 Nr("RUNTIME_EXECUTOR_FAILED",`Docker container ${e} does not publish ${t}.`);throw Nr("RUNTIME_EXECUTOR_FAILED",`Could not resolve the published port for Docker container ${e}.`,n)}}function Ar(e){const t=e.split(/\r?\n/).find(Boolean);return t?.match(/:(\d+)$/)?.[1]}function br(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 vr(e){return new Promise(t=>setTimeout(t,e))}function wr(e){return"linux"===e||"darwin"===e?e:"windows"===e||"win32"===e?"win32":void 0}function Sr(e){return"amd64"===e||"x86_64"===e||"x64"===e?"x64":"arm64"===e||"aarch64"===e?"arm64":void 0}function Er(){const e=("undefined"==typeof document?require("url").pathToFileURL(__filename).href:w&&"SCRIPT"===w.tagName.toUpperCase()&&w.src||new URL("cli.js",document.baseURI).href)?n.dirname(s.fileURLToPath("undefined"==typeof document?require("url").pathToFileURL(__filename).href:w&&"SCRIPT"===w.tagName.toUpperCase()&&w.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 zr(e){return`task-handoff/environment-image:${e.replace(/^sha256:/,"")}`}function Nr(e,t,n){const i=_r(n),s=new Error(i?`${t} Cause: ${i}`:t,void 0===n?void 0:{cause:n});return Object.assign(s,{statusCode:502,code:e}),s}const Tr=new Set(["AUTHENTICATION_REJECTED","CLONE_FAILED","CREDENTIAL_AMBIGUOUS","CREDENTIAL_MISSING","HOST_KEY_REQUIRED","LFS_FAILED","REF_NOT_FOUND","REMOTE_UNSUPPORTED","SSH_AGENT_UNAVAILABLE","SUBDIRECTORY_NOT_FOUND","WORKSPACE_NOT_EMPTY","WORKSPACE_OWNERSHIP_MISMATCH"]);function _r(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 kr(e){const t=_r(e)?.toLowerCase()||"";return t.includes("no such container")||t.includes("no such object")}function Cr(e,t,n,i,s){if(n&&t!==n)throw Nr(s,`Docker container ${e} identity mismatch ${i}: expected ${n}, got ${t}.`)}async function Or(e=rr){return async function(e=rr){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>",s=t.ID||t.IDShort||"",r="<none>"!==n&&"<none>"!==i?`${n}:${i}`:s,o="<none>"!==n&&t.Digest&&"<none>"!==t.Digest?[`${n}@${t.Digest}`]:[];return{repository:n,tag:i,id:s,createdSince:t.CreatedSince,size:t.Size,sizeBytes:cr(t.Size),reference:r,repoDigests:o}}).filter(e=>Boolean(e.reference))}(e)}function xr(e){return`task-handoff-${e.replace(/[^a-zA-Z0-9_.-]/g,"-")}`}function Rr(e,t,n){e.push("-e",`${t}=${n}`)}function Pr(e,t,i={}){const s=i.publishHost||"127.0.0.1",r=n.resolve(i.launcherAssetsDir||Er()),o=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=${o}`,"--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,nosuid,nodev,exec,mode=1777","-p",`${s}::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=${r},dst=${dr},readonly`,"--entrypoint",ur);for(const t of gr(e))c.push("--mount",`type=volume,src=${t.name},dst=${t.mountPath}`);const d=hr(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:o,TASK_HANDOFF_RUNTIME_ID:a,TASK_HANDOFF_IMAGE_ID:e.image.id,TASK_HANDOFF_INSTANCE_LAUNCHER:`${dr}/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,..."local-folder"===e.project.source.type?{}:{TASK_HANDOFF_SKIP_WORKSPACE_BOOTSTRAP:"true"}};for(const[e,t]of Object.entries(l))Rr(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"}`):(Rr(c,"TASK_HANDOFF_PROJECT_SOURCE",JSON.stringify(e.project.source)),Rr(c,"TASK_HANDOFF_WORKSPACE_POLICY",JSON.stringify(e.project.workspacePolicy)),Rr(c,"TASK_HANDOFF_GIT_URL",e.project.source.url),"commit"===e.project.source.ref.type?Rr(c,"TASK_HANDOFF_GIT_COMMIT",e.project.source.ref.commit):Rr(c,"TASK_HANDOFF_GIT_REF",e.project.source.ref.name),e.project.source.clone?.depth&&Rr(c,"TASK_HANDOFF_GIT_DEPTH",String(e.project.source.clone.depth)),Rr(c,"TASK_HANDOFF_GIT_SUBMODULES",e.project.source.clone?.submodules?"true":"false"),Rr(c,"TASK_HANDOFF_GIT_LFS",e.project.source.clone?.lfs?"true":"false"),e.project.source.clone?.subdirectory&&Rr(c,"TASK_HANDOFF_WORKSPACE_SUBDIRECTORY",e.project.source.clone.subdirectory));for(const[t,n]of Object.entries(e.image.defaultEnv))Rr(c,t,n);return c.push(i.imageReference||e.instance.environmentTemplateOrigin?.imageId||e.image.resolvedReference||e.image.requestedReference,lr,"task-handoff","web"),c}function Dr(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}}const Mr="app.sessions";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 jr="app-session.snapshot",Lr="app-session.patch",Fr="app-session.removed",$r=a.z.enum(["created","starting","running","stopping","stopped","exited","failed","closed","terminated","unknown"]),Ur=a.z.enum(["tty","vnc","web"]);a.z.object({mode:Ur,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 Vr=new Set(["stopped","failed","exited","closed","terminated"]),Hr=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:$r.default("unknown"),bindings:a.z.array(Hr).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()})),qr=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(),Kr=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:qr}).strict();qr.pick({runningCount:!0,problemCount:!0,updatedAt:!0}).extend({revision:a.z.number().int().min(0).optional()});const Gr=a.z.enum(["app-session-created","app-session-updated","app-session-deleted","app-session-recovered","control-action","heartbeat-sync","startup"]),Wr=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:Gr}).strict(),Jr=a.z.object({meta:Wr,snapshot:qr}).strict(),Yr=a.z.object({meta:Wr,session:Br}).strict(),Xr=a.z.object({meta:Wr,sessionId:a.z.string().trim().min(1).max(160),tombstone:Br.optional(),expiresAt:a.z.string().datetime().optional()}).strict();function Qr(e,t=(new Date).toISOString()){const n=e.map(e=>function(e){const t=eo("string"==typeof e.status?e.status:void 0),n="string"==typeof e.id?e.id:"",i=function(e){const t=ro(e.workspace),n=ro(e.tty),i=ro(e.launch),s=ro(e.ai),r=ro(s.claude),o=oo(t.cwd)||oo(n.cwd)||oo(r.cwd)||oo(i.cwd);return o?{cwd:o}:void 0}(e),{workspace:s,...r}=e;return Br.parse({...r,status:t,bindings:so([...(o=e.bindings,Array.isArray(o)?o.flatMap(e=>{const t=Hr.safeParse(e);return t.success?[t.data]:[]}):[]),...n?[{type:"app-session",id:n}]:[],...io(e)]),...i?{workspace:i}:{}});var o}(e));return qr.parse({runningCount:n.filter(e=>"running"===e.status).length,problemCount:n.filter(e=>"failed"===e.status).length,sessions:n,updatedAt:t})}function Zr(e,t=(new Date).toISOString()){return Qr(e.filter(e=>to("string"==typeof e.status?e.status:void 0)),t)}function eo(e){const t=(e||"unknown").trim().toLowerCase();return"ended"===t?"closed":"terminating"===t?"stopping":$r.options.includes(t)?t:"unknown"}function to(e){return!Vr.has(eo(e))}function no(e){return"app-session"===e.type?`app:${e.id}`:"provider-session"===e.type?`provider:${e.agent||""}:${e.id}`:`adapter:${e.adapter||""}:${e.key||e.id}`}function io(e){const t=ro(e.ai),n=ro(t.claude),i=ro(t.appServer),s=ro(e.launch),r=[],o=oo(ro(s.aiSessionResume).providerSessionId),a="codex"===e.appId||"claude"===e.appId||"opencode"===e.appId?e.appId:void 0;a&&o&&r.push({type:"provider-session",agent:a,id:o});const c=oo(n.short);c&&r.push({type:"adapter-key",adapter:"claude",agent:"claude",id:`short:${c}`,key:`short:${c}`});const d=oo(n.providerSessionId);d&&r.push({type:"provider-session",agent:"claude",id:d});const l=Array.isArray(t.threadIds)?t.threadIds.filter(e=>"string"==typeof e&&Boolean(e.trim())):[],u=oo(t.activeThreadId);for(const e of[...new Set([u,...l].filter(Boolean))])r.push({type:"provider-session",agent:"codex",id:e});const p=oo(i.socketPath);return p&&r.push({type:"adapter-key",adapter:"codex-app-server",agent:"codex",id:`socket:${p}`,key:`socket:${p}`}),r}function so(e){const t=new Map;for(const n of e)t.set(no(n),n);return[...t.values()]}function ro(e){return e&&"object"==typeof e&&!Array.isArray(e)?e:{}}function oo(e){return"string"==typeof e&&e.trim()?e.trim():""}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(jr),payload:Jr}).strict(),a.z.object({type:a.z.literal(Lr),payload:Yr}).strict(),a.z.object({type:a.z.literal(Fr),payload:Xr}).strict()])).default([])}).strict();const ao="2026-08-25",co=a.z.object({nodeId:a.z.string().optional(),instanceId:a.z.string().optional()}).passthrough(),lo=a.z.object({v:a.z.literal(1),id:a.z.string().min(1),seq:a.z.number().finite(),type:a.z.string().min(1),topic:a.z.string().min(1),createdAt:a.z.string().datetime(),payload:a.z.unknown(),replay:a.z.literal(!0).optional(),scope:co.optional()}).passthrough(),uo=a.z.object({v:a.z.literal(ao),id:a.z.string().min(1),type:a.z.string().min(1),createdAt:a.z.string().datetime(),payload:a.z.unknown(),topic:a.z.string().min(1).optional(),replay:a.z.literal(!0).optional(),scope:co.optional()}).passthrough();function po(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.discriminatedUnion("v",[lo,uo]),a.z.object({v:a.z.literal(1),type:a.z.literal("ping"),sentAt:a.z.string().datetime()}).strict(),a.z.object({v:a.z.literal(1),type:a.z.literal("pong"),sentAt:a.z.string().datetime(),receivedAt:a.z.string().datetime()}).strict();const mo=a.z.object({replaySince:a.z.string().datetime().optional(),messageDeltas:a.z.object({allInstances:a.z.boolean().default(!1),instanceIds:a.z.array(a.z.string().trim().min(1).max(160)).max(1e3).default([])}).default({allInstances:!1,instanceIds:[]}),timelineAllSessions:a.z.boolean().default(!1),timelineSessions:a.z.array(a.z.object({instanceId:a.z.string().trim().min(1).max(160),sessionId:a.z.string().trim().min(1).max(120)})).max(1e3).default([])}),ho=a.z.enum(["ai.sessions","app.sessions"]),go=a.z.object({topic:ho,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(),fo=a.z.object({protocolVersion:a.z.literal(1),streams:a.z.array(go)}).strict();function yo(e,t=Math.random){const n=Math.max(1,Math.floor(e));if(1===n)return 0;if(2===n)return 250;const i=Math.min(6e4,250*2**(n-2));return Math.min(6e4,Math.round(i*(.75+.5*t())))}class Io{retryNumber=0;random;constructor(e=Math.random){this.random=e}get attempts(){return this.retryNumber}next(){return this.retryNumber+=1,{attempt:this.retryNumber,delay:yo(this.retryNumber,this.random)}}reset(){this.retryNumber=0}}class Ao{backoff;timer;constructor(e=Math.random){this.backoff=new Io(e)}get pending(){return Boolean(this.timer)}get attempts(){return this.backoff.attempts}schedule(e,t={}){if(this.timer)return;const n=this.backoff.next(),i=t.setTimeoutFn||setTimeout;return this.timer=i(()=>{this.timer=void 0,e()},n.delay),n}reset(e=clearTimeout){this.timer&&e(this.timer),this.timer=void 0,this.backoff.reset()}cancel(e=clearTimeout){this.timer&&e(this.timer),this.timer=void 0}}class bo extends Ao{}function vo(e,t=6e4){const n=[];for(let i=0;i<e.length;i+=t)n.push(e.slice(i,i+t));return n}const wo=262144,So=262144;class Eo{sockets=new Map;socketUrls=new Map;retries=new Map;outputs=new Set;outputSubscriptions=new Map;outputEnvelopeVersions=new Map;outputDiagnostics=new Map;aiSessionProjectionByInstance=new Map;appSessionProjectionByInstance=new Map;sessionStreamsHelloByInstance=new Map;sessionAuthorityReplayedOutputs=new Set;pendingAiSessionAuthorityByOutput=new Map;pendingAiSessionAuthorityFlush=new Map;eventTransportCongestion;imagePullTerminalByInstance=new Map;state;token;logger;safetyIntervalMs;lastAiSessionEventByInstance=new Map;lastAppSessionEventByInstance=new Map;timer;reconnectAttempts=0;safetyReconciliations=0;localSequence=0;outputSequence=0;createSocket;setIntervalFn;clearIntervalFn;setTimeoutFn;clearTimeoutFn;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 p(e,t)),this.setIntervalFn=n.setIntervalFn||setInterval,this.clearIntervalFn=n.clearIntervalFn||clearInterval,this.setTimeoutFn=n.setTimeoutFn||setTimeout,this.clearTimeoutFn=n.clearTimeoutFn||clearTimeout}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(),this.outputSubscriptions.clear(),this.outputEnvelopeVersions.clear(),this.outputDiagnostics.clear();for(const e of this.pendingAiSessionAuthorityFlush.values())this.clearTimeoutFn(e);this.pendingAiSessionAuthorityFlush.clear(),this.pendingAiSessionAuthorityByOutput.clear(),this.aiSessionProjectionByInstance.clear(),this.appSessionProjectionByInstance.clear(),this.sessionStreamsHelloByInstance.clear(),this.sessionAuthorityReplayedOutputs.clear()}addOutput(e,t={}){let n;this.outputs.add(e),this.outputDiagnostics.set(e,{outputId:"event_output_"+ ++this.outputSequence,kind:t.expectsTransientSubscription?"events-websocket":void 0!==t.legacyFallbackMs?"reverse-tunnel":"legacy"}),this.outputSubscriptions.set(e,t.expectsTransientSubscription?mo.parse({}):void 0),this.outputEnvelopeVersions.set(e,1),t.expectsTransientSubscription||void 0===t.legacyFallbackMs||(n=this.setTimeoutFn(()=>{n=void 0,this.outputs.has(e)&&void 0===this.outputSubscriptions.get(e)&&(this.replaySessionAuthority(e),this.syncNow())},t.legacyFallbackMs));let i=!1;const s=()=>{if(i)return;i=!0,this.outputs.delete(e),this.outputSubscriptions.delete(e),this.outputEnvelopeVersions.delete(e),this.outputDiagnostics.delete(e),this.sessionAuthorityReplayedOutputs.delete(e);const t=this.pendingAiSessionAuthorityFlush.get(e);t&&this.clearTimeoutFn(t),this.pendingAiSessionAuthorityFlush.delete(e),this.pendingAiSessionAuthorityByOutput.delete(e),this.refreshEventTransportRecovery(),n&&clearTimeout(n),this.syncNow()};e.on("close",s),e.on("error",s);for(const t of this.state.listInstances()){const n=zo(t);n?this.sendForwarded(e,this.createEvent(Bs,n,{instanceId:t.id})):this.logger?.warn?.({instanceId:t.id},"instance.lifecycle.snapshot.invalid")}for(const[t,n]of this.imagePullTerminalByInstance)vo(n.tail).forEach((i,s)=>this.sendForwarded(e,this.createEvent(ys,{...n.output,sequence:n.output.sequence+s,data:i,...0===s?{replay:!0}:{}},{instanceId:t}))),n.finished&&this.sendForwarded(e,this.createEvent(Is,n.finished,{instanceId:t}));return(t.expectsTransientSubscription||void 0===t.legacyFallbackMs)&&(this.replaySessionAuthority(e),this.syncNow()),s}setOutputSubscription(e,t,n){if(!this.outputs.has(e))return!1;const i=mo.safeParse(t);if(!i.success)return!1;this.outputSubscriptions.set(e,i.data),this.outputEnvelopeVersions.set(e,n===ao?ao:1),this.replaySessionAuthority(e),this.syncNow();for(const[e,t]of this.sockets)this.sendInstanceSubscription(e,t);return!0}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===ys){const e=er(bs,t);if(!e.success)return;const n=e.data,i=this.imagePullTerminalByInstance.get(n.instanceId);if(i&&n.generation<i.output.generation)return;const s=i?.output.generation===n.generation,r=n.replay||!s?n.data:`${i.tail}${n.data}`.slice(-262144);return void this.imagePullTerminalByInstance.set(n.instanceId,{output:n,tail:r})}if(e===Is){const e=er(vs,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(Bs,function(e){return qs.parse(No(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:po(e),createdAt:(new Date).toISOString(),payload:t,scope:n}}sendForwarded(e,t){const n=t.type===he?xt.safeParse(t.payload):void 0,i=this.outputEnvelopeVersions.get(e)===ao?function(e,t,n={}){const i=e.scope?n.publicScope&&e.scope.instanceId?{instanceId:e.scope.instanceId}:e.scope:void 0;return{v:ao,id:e.id,type:e.type,createdAt:e.createdAt,payload:void 0===n.payload?e.payload:n.payload,...e.topic!==po(e.type)?{topic:e.topic}:{},...e.replay?{replay:!0}:{},...i&&Object.keys(i).length?{scope:i}:{}}}(t,0,{...n?.success?{payload:(s=n.data,Rt.parse({sessionId:s.sessionId,turnId:s.turnId,itemId:s.itemId,delta:s.delta,generatedAt:s.generatedAt}))}:{}}):t;var s;const r=JSON.stringify({type:"node-agent.event.forwarded",event:i});this.sendOutput(e,r,t)}sendOutput(e,t,n){const i=Buffer.byteLength(t,"utf8"),s=n?.topic===Mr?"app-session":n?.topic===le?"ai-session":void 0,r=s?{...this.outputDiagnostics.get(e),instanceId:n.scope?.instanceId,eventType:n.type,...To(n.payload)}:void 0;if(e.readyState!==p.OPEN)return r&&this.logger?.warn?.({...r,readyState:e.readyState,outcome:"not-open"},`${s}.event.output.rejected`),!1;if(n&&this.shouldCoalesceAiSessionAuthority(e,n)&&this.deferAiSessionAuthority(e,n))return!0;if(n&&ko(n)&&i>So){if(n.type!==ue&&this.deferAiSessionAuthority(e,n))return!0;this.observeEventTransportCongestion(e,!1,i),r&&this.logger?.warn?.({...r,bufferedAmount:e.bufferedAmount,bytes:i,maxBytes:So,outcome:"payload-too-large"},`${s}.event.output.rejected`);try{e.close(1009,"AI Session authority event exceeds the transport limit.")}catch{}return!1}if(e.bufferedAmount+i>16777216){this.observeEventTransportCongestion(e,!1),r&&this.logger?.warn?.({...r,bufferedAmount:e.bufferedAmount,outcome:"backpressure"},`${s}.event.output.rejected`);try{e.close(1013,"Event consumer is too slow.")}catch{}return!1}try{return e.send(t),r&&this.logger?.info?.({...r,bufferedAmount:e.bufferedAmount,bytes:i,outcome:"queued"},`${s}.event.output.queued`),!0}catch(t){r&&this.logger?.warn?.({...r,error:t instanceof Error?t.message:String(t),outcome:"send-failed"},`${s}.event.output.rejected`);try{e.close(1011,"Event delivery failed.")}catch{}return!1}}shouldCoalesceAiSessionAuthority(e,t){if(!ko(t))return!1;const n=t.scope?.instanceId;return!!n&&(!!this.pendingAiSessionAuthorityByOutput.get(e)?.has(n)||e.bufferedAmount>=wo)}deferAiSessionAuthority(e,t){const n=t.scope?.instanceId,i=n?this.aiSessionProjectionByInstance.get(n):void 0;if(!n||!i)return!1;const s=function(e,t){const n=_o(e);return n?n.payload.meta.streamId!==t.streamId||n.payload.meta.revision!==t.revision?void 0:kt.parse({meta:n.payload.meta,snapshot:t.snapshot}):void 0}(t,i);if(!s)return!1;const r=this.pendingAiSessionAuthorityByOutput.get(e)||new Map;return r.set(n,{...t,type:ue,topic:le,payload:s}),this.pendingAiSessionAuthorityByOutput.set(e,r),this.observeEventTransportCongestion(e,!0),this.logger?.info?.({...this.outputDiagnostics.get(e),instanceId:n,eventType:t.type,...To(s),bufferedAmount:e.bufferedAmount,outcome:"coalesced-latest"},"ai-session.event.output.coalesced"),this.scheduleAiSessionAuthorityFlush(e),!0}scheduleAiSessionAuthorityFlush(e){if(this.pendingAiSessionAuthorityFlush.has(e))return;const t=this.setTimeoutFn(()=>{this.pendingAiSessionAuthorityFlush.delete(e),this.flushAiSessionAuthority(e)},25);t.unref?.(),this.pendingAiSessionAuthorityFlush.set(e,t)}flushAiSessionAuthority(e){const t=this.pendingAiSessionAuthorityByOutput.get(e);if(!t?.size)return void this.pendingAiSessionAuthorityByOutput.delete(e);if(e.readyState!==p.OPEN)return void this.pendingAiSessionAuthorityByOutput.delete(e);const[n,i]=t.entries().next().value;e.bufferedAmount>=wo?this.scheduleAiSessionAuthorityFlush(e):(t.delete(n),t.size||this.pendingAiSessionAuthorityByOutput.delete(e),this.sendForwarded(e,i),this.refreshEventTransportRecovery(),t.size&&this.scheduleAiSessionAuthorityFlush(e))}observeEventTransportCongestion(e,t,n=0){const i=(new Date).toISOString(),s=Math.max(0,Math.floor(e.bufferedAmount)),r=this.eventTransportCongestion;this.eventTransportCongestion={congestedSince:r?.recoveredAt?i:r?.congestedSince||i,lastCongestedAt:i,peakBufferedBytes:Math.max(r?.recoveredAt?0:r?.peakBufferedBytes||0,s),coalescedEvents:(r?.recoveredAt?0:r?.coalescedEvents||0)+(t?1:0),oversizedEvents:(r?.recoveredAt?0:r?.oversizedEvents||0)+(n>0?1:0),peakEventBytes:Math.max(r?.recoveredAt?0:r?.peakEventBytes||0,n)}}eventTransportIsCongested(){return!![...this.pendingAiSessionAuthorityByOutput.values()].some(e=>e.size>0)||[...this.outputs].some(e=>e.readyState===p.OPEN&&e.bufferedAmount>=wo)}refreshEventTransportRecovery(){const e=this.eventTransportCongestion;!e||e.recoveredAt||this.eventTransportIsCongested()||(e.recoveredAt=(new Date).toISOString())}eventTransportHealth(){this.refreshEventTransportRecovery();const e=[...this.outputs].filter(e=>e.readyState===p.OPEN),t=e.reduce((e,t)=>Math.max(e,Math.max(0,Math.floor(t.bufferedAmount))),0),n=this.eventTransportIsCongested();let i=this.eventTransportCongestion;return i?.recoveredAt&&Date.now()-Date.parse(i.recoveredAt)>3e5&&(this.eventTransportCongestion=void 0,i=void 0),{status:n?"congested":i?"recovering":"healthy",activeOutputs:e.length,bufferedBytes:t,peakBufferedBytes:i?.peakBufferedBytes||t,coalescedEvents:i?.coalescedEvents||0,oversizedEvents:i?.oversizedEvents||0,peakEventBytes:i?.peakEventBytes||0,...n&&i?{congestedSince:i.congestedSince}:{},...i?{lastCongestedAt:i.lastCongestedAt}:{}}}syncNow(){this.sync()}diagnostics(){const e=[...this.outputSubscriptions.values()];return{reconnectAttempts:this.reconnectAttempts,safetyReconciliations:this.safetyReconciliations,activeConnections:this.sockets.size,pendingRetries:[...this.retries.values()].filter(e=>e.timer.pending).length,safetyIntervalMs:this.safetyIntervalMs,eventTransport:this.eventTransportHealth(),transientDemand:{legacyOutputs:e.filter(e=>void 0===e).length,scopedOutputs:e.filter(e=>void 0!==e).length,messageDeltaAllInstances:e.some(e=>e?.messageDeltas.allInstances),messageDeltaInstanceCount:new Set(e.flatMap(e=>e?.messageDeltas.instanceIds||[])).size,timelineAllSessions:e.some(e=>e?.timelineAllSessions),timelineSessionCount:new Set(e.flatMap(e=>e?.timelineSessions.map(e=>JSON.stringify([e.instanceId,e.sessionId]))||[])).size}}}sync(){const e=new Set(this.state.listInstances().map(e=>e.id));for(const t of this.aiSessionProjectionByInstance.keys())e.has(t)||this.aiSessionProjectionByInstance.delete(t);for(const t of this.appSessionProjectionByInstance.keys())e.has(t)||this.appSessionProjectionByInstance.delete(t);for(const t of this.sessionStreamsHelloByInstance.keys())e.has(t)||this.sessionStreamsHelloByInstance.delete(t);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=Co(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);this.retries.set(e,{timer:n?.timer||new bo,url:t}),i.readyState===p.OPEN&&(this.sendInstanceSubscription(e,i),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=function(e,t={}){if(!e||"object"!=typeof e||Array.isArray(e))return;const n=e,i="string"==typeof n.type?n.type:"";if(!i)return;const s=n.scope&&"object"==typeof n.scope&&!Array.isArray(n.scope)?n.scope:{};return{v:1,id:"string"==typeof n.id?n.id:`event_${Date.now().toString(36)}`,seq:"number"==typeof n.seq&&Number.isFinite(n.seq)?n.seq:0,type:i,topic:"string"==typeof n.topic?n.topic:po(i),createdAt:"string"==typeof n.createdAt?n.createdAt:(new Date).toISOString(),payload:"payload"in n?n.payload:{},...!0===n.replay?{replay:!0}:{},scope:{...t,...s}}}(JSON.parse(String(e)),{instanceId:t});if(!n||"events.connected"===n.type)return;if(n.type===he){const e=function(e,t){const n=Rt.safeParse(e);return n.success?xt.parse({instanceId:t,...n.data}):xt.parse(e)}(n.payload,t);return{...n,payload:e,scope:{...n.scope,instanceId:t}}}return{...n,scope:{...n.scope,instanceId:t}}}catch{return}}(t,e);if(n){if("streams.hello"===n.type){const t=er(fo,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.");this.retries.get(e)?.timer.reset(),this.sessionStreamsHelloByInstance.set(e,t.data);const s=JSON.stringify({type:"node-agent.streams.hello",instanceId:e,payload:t.data});for(const e of this.outputs)this.sendOutput(e,s);return}this.recordAiSessionEvent(e,n),this.recordAppSessionEvent(e,n);for(const e of this.outputs)this.outputAccepts(e,n)&&this.sendForwarded(e,n)}}),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()})}sendInstanceSubscription(e,t){if(t.readyState!==p.OPEN)return;const n=[...this.outputs].map(e=>this.outputSubscriptions.get(e));if(n.some(e=>void 0===e))return void t.send(JSON.stringify({v:1,type:"subscribe",eventEnvelopeVersion:ao,topics:[le,"app.sessions","apps","instances"]}));const i=n.some(t=>t.messageDeltas.allInstances||t.messageDeltas.instanceIds.includes(e)),s=n.some(e=>e.timelineAllSessions),r=[...new Set(n.flatMap(t=>t.timelineSessions.filter(t=>t.instanceId===e).map(e=>e.sessionId)))],o=n.map(e=>e.replaySince).filter(e=>Boolean(e)).sort()[0];t.send(JSON.stringify({v:1,type:"subscribe",eventEnvelopeVersion:ao,topics:[ue,pe,me,...i?[he]:[],...s||r.length?[ge]:[],"app.sessions","apps","instances"],aiSessionTransient:{...o?{replaySince:o}:{},messageDeltas:{allInstances:i,instanceIds:[]},timelineAllSessions:s,timelineSessions:r.map(t=>({instanceId:e,sessionId:t}))}}))}outputAccepts(e,t){const n=this.outputSubscriptions.get(e);return!n||function(e,t){if(!e)return!0;if("ai-session.message-delta"!==t.type&&"ai-session.timeline-item"!==t.type)return!0;const n=t.payload&&"object"==typeof t.payload&&!Array.isArray(t.payload)?t.payload:{},i=String(n.instanceId||t.scope?.instanceId||"");return"ai-session.message-delta"===t.type?e.messageDeltas.allInstances||e.messageDeltas.instanceIds.includes(i):e.timelineAllSessions||e.timelineSessions.some(e=>e.instanceId===i&&e.sessionId===n.sessionId)}(n,t)}scheduleReconnect(e){const t=this.state.listInstances().find(t=>t.id===e),n=t&&Co(t);if(!n||!this.outputs.size)return;const i=this.retries.get(e)??{timer:new bo};if(i.timer.pending)return;i.url=n;const s=i.timer.schedule(()=>{this.sockets.has(e)||this.connect(e,n)},{setTimeoutFn:this.setTimeoutFn});s&&(this.reconnectAttempts+=1,this.logger?.info?.({instanceId:e,url:n,attempt:s.attempt,delay:s.delay,reconnectAttempts:this.reconnectAttempts},"session-stream.connection.reconnect-scheduled")),this.retries.set(e,i)}recordAiSessionEvent(e,t){if(t.topic!==le)return;if(t.type===he||t.type===ge)return;const n=_o(t);if(n){const t=function(e,t){const{meta:n}=t.payload;if(t.type===ue)return e?.streamId===n.streamId&&n.revision===e.revision?{kind:"duplicate",projection:e}:e?.streamId===n.streamId&&n.revision<e.revision?{kind:"stale",projection:e}:{kind:"applied",projection:Nt.parse({streamId:n.streamId,revision:n.revision,lastEventAt:n.generatedAt,snapshot:t.payload.snapshot})};if(!e||e.streamId!==n.streamId)return{kind:"snapshot-required",projection:e,streamId:n.streamId};if(n.revision===e.revision)return{kind:"duplicate",projection:e};if(n.revision<e.revision)return{kind:"stale",projection:e};if(n.revision!==e.revision+1||n.previousRevision!==e.revision)return{kind:"gap",projection:e,expectedRevision:e.revision+1,receivedRevision:n.revision};const i=new Map(e.snapshot.sessions.map(e=>[e.id,e]));if(t.type===pe){for(const e of t.payload.upserted)i.set(e.id,e);for(const e of t.payload.removed)i.delete(e)}else for(const e of t.payload.sessionIds)i.delete(e);const s=[...i.values()],r=zt.parse({runningCount:s.filter(e=>"running"===e.status).length,waitingCount:s.filter(e=>"waiting"===e.status).length,staleCount:e.snapshot.staleCount,sessions:s,updatedAt:n.generatedAt});return{kind:"applied",projection:Nt.parse({streamId:n.streamId,revision:n.revision,lastEventAt:n.generatedAt,snapshot:r})}}(this.aiSessionProjectionByInstance.get(e),n);"applied"!==t.kind&&"duplicate"!==t.kind&&"stale"!==t.kind||this.aiSessionProjectionByInstance.set(e,t.projection)}const i=To(t.payload),s=this.lastAiSessionEventByInstance.get(e);s?.streamId===i.streamId&&void 0!==s.revision&&void 0!==i.revision&&i.revision>s.revision+1&&this.logger?.warn?.({instanceId:e,traceId:i.traceId,streamId:i.streamId,previousRevision:s.revision,revision:i.revision},"ai-session.event.forward.gap"),this.lastAiSessionEventByInstance.set(e,{streamId:i.streamId??s?.streamId,revision:i.revision??s?.revision}),this.logger?.info?.({instanceId:e,traceId:i.traceId,eventType:t.type,streamId:i.streamId,revision:i.revision},"ai-session.event.forward.message")}recordAppSessionEvent(e,t){if(t.topic!==Mr)return;const n=function(e){const t=e.type===jr?Jr:e.type===Lr?Yr:e.type===Fr?Xr:void 0;if(!t)return;const n=er(t,e.payload);return n.success?{type:e.type,payload:n.data}:void 0}(t);if(n){const t=function(e,t){const{meta:n}=t.payload;if(t.type===jr)return e?.streamId===n.streamId&&n.revision===e.revision?{kind:"duplicate",projection:e}:e?.streamId===n.streamId&&n.revision<e.revision?{kind:"stale",projection:e}:{kind:"applied",projection:Kr.parse({streamId:n.streamId,revision:n.revision,lastEventAt:n.generatedAt,snapshot:Zr(t.payload.snapshot.sessions,t.payload.snapshot.updatedAt)})};if(!e||e.streamId!==n.streamId)return{kind:"snapshot-required",projection:e,streamId:n.streamId};if(n.revision===e.revision)return{kind:"duplicate",projection:e};if(n.revision<e.revision)return{kind:"stale",projection:e};if(n.revision!==e.revision+1||n.previousRevision!==e.revision)return{kind:"gap",projection:e,expectedRevision:e.revision+1,receivedRevision:n.revision};const i=[...e.snapshot.sessions];if(t.type===Lr){const e=i.findIndex(e=>e.id===t.payload.session.id);to(t.payload.session.status)?e<0?i.push(t.payload.session):i[e]=t.payload.session:e>=0&&i.splice(e,1)}else{const e=i.findIndex(e=>e.id===t.payload.sessionId);e>=0&&i.splice(e,1)}const s=Qr(i,n.generatedAt);return{kind:"applied",projection:Kr.parse({streamId:n.streamId,revision:n.revision,lastEventAt:n.generatedAt,snapshot:s})}}(this.appSessionProjectionByInstance.get(e),n);"applied"!==t.kind&&"duplicate"!==t.kind&&"stale"!==t.kind||this.appSessionProjectionByInstance.set(e,t.projection)}const i=To(t.payload),s=this.lastAppSessionEventByInstance.get(e);s?.streamId===i.streamId&&void 0!==s.revision&&void 0!==i.revision&&i.revision>s.revision+1&&this.logger?.warn?.({instanceId:e,traceId:i.traceId,streamId:i.streamId,previousRevision:s.revision,revision:i.revision},"app-session.event.forward.gap"),this.lastAppSessionEventByInstance.set(e,{streamId:i.streamId??s?.streamId,revision:i.revision??s?.revision}),this.logger?.info?.({instanceId:e,traceId:i.traceId,eventType:t.type,streamId:i.streamId,revision:i.revision},"app-session.event.forward.message")}replaySessionAuthority(e){if(!this.sessionAuthorityReplayedOutputs.has(e)&&e.readyState===p.OPEN){this.sessionAuthorityReplayedOutputs.add(e);for(const[t,n]of this.sessionStreamsHelloByInstance){const i=n.streams.map(e=>{const n=e.topic===le?this.aiSessionProjectionByInstance.get(t):this.appSessionProjectionByInstance.get(t);return n?n.streamId!==e.streamId?{...e,streamId:n.streamId,latestRevision:n.revision,earliestRetainedRevision:n.revision}:{...e,latestRevision:Math.max(e.latestRevision,n.revision)}:e});this.sendOutput(e,JSON.stringify({type:"node-agent.streams.hello",instanceId:t,payload:{...n,streams:i}}))}for(const[t,n]of this.aiSessionProjectionByInstance)this.sendForwarded(e,this.createEvent(ue,{meta:{streamId:n.streamId,instanceId:t,revision:n.revision,traceId:`ais_replay_${Date.now().toString(36)}`,generatedAt:n.lastEventAt,reason:"startup"},snapshot:n.snapshot},{instanceId:t}));for(const[t,n]of this.appSessionProjectionByInstance)this.sendForwarded(e,this.createEvent(jr,{meta:{streamId:n.streamId,instanceId:t,revision:n.revision,traceId:`aps_replay_${Date.now().toString(36)}`,generatedAt:n.lastEventAt,reason:"startup"},snapshot:n.snapshot},{instanceId:t}))}}}function zo(e){const t=qs.safeParse(No(e));return t.success?t.data:void 0}function No(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 To(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 _o(e){const t=e.type===ue?kt:e.type===pe?Ct:e.type===me?Ot:void 0;if(!t)return;const n=er(t,e.payload);return n.success?{type:e.type,payload:n.data}:void 0}function ko(e){return e.topic===le&&(e.type===ue||e.type===pe||e.type===me)}function Co(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.searchParams.set("aiSessionTransient","1"),e.searchParams.set("aiSessionAuthoritySnapshot","1"),e.protocol="https:"===e.protocol?"wss:":"ws:",e.toString()}catch{return}}const Oo=new Set(["provisioning","starting","registering","registered","running","unhealthy"]),xo=JSON.stringify({id:"{{.ID}}",name:"{{.Name}}",cpu:"{{.CPUPerc}}",memory:"{{.MemUsage}}",memoryPercent:"{{.MemPerc}}",network:"{{.NetIO}}",blockIo:"{{.BlockIO}}",pids:"{{.PIDs}}"});class Ro{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(!Oo.has(t.status))return Fo(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=Po(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,Po(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=>Oo.has(e.status)&&(e.runtime.containerId||e.runtime.containerName));for(const t of e.filter(e=>Oo.has(e.status)&&!e.runtime.containerId&&!e.runtime.containerName))this.update($o(t.id));for(const t of e.filter(e=>!Oo.has(e.status)))this.update(Fo(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",xo,...n],{timeoutMs:5e3});this.applyDockerOutput(t,e.stdout,i)}catch(e){if(1===t.length)return void this.update(Uo(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",xo,t],{timeoutMs:5e3});this.applyDockerOutput([e],n.stdout,i)}catch(t){this.update(Uo(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 s=Lo(e.id),r=Lo(e.name),o=s||r;if(!o)continue;const a=Do(Lo(e.memory)),c=Do(Lo(e.network)),d=Do(Lo(e.blockIo)),l=Ts.parse({instanceId:o,runtimeKind:"docker",state:"available",sampledAt:t,cpu:Mo(e.cpu,"usagePercent"),memory:a?{usageBytes:a[0],...void 0!==a[1]?{limitBytes:a[1]}:{},...Mo(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:jo(e.pids)});s&&n.set(s,l),r&&n.set(r,l)}return n}(t,n);for(const t of e){const e=[t.runtime.containerId,t.runtime.containerName].filter(Boolean),s=[...i.entries()].find(([t])=>e.some(e=>e===t||e.startsWith(t)||t.startsWith(e)))?.[1];this.update(s?{...s,instanceId:t.id}:Uo(t.id,n,"Container metrics were not returned by Docker."))}}update(e){const t=Ts.parse(e);this.snapshots.set(t.instanceId,t),this.publish?.(t)}}function Po(e){return[e.status,e.runtime.containerId||"",e.runtime.containerName||""].join("\0")}function Do(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(),s=i.includes("i"),r="b"===i[0]?"":i[0],o=r?"kmgtpe".indexOf(r)+1:0;return Math.round(n*(s?1024:1e3)**o)}(e||""));return void 0===t?void 0:[t,n]}function Mo(e,t){const n=Number(Lo(e).replace(/%$/,""));return Number.isFinite(n)&&n>=0?{[t]:n}:void 0}function jo(e){const t=Number(Lo(e));return Number.isFinite(t)&&t>=0?t:void 0}function Lo(e){return"string"==typeof e||"number"==typeof e?String(e).trim():""}function Fo(e){return{instanceId:e,runtimeKind:"docker",state:"stopped",sampledAt:(new Date).toISOString()}}function $o(e){return{instanceId:e,runtimeKind:"docker",state:"pending",sampledAt:(new Date).toISOString()}}function Uo(e,t,n){return{instanceId:e,runtimeKind:"docker",state:"unavailable",sampledAt:t,error:n.slice(0,2048)}}function Vo(e,t,n){return Object.assign(new Error(e),{statusCode:t,code:n})}function Ho(e){const i=n.resolve(e);let s;try{s=t.statSync(i)}catch(e){const t=e&&"object"==typeof e?e.code:void 0;if("ENOENT"===t||"ENOTDIR"===t)throw Vo(`Folder ${i} was not found.`,404,"NODE_FOLDER_PATH_NOT_FOUND");throw Vo(`Folder ${i} is not accessible.`,403,"NODE_FOLDER_PATH_UNREADABLE")}if(!s.isDirectory())throw Vo(`Path ${i} is not a folder.`,400,"NODE_FOLDER_PATH_NOT_DIRECTORY");try{t.accessSync(i,t.constants.R_OK|t.constants.X_OK)}catch{throw Vo(`Folder ${i} is not accessible.`,403,"NODE_FOLDER_PATH_UNREADABLE")}return i}function Bo(e){try{return t.statSync(e).isDirectory()}catch{return!1}}function qo(){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(Bo)}function Ko(){const e=n.resolve(c.homedir()),t=qo().map(e=>n.resolve(e));return[...Bo(e)?[{kind:"home",name:n.basename(e)||e,path:e}]:[],...t.map(e=>({kind:"root",name:e,path:e}))]}function Go(e,i){let s;try{s=t.statSync(e)}catch{return}if(!s.isDirectory())return;const r=n.resolve(e),o=n.basename(r)||r;let a=[];try{a=i>0?t.readdirSync(r,{withFileTypes:!0}):[]}catch{a=[]}const c=i>0?a.filter(e=>e.isDirectory()||e.isSymbolicLink()&&Bo(n.join(r,e.name))).sort((e,t)=>e.name.localeCompare(t.name)).slice(0,80).flatMap(e=>{const t=Go(n.join(r,e.name),i-1);return t?[t]:[]}):[];return{name:o,path:r,children:c}}function Wo(e){return(e.path?[Ho(e.path)]:qo()).flatMap(t=>{const n=Go(t,e.depth);return n?[n]:[]})}function Jo(){return process.env.TASK_HANDOFF_NODE_AGENT_DATA_DIR||n.join(c.homedir(),".config","task-handoff","node-agent")}function Yo(e=Jo()){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"),gitCredentialPayloadsDir:n.join(t,"git-credentials","payloads"),gitCredentialAssignmentsDir:n.join(t,"git-credentials","assignments"),gitCredentialAuthorizationSetsDir:n.join(t,"git-credentials","authorization-sets"),gitWorkspaceProvisioningIntentsDir:n.join(t,"git-credentials","workspace-provisioning-intents"),updatesDir:n.join(t,"updates"),logsDir:n.join(t,"logs")}}function Xo(e,t){const i=n.extname(e);return`${i?e.slice(0,-i.length):e}.${t}${i}`}function Qo(e,n=10485760,i=2){if(!t.existsSync(e))return!1;const s=t.lstatSync(e);if(!s.isFile()||s.isSymbolicLink()||s.size<=n)return!1;if(i>0){!function(e,n){if(!(n<=0)){t.rmSync(Xo(e,n),{force:!0});for(let i=n-1;i>=1;i-=1){const n=Xo(e,i);t.existsSync(n)&&t.renameSync(n,Xo(e,i+1))}}}(e,i);const s=function(e,n){const i=t.statSync(e),s=Math.min(i.size,n),r=Buffer.allocUnsafe(s),o=t.openSync(e,"r");let a=0;try{for(;a<s;){const e=t.readSync(o,r,a,s-a,i.size-s+a);if(0===e)break;a+=e}}finally{t.closeSync(o)}return a===s?r:r.subarray(0,a)}(e,n);t.writeFileSync(Xo(e,1),s,{mode:384})}return t.truncateSync(e,0),t.chmodSync(e,384),!0}class Zo{logsDir;localInstancesRoot;localInstancesTrashRoot;options;constructor(e,t={}){this.options=t,this.logsDir=e.logsDir,this.localInstancesRoot=n.join(e.dataDir,"local-instances"),this.localInstancesTrashRoot=n.join(e.dataDir,"local-instances-trash")}run(e){this.capNodeAgentLogs();const n=new Set(e);if(t.existsSync(this.localInstancesRoot)){se(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??ne,s=[];for(const r of t.readdirSync(e.trashRoot,{withFileTypes:!0})){const o=ie(e.trashRoot,r.name);try{const e=Number(r.name.split("-",1)[0]);if(!Number.isFinite(e)||e+i>n)continue;const a=t.lstatSync(o);a.isSymbolicLink()?t.unlinkSync(o):a.isDirectory()?t.rmSync(o,{recursive:!0,force:!0}):t.unlinkSync(o),s.push(o)}catch(t){e.logger?.("retired persistence entry cleanup failed",{path:o,error:t instanceof Error?t.message:String(t)})}}return s}({trashRoot:this.localInstancesTrashRoot,retentionMs:this.options.retentionMs??ne,nowMs:this.now(),logger:this.options.logger})}capActiveInstanceLogs(e){for(const t of e)this.capControlledInstanceLogs(t)}capNodeAgentLogs(){const e=[];for(const t of["node-agent.out.log","node-agent.err.log"]){const i=n.join(this.logsDir,t);try{Qo(i)&&e.push(i)}catch(e){this.options.logger?.("node-agent log rotation failed",{filePath:i,error:e instanceof Error?e.message:String(e)})}}return e}capControlledInstanceLogs(e){const t=n.resolve(this.localInstancesRoot,e);if(n.dirname(t)!==n.resolve(this.localInstancesRoot))return[];const i=n.join(t,"logs"),s=[];for(const t of["controlled-instance.out.log","controlled-instance.err.log"]){const r=n.join(i,t);try{Qo(r)&&s.push(r)}catch(t){this.options.logger?.("controlled instance log rotation failed",{instanceId:e,filePath:r,error:t instanceof Error?t.message:String(t)})}}return s}retire(e){try{return function(e){const n=ie(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}`);se(e.trashRoot);const s=e.nowMs??Date.now();let r=0,o=`${s}-${e.entryName}`;for(;t.existsSync(ie(e.trashRoot,o));)r+=1,o=`${s}-${r}-${e.entryName}`;const a=ie(e.trashRoot,o);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 ea(e,t=process.platform){const i=n.resolve(e),s=d.createHash("sha256").update(i).digest("hex").slice(0,16);return"win32"===t?`\\\\.\\pipe\\task-handoff-node-agent-${s}`:n.join("/tmp",`task-handoff-node-agent-${process.getuid?.()??"user"}`,`${s}.sock`)}async function ta(e,t,n={}){const s=n.method||"GET",r="string"==typeof n.body||n.body instanceof Buffer?n.body:void 0===n.body||null===n.body?void 0:String(n.body),o=new Headers(n.headers||{});return void 0===r||o.has("content-length")||o.set("content-length",String(Buffer.byteLength(r))),new Promise((a,c)=>{const d=i.request({socketPath:e,method:s,path:`/api/node-agent${t}`,headers:Object.fromEntries(o.entries())},e=>{const t=e.statusCode||500;a(new Response("HEAD"!==s&&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!==r&&d.write(r),d.end()})}const na="runtime-manifest.json";class ia 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 sa(e,t=""){const i=[],s=await g.readdir(n.join(e,t),{withFileTypes:!0});for(const r of s){const s=t?n.posix.join(t,r.name):r.name;if(!t&&s===na)continue;const o=n.join(e,...s.split("/"));if(r.isDirectory()){i.push(...await sa(e,s));continue}if(r.isSymbolicLink()){const t=await g.readlink(o);if(n.isAbsolute(t))throw new ia("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload symlink is absolute: ${s}`);const r=n.resolve(n.dirname(o),t),a=n.relative(n.resolve(e),r);if(!a||".."===a||a.startsWith(`..${n.sep}`)||n.isAbsolute(a))throw new ia("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload symlink escapes the artifact: ${s}`);if(!await g.lstat(r).catch(()=>{}))throw new ia("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload symlink is broken: ${s}`);i.push({absolutePath:o,relativePath:s,kind:"symlink",target:t,size:Buffer.byteLength(t)});continue}if(!r.isFile())throw new ia("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload contains unsupported entry: ${s}`);const a=await g.lstat(o);i.push({absolutePath:o,relativePath:s,kind:"file",size:a.size})}return i}async function ra(e){const n=(await sa(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 oa(e){for(const[t,n]of[["version",e.version],["platform",e.platform],["arch",e.arch]])if(!/^[0-9A-Za-z._-]+$/.test(n))throw new ia("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Invalid runtime artifact ${t}: ${n}`);return`${e.version}-${e.platform}-${e.arch}`}function aa(e,t){return`${oa(e)}-${e.sha256}-${t}`}async function ca(e){const n=d.createHash("sha256");for await(const i of t.createReadStream(e))n.update(i);return n.digest("hex")}class da{#e;#t;#n=new Map;constructor(e){this.#e=e.cacheDir,this.#t=e.fetchImpl??fetch}resolve(e,t){const n=Ei.parse(e);if(!/^[a-f0-9]{64}$/.test(t.archiveSha256))throw new ia("INSTANCE_RUNTIME_ARTIFACT_INVALID","Runtime archive SHA-256 is invalid.");if((t.archiveUrl?1:0)+(t.archivePath?1:0)!=1)throw new ia("INSTANCE_RUNTIME_ARTIFACT_INVALID","Runtime artifact source must specify exactly one archive location.");const i=aa(n,t.archiveSha256),s=this.#n.get(i);if(s)return s;const r=this.#i(n,t).finally(()=>this.#n.delete(i));return this.#n.set(i,r),r}async#i(e,i){if(!/^[a-f0-9]{64}$/.test(i.archiveSha256))throw new ia("INSTANCE_RUNTIME_ARTIFACT_INVALID","Runtime archive SHA-256 is invalid.");const s=aa(e,i.archiveSha256),r=n.join(this.#e,"archives"),o=n.join(r,`${s}.tar.gz`);if(await g.mkdir(r,{recursive:!0}),await this.#s(o,e,i.archiveSha256))return{identity:e,archivePath:o,cacheHit:!0};await g.rm(o,{force:!0});const a=n.join(r,`.${s}.${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 ia("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 ca(a)!==i.archiveSha256)throw new ia("INSTANCE_RUNTIME_ARTIFACT_INVALID","Downloaded runtime archive SHA-256 does not match release metadata.");return await this.#r(a,e),await g.rename(a,o),{identity:e,archivePath:o,cacheHit:!1}}catch(e){if(e instanceof ia)throw e;throw new ia("INSTANCE_RUNTIME_ARTIFACT_UNAVAILABLE","Could not download runtime artifact.",{cause:e,retryable:!0})}finally{await g.rm(a,{force:!0})}}async#s(e,t,n){try{return await ca(e)===n&&(await this.#r(e,t),!0)}catch{return!1}}async#r(e,t){const i=n.join(this.#e,"validation",`${oa(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 ia("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime archive entry escapes the artifact root: ${e}`);const s=t.type;if("File"!==s&&"OldFile"!==s&&"Directory"!==s&&"SymbolicLink"!==s)throw new ia("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime archive contains unsupported entry type ${s??"unknown"}: ${e}`);return!0}})}catch(e){throw new ia("INSTANCE_RUNTIME_ARTIFACT_INVALID","Could not extract runtime artifact safely.",{cause:e})}}(e,i),await async function(e,t,i){const s=await async function(e){let t;try{t=JSON.parse(await g.readFile(n.join(e,na),"utf8"))}catch(e){throw new ia("INSTANCE_RUNTIME_ARTIFACT_INVALID","Runtime artifact manifest is missing or invalid JSON.",{cause:e})}const i=er(Ei,t);if(!i.success)throw new ia("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 ia("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime artifact ${"sha256"===n?"SHA-256":n} mismatch: expected ${t[n]}, got ${e[n]}.`)}(s,t),1!==s.formatVersion)throw new ia("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Unsupported runtime artifact format ${s.formatVersion}.`);if(i?.platform&&"universal"!==s.platform&&s.platform!==i.platform)throw new ia("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime artifact platform ${s.platform} does not match ${i.platform}.`);if(i?.arch&&"universal"!==s.arch&&s.arch!==i.arch)throw new ia("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime artifact architecture ${s.arch} does not match ${i.arch}.`);if(void 0!==i?.launcherAbi&&s.launcherAbi>i.launcherAbi)throw new ia("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Runtime requires launcher ABI ${s.launcherAbi}, but the base runtime provides ${i.launcherAbi}.`);const r=function(e,t){if(!e||e.includes("\\")||n.posix.isAbsolute(e))throw new ia("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 ia("INSTANCE_RUNTIME_ARTIFACT_INVALID",`${t} escapes the runtime root.`);return i}(s.entrypoint,"Runtime entrypoint"),o=await g.lstat(n.join(e,...r.split("/"))).catch(()=>{});if(!o?.isFile())throw new ia("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime entrypoint is missing: ${r}`);const a=await ra(e);if(a!==s.sha256)throw new ia("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload SHA-256 mismatch: expected ${s.sha256}, got ${a}.`);return s}(i,t,{platform:t.platform,arch:t.arch})}finally{await g.rm(i,{recursive:!0,force:!0})}}}async function la(e,t,i,s=fetch){if("linux"!==t||!["x64","arm64"].includes(i))throw new ia("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Managed controlled-instance updates require a Linux x64 or arm64 target, received ${t}/${i}.`);const r=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[s,r]=await Promise.all([g.readFile(n.join(i,`${t}.manifest.json`),"utf8"),g.readFile(n.join(i,`${t}.tar.gz.sha256`),"utf8")]),o=er(Ei,JSON.parse(s));if(!o.success||o.data.version!==e||"linux"!==o.data.platform||"universal"!==o.data.arch)throw new ia("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Bundled controlled-instance ${e} has an invalid Linux manifest.`);const a=r.trim().split(/\s+/)[0]?.toLowerCase();if(!a||!/^[a-f0-9]{64}$/.test(a))throw new ia("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Bundled controlled-instance ${e} has an invalid archive checksum.`);return{identity:o.data,source:{archivePath:n.join(i,`${t}.tar.gz`),archiveSha256:a}}}catch(t){if("ENOENT"===t.code)return;if(t instanceof ia)throw t;throw new ia("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Could not read bundled controlled-instance ${e}.`,{cause:t})}}(e);if(r)return r;const o=`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}/${o}.manifest.json`,d=`${a}/${o}.tar.gz`,l=`${a}/${o}.tar.gz.sha256`,[u,p]=await Promise.all([s(c),s(l)]).catch(t=>{throw new ia("INSTANCE_RUNTIME_ARTIFACT_UNAVAILABLE",`Could not read release metadata for controlled-instance ${e}.`,{cause:t,retryable:!0})});if(!u.ok||!p.ok)throw new ia("INSTANCE_RUNTIME_ARTIFACT_UNAVAILABLE",`Release metadata for controlled-instance ${e} is unavailable (manifest HTTP ${u.status}, checksum HTTP ${p.status}).`,{retryable:u.status>=500||p.status>=500});let m;try{m=await u.json()}catch(t){throw new ia("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Release manifest for controlled-instance ${e} is not valid JSON.`,{cause:t})}const h=er(Ei,m);if(!h.success)throw new ia("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 ia("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Release identity mismatch: requested ${e}-linux-universal, received ${h.data.version}-${h.data.platform}-${h.data.arch}.`);const f=(await p.text()).trim().split(/\s+/)[0]?.toLowerCase();if(!f||!/^[a-f0-9]{64}$/.test(f))throw new ia("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Release checksum for controlled-instance ${e} is invalid.`);return{identity:h.data,source:{archiveUrl:d,archiveSha256:f}}}class ua{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=ba(i.retryBaseDelayMs??1e3,"retryBaseDelayMs"),this.retryMaxDelayMs=ba(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 s=Promise.resolve().then(()=>this.reconcile(e,n)).finally(()=>{this.inFlight.delete(e),this.requests.delete(e)});return this.inFlight.set(e,s),s}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");if(ha(n))return this.storePhase(n,"pending");const s=n.runtimeVersion?.desiredVersion!==i||t.startRequested||ga(n)?0:this.remainingRetryDelayMs(n.runtimeVersion);if(s>0&&(await this.delay(s),n=this.requireInstance(e),this.cancelled.has(e)))return this.storePhase(n,"pending");const r=pa(n),o=r===i&&(await(this.hooks.isInstalled?.(n,i))??!0);if(this.cancelled.has(e))return this.storePhase(this.requireInstance(e),"pending");if(r===i&&o)return this.storeState(n,{desiredVersion:i,actualVersion:r,phase:"matched",attempt:n.runtimeVersion?.attempt||0,matchedAt:this.timestamp()},!ga(n)&&"failed"!==n.health);if(n=this.storeState(n,function(e,t,n,i=!1){const s=e.runtimeVersion,r=s?.desiredVersion===t&&"matched"!==s.phase;return{desiredVersion:t,...n?{actualVersion:n}:{},phase:"pending",attempt:r?s.attempt:0,error:(r?s.error:void 0)||(n!==t||i?fa(t,n):ya("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,r,o)),ga(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 s;try{if(n=this.storePhase(n,"draining"),await(this.hooks.beginDrain?.(n)),a=!0,n=this.requireInstance(e),ma(n)){const t=await this.waitUntil(e,this.drainTimeoutMs,e=>!ma(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)||ga(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 s=await this.waitUntil(e,this.verificationTimeoutMs,e=>pa(e)===i);if(this.cancelled.has(e))return this.storePhase(this.requireInstance(e),"pending");if(!s)throw ya("INSTANCE_RUNTIME_VERIFICATION_FAILED",`Instance ${e} did not register controlled-instance ${i} after restart.`,i,pa(this.requireInstance(e)),!0);const r=this.requireInstance(e);if(this.hooks.isInstalled&&!await this.hooks.isInstalled(r,i))throw ya("INSTANCE_RUNTIME_VERIFICATION_FAILED",`Instance ${e} reported controlled-instance ${i}, but its active runtime release is missing.`,i,pa(r),!0);return this.storeState(r,{desiredVersion:i,actualVersion:i,phase:"matched",attempt:r.runtimeVersion?.attempt||1,matchedAt:this.timestamp()},!ga(r)&&"failed"!==r.health)}catch(t){if(this.cancelled.has(e))return this.storePhase(this.requireInstance(e),"pending");s=Ia(t,i,pa(this.store.get(e)))}n=this.requireInstance(e);const r=n.runtimeVersion?.attempt||1;if(!s.retryable||c>=this.maxAttempts)return this.storeBatchFailure(n,i,r>=this.maxAttempts&&s.retryable?Aa(i,pa(n),this.maxAttempts,s):s);n=this.storeState(n,{desiredVersion:i,...pa(n)?{actualVersion:pa(n)}:{},phase:"pending",attempt:r,lastAttemptAt:this.timestamp(),error:s}),await this.delay(this.retryDelayMs(r))}return this.storeBatchFailure(n,i,Aa(i,pa(n),this.maxAttempts,n.runtimeVersion?.error))}finally{a&&await(this.hooks.endDrain?.(this.requireInstance(e)))}}storeBatchFailure(e,t,n){const i=pa(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(),s=pa(e),r=e.runtimeVersion?.desiredVersion===i?e.runtimeVersion.error:void 0;return this.storeState(e,{desiredVersion:i,...s?{actualVersion:s}:{},phase:t,attempt:(e.runtimeVersion?.attempt||0)+(n?1:0),lastAttemptAt:this.timestamp(),...r?{error:r}:"pending"===t?{error:fa(i,s)}:{}},"restarting"!==t&&void 0)}storeState(e,t,n){const i=this.store.get(e.id)||e;return this.store.put(Vs.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 pa(e){return e?.build?.packageVersion||e?.instanceVersion}function ma(e){return e.apps.runningCount>0||e.aiSessions.runningCount>0}function ha(e){return Boolean(e.imageProvisioning&&"ready"!==e.imageProvisioning.phase)}function ga(e){return["created","stopped","failed"].includes(e.status)}function fa(e,t){return ya("INSTANCE_RUNTIME_VERSION_MISMATCH",`Expected controlled-instance ${e}, received ${t||"an unknown version"}.`,e,t,!0)}function ya(e,t,n,i,s){return{code:e,message:t,expectedVersion:n,...i?{actualVersion:i}:{},retryable:s}}function Ia(e,t,n){if(e&&"object"==typeof e&&"code"in e&&"message"in e){const i=e,s=zi.shape.code.safeParse(i.code);if(s.success&&"string"==typeof i.message)return ya(s.data,i.message,t,n,"boolean"!=typeof i.retryable||i.retryable)}return ya("INSTANCE_RUNTIME_INSTALL_FAILED",e instanceof Error?e.message:String(e),t,n,!0)}function Aa(e,t,n,i){const s=i?.message?` Last error: ${i.message}`:"";return ya(i?.code||"INSTANCE_RUNTIME_INSTALL_FAILED",`Runtime convergence paused after ${n} attempts and will retry.${s}`,e,t,!0)}function ba(e,t){if(!Number.isFinite(e)||e<0)throw new TypeError(`${t} must be a nonnegative finite number.`);return e}function va(e,n=448){t.mkdirSync(e,{recursive:!0,mode:n}),t.chmodSync(e,n)}function wa(e,i,s={}){const r=s.directoryMode??448,o=s.fileMode??384;va(n.dirname(e),r),I.sync(e,`${JSON.stringify(i,null,2)}\n`,{encoding:"utf8",mode:o}),t.chmodSync(e,o)}function Sa(e,t){console.warn(JSON.stringify({message:e,...t}))}function Ea(e){return e&&"object"==typeof e&&"issues"in e?{issues:e.issues}:{error:e instanceof Error?e.message:String(e)}}function za(e,n){const i=n.logger||Sa;let s;try{s=JSON.parse(t.readFileSync(e,"utf8"))}catch(t){return void i("stored JSON could not be read",{filePath:e,...Ea(t)})}if(!n.schema)return s;const r=n.sanitize?n.sanitize(s):s,o=n.schema.safeParse(r);if(o.success)return o.data;const a="strip"in n.schema&&"function"==typeof n.schema.strip?n.schema.strip().safeParse(r):void 0;if(a?.success)return i("unknown stored fields were ignored",{filePath:e,issues:o.error.issues}),a.data;i("stored record failed validation and was isolated",{filePath:e,issues:o.error.issues})}function Na(e){return`${e}_${d.randomUUID().replace(/-/g,"").slice(0,20)}`}function Ta(){return d.randomBytes(24).toString("base64url")}class _a{directory;options;permissionsInitialized=!1;constructor(e,t={}){this.directory=e,this.options=t}init(){if(this.permissionsInitialized&&t.existsSync(this.directory))return;va(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=za(n.join(this.directory,e),this.options);return t?[t]:[]})}get(e){this.init();const n=this.filePath(e);return t.existsSync(n)?za(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 wa(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 ka{filePathValue;defaults;options;constructor(e,t,n={}){this.filePathValue=e,this.defaults=t,this.options=n}init(){va(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)?za(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 wa(this.filePathValue,n,this.options),n}}const Ca=a.z.record(a.z.string(),a.z.string()),Oa=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 xa{directory;constructor(e){this.directory=e}get(e){try{return Ca.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=Ca.parse(n);t.mkdirSync(this.directory,{recursive:!0,mode:448});const s=this.filePath(e);return I.sync(s,`${JSON.stringify(i,null,2)}\n`,{encoding:"utf8",mode:384}),t.chmodSync(s,384),i}delete(e){t.rmSync(this.filePath(e),{force:!0})}filePath(e){return n.join(this.directory,`${e}.json`)}}class Ra{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=Ki.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")),s=n.basename(e,".json"),r=Ki.safeParse(i);if(r.success&&r.data.id===s&&is(r.data)===r.data.id)return r.data;const o=Ki.strip().safeParse(i);return o.success&&o.data.id===s&&is(o.data)===o.data.id?(console.warn(JSON.stringify({message:"unknown stored node model fields were ignored",nodeId:this.nodeId,filePath:e})),o.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 Pa{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")),s=Ji.safeParse(i);if(s.success)return s.data;const r=i&&"object"==typeof i&&!Array.isArray(i)?i:{},o=Ji.safeParse({instanceId:r.instanceId,modelEntityIds:r.modelEntityIds,codexModelHash:r.codexModelHash,claudeModelHash:r.claudeModelHash,opencodeModelHash:r.opencodeModelHash,updatedAt:r.updatedAt});if(o.success)return console.warn(JSON.stringify({message:"unknown stored model assignment fields were ignored",instanceId:e,filePath:n})),o.data;throw s.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=Ji.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`)}}const Da=a.z.enum(["openai-responses","openai-chat-completions","anthropic-messages"]),Ma=a.z.object({protocolVersion:a.z.literal("2026-08-27"),instanceId:a.z.string().trim().min(1).max(120),entities:a.z.array(a.z.object({id:a.z.string().trim().min(1).max(120),endpoint:a.z.string().trim().min(1).max(2048),key:a.z.string().trim().min(1).max(4096),protocols:a.z.array(Da).min(1).max(3),modelNames:a.z.array(a.z.object({name:a.z.string().trim().min(1).max(240),order:a.z.number().int().min(0).max(1e6)}).strip()).min(1).max(256)}).strip()).max(64),updatedAt:a.z.string().datetime()}).strip();function ja(e){if(!e||"object"!=typeof e||Array.isArray(e))return e;const t=e;return{protocolVersion:t.protocolVersion,instanceId:t.instanceId,entities:Array.isArray(t.entities)?t.entities.map(e=>{if(!e||"object"!=typeof e||Array.isArray(e))return e;const t=e;return{id:t.id,endpoint:t.endpoint,key:t.key,protocols:t.protocols,modelNames:Array.isArray(t.modelNames)?t.modelNames.map(e=>{if(!e||"object"!=typeof e||Array.isArray(e))return e;const t=e;return{name:t.name,order:t.order}}):t.modelNames}}):t.entities,updatedAt:t.updatedAt}}class La{models;assignments;legacyEnvironments;nodeId;instances;constructor(e,t,n){this.nodeId=t,this.instances=n,this.models=new Ra(e.nodeModelsDir,t),this.assignments=new Pa(e.modelAssignmentsDir),this.legacyEnvironments=new xa(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 new Set([...n?.modelEntityIds||[],n?.codexModelHash,n?.claudeModelHash,n?.opencodeModelHash]))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=te(),n=Ua(e.modelNames,e.model),i={...e,model:n[0].name,modelNames:n,protocols:e.protocols?.length?e.protocols:$a(e.app)},s=is(i),r=this.models.get(s),o=Ki.parse({...i,id:s,enabled:e.enabled??!0,order:e.order??this.nextOrder(),labels:e.labels||{},createdAt:r?.createdAt||t,updatedAt:t});return this.toPublic(this.models.put(o),this.referenceIds(s).length)}deploy(e){const t=is(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=Ua(e.modelNames,e.model),i=this.models.get(e.id)||this.models.put(Ki.parse({...e,model:n[0].name,modelNames:n,protocols:e.protocols?.length?e.protocols:$a(e.app)}));return this.toPublic(i,this.referenceIds(i.id).length)}update(e,t){const n=this.requireModel(e),i=t.modelNames?.length?Ua(t.modelNames,t.model||n.model):t.model?Ua(void 0,t.model):Ua(n.modelNames,n.model),s=t.protocols?.length?t.protocols:n.protocols?.length?n.protocols:$a(t.app||n.app),r=Ki.parse({...n,...t,key:t.key?.trim()?t.key:n.key,protocols:s,model:i[0].name,modelNames:i,createdAt:n.createdAt,updatedAt:te()}),o=is(r),a=this.models.put(Ki.parse({...r,id:o}));return this.toPublic(a,this.referenceIds(o).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)}resolveProbeKey(e,t){const n=t?.trim()||(e?this.requireModel(e).key:"");if(!n)throw Object.assign(new Error("An API key is required to contact the model endpoint."),{statusCode:400,code:"MODEL_API_KEY_REQUIRED"});return n}assign(e,t){const n=this.instances.require(e);for(const e of t.modelEntityIds)this.validateEntityRef(e);if(void 0!==t.modelSelection.modelEntityIds&&JSON.stringify(t.modelSelection.modelEntityIds)!==JSON.stringify(t.modelEntityIds))throw Object.assign(new Error("Ordered model entity selection does not match its node assignment."),{statusCode:400,code:"NODE_MODEL_SELECTION_MISMATCH"});if(this.validateRef("codex",t.codexModelHash),this.validateRef("claude",t.claudeModelHash),this.validateRef("opencode",t.opencodeModelHash),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"});if(void 0!==t.modelSelection.opencodeModelHash&&(t.modelSelection.opencodeModelHash??void 0)!==t.opencodeModelHash)throw Object.assign(new Error("OpenCode model selection does not match its node assignment."),{statusCode:400,code:"NODE_MODEL_SELECTION_MISMATCH"});const i=this.assignments.get(e),s=Ji.parse({instanceId:e,modelEntityIds:t.modelEntityIds,codexModelHash:t.codexModelHash,claudeModelHash:t.claudeModelHash,opencodeModelHash:t.opencodeModelHash,updatedAt:te()});this.assignments.put(s);try{return{assignment:s,instance:this.instances.put(Vs.parse({...n,modelSelection:t.modelSelection,updatedAt:te()}))}}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{}}const n=e=>t.modelEntityIds.find(t=>this.modelSupportsApp(this.requireModel(t),e));return{...this.environmentForRef("codex",n("codex")||t.codexModelHash),...this.environmentForRef("claude",n("claude")||t.claudeModelHash),...this.environmentForOpenCode(t)}}privateCatalog(e){const t=this.assignments.get(e);return Ma.parse({protocolVersion:"2026-08-27",instanceId:e,entities:(t?.modelEntityIds||[]).map(e=>{const t=this.requireModel(e);return this.validateEntityRef(e),{id:t.id,endpoint:t.endpoint,key:t.key,protocols:t.protocols?.length?t.protocols:$a(t.app),modelNames:Ua(t.modelNames,t.model)}}),updatedAt:t?.updatedAt||te()})}deleteInstanceMetadata(e){this.assignments.delete(e),this.legacyEnvironments.delete(e)}validateRef(e,t){if(!t)return;const n=this.requireModel(t);if(!this.modelSupportsApp(n,e))throw Object.assign(new Error(`Model ${n.id} does not support the ${e} runtime protocol.`),{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"})}modelSupportsApp(e,t){const n="claude"===t?"anthropic-messages":"opencode"===t?"openai-chat-completions":"openai-responses";return e.protocols?.length?e.protocols.includes(n):e.app===t}validateEntityRef(e){const t=this.requireModel(e);if(!t.enabled)throw Object.assign(new Error(`Model ${t.id} is disabled.`),{statusCode:409,code:"NODE_MODEL_DISABLED"});if(!t.protocols?.length&&!$a(t.app).length)throw Object.assign(new Error(`Model ${t.id} does not expose a supported protocol.`),{statusCode:400,code:"NODE_MODEL_PROTOCOL_UNSUPPORTED"})}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}:"claude"===e?{ANTHROPIC_API_KEY:n.key,ANTHROPIC_BASE_URL:n.endpoint,TASK_HANDOFF_CLAUDE_MODEL:n.model}:{TASK_HANDOFF_OPENCODE_CONFIG_CONTENT:JSON.stringify({$schema:"https://opencode.ai/config.json",model:`task-handoff/${n.model}`,provider:{"task-handoff":{npm:"@ai-sdk/openai-compatible",name:"TaskHandoff",options:{baseURL:n.endpoint,apiKey:n.key},models:{[n.model]:{name:n.name,variants:Fa()}}}}})}}environmentForOpenCode(e){if(e.opencodeModelHash)return this.environmentForRef("opencode",e.opencodeModelHash);const t=e.modelEntityIds.map(e=>this.requireModel(e)).filter(e=>this.modelSupportsApp(e,"opencode"));if(!t.length)return{};const n=t[0],i=Ua(n.modelNames,n.model)[0].name,s=Object.fromEntries(t.map(e=>[`task-handoff-${e.id}`,{npm:"@ai-sdk/openai-compatible",name:e.name,options:{baseURL:e.endpoint,apiKey:e.key},models:Object.fromEntries(Ua(e.modelNames,e.model).map(t=>[t.name,{name:e.name,variants:Fa()}]))}]));return{TASK_HANDOFF_OPENCODE_CONFIG_CONTENT:JSON.stringify({$schema:"https://opencode.ai/config.json",model:`task-handoff-${n.id}/${i}`,provider:s})}}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(is(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?.modelEntityIds.includes(e)||n?.codexModelHash===e||n?.claudeModelHash===e||n?.opencodeModelHash===e}).map(e=>e.id)}toPublic(e,t){const{key:n,...i}=e;return Wi.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=>!Oa.has(e))){this.warnMigration(e,"unknown-fields");continue}const n=[];try{const i=this.migrateApp(t,"codex",n),s=this.migrateApp(t,"claude",n);if(!i&&!s)throw new Error("no complete model configuration");const r=[...new Set([i,s].filter(e=>Boolean(e)))],o={modelEntityIds:r,...i?{codexModelHash:i}:{},...s?{claudeModelHash:s}:{}};this.assign(e,{modelSelection:o,modelEntityIds:r,codexModelHash:i,claudeModelHash:s}),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"],s="codex"===t?e.TASK_HANDOFF_CODEX_BASE_URL||e.OPENAI_BASE_URL:e.ANTHROPIC_BASE_URL,r="codex"===t?e.TASK_HANDOFF_CODEX_MODEL||e.CODEX_MODEL:e.TASK_HANDOFF_CLAUDE_MODEL||e.CLAUDE_MODEL;if(!i&&!s&&!r)return;if(!i||!s||!r)throw new Error("model configuration incomplete");const o=is({app:t,endpoint:s,key:i,model:r}),a=this.models.get(o);if(a){if(a.app!==t||a.key!==i||a.endpoint!==s||a.model!==r||!a.enabled)throw new Error("existing model conflicts with legacy environment");return o}const c=te();return this.models.put(Ki.parse({id:o,name:`Migrated ${"codex"===t?"Codex":"Claude"} model`,endpoint:s,key:i,model:r,app:t,enabled:!0,order:this.nextOrder(),labels:{migratedFrom:"instance-model-environment"},createdAt:c,updatedAt:c})),n.push(o),o}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 Fa(){return Object.fromEntries(["none","minimal","low","medium","high","xhigh","max","ultra"].map(e=>[e,{reasoningEffort:e}]))}function $a(e){return"claude"===e?["anthropic-messages"]:"opencode"===e?["openai-chat-completions"]:["openai-responses"]}function Ua(e,t){const n=e?.length?e:[{name:t,order:100}],i=new Set;return n.map(e=>({name:e.name.trim(),order:e.order})).filter(e=>!(!e.name||i.has(e.name)||(i.add(e.name),0))).sort((e,t)=>e.order-t.order||e.name.localeCompare(t.name)).map((e,t)=>({name:e.name,order:100*(t+1)}))}function Va(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 Ha(){return process.env.TASK_HANDOFF_NPM_COMMAND||"npm"}function Ba(e,i){const s=n.join(e,...i.split("/"),"package.json");try{const e=JSON.parse(t.readFileSync(s,"utf8"));if(e.name!==i||"string"!=typeof e.version||!e.version.trim())throw new Error(`Installed package manifest is invalid: ${s}`);return{name:i,version:e.version.trim()}}catch(e){if("ENOENT"===e.code)return;throw e}}async function qa(e,i){const s=i?function(e){const i=function(e){let t=n.resolve(e);for(;t!==n.dirname(t);){if("node_modules"===n.basename(t)&&"lib"===n.basename(n.dirname(t)))return n.dirname(n.dirname(t));t=n.dirname(t)}}(e);if(!i)return;let s,r=n.resolve(e);for(;r!==n.dirname(r);){try{const e=JSON.parse(t.readFileSync(n.join(r,"package.json"),"utf8"));if("@task-handoff/node-agent"===e.name&&"string"==typeof e.version&&e.version.trim()&&(s=e.version.trim()),"@task-handoff/server"===e.name&&"string"==typeof e.version&&e.version.trim())return{packageName:"@task-handoff/server",currentVersion:e.version.trim(),relatedCurrentVersions:s?[s]:[],installPrefix:i}}catch(e){if("ENOENT"!==e.code)throw e}r=n.dirname(r)}return s?{packageName:"@task-handoff/node-agent",currentVersion:s,relatedCurrentVersions:[],installPrefix:i}:void 0}(i):void 0;if(s)return s;const r=(await e(Ha(),["root","--global"])).stdout.trim();if(!r)throw new Error("npm did not return its global module root.");const o=(await e(Ha(),["prefix","--global"])).stdout.trim();if(!n.isAbsolute(o))throw new Error(`npm did not return an absolute global prefix: ${o||"empty"}`);const a=Ba(r,"@task-handoff/server"),c=Ba(r,"@task-handoff/node-agent");return a?{packageName:"@task-handoff/server",currentVersion:a.version,relatedCurrentVersions:c?[c.version]:[],installPrefix:o}:{packageName:"@task-handoff/node-agent",currentVersion:c?.version,relatedCurrentVersions:[],installPrefix:o}}function Ka(e){if(!e||"object"!=typeof e||Array.isArray(e))return e;const t=e,n="string"==typeof t.updatedAt?t.updatedAt:te(),i=t.target&&"object"==typeof t.target&&!Array.isArray(t.target)?t.target:void 0,s="controlled-instance"===i?.component,r={updating:"updating-node",downloading:"updating-node",installing:"updating-node",restarting:"restarting-node",completed:"succeeded",success:"succeeded",error:"failed"},o=new Set(["queued","updating-node","restarting-node","converging-instances","succeeded","degraded","failed"]),a="string"==typeof t.status?t.status:"queued",c=s?"failed":o.has(a)?a:r[a]||"failed",d="string"==typeof t.toVersion&&t.toVersion?t.toVersion:"unknown",l=Ti.strip().safeParse(t.impact).success?Ti.strip().parse(t.impact):{runningInstanceCount:0,stoppedInstanceCount:0,activeInstanceCount:0,restartInstanceCount:0,runningInstanceIds:[],stoppedInstanceIds:[],activeInstanceIds:[]},u=s?{code:"LEGACY_INSTANCE_UPDATE_RETIRED",message:"Independent controlled-instance update jobs were retired in favor of Node reconciliation.",retryable:!1}:"failed"!==c||t.error||o.has(a)||a in r?"string"==typeof t.error?{code:"NODE_UPDATE_FAILED",message:t.error,retryable:!1}:zi.strip().safeParse(t.error).success?zi.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:p,error:m,...h}=t,g={phase:"succeeded"===c?"succeeded":"failed"===c?"failed":c||"queued",desiredVersion:d,expectedInstanceIds:[],expectedInstanceCount:0,matchedInstanceCount:0,pendingInstanceCount:0,failedInstanceCount:s||"failed"===c?1:0,deferredInstanceCount:0},f=_i.strip().safeParse(t.rollout);return{...h,source:"npm",status:c,impact:l,runtimeArtifacts:Array.isArray(t.runtimeArtifacts)?t.runtimeArtifacts.flatMap(e=>{const t=Ei.strip().safeParse(e);return t.success?[t.data]:[]}):[],rollout:f.success?f.data:g,...u?{error:u}:{},...s?{completedAt:t.completedAt||n}:{}}}class Ga{records;constructor(e){this.records=new _a(e.updatesDir,{schema:Oi,sanitize:Ka})}init(){this.records.init()}list(){return this.records.list().sort((e,t)=>t.createdAt.localeCompare(e.createdAt))}create(e,t){const n=te();return this.records.put(Oi.parse({id:Na("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(Oi.parse({...n,...t,id:e,createdAt:n.createdAt,updatedAt:te()}))}reconcileRollouts(e,t,n={}){const i=new Map(e.map(e=>[e.id,e]));if(n.processStarted)for(const e of this.list().filter(e=>"queued"===e.status))this.patch(e.id,{status:"failed",rollout:{...e.rollout,phase:"failed"},error:{code:"NODE_UPDATE_FAILED",message:"The node agent restarted before the update worker claimed this job.",retryable:!0},completedAt:te()});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:te()});continue}const s="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"!==s.status)continue;const r=s.rollout.expectedInstanceIds,o=r.map(e=>i.get(e)),a=o.filter(e=>e?.ready&&"matched"===e.runtimeVersion?.phase&&e.runtimeVersion.actualVersion===s.toVersion).length,c=o.filter(e=>e&&["created","stopped","failed"].includes(e.status||"")&&"failed"!==e.runtimeVersion?.phase).length,d=o.filter(e=>!e||"failed"===e.runtimeVersion?.phase).length,l=Math.max(0,r.length-a-d-c),u=d>0?"degraded":0===l?"succeeded":"converging-instances";this.patch(s.id,{status:u,rollout:{...s.rollout,phase:u,nodeVersion:t,expectedInstanceCount:r.length,matchedInstanceCount:a,pendingInstanceCount:l,failedInstanceCount:d,deferredInstanceCount:s.impact.stoppedInstanceCount+c},..."succeeded"===u||"degraded"===u?{completedAt:te()}:{}})}}run(e,t){(async()=>{this.patch(e.id,{status:"updating-node",rollout:{...e.rollout,phase:"updating-node"},startedAt:te(),error:void 0});try{await t(e),this.patch(e.id,{status:"succeeded",completedAt:te()})}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:te()})}})()}}class Wa{records;constructor(e){this.records=new _a(e.environmentTemplatesDir,{schema:ai,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"]),s="string"==typeof n.id?n.id:void 0;for(const e of Object.keys(n))i.has(e)||t?.({templateId:s,field:e});const r=Ys(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:s,field:`error.${n}`});r.error=Ys(e,["code","message","phase"])}return r}(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(ai.parse({...e,status:"failed",error:{code:"ENVIRONMENT_TEMPLATE_CREATION_INTERRUPTED",message:"Environment template creation was interrupted by a node-agent restart.",phase:"recovery"},updatedAt:te()}))}list(){return this.records.list()}get(e){return this.records.get(e)}put(e){return this.records.put(ai.parse(e))}patch(e,t){return this.records.patch(e,t)}delete(e){return this.records.delete(e)}}const Ja=a.z.record(a.z.string().regex(/^[A-Za-z_][A-Za-z0-9_]*$/),a.z.string()),Ya=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:Ja,modelCatalog:Ma.optional(),updatedAt:a.z.string().datetime()}).strict();class Xa{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")),s=i&&"object"==typeof i&&!Array.isArray(i)?i:{},r=Ya.parse({version:s.version,instanceId:s.instanceId,instanceCredential:s.instanceCredential??s.registrationToken,environment:s.environment,modelCatalog:void 0===s.modelCatalog?void 0:ja(s.modelCatalog),updatedAt:s.updatedAt});if(r.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===s.instanceCredential&&void 0!==s.registrationToken||void 0!==s.gitCredentials)&&this.put(r),r}put(e){const n=Ya.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,i){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,...i?{modelCatalog:i}:{},updatedAt:(new Date).toISOString()})}delete(e){t.rmSync(this.filePath(e),{force:!0})}}const Qa=a.z.string().trim().min(1).max(120).regex(/^[a-zA-Z0-9][a-zA-Z0-9_.:-]*$/),Za=a.z.string().datetime(),ec=a.z.number().int().nonnegative(),tc=a.z.enum(["https-token","ssh-key"]),nc=a.z.enum(["operation-only","instance-retained"]),ic=a.z.enum(["enabled","disabled"]),sc=a.z.enum(["pending","synced","deferred","revoking","revoked"]),rc=a.z.object({scheme:a.z.enum(["https","ssh"]),host:a.z.string().trim().min(1).max(253),port:a.z.number().int().min(1).max(65535).optional(),pathPrefix:a.z.string().min(1).max(2048).default("/")}).strict();function oc(e){throw new Error(`Invalid Git credential scope: ${e}`)}function ac(e){const t=e.trim().replace(/^\[|\]$/g,"");(!t||t.includes("*")||/[/?#@\s]/.test(t))&&oc("host is invalid");try{const e=new URL(t.includes(":")?`http://[${t}]/`:`http://${t}/`).hostname.replace(/^\[|\]$/g,"").toLowerCase();return(!e||e.length>253||e.includes("*"))&&oc("host is invalid"),e}catch{oc("host is invalid")}}function cc(e){try{return decodeURIComponent(e)}catch{oc("path contains invalid percent encoding")}}function dc(e){const t=e?.trim()||"/";(t.includes("?")||t.includes("#")||t.includes("\\")||t.includes("\0"))&&oc("path contains an unsupported delimiter");const n=(t.startsWith("/")?t:`/${t}`).split("/").filter(Boolean);for(const e of n){const t=cc(e);("."===t||".."===t||t.includes("/")||t.includes("\\")||t.includes("\0"))&&oc("path contains an unsafe segment")}return 0===n.length?"/":`/${n.join("/")}/`}function lc(e){const t=rc.parse(e),n="https"===t.scheme?443:22;return rc.parse({scheme:t.scheme,host:ac(t.host),...void 0===t.port||t.port===n?{}:{port:t.port},pathPrefix:dc(t.pathPrefix)})}function uc(e){return dc(e.replace(/\.git\/?$/,""))}const pc=a.z.object({id:Qa,name:a.z.string().trim().min(1).max(160),kind:tc,scope:rc,secretSet:a.z.literal(!0),status:ic,revision:ec,createdAt:Za,updatedAt:Za}).strict(),mc=a.z.object({kind:a.z.literal("https-token"),username:a.z.string().trim().min(1).max(240),token:a.z.string().min(1).max(8192)}).strict(),hc=a.z.object({kind:a.z.literal("ssh-key"),privateKey:a.z.string().min(1).max(131072),passphrase:a.z.string().max(8192).optional(),pinnedKnownHosts:a.z.string().min(1).max(131072)}).strict(),gc=a.z.discriminatedUnion("kind",[mc,hc]);a.z.object({name:a.z.string().trim().min(1).max(160),scope:rc,secret:gc}).strict().superRefine((e,t)=>{"https"===e.scope.scheme!=("https-token"===e.secret.kind)&&t.addIssue({code:"custom",path:["scope","scheme"],message:"Credential kind must match the remote scheme."});try{lc(e.scope)}catch(e){t.addIssue({code:"custom",path:["scope"],message:e instanceof Error?e.message:"Invalid Git scope."})}}),a.z.object({name:a.z.string().trim().min(1).max(160).optional(),scope:rc.optional(),secret:gc.optional(),status:ic.optional()}).strict().refine(e=>Object.keys(e).length>0,"At least one credential field must be updated."),a.z.object({items:a.z.array(pc).max(1e4)}).strict();const fc=a.z.object({instanceId:Qa,credentialId:Qa,credentialRevision:ec,assignmentRevision:ec,status:sc,authorizedAt:Za,updatedAt:Za}).strict(),yc=a.z.object({credential:pc,secret:gc}).strict().superRefine((e,t)=>{e.credential.kind!==e.secret.kind&&t.addIssue({code:"custom",path:["secret","kind"],message:"Credential payload kind mismatch."})}),Ic=a.z.object({instanceId:Qa,generation:ec,credentialIds:a.z.array(Qa).max(256).transform(e=>[...new Set(e)].sort()),updatedAt:Za}).strict(),Ac=a.z.object({remoteUrl:a.z.string().trim().min(1).max(4096)}).strict(),bc=a.z.discriminatedUnion("status",[a.z.object({status:a.z.literal("ok"),username:a.z.string().min(1).max(240),password:a.z.string().min(1).max(8192)}).strict(),a.z.object({status:a.z.enum(["none","ambiguous","unsupported","missing-host-key","rejected"])}).strict()]),vc=a.z.object({remoteUrl:a.z.string().trim().min(1).max(4096)}).strict(),wc=a.z.discriminatedUnion("status",[a.z.object({status:a.z.literal("ok"),invocationId:Qa,publicIdentity:a.z.string().min(1).max(131072),pinnedKnownHosts:a.z.string().min(1).max(131072)}).strict(),a.z.object({status:a.z.enum(["none","ambiguous","unsupported","missing-host-key","rejected"])}).strict()]),Sc=a.z.object({invocationId:Qa,frame:a.z.string().min(1).max(1048576)}).strict(),Ec=a.z.object({frame:a.z.string().min(1).max(1048576)}).strict(),zc=a.z.object({operationId:Qa,retention:nc,payload:yc}).strict(),Nc=a.z.object({operationId:Qa,instanceId:Qa,remoteUrl:a.z.string().trim().min(1).max(4096),ref:a.z.discriminatedUnion("type",[a.z.object({type:a.z.enum(["branch","tag"]),name:a.z.string().trim().min(1).max(240)}).strict(),a.z.object({type:a.z.literal("commit"),commit:a.z.string().trim().regex(/^[0-9a-fA-F]{4,64}$/,"commit must be a hexadecimal Git object id")}).strict()]),clone: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).refine(e=>!e.startsWith("/")&&!e.split("/").some(e=>".."===e),"subdirectory must be a relative path within the repository").transform(e=>e.split("/").filter(e=>e&&"."!==e).join("/")).default("")}).strict(),credentials:a.z.array(zc).max(256).default([])}).strict();function Tc(e){return e&&"object"==typeof e&&!Array.isArray(e)?e:void 0}function _c(e,t){if(e)return Object.fromEntries(t.filter(t=>Object.prototype.hasOwnProperty.call(e,t)).map(t=>[t,e[t]]))}function kc(e){const t=Tc(e),n=Tc(t?.scope);return pc.safeParse({..._c(t,["id","name","kind","secretSet","status","revision","createdAt","updatedAt"]),scope:_c(n,["scheme","host","port","pathPrefix"])})}function Cc(e,t){let n;try{n=function(e){const t=e.trim();if(t&&!t.includes("\0")||oc("remote is empty or invalid"),/^https?:\/\//i.test(t)||/^ssh:\/\//i.test(t)){let e;dc(t.replace(/^[a-z][a-z0-9+.-]*:\/\/[^/]+/i,"").split(/[?#]/,1)[0]||"/");try{e=new URL(t)}catch{oc("remote URL is invalid")}"https:"!==e.protocol&&"ssh:"!==e.protocol&&oc("remote scheme is unsupported"),(e.password||"https:"===e.protocol&&e.username)&&oc("HTTPS userinfo is forbidden"),(e.search||e.hash)&&oc("query and fragment are forbidden");const n="https:"===e.protocol?"https":"ssh",i=e.port?Number(e.port):void 0;return{...lc({scheme:n,host:e.hostname,port:i,pathPrefix:uc(e.pathname)}),original:t}}/^[a-z][a-z0-9+.-]*:\/\//i.test(t)&&oc("remote scheme is unsupported");const n=/^(?:([^@/:\s]+)@)?([^/:\s]+):(.+)$/.exec(t);n||oc("remote must use HTTPS, ssh://, or scp-like SSH syntax");const[,,i,s]=n;return(s.includes("?")||s.includes("#"))&&oc("query and fragment are forbidden"),{...lc({scheme:"ssh",host:i,pathPrefix:uc(s)}),original:t}}(e)}catch(e){return{status:"unsupported",reason:e instanceof Error?e.message:"Unsupported Git remote."}}const i=t.filter(e=>"enabled"===e.status).filter(e=>"https"===n.scheme==("https-token"===e.kind)).filter(e=>function(e,t){const n=lc(e);return n.scheme===t.scheme&&n.host===t.host&&n.port===t.port&&("/"===n.pathPrefix||t.pathPrefix.startsWith(n.pathPrefix))}(e.scope,n)).map(e=>({candidate:e,specificity:lc(e.scope).pathPrefix.length}));if(0===i.length)return{status:"none",remote:n};const s=Math.max(...i.map(e=>e.specificity)),r=i.filter(e=>e.specificity===s).map(e=>e.candidate);if(r.length>1)return{status:"ambiguous",remote:n,credentialIds:r.map(e=>e.id).sort()};const o=r[0];return"ssh-key"===o.kind&&!0!==o.pinnedKnownHosts?{status:"missing-host-key",remote:n,credentialId:o.id}:{status:"unique",remote:n,credential:o}}const Oc=a.z.object({id:a.z.string().trim().min(1).max(120),payload:yc,createdAt:a.z.string().datetime(),updatedAt:a.z.string().datetime()}).strict(),xc=fc.extend({id:a.z.string().trim().min(1).max(300),createdAt:a.z.string().datetime()}).strict(),Rc=Ic.extend({id:a.z.string().trim().min(1).max(120),createdAt:a.z.string().datetime()}).strict(),Pc=a.z.object({id:a.z.string().trim().min(1).max(120),status:a.z.literal("pending"),input:Nc,createdAt:a.z.string().datetime(),updatedAt:a.z.string().datetime(),expiresAt:a.z.string().datetime()}).strict(),Dc=a.z.object({id:a.z.string().trim().min(1).max(120),status:a.z.literal("consumed"),operationId:Nc.shape.operationId,createdAt:a.z.string().datetime(),updatedAt:a.z.string().datetime(),expiresAt:a.z.string().datetime()}).strict(),Mc=a.z.discriminatedUnion("status",[Pc,Dc]),jc=864e5;function Lc(e){return e&&"object"==typeof e&&!Array.isArray(e)?e:void 0}function Fc(e){const t=Lc(e),n=Lc(t?.payload),i=kc(n?.credential),s=Lc(n?.secret);return{id:t?.id,payload:{credential:i.success?i.data:n?.credential,secret:"https-token"===s?.kind?{kind:s.kind,username:s.username,token:s.token}:{kind:s?.kind,privateKey:s?.privateKey,passphrase:s?.passphrase,pinnedKnownHosts:s?.pinnedKnownHosts}},createdAt:t?.createdAt,updatedAt:t?.updatedAt}}function $c(e){const t=Lc(e);return Object.fromEntries(["id","instanceId","credentialId","credentialRevision","assignmentRevision","status","authorizedAt","createdAt","updatedAt"].flatMap(e=>t&&Object.prototype.hasOwnProperty.call(t,e)?[[e,t[e]]]:[]))}function Uc(e){const t=Lc(e);return Object.fromEntries(["id","instanceId","generation","credentialIds","createdAt","updatedAt"].flatMap(e=>t&&Object.prototype.hasOwnProperty.call(t,e)?[[e,t[e]]]:[]))}function Vc(e){const t=Lc(e),n="string"==typeof t?.updatedAt?Date.parse(t.updatedAt):Number.NaN;if("consumed"===t?.status)return{id:t.id,status:"consumed",operationId:t.operationId,createdAt:t.createdAt,updatedAt:t.updatedAt,expiresAt:t.expiresAt};const i=function(e){const t=Tc(e),n=Tc(t?.ref),i=Tc(t?.clone),s=Array.isArray(t?.credentials)?t.credentials.map(e=>{const t=Tc(e),n=Tc(t?.payload),i=kc(n?.credential),s=Tc(n?.secret);return{..._c(t,["operationId","retention"]),payload:{credential:i.success?i.data:n?.credential,secret:_c(s,"https-token"===s?.kind?["kind","username","token"]:["kind","privateKey","passphrase","pinnedKnownHosts"])}}}):t?.credentials;return Nc.safeParse({..._c(t,["operationId","instanceId","remoteUrl"]),ref:_c(n,["type","name","commit"]),clone:_c(i,["depth","submodules","lfs","subdirectory"]),credentials:s})}(t?.input);return{id:t?.id,status:"pending",input:i.success?i.data:t?.input,createdAt:t?.createdAt,updatedAt:t?.updatedAt,expiresAt:t?.expiresAt||(Number.isFinite(n)?new Date(n+jc).toISOString():t?.updatedAt)}}function Hc(e,t){return Object.assign(new Error(`Refusing stale ${e} revision for ${t}.`),{code:"GIT_CREDENTIAL_REVISION_STALE",statusCode:409})}function Bc(e,t){return Object.assign(new Error(`Refusing conflicting ${e} revision for ${t}.`),{code:"GIT_CREDENTIAL_REVISION_CONFLICT",statusCode:409})}class qc{payloads;legacyAssignments;authorizationSets;workspaceProvisioning;workspaceProvisioningTtlMs;workspaceProvisioningCleanupTimer;constructor(e,t={}){this.workspaceProvisioningTtlMs=t.workspaceProvisioningTtlMs??jc,this.payloads=new _a(e.gitCredentialPayloadsDir,{schema:Oc,sanitize:Fc,directoryMode:448,fileMode:384}),this.legacyAssignments=new _a(e.gitCredentialAssignmentsDir,{schema:xc,sanitize:$c,directoryMode:448,fileMode:384}),this.authorizationSets=new _a(e.gitCredentialAuthorizationSetsDir,{schema:Rc,sanitize:Uc,directoryMode:448,fileMode:384}),this.workspaceProvisioning=new _a(e.gitWorkspaceProvisioningIntentsDir,{schema:Mc,sanitize:Vc,directoryMode:448,fileMode:384})}init(){this.payloads.init(),this.legacyAssignments.init(),this.authorizationSets.init(),this.workspaceProvisioning.init();for(const e of this.workspaceProvisioning.list())("pending"===e.status&&!Kc(e.input)||Date.parse(e.expiresAt)<=Date.now())&&this.workspaceProvisioning.delete(e.id);this.scheduleWorkspaceProvisioningCleanup();const e=new Set(this.legacyAssignments.list().map(e=>e.instanceId));for(const t of e){if(this.authorizationSets.get(t))continue;const e=this.legacyAssignments.list().filter(e=>e.instanceId===t),n=(new Date).toISOString();this.putAuthorizationSet({instanceId:t,generation:Math.max(0,...e.map(e=>e.assignmentRevision)),credentialIds:e.filter(e=>"revoking"!==e.status&&"revoked"!==e.status).map(e=>e.credentialId),updatedAt:n})}}putPayload(e){const t=yc.parse(e),n=this.payloads.get(t.credential.id);if(n&&n.payload.credential.revision>t.credential.revision)throw Hc("payload",t.credential.id);if(n&&n.payload.credential.revision===t.credential.revision&&JSON.stringify(n.payload)!==JSON.stringify(t))throw Bc("payload",t.credential.id);const i=(new Date).toISOString();return this.payloads.put({id:t.credential.id,payload:t,createdAt:n?.createdAt||i,updatedAt:i}).payload}getPayload(e){return this.payloads.get(e)?.payload}putAuthorizationSet(e){const t=Ic.parse(e),n=this.authorizationSets.get(t.instanceId);if(n&&n.generation>t.generation)throw Hc("authorization set",t.instanceId);if(n&&n.generation===t.generation){if(JSON.stringify(n.credentialIds)!==JSON.stringify(t.credentialIds))throw Bc("authorization set",t.instanceId);return this.publicAuthorizationSet(n)}for(const e of t.credentialIds)if(!this.payloads.get(e))throw Object.assign(new Error(`Credential payload ${e} is not deployed.`),{code:"GIT_CREDENTIAL_PAYLOAD_MISSING",statusCode:409});const i=(new Date).toISOString();return this.publicAuthorizationSet(this.authorizationSets.put({id:t.instanceId,...t,createdAt:n?.createdAt||i}))}getAuthorizationSet(e){const t=this.authorizationSets.get(e);return t?this.publicAuthorizationSet(t):{instanceId:e,generation:0,credentialIds:[],updatedAt:new Date(0).toISOString()}}resolve(e,t){const n=this.getAuthorizationSet(e).credentialIds.flatMap(e=>{const t=this.getPayload(e);return t?[t]:[]}),i=Cc(t,n.map(e=>({id:e.credential.id,kind:e.credential.kind,scope:e.credential.scope,status:e.credential.status,pinnedKnownHosts:"ssh-key"===e.secret.kind&&Boolean(e.secret.pinnedKnownHosts.trim())}))),s="unique"===i.status?n.find(e=>e.credential.id===i.credential.id):void 0;return{match:i,payload:s}}removePayload(e){if(this.authorizationSets.list().some(t=>t.credentialIds.includes(e)))throw Object.assign(new Error(`Credential payload ${e} is still authorized.`),{code:"GIT_CREDENTIAL_PAYLOAD_IN_USE",statusCode:409});return this.payloads.delete(e)}collectUnreferencedPayloads(){const e=new Set(this.authorizationSets.list().flatMap(e=>e.credentialIds));let t=0;for(const n of this.payloads.list())!e.has(n.id)&&this.payloads.delete(n.id)&&(t+=1);return t}removeInstance(e){const t=this.authorizationSets.delete(e)?1:0;this.workspaceProvisioning.delete(e),this.scheduleWorkspaceProvisioningCleanup();for(const t of this.legacyAssignments.list().filter(t=>t.instanceId===e))this.legacyAssignments.delete(t.id);return t}putWorkspaceProvisioning(e){const t=Nc.parse(e);if(!Kc(t))throw Object.assign(new Error("Only operation-only Git provisioning may be persisted."),{code:"GIT_CREDENTIAL_PROVISIONING_RETENTION_INVALID",statusCode:400});const n=this.workspaceProvisioning.get(t.instanceId);if("consumed"===n?.status&&n.operationId===t.operationId)return t;const i=(new Date).toISOString(),s=Pc.parse(this.workspaceProvisioning.put({id:t.instanceId,status:"pending",input:t,createdAt:n?.createdAt||i,updatedAt:i,expiresAt:new Date(Date.now()+this.workspaceProvisioningTtlMs).toISOString()})).input;return this.scheduleWorkspaceProvisioningCleanup(),s}getWorkspaceProvisioning(e){const t=this.workspaceProvisioning.get(e);if(t&&"pending"===t.status)return!Kc(t.input)||Date.parse(t.expiresAt)<=Date.now()?(this.workspaceProvisioning.delete(e),void this.scheduleWorkspaceProvisioningCleanup()):t.input}removeWorkspaceProvisioning(e){const t=this.workspaceProvisioning.delete(e);return this.scheduleWorkspaceProvisioningCleanup(),t}discardPendingWorkspaceProvisioning(e){const t=this.workspaceProvisioning.get(e);return!(!t||"pending"!==t.status)&&this.removeWorkspaceProvisioning(e)}completeWorkspaceProvisioning(e,t){const n=this.workspaceProvisioning.get(e);if(!n||"pending"!==n.status||n.input.operationId!==t)return!1;const i=(new Date).toISOString();return this.workspaceProvisioning.put({id:e,status:"consumed",operationId:t,createdAt:n.createdAt,updatedAt:i,expiresAt:new Date(Date.now()+6048e5).toISOString()}),this.scheduleWorkspaceProvisioningCleanup(),!0}workspaceProvisioningStatus(e){const t=this.workspaceProvisioning.get(e);if(t){if(!(Date.parse(t.expiresAt)<=Date.now()))return"pending"===t.status?{status:t.status,operationId:t.input.operationId}:{status:t.status,operationId:t.operationId};this.removeWorkspaceProvisioning(e)}}scheduleWorkspaceProvisioningCleanup(){this.workspaceProvisioningCleanupTimer&&clearTimeout(this.workspaceProvisioningCleanupTimer),this.workspaceProvisioningCleanupTimer=void 0;const e=Math.min(...this.workspaceProvisioning.list().map(e=>Date.parse(e.expiresAt)));Number.isFinite(e)&&(this.workspaceProvisioningCleanupTimer=setTimeout(()=>{this.workspaceProvisioningCleanupTimer=void 0;const e=Date.now();for(const t of this.workspaceProvisioning.list())Date.parse(t.expiresAt)<=e&&this.workspaceProvisioning.delete(t.id);this.scheduleWorkspaceProvisioningCleanup()},Math.max(0,e-Date.now())),this.workspaceProvisioningCleanupTimer.unref?.())}listAssignments(e){return this.legacyAssignments.list().filter(t=>!e||t.instanceId===e).map(({id:e,createdAt:t,...n})=>fc.parse(n))}publicAuthorizationSet(e){const{id:t,createdAt:n,...i}=e;return Ic.parse(i)}}function Kc(e){return e.credentials.length>0&&e.credentials.every(e=>"operation-only"===e.retention)}const Gc=function(e,t=process.env,n=e){let i;return()=>{const s=t.TASK_HANDOFF_VERSION?.trim();return s||(i||=z(e,t,n),i)}}("@task-handoff/node-agent",process.env,"@task-handoff/control-plane");function Wc(){return Gc()}function Jc(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 Yc(e){const t=Wc();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:Jc(t,e)}}function Xc(e,t,n=!0){if(!n){const n=Wc(),i=e.runtimeVersion;return"matched"===i?.phase&&i.desiredVersion===n&&i.actualVersion===t?i:Yc(t)}const i=Wc(),s=e.runtimeVersion;if(!s||s.desiredVersion!==i)return Yc(t);const r="INSTANCE_RUNTIME_VERSION_MISMATCH"!==s.error?.code?s.error:t===i?void 0:Jc(i,t);return Ni.parse({...s,desiredVersion:i,...t?{actualVersion:t}:{actualVersion:void 0},..."pending"===s.phase?{error:r||(t!==i?Jc(i,t):void 0)}:{}})}const Qc="runtime_local_host",Zc="task-handoff.node-agent.builtin";function ed(e){const t={...e};return delete t[Zc],t}function td(e){return"local-folder"===e.type?$i.parse({mode:"local-bind",path:"/workspace",readOnly:!1}):$i.parse({mode:"git-clone",path:"/workspace",readOnly:!1})}function nd(e){const t=Fi.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 Bi.parse({id:n,name:"string"==typeof e.sourceSnapshot.name?e.sourceSnapshot.name:e.name,source:t,defaultImageSelection:e.imageSelection,defaultNodeId:e.nodeId,workspacePolicy:td(t),labels:{},createdAt:e.createdAt,updatedAt:e.updatedAt})}function id(e,t){throw Object.assign(new Error(t),{statusCode:403,code:e})}function sd(e,t){e!==In&&console.warn(JSON.stringify({message:"protocol version mismatch",peer:t,expectedProtocolVersion:In,actualProtocolVersion:e||"missing",errorCode:"PROTOCOL_VERSION_MISMATCH"}))}function rd(e){return"none"!==e.capabilities.artifactKind}function od(e={}){return{...e,requiresImage:!1,supportsControlledInstanceApi:!0,supportsContainerLifecycle:!1,supportsAppSessions:!0,supportsHostSessions:!0,artifactKind:"none",isolation:"none"}}class ad extends _a{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||{},n?.modelCatalog);const{registrationToken:s,...r}=e,o=super.put(Vs.parse({...r,stateRevision:Math.max(e.stateRevision||0,t)+1})),a=this.hydrate(o);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 Vs.parse({...e,registrationToken:t})}}class cd{nodeId;paths;localFolders;nodeRuntimes;controlledInstances;environmentTemplates;instancePrivateConfigs;modelRegistry;gitCredentials;updateJobs;node;listenerPort;containerUrlOverride;platform;constructor(e,t,n,i,s,r){this.paths=e,this.nodeId=t,this.localFolders=new _a(e.localFoldersDir,{schema:Li,sanitize:ii}),this.nodeRuntimes=new _a(e.nodeRuntimesDir,{schema:Ns}),this.instancePrivateConfigs=new Xa(e),this.controlledInstances=new ad(e.controlledInstancesDir,{schema:Vs,sanitize:e=>Gs(e,e=>{console.warn(JSON.stringify({message:"legacy controlled instance field was ignored",...e}))})},this.instancePrivateConfigs),this.environmentTemplates=new Wa(e),this.gitCredentials=new qc(e),this.modelRegistry=new La(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 Ga(e),this.listenerPort=s,this.platform=r,this.containerUrlOverride=i;const o=te();this.node=zs.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:o,updatedAt:o})}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.gitCredentials.init(),this.modelRegistry.init(),this.updateJobs.init(),this.updateJobs.reconcileRollouts(this.controlledInstances.list(),Wc(),{processStarted:!0}),!this.nodeRuntimes.get("runtime_local_docker")){const e=te();this.nodeRuntimes.put(Ns.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(Qc),t=te();this.nodeRuntimes.put(Ns.parse({id:Qc,nodeId:this.nodeId,name:"Local Runtime",type:"local",status:e?.status||"unknown",accessStrategy:"node-proxy",capabilities:od(e?.capabilities),labels:{...e?.labels,[Zc]:"true"},createdAt:e?.createdAt||t,updatedAt:e?.updatedAt||t}))}for(const e of this.nodeRuntimes.list())e.nodeId!==this.nodeId&&this.nodeRuntimes.put(Ns.parse({...e,nodeId:this.nodeId,updatedAt:te()}));for(const e of this.localFolders.list())e.nodeId!==this.nodeId&&this.localFolders.put(Li.parse({...e,nodeId:this.nodeId,updatedAt:te()}));this.normalizeInstanceRuntimeVersions()}normalizeInstanceRuntimeVersions(){for(const e of this.controlledInstances.list()){const t=Yc(e.build?.packageVersion||e.instanceVersion),n=rd(this.requireRuntime(e.runtimeId)),i=["created","stopped","failed"].includes(e.status),s=n&&e.runtimeVersion?.desiredVersion===t.desiredVersion?e.runtimeVersion:void 0,r=n?"matched"===t.phase?i?t:{...t,phase:"verifying",matchedAt:void 0}:{...t,phase:"pending",attempt:s?.attempt||0,lastAttemptAt:s?.lastAttemptAt,error:s?.error||t.error}:t;this.controlledInstances.put(Vs.parse({...e,ready:!1,runtimeVersion:r,updatedAt:te()}))}}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=te()}runningInstanceCount(){const e=new Set(["created","stopped","failed"]);return this.listInstances().filter(t=>!e.has(t.status)).length}createLocalFolder(e){const t=te(),i=Ho(e.path),s=Li.parse({...e,name:e.name.trim()||n.basename(i),path:i,id:e.id||Na("folder"),nodeId:this.nodeId,labels:e.labels||{},createdAt:t,updatedAt:t});return this.localFolders.put(s)}updateLocalFolder(e,t){const i=this.localFolders.get(e);if(!i){const t=new Error(`Local folder ${e} was not found.`);throw Object.assign(t,{statusCode:404,code:"NODE_LOCAL_FOLDER_NOT_FOUND"})}return this.localFolders.put(Li.parse({...i,name:t.name.trim()||n.basename(i.path),updatedAt:te()}))}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=te(),n=Ns.parse({...e,id:e.id||Na("runtime"),nodeId:this.nodeId,accessStrategy:e.accessStrategy||(i=e.type,"docker"===i?"direct-port":"node-proxy"),capabilities:e.capabilities||{},labels:ed(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[Zc]){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=Ns.parse({...n,...t,id:n.id,nodeId:this.nodeId,accessStrategy:t.accessStrategy||n.accessStrategy,capabilities:t.capabilities||n.capabilities,labels:t.labels?ed(t.labels):n.labels,createdAt:n.createdAt,updatedAt:te()});return this.nodeRuntimes.put(i)}deleteRuntime(e){if("true"===this.requireRuntime(e).labels[Zc]){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=Ns.parse({...n,...e,id:n.id,nodeId:this.nodeId,createdAt:n.createdAt,updatedAt:te()});return this.nodeRuntimes.put(t)}):this.nodeRuntimes.put(Ns.parse({...n,status:"unknown",updatedAt:te()}))}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=Ks(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 ${In}: ${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 Vs.parse({...e,status:"starting",ready:!1,updatedAt:n});case"stop-requested":return Vs.parse({...e,status:"stopping",ready:!1,updatedAt:n});case"stop-failed":return"stopping"!==e.status?e:Vs.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 Vs.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 s=t.stateRevision>e.stateRevision&&t.lastHeartbeatAt!==e.lastHeartbeatAt&&"online"===t.agentStatus;return Vs.parse({...t,...n,...s?{status:t.status,health:t.health,connectionStatus:t.connectionStatus,agentStatus:t.agentStatus,targetStatus:t.targetStatus,uiAccessStatus:t.uiAccessStatus}:{},ready:!!s&&t.ready,target:n.target?{...t.target,...n.target}:t.target,workspace:n.workspace?s?{...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 Vs.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 Vs.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=Ks(e);return t.success?[t.data]:[]})}resolvedAssignedModelEnvironment(e){return this.modelRegistry.resolvedEnvironment(e)}createInstance(e){const t=this.requireRuntime(e.runtimeId),i=te(),s=e.id||Na("inst"),r=function(e){const t=Fi.parse(e);return"local-folder"===t.type?t:Fi.parse({...t,auth:{type:"none"}})}(e.source),o=e.environmentSource||(e.imageSelection?{type:"image",imageSelection:e.imageSelection}:void 0);if("template"===o?.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"===o?.type?this.environmentTemplates.get(o.environmentTemplateId):void 0;if("template"===o?.type&&(!a||"ready"!==a.status)){const e=new Error(`Environment template ${o.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)&&(!o||"image"===o.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"!==r.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?gs.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?gs.parse(e.image):void 0,d="local"===t.type&&"local-folder"===r.type?n.resolve(r.path):void 0,l=Vs.parse({id:s,name:e.name||`instance-${s.replace(/^inst_?/,"").slice(0,6)}`,source:r,sourceSnapshot:e.sourceSnapshot||{},modelSelection:e.modelSelection,projectId:e.projectId,nodeId:this.nodeId,runtimeId:t.id,imageSelection:"image"===o?.type?o.imageSelection:void 0,environmentSource:o,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"!==o?.type?{phase:"checking-image",requestedReference:c.requestedReference,generation:0,startedAt:i,updatedAt:i}:void 0,status:c&&"docker"===t.type&&"template"!==o?.type?"provisioning":"created",health:"unknown",connectionStatus:"unknown",agentStatus:"unknown",targetStatus:"unknown",uiAccessStatus:"unknown",controlMode:"controlled",ready:!1,runtimeVersion:Yc(),capabilities:{},config:{autoImportAgentConfigs:e.config?.autoImportAgentConfigs??!0,codexConfigEnabled:e.config?.codexConfigEnabled??!0,codexHomeMode:e.config?.codexHomeMode??("local"===t.type?"taskhandoff":"default"),defaultCodexPermissionMode:e.config?.defaultCodexPermissionMode??("docker"===t.type?"full-access":"ask"),aiSessionHistoryLimit:e.config?.aiSessionHistoryLimit??50,aiSessionAttachmentRetentionDays:e.config?.aiSessionAttachmentRetentionDays??30,aiSessionMaxFileAttachmentBytes:e.config?.aiSessionMaxFileAttachmentBytes??ae},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:Ta(),createdAt:i,updatedAt:i}),u=this.controlledInstances.put(l);return this.instancePrivateConfigs.materialize(u.id,u.registrationToken,this.resolvedAssignedModelEnvironment(u.id),this.modelRegistry.privateCatalog(u.id)),e.gitWorkspaceProvisioning?.credentials.every(e=>"operation-only"===e.retention)&&this.gitCredentials.putWorkspaceProvisioning(e.gitWorkspaceProvisioning),u}takeGitWorkspaceProvisioning(e){const t=this.gitCredentials.getWorkspaceProvisioning(e);return this.gitCredentials.removeWorkspaceProvisioning(e),t}setGitWorkspaceProvisioning(e){const t=this.requireInstance(e.instanceId);if("local-folder"===t.source.type||t.source.url!==e.remoteUrl)throw Object.assign(new Error(`Git provisioning does not match instance ${t.id}.`),{code:"GIT_WORKSPACE_PROVISIONING_INSTANCE_MISMATCH",statusCode:409});this.gitCredentials.putWorkspaceProvisioning(e)}gitWorkspaceProvisioningFor(e){if("local-folder"===e.source.type)return;const t=this.gitCredentials.getWorkspaceProvisioning(e.id);if(t)return t;const n=this.gitCredentials.getAuthorizationSet(e.id).credentialIds.flatMap(e=>{const t=this.gitCredentials.getPayload(e);return t?[t]:[]}),i=n.map(e=>({id:e.credential.id,kind:e.credential.kind,scope:e.credential.scope,status:e.credential.status,pinnedKnownHosts:"ssh-key"===e.secret.kind&&Boolean(e.secret.pinnedKnownHosts.trim())})),s=Cc(e.source.url,i);if("ambiguous"===s.status||"missing-host-key"===s.status)throw Object.assign(new Error(`Git credential resolution failed for instance ${e.id}: ${s.status}.`),{code:`GIT_CREDENTIAL_${s.status.replace(/-/g,"_").toUpperCase()}`,statusCode:409});return{operationId:`gitop_${e.id}_${e.stateRevision}`,instanceId:e.id,remoteUrl:e.source.url,ref:e.source.ref,clone:e.source.clone,credentials:n.map((t,n)=>({operationId:`gitcredop_${e.id}_${e.stateRevision}_${n}`,retention:"instance-retained",payload:t}))}}discardGitWorkspaceProvisioning(e){return this.gitCredentials.discardPendingWorkspaceProvisioning(e)}gitWorkspaceProvisioningStatus(e){return this.gitCredentials.workspaceProvisioningStatus(e)}registerInstance(e,t,n){const i=Xs.parse(t),s=te(),r=this.controlledInstances.get(e);if(!r){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(r,i,n),i.processIncarnationId&&i.processIncarnationId===r.processIncarnationId)return r;sd(i.protocolVersion,`Instance ${e}`);const o=i.build?.packageVersion||i.instanceVersion,a=rd(this.requireRuntime(r.runtimeId)),c=Xc(r,o,a),d=Vs.parse({...r,status:"registered",health:o===Wc()?"ok":"degraded",ready:!a&&o===Wc(),connectionStatus:"online",agentStatus:"online",targetStatus:r.targetStatus,uiAccessStatus:r.uiAccessStatus,controlMode:i.controlMode,protocolVersion:i.protocolVersion,instanceVersion:i.instanceVersion,build:i.build,runtimeVersion:c,processIncarnationId:i.processIncarnationId||r.processIncarnationId,capabilities:i.capabilities,appInventory:i.appInventory,workspace:i.workspace,target:r.target,registrationToken:r.registrationToken||i.registrationToken,lastHeartbeatAt:s,updatedAt:s});return this.controlledInstances.put(d)}heartbeatInstance(e,t,n){const i=this.requireInstance(e);this.validateInstanceToken(i,n);const s=Qs.parse(t);i.processIncarnationId&&s.processIncarnationId&&s.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.`),sd(s.protocolVersion,`Instance ${e}`);const r=te(),o=i.target,a=i.targetStatus,c=Xc(i,s.build?.packageVersion||i.build?.packageVersion||i.instanceVersion,rd(this.requireRuntime(i.runtimeId))),d=s.health||i.health,l="running"===(s.status||i.status)&&"failed"!==d,u=Vs.parse({...i,...s,target:o,ready:l,health:d,runtimeVersion:c,processIncarnationId:s.processIncarnationId||i.processIncarnationId,agentStatus:"online",targetStatus:a,uiAccessStatus:a,connectionStatus:"online",build:s.build||i.build,lastHeartbeatAt:r,updatedAt:r});return this.controlledInstances.put(u)}validateInstanceReport(e,t,n){this.validateInstanceToken(e,n||t.registrationToken),t.instanceId&&t.instanceId!==e.id&&id("INSTANCE_ID_MISMATCH",`Instance ${t.instanceId} cannot register as ${e.id}.`),t.nodeId&&t.nodeId!==this.nodeId&&id("INSTANCE_NODE_MISMATCH",`Instance ${e.id} belongs to node ${this.nodeId}.`),t.runtimeId&&t.runtimeId!==e.runtimeId&&id("INSTANCE_RUNTIME_MISMATCH",`Instance ${e.id} belongs to runtime ${e.runtimeId}.`),t.imageSelection&&t.imageSelection.imageId!==e.imageSelection?.imageId&&id("INSTANCE_IMAGE_MISMATCH",`Instance ${e.id} belongs to image ${e.imageSelection?.imageId}.`)}validateInstanceToken(e,t){e.registrationToken&&t===e.registrationToken||id("INSTANCE_REGISTRATION_TOKEN_INVALID",`Invalid registration token for instance ${e.id}.`)}authenticateInstance(e,t){const n=this.requireInstance(e);return this.validateInstanceToken(n,t),n}context(e,t=this.resolvedAssignedModelEnvironment(e.id)){const n=t,i=e.imageSnapshot||gs.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});this.instancePrivateConfigs.get(e.id);const s=this.instancePrivateConfigs.materialize(e.id,e.registrationToken,n,this.modelRegistry.privateCatalog(e.id)),r=this.gitWorkspaceProvisioningFor(e);return{project:nd(e),image:i,node:this.node,runtime:this.requireRuntime(e.runtimeId),instance:e,nodeAgentUrl:this.containerUrl,modelEnv:n,privateConfigPath:this.instancePrivateConfigs.filePath(s.instanceId),...r?{gitWorkspaceProvisioning:r,completeGitWorkspaceProvisioning:()=>this.gitCredentials.completeWorkspaceProvisioning(e.id,r.operationId)}:{}}}}async function dd(e,t){const n=function(e){const t=md(e),n=[],i=t.pathname.split("/").filter(Boolean).at(-1)||"";return Id(n,ud(t.toString(),/^v\d+$/.test(i)?"models":"v1/models")),Id(n,new URL("/v1/models",t.origin).toString()),Id(n,new URL("/models",t.origin).toString()),n}(t.endpoint),i=Date.now();let s;for(const r of n){const n=await hd(e,r,{method:"GET",headers:{accept:"application/json",authorization:`Bearer ${t.key}`}});if(404===n.status||405===n.status){s=n.status;continue}if(!n.ok)throw fd("MODEL_DISCOVERY_FAILED",n.status);const o=await gd(n,"MODEL_DISCOVERY_RESPONSE_INVALID"),a=Array.isArray(o.data)?o.data:void 0;if(!a)throw yd("MODEL_DISCOVERY_RESPONSE_INVALID","The model endpoint returned an invalid model list.",502);return{models:Ad(a.flatMap(e=>{if(!e||"object"!=typeof e||Array.isArray(e))return[];const t=e,n="string"==typeof t.id?t.id.trim():"";if(!n)return[];const i="string"==typeof t.owned_by?t.owned_by.trim():"";return[{id:n,...i?{ownedBy:i}:{}}]}).sort((e,t)=>e.id.localeCompare(t.id))),latencyMs:Date.now()-i}}throw yd("MODEL_DISCOVERY_UNSUPPORTED","No compatible model-list endpoint was found for this endpoint.",502,s)}async function ld(e,t){const n=Date.now(),i=t.protocol||("claude"===t.app?"anthropic-messages":"opencode"===t.app?"openai-chat-completions":"openai-responses"),s="openai-responses"===i?await hd(e,pd(t.endpoint,"responses"),{method:"POST",headers:{accept:"application/json",authorization:`Bearer ${t.key}`,"content-type":"application/json"},body:JSON.stringify({model:t.model,input:"Reply with OK.",max_output_tokens:32,stream:!1})}):"openai-chat-completions"===i?await hd(e,pd(t.endpoint,"chat/completions"),{method:"POST",headers:{accept:"application/json",authorization:`Bearer ${t.key}`,"content-type":"application/json"},body:JSON.stringify({model:t.model,messages:[{role:"user",content:"Reply with OK."}],max_tokens:32,stream:!1})}):await hd(e,function(e){const t=md(e);if(/\/messages\/?$/.test(t.pathname))return t.toString();const n=t.pathname.split("/").filter(Boolean).at(-1)||"";return ud(t.toString(),/^v\d+$/.test(n)?"messages":"v1/messages")}(t.endpoint),{method:"POST",headers:{accept:"application/json","anthropic-version":"2023-06-01","content-type":"application/json","x-api-key":t.key},body:JSON.stringify({model:t.model,max_tokens:8,messages:[{role:"user",content:"Reply with OK."}]})});if(!s.ok)throw fd("MODEL_TEST_FAILED",s.status);if((await gd(s,"MODEL_TEST_RESPONSE_INVALID")).error)throw yd("MODEL_TEST_RESPONSE_INVALID","The model endpoint returned an error payload.",502);return{success:!0,latencyMs:Date.now()-n}}function ud(e,t){const n=md(e);return n.pathname=`${n.pathname.replace(/\/+$/,"")}/${t.replace(/^\/+/,"")}`,n.search="",n.hash="",n.toString()}function pd(e,t){const n=md(e);return n.pathname.replace(/\/+$/,"").endsWith(`/${t}`)?n.toString():ud(n.toString(),t)}function md(e){let t;try{t=new URL(e.trim())}catch{throw yd("MODEL_ENDPOINT_INVALID","The model endpoint must be a valid HTTP or HTTPS URL.",400)}if("http:"!==t.protocol&&"https:"!==t.protocol||t.username||t.password)throw yd("MODEL_ENDPOINT_INVALID","The model endpoint must be an HTTP or HTTPS URL without embedded credentials.",400);return t}async function hd(e,t,n){try{return await e(t,{...n,redirect:"error",signal:AbortSignal.timeout(15e3)})}catch(e){const t=e&&"object"==typeof e&&"name"in e&&"TimeoutError"===e.name;throw yd(t?"MODEL_ENDPOINT_TIMEOUT":"MODEL_ENDPOINT_UNREACHABLE",t?"The model endpoint timed out.":"The model endpoint could not be reached.",t?504:502)}}async function gd(e,t){const n=await e.text();if(n.length>1e6)throw yd(t,"The model endpoint response was too large.",502);try{const e=JSON.parse(n);if(!e||"object"!=typeof e||Array.isArray(e))throw new Error("not an object");return e}catch{throw yd(t,"The model endpoint returned invalid JSON.",502)}}function fd(e,t){return yd(e,401===t||403===t?"The model endpoint rejected the API key.":"The model endpoint rejected the request.",502,t)}function yd(e,t,n,i){return Object.assign(new Error(t),{code:e,statusCode:n,...i?{details:{upstreamStatus:i}}:{}})}function Id(e,t){e.includes(t)||e.push(t)}function Ad(e){const t=new Set;return e.filter(e=>!t.has(e.id)&&(t.add(e.id),!0))}const bd=a.z.object({endpoint:a.z.string().trim().url().max(2048),key:a.z.string().trim().min(1).max(4096).optional(),existingModelId:a.z.string().trim().min(1).max(120).optional()}).strict(),vd=bd.extend({model:a.z.string().trim().min(1).max(240),app:a.z.enum(["codex","claude","opencode"]).optional(),protocol:a.z.enum(["openai-responses","openai-chat-completions","anthropic-messages"]).optional()}).strict().refine(e=>Boolean(e.protocol||e.app),{message:"A model protocol is required.",path:["protocol"]});class wd{invocations=new Map;store;idleTtlMs;maxTtlMs;cleanupTimer;constructor(e,t={}){this.store=e,this.idleTtlMs=t.idleTtlMs??6e4,this.maxTtlMs=t.maxTtlMs??3e5}resolveHttps(e,t){const{match:n,payload:i}=this.store.resolve(e,t);return"unique"!==n.status||"https-token"!==i?.secret.kind?{status:n.status}:{status:"ok",username:i.secret.username,password:i.secret.token}}async prepareSsh(e,i){this.cleanupExpired();const{match:s,payload:r}=this.store.resolve(e,i);if("unique"!==s.status||"ssh-key"!==r?.secret.kind)return{status:s.status};const o=`gitssh_${d.randomUUID()}`,a=t.mkdtempSync(n.join(c.tmpdir(),"task-handoff-node-git-ssh-"));t.chmodSync(a,448);const l=n.join(a,"agent.sock"),u=n.join(a,"askpass.sh");let p;t.writeFileSync(u,"#!/bin/sh\nprintf '%s' \"${TASK_HANDOFF_SSH_KEY_PASSPHRASE:-}\"\n",{mode:448});try{const n=await Ed("ssh-agent",["-s","-a",l]);if(p=Number(/SSH_AGENT_PID=(\d+)/.exec(n)?.[1]),!Number.isInteger(p)||p<=0)throw new Error("ssh-agent did not report a process id.");const s={...process.env,SSH_AUTH_SOCK:l,SSH_ASKPASS:u,SSH_ASKPASS_REQUIRE:"force",DISPLAY:process.env.DISPLAY||":0",TASK_HANDOFF_SSH_KEY_PASSPHRASE:r.secret.passphrase||""};await zd("ssh-add",["-"],r.secret.privateKey,s);const c=await Ed("ssh-add",["-L"],s);t.rmSync(u,{force:!0});const d=Date.now();return this.invocations.set(o,{instanceId:e,remoteUrl:i,credentialId:r.credential.id,credentialRevision:r.credential.revision,socketPath:l,agentPid:p,directory:a,idleExpiresAt:d+this.idleTtlMs,absoluteExpiresAt:d+this.maxTtlMs}),this.scheduleCleanup(),{status:"ok",invocationId:o,publicIdentity:c,pinnedKnownHosts:r.secret.pinnedKnownHosts}}catch(e){if(p)try{process.kill(p,"SIGTERM")}catch{}throw t.rmSync(a,{recursive:!0,force:!0}),e}}async exchangeAgentFrame(e,t,n){this.cleanupExpired();const i=this.invocations.get(t);if(!i||i.instanceId!==e)throw Sd("GIT_CREDENTIAL_SSH_INVOCATION_INVALID",404);const{match:s,payload:r}=this.store.resolve(e,i.remoteUrl);if("unique"!==s.status||"ssh-key"!==r?.secret.kind||r.credential.id!==i.credentialId||r.credential.revision!==i.credentialRevision)throw this.release(t,e),Sd("GIT_CREDENTIAL_SSH_INVOCATION_REVOKED",403);const o=Buffer.from(n,"base64");if(o.length<5||o.length>1048576||o.readUInt32BE(0)!==o.length-4)throw Sd("GIT_CREDENTIAL_SSH_AGENT_FRAME_INVALID",400);i.idleExpiresAt=Math.min(i.absoluteExpiresAt,Date.now()+this.idleTtlMs),this.scheduleCleanup();const a=Math.max(1,Math.min(i.idleExpiresAt,i.absoluteExpiresAt)-Date.now());try{const e=await function(e,t,n){return new Promise((i,s)=>{const r=m.createConnection(e),o=[];let a=0,c=!1;const d=(e,t)=>{c||(c=!0,r.destroy(),e?s(e):i(t))};r.setTimeout(n),r.once("timeout",()=>d(new Error("Managed Git SSH agent exchange timed out."))),r.once("error",e=>d(e)),r.once("end",()=>d(new Error("Managed Git SSH agent closed before returning a complete frame."))),r.once("close",()=>d(new Error("Managed Git SSH agent closed before returning a complete frame."))),r.on("data",e=>{o.push(e);const t=Buffer.concat(o);!a&&t.length>=4&&(a=t.readUInt32BE(0)+4,a<5||a>1048576)?d(new Error("Managed Git SSH agent returned an invalid frame length.")):a&&t.length>=a&&d(void 0,t.subarray(0,a))}),r.once("connect",()=>r.write(t,e=>{e&&d(e)}))})}(i.socketPath,o,a);return{frame:e.toString("base64")}}catch{throw this.release(t,e),Sd("GIT_CREDENTIAL_SSH_AGENT_UNAVAILABLE",502)}}release(e,n){const i=this.invocations.get(e);if(!i||void 0!==n&&i.instanceId!==n)return!1;this.invocations.delete(e);try{process.kill(i.agentPid,"SIGTERM")}catch{}return t.rmSync(i.directory,{recursive:!0,force:!0}),this.scheduleCleanup(),!0}close(){this.cleanupTimer&&clearTimeout(this.cleanupTimer),this.cleanupTimer=void 0;for(const e of[...this.invocations.keys()])this.release(e)}cleanupExpired(){const e=Date.now();for(const[t,n]of this.invocations)(n.idleExpiresAt<=e||n.absoluteExpiresAt<=e)&&this.release(t)}scheduleCleanup(){this.cleanupTimer&&clearTimeout(this.cleanupTimer),this.cleanupTimer=void 0;const e=Math.min(...[...this.invocations.values()].map(e=>Math.min(e.idleExpiresAt,e.absoluteExpiresAt)));Number.isFinite(e)&&(this.cleanupTimer=setTimeout(()=>{this.cleanupTimer=void 0,this.cleanupExpired(),this.scheduleCleanup()},Math.max(0,e-Date.now())),this.cleanupTimer.unref?.())}}function Sd(e,t){return Object.assign(new Error("Managed Git broker request was rejected."),{code:e,statusCode:t})}function Ed(e,t,n=process.env){return zd(e,t,void 0,n)}function zd(e,t,n,i){return new Promise((s,r)=>{const o=l.spawn(e,t,{shell:!1,env:i,stdio:[void 0===n?"ignore":"pipe","pipe","pipe"]}),a=[];o.stdout.on("data",e=>a.push(e)),o.once("error",()=>r(new Error(`Managed Git SSH broker could not start ${e}.`))),o.once("close",t=>0===t?s(Buffer.concat(a).toString("utf8")):r(new Error(`Managed Git SSH broker command ${e} failed.`))),void 0!==n&&o.stdin.end(n)})}const Nd=a.z.object({credentialId:a.z.string().trim().min(1).max(120)}).strict(),Td=a.z.object({id:a.z.string().trim().min(1).max(120)}).strict(),_d=Td.extend({invocationId:a.z.string().trim().min(1).max(120)}).strict();function kd(e){const t=e.authorization;return"string"==typeof t&&t.startsWith("Bearer ")?t.slice(7).trim():void 0}const Cd=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(),Od=a.z.object({id:a.z.string().trim().min(1).max(120).optional(),name:a.z.string().trim().max(160),path:a.z.string().trim().min(1).max(4096),defaultImageSelection:Bn.optional(),labels:a.z.record(a.z.string(),a.z.string()).default({})}).strict(),xd=a.z.object({name:a.z.string().trim().max(160)}).strict(),Rd=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(),Pd=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:Bn.optional(),environmentSource:qn.optional(),projectId:a.z.string().trim().min(1).max(120).optional(),image:gs.optional(),source:Fi,sourceSnapshot:a.z.record(a.z.string(),a.z.unknown()).default({}),config:a.z.object({autoImportAgentConfigs:a.z.boolean().optional(),codexConfigEnabled:a.z.boolean().optional(),codexHomeMode:a.z.enum(["default","taskhandoff"]).optional(),defaultCodexPermissionMode:Be.optional(),aiSessionHistoryLimit:a.z.number().int().min(1).max(vt).optional(),aiSessionAttachmentRetentionDays:a.z.number().int().min(0).max(365).optional(),aiSessionMaxFileAttachmentBytes:a.z.number().int().positive().max(ce).optional()}).strict().optional(),modelSelection:Vs.shape.modelSelection,gitWorkspaceProvisioning:Nc.optional()}).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."}),e.gitWorkspaceProvisioning&&"local-folder"===e.source.type&&t.addIssue({code:"custom",path:["gitWorkspaceProvisioning"],message:"Git provisioning requires a Git source."})}),Dd=a.z.object({name:a.z.string().trim().min(1).max(160).optional(),config:a.z.object({autoImportAgentConfigs:a.z.boolean().optional(),codexConfigEnabled:a.z.boolean().optional(),codexHomeMode:a.z.enum(["default","taskhandoff"]).optional(),defaultCodexPermissionMode:Be.optional(),aiSessionHistoryLimit:a.z.number().int().min(1).max(vt).optional(),aiSessionAttachmentRetentionDays:a.z.number().int().min(0).max(365).optional(),aiSessionMaxFileAttachmentBytes:a.z.number().int().positive().max(ce).optional()}).strict().optional(),modelSelection:Vs.shape.modelSelection.optional()}).strict(),Md=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(),jd=Md.omit({id:!0}).partial().strict();function Ld(e){const t=e.authorization;return"string"==typeof t&&t.startsWith("Bearer ")?t.slice(7).trim():void 0}class Fd{operations=new Map;intents=new Map;intent(e){const t=this.intents.get(e);if(t)return t;const n={controller:new AbortController};return this.intents.set(e,n),n}invalidate(e){this.intents.get(e)?.controller.abort();const t={controller:new AbortController};return this.intents.set(e,t),t}isIntentCurrent(e,t){return this.intents.get(e)===t}signal(e,t){const n=this.intents.get(e);return n===t?n.controller.signal:AbortSignal.abort()}clearIntent(e){this.intents.delete(e)}async run(e,t){const n=this.operations.get(e)||Promise.resolve();let i;const s=new Promise(e=>{i=e});this.operations.set(e,s),await n;try{return await t()}finally{i(),this.operations.get(e)===s&&this.operations.delete(e)}}}const $d=a.z.object({gitWorkspaceProvisioning:Nc.optional()}).strict().default({});class Ud{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=te();return this.state.controlledInstances.put(Vs.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}`,s=this.inFlight.get(i);if(s)return s;const r=this.provisionGeneration(e,n,t).finally(()=>{this.inFlight.get(i)===r&&this.inFlight.delete(i)});return this.inFlight.set(i,r),r}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 s,r=0,o=!1,a=Promise.resolve();try{const c=await this.images.ensure(i.imageSnapshot.requestedReference,n=>{a=a.then(async()=>{if(!s)try{await this.updatePhase(e.id,t,n,e.createdAt)}catch(e){s={error:e}}})},n=>{this.stopped||(o=!0,r=n.sequence,this.publishTerminalOutput(e,t,n))},this.abortController.signal);if(await a,s)throw s.error;if(this.stopped)return;o&&this.publishFinished(e,t,r+1,"succeeded");const d=async()=>{if(this.stopped)return;const i=this.currentGeneration(e.id,t,!0,e.createdAt);if(!i)return;const s=this.state.controlledInstances.put(Vs.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:te()},updatedAt:te()}));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"===s.status&&await(n?.())};await(this.options.runInstanceOperation?.(e.id,d)??d())}catch(n){if(await a,s&&(n=s.error),this.stopped)return;o&&this.publishFinished(e,t,r+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(Vs.parse({...n,status:"failed",health:"failed",imageProvisioning:{...n.imageProvisioning,phase:"failed",error:i,updatedAt:te()},updatedAt:te()})),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 s=this.state.controlledInstances.get(e);if(!(!s||i&&s.createdAt!==i||s.imageProvisioning?.generation!==t||n&&!s.imageSnapshot))return s}async updatePhase(e,t,n,i){if(this.stopped)return;const s=async()=>{if(this.stopped)return;const s=this.currentGeneration(e,t,!0,i);s&&["provisioning","starting"].includes(s.status)&&(this.state.controlledInstances.put(Vs.parse({...s,status:"starting"===s.status?"starting":"provisioning",imageProvisioning:{...s.imageProvisioning,phase:n,error:void 0,updatedAt:te()},updatedAt:te()})),this.options.sync())};await(this.options.runInstanceOperation?.(e,s)??s())}eventBase(e,t){return{instanceId:e.id,generation:t,requestedReference:e.imageProvisioning.requestedReference,observedAt:te()}}publishTerminalOutput(e,t,n){for(const[i,s]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(ys,{...this.eventBase(e,t),sequence:1e3*n.sequence+i,data:s,...n.replay?{replay:!0}:{}},e.id)}publishFinished(e,t,n,i){this.options.publish(Is,{...this.eventBase(e,t),sequence:1e3*n,outcome:i},e.id)}}const Vd=a.z.object({name:a.z.string().trim().min(1).max(160)}).strict();function Hd(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 Bd{templateOperations=new Fd;store;privateConfigs;docker;requireInstanceValue;requireRuntimeValue;runInstanceOperationValue;isImageReferencedValue;constructor(e,t,n,i,s,r,o=()=>!1){this.store=e,this.privateConfigs=t,this.docker=n,this.requireInstanceValue=i,this.requireRuntimeValue=s,this.runInstanceOperationValue=r,this.isImageReferencedValue=o}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=Vd.parse(t),i=this.requireInstanceValue(e),s=this.requireRuntimeValue(i.runtimeId);if("docker"!==s.type)throw Object.assign(new Error(`Runtime ${s.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 r=te(),o=Na("envtpl"),a=`task-handoff/environment-template:${o.toLowerCase().replace(/[^a-z0-9_.-]/g,"-")}`;return this.store.put(ai.parse({id:o,name:n.name,sourceInstanceId:i.id,nodeId:i.nodeId,internalTag:a,status:"creating",createdAt:r,updatedAt:r})),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 s=this.privateConfigs.get(i.id);if(!s)throw Object.assign(new Error(`Instance ${i.id} private configuration is missing.`),{code:"INSTANCE_PRIVATE_CONFIG_MISSING"});const r=[s.instanceCredential,...Object.values(s.environment)];await this.docker.inspectContainerConfigSecurity(n.runtime.containerName,r),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,r),this.store.put(ai.parse({...this.require(o),...c,status:"ready",error:void 0,updatedAt:te()}))}catch(n){return t&&(await this.docker.untagEnvironmentTemplate(a,e).catch(()=>!1),e&&await this.docker.garbageCollectEnvironmentTemplateImage(e).catch(()=>!1)),this.store.put(ai.parse({...this.require(o),status:"failed",error:Hd(n,"ENVIRONMENT_TEMPLATE_CREATE_FAILED","commit"),updatedAt:te()}))}})}async delete(e){return this.runTemplateOperation(e,async()=>{const t=this.require(e);this.store.put(ai.parse({...t,status:"deleting",error:void 0,updatedAt:te()}));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(ai.parse({...t,status:"failed",error:Hd(e,"ENVIRONMENT_TEMPLATE_DELETE_FAILED","delete"),updatedAt:te()})),e}})}async releaseUnusedImage(e){return!this.store.list().some(t=>t.imageId===e)&&!this.isImageReferencedValue(e)&&this.docker.garbageCollectEnvironmentTemplateImage(e)}}const qd=new Set(["content-encoding","content-length","transfer-encoding"]),Kd=67108864;function Gd(e){return Object.fromEntries([...e.entries()].filter(([e])=>!qd.has(e.toLowerCase())))}function Wd(e){return e.bodyBase64?Buffer.from(e.bodyBase64,"base64"):e.body}function Jd(){const e=Number(process.env.TASK_HANDOFF_INSTANCE_PROXY_MAX_RESPONSE_BYTES);return Number.isSafeInteger(e)&&e>0?e:67108864}const Yd="x-task-handoff-trace-id";function Xd(e){return e.startsWith("/")?e:`/${e}`}function Qd(e,t){return e.code(502).send({error:{code:"INSTANCE_PROXY_RESPONSE_TOO_LARGE",message:`Instance response exceeds ${t} bytes.`}})}async function Zd(e,t,n,i){try{return await e(t,n)}catch(e){if(n.signal?.aborted)throw e;throw i.diagnostic({instanceId:i.instanceId,action:"proxy.upstream.failed",method:i.method,path:i.path,error:e instanceof Error?e.message:String(e)},"node instance proxy upstream unavailable"),Object.assign(new Error(`Instance ${i.instanceId} web endpoint is not reachable.`),{statusCode:502,code:"INSTANCE_PROXY_UPSTREAM_UNREACHABLE",retryable:!0,cause:e})}}function el(e,t){return Object.assign(new Error(`Instance ${e.id} has an invalid node-owned web endpoint: ${t}`),{statusCode:409,code:"NODE_INSTANCE_WEB_ENDPOINT_INVALID"})}function tl(e,t){const n=t||("local"===e.runtime?.kind&&e.runtime.port?`http://127.0.0.1:${e.runtime.port}`:void 0);if(!n){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}let i;try{i=new URL(n)}catch{throw el(e,"endpoint is not a URL")}if("http:"!==i.protocol||"127.0.0.1"!==i.hostname||!i.port||i.username||i.password||"/"!==i.pathname&&""!==i.pathname||i.search||i.hash)throw el(e,"endpoint must be an origin-only http://127.0.0.1:<port> URL");return i.origin}const nl=a.z.object({version:a.z.literal(1),externalListener:xs}).strict();function il(e){return"all-ipv4"===e?"0.0.0.0":"127.0.0.1"}function sl(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),s=Object.keys(n).filter(e=>"bindScope"!==e&&"port"!==e);return(i.length||s.length)&&console.warn(JSON.stringify({message:"unknown stored node agent runtime setting fields were ignored",filePath:"runtime-settings.json",fields:[...i,...s.map(e=>`externalListener.${e}`)]})),{version:t.version,externalListener:{bindScope:n.bindScope,port:n.port}}}async function rl(e){const t=il(e.bindScope);return!await new Promise(t=>{const n=m.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=m.createServer();i.once("error",()=>n(!1)),i.listen({host:t,port:e.port,exclusive:!0},()=>i.close(()=>n(!0)))})}class ol{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 Rs.parse({...this.config,host:il(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:il(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 ${il(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=Ps.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 ${il(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",s),n(e)},s=()=>{this.app.server.off("error",i),t()};this.app.server.once("error",i),this.app.server.once("listening",s),this.app.server.listen({host:il(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 al="TASK_HANDOFF_NODE_AGENT_V1",cl="/api/node-tunnel";function dl(e=""){return d.createHash("sha256").update(e).digest("hex")}function ll(e,t){return d.createHmac("sha256",e).update(function(e){return[al,e.keyId,e.method.toUpperCase(),e.pathWithQuery,e.timestamp,e.nonce,e.bodySha256].join("\n")}(t)).digest("hex")}function ul(e){const t=e.timestamp||(new Date).toISOString(),n=e.nonce||d.randomBytes(18).toString("base64url"),i=dl(e.body||""),s=ll(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":s}}class pl{usedNonces=new Map;identity;nodeId;overrideSecret;overrideKeyId;nowMs;constructor(e,t,n,i,s=Date.now){this.identity=e,this.nodeId=t,this.overrideSecret=n,this.overrideKeyId=i,this.nowMs=s}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 s=i.filter(e=>t.keyId===e.keyId);if(!s.length)throw Object.assign(new Error("Invalid node agent HMAC key id."),{statusCode:401,code:"NODE_AGENT_HMAC_KEY_INVALID"});const r=Date.parse(t.timestamp);if(!Number.isFinite(r)||Math.abs(this.nowMs()-r)>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 o=`${t.nodeId}:${t.keyId}:${t.nonce}`;if(this.usedNonces.has(o))throw Object.assign(new Error("Node agent HMAC nonce was already used."),{statusCode:401,code:"NODE_AGENT_HMAC_NONCE_REPLAY"});const a=dl(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(!s.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,ll(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(o,r+6e4+1),t.keyId}pruneNonces(){const e=this.nowMs();for(const[t,n]of this.usedNonces)n<=e&&this.usedNonces.delete(t)}}const ml=a.z.string().trim().min(1).max(160),hl=a.z.string().datetime(),gl=a.z.string().min(1).max(4096),fl=a.z.string().trim().url().max(2048),yl=a.z.object({id:ml,keyId:ml,name:a.z.string().trim().min(1).max(160).optional(),secret:gl,pairedAt:hl,revokedAt:hl.optional(),updatedAt:hl}).strip(),Il=a.z.object({id:ml,pairingKeyId:ml,name:a.z.string().trim().min(1).max(160).optional(),url:fl,enabled:a.z.boolean().default(!0),createdAt:hl,updatedAt:hl}).strip(),Al=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(),bl=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(),vl=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(),wl=new Set(["nodeId","createdAt","updatedAt","pairingInvites","controlPlanePairings","controlPlaneConnections","remoteControlPlanes"]),Sl=new Set(["id","keyId","name","secret","pairedAt","revokedAt","updatedAt"]),El=new Set(["id","pairingKeyId","name","url","enabled","createdAt","updatedAt"]),zl=new Set(["id","keyId","name","url","secret","pairedAt","updatedAt","active"]);function Nl(e,t){console.warn(JSON.stringify({message:e,...t}))}function Tl(e,t){return Object.assign(new Error(e,void 0===t?void 0:{cause:t}),{code:"NODE_AGENT_IDENTITY_INVALID"})}function _l(e,t){return Object.keys(e).filter(e=>!t.has(e))}function kl(e,t,n){const i=hl.safeParse(e);return i.success?i.data:(n("invalid node agent identity timestamp was replaced",{field:t}),te())}function Cl(e,t){if(!e||"object"!=typeof e||Array.isArray(e))throw Tl("Node agent identity must be a JSON object.");const n=e,i=ml.safeParse(n.nodeId);if(!i.success)throw Tl("Node agent identity has an invalid nodeId.",i.error);const s=i.data,r=_l(n,wl);r.length&&t("unknown node agent identity fields were ignored",{fields:r}),Array.isArray(n.pairingInvites)&&n.pairingInvites.length&&t("persisted node agent pairing invites were discarded",{count:n.pairingInvites.length});const o=Array.isArray(n.remoteControlPlanes)?n.remoteControlPlanes.flatMap(e=>{if(!e||"object"!=typeof e||Array.isArray(e))return[];const n=e,i=_l(n,zl);i.length&&t("unknown legacy node agent remote control-plane fields were ignored",{fields:i});const s=yl.safeParse(n);if(!s.success)return t("invalid legacy node agent control-plane pairing was ignored",{issues:s.error.issues}),[];const r=n.url?Il.safeParse({id:`connection_${s.data.keyId}`,pairingKeyId:s.data.keyId,name:n.name,url:n.url,enabled:!1!==n.active,createdAt:s.data.pairedAt,updatedAt:s.data.updatedAt}):void 0;return[{pairing:s.data,...r?.success?{connection:r.data}:{}}]}):[],a=(e,n,i,s)=>Array.isArray(e)?e.flatMap(e=>{if(!e||"object"!=typeof e||Array.isArray(e))return t(`invalid node agent ${s} was ignored`,{}),[];const r=_l(e,n);r.length&&t(`unknown node agent ${s} fields were ignored`,{fields:r});const o=i.safeParse(e);return o.success?[o.data]:(t(`invalid node agent ${s} was ignored`,{issues:o.error.issues}),[])}):[];return{nodeId:s,createdAt:kl(n.createdAt,"createdAt",t),updatedAt:kl(n.updatedAt,"updatedAt",t),controlPlanePairings:n.controlPlanePairings?a(n.controlPlanePairings,Sl,yl,"control-plane pairing"):o.map(e=>e.pairing),controlPlaneConnections:n.controlPlaneConnections?a(n.controlPlaneConnections,El,Il,"control-plane connection"):o.flatMap(e=>e.connection?[e.connection]:[])}}class Ol{paths;logger;constructor(e,t={}){this.paths=e,this.logger=t.logger||Nl}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 Tl(`Node agent identity contains invalid JSON: ${this.paths.identityPath}`,e)}return Cl(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=Cl({...e,updatedAt:te()},this.logger);I.sync(this.paths.identityPath,`${JSON.stringify(i,null,2)}\n`,{encoding:"utf8",mode:384})}}class xl{values=new Map;put(e,t,n=Date.now()){this.prune(n),this.values.set(e,t)}take(e,t=Date.now()){this.prune(t);const n=this.values.get(e);return n&&this.values.delete(e),n}peek(e,t=Date.now()){return this.prune(t),this.values.get(e)}delete(e,t=Date.now()){this.prune(t);const n=this.values.get(e);return n&&this.values.delete(e),n}list(e=Date.now()){return this.prune(e),[...this.values.values()]}prune(e=Date.now()){for(const[t,n]of this.values)Date.parse(n.expiresAt)<=e&&this.values.delete(t)}}class Rl{store;pairingInvites=new xl;controlPlaneConnectionOperations=new Map;constructor(e){this.store=new Ol(e),this.store.init()}async runControlPlaneConnectionOperation(e,t){const n=e.replace(/\/$/,""),i=this.controlPlaneConnectionOperations.get(n)||Promise.resolve();let s;const r=new Promise(e=>{s=e});this.controlPlaneConnectionOperations.set(n,r),await i;try{return await t()}finally{s(),this.controlPlaneConnectionOperations.get(n)===r&&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=Na("node");return this.writeNodeId(n),n}createPairingInvite(e){const t=te(),n=new Date(Date.now()+(e.expiresInMs||6e5)).toISOString(),i=Ta(),s={tokenHash:dl(i),createdAt:t,expiresAt:n,...e.controlPlaneName?{controlPlaneName:e.controlPlaneName}:{}};return this.pairingInvites.put(s.tokenHash,s),{...s,token:i}}completePairingInvite(e){const t=this.store.read()||this.newIdentity(),n=dl(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 s=te(),r={id:e.controlPlaneId||Na("cp"),keyId:Na("key"),...e.controlPlaneName||i.controlPlaneName?{name:e.controlPlaneName||i.controlPlaneName}:{},secret:Ta(),pairedAt:s,updatedAt:s};return this.store.write({...t,controlPlanePairings:[...(t.controlPlanePairings||[]).filter(e=>e.id!==r.id),r]}),r}stageControlPlaneConnection(e){const{pairing:t,connection:n}=this.createControlPlaneConnection(e),i=this.store.read()||this.newIdentity(),s=n.url.replace(/\/$/,""),r=(i.controlPlaneConnections||[]).filter(e=>e.id===n.id||e.url.replace(/\/$/,"")===s);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(/\/$/,"")!==s),n]}),{pairing:t,connection:n,replacedConnections:r}}commitControlPlaneConnection(e,t={}){const n=this.store.read()||this.newIdentity(),i={...e.pairing,...t.name?{name:t.name}:{}},s={...e.connection,...t.name?{name:t.name}:{}},r=new Set((n.controlPlaneConnections||[]).map(e=>e.pairingKeyId)),o=new Set(e.replacedConnections.map(e=>e.pairingKeyId));return this.store.write({...n,controlPlanePairings:[...(n.controlPlanePairings||[]).filter(e=>e.keyId!==i.keyId&&(!o.has(e.keyId)||r.has(e.keyId))),i],controlPlaneConnections:[...(n.controlPlaneConnections||[]).filter(e=>e.id!==s.id),s]}),{pairing:i,connection:s}}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=te(),n={id:Na("cp"),keyId:Na("key"),...e.name?{name:e.name}:{},secret:Ta(),pairedAt:t,updatedAt:t};return{pairing:n,connection:{id:Na("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=te();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(),s=(i?.controlPlanePairings||[]).filter(e=>!e.revokedAt);if(!s.length)return;if(e){const t=e.replace(/\/$/,""),n=(i?.controlPlaneConnections||[]).find(e=>e.url.replace(/\/$/,"")===t),r=n&&s.find(e=>e.keyId===n.pairingKeyId);if(r)return{keyId:r.keyId,secret:r.secret}}const r=[...s].sort((e,t)=>t.updatedAt.localeCompare(e.updatedAt))[0];return r?{keyId:r.keyId,secret:r.secret}:void 0}newIdentity(){return{nodeId:this.resolveNodeId(),createdAt:te(),updatedAt:te(),controlPlanePairings:[],controlPlaneConnections:[]}}writeNodeId(e){const t=this.store.read();this.store.write({...t||{createdAt:te()},nodeId:e,updatedAt:te(),controlPlanePairings:t?.controlPlanePairings||[],controlPlaneConnections:t?.controlPlaneConnections||[]})}}const Pl=a.z.string().trim().min(1).max(160);const Dl=xi.strict();function Ml(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 jl{preflights=new Map;options;applying=!1;constructor(e){this.options=e}async check(e){const t=ki.parse(e),n=Ml(this.options.listInstances()),i=await qa(this.options.runCommand,this.options.moduleDir),s=this.options.currentRuntimeVersion(),r=this.options.managedUpdateSupport?.(i)||{supported:!0};if(!r.supported)return Ci.parse({source:"npm",channel:t.channel,currentVersion:i.currentVersion||s,availableVersion:i.currentVersion||s||"unavailable",impact:n,updateAvailable:!1,supported:!1,reason:r.reason||"Managed updates are unavailable on this node.",checkedAt:(new Date).toISOString()});const o="@task-handoff/server"===i.packageName?[...new Set([...i.relatedCurrentVersions,s])]:i.relatedCurrentVersions,a=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),s=await e(Ha(),["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(!s)return;const r=JSON.parse(s.stdout);if("string"!=typeof r)throw new Error(`npm did not resolve ${t}@${i} to one version.`);return r}(e.runCommand,t,e.channel);if(!n)return function(e){return Ci.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:te()})}({channel:e.channel,currentVersion:e.currentVersion,impact:e.impact});const i=Va(e.currentVersion,n)||(e.relatedCurrentVersions||[]).some(e=>Va(e,n)),s=i?await async function(e,t,n){const i=await e(Ha(),["view",`${t}@${n}`,"dist.integrity","--json"]),s=JSON.parse(i.stdout);if("string"!=typeof s||!/^sha(?:256|384|512)-[A-Za-z0-9+/=]+$/.test(s))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 s}(e.runCommand,t,n):void 0;return Ci.parse({source:"npm",channel:e.channel,currentVersion:e.currentVersion,availableVersion:n,...s?{artifactRef:`npm:${t}@${n}#${s}`}:{},runtimeArtifacts:e.runtimeArtifacts||[],impact:e.impact||{runningInstanceCount:0,stoppedInstanceCount:0,activeInstanceCount:0,restartInstanceCount:0,runningInstanceIds:[],stoppedInstanceIds:[],activeInstanceIds:[]},updateAvailable:i,checkedAt:te()})}({channel:t.channel,currentVersion:i.currentVersion||s,runCommand:this.options.runCommand,packageName:i.packageName,relatedCurrentVersions:o,impact:n});if(!a.updateAvailable)return a;const c={...a,runtimeArtifacts:await this.options.resolveRuntimeArtifacts(a.availableVersion),preflightToken:Ta()};return this.preflights.set(c.preflightToken,{result:c,expiresAt:Date.now()+6e5}),c}async apply(e){const i=Dl.parse(e),s=this.preflights.get(i.preflightToken);(!s||s.expiresAt<=Date.now())&&await this.consumePreflight(i),this.applying&&this.throwAlreadyRunning(),this.applying=!0;try{const{check:e,selection:s}=await this.consumePreflight(i);if(this.options.jobs.list().some(e=>!["succeeded","degraded","failed"].includes(e.status))&&this.throwAlreadyRunning(),!e.supported)throw Object.assign(new Error(e.reason||"The requested update is not supported."),{statusCode:400,code:"UPDATE_UNSUPPORTED"});if(!e.updateAvailable)throw Object.assign(new Error(e.reason||"No update is available for the selected channel."),{statusCode:409,code:"UPDATE_NOT_AVAILABLE"});const r=this.options.jobs.create(this.options.nodeId,e),{worker:o,packaged:a,expectedWorker:c}=function(e,i=t.existsSync){const s=[n.resolve(e,"..","bin","task-handoff-node-update-worker"),n.resolve(e,"..","..","bin","task-handoff-node-update-worker")],r=s.find(i),o=n.resolve(e,"..","..","..","..","scripts","node-update-worker.cts");return r?{worker:r,packaged:!0,expectedWorker:s[0]}:i(o)?{worker:o,packaged:!1,expectedWorker:s[0]}:{worker:void 0,packaged:!1,expectedWorker:s[0]}}(this.options.moduleDir);if(!o)throw this.options.jobs.patch(r.id,{status:"failed",rollout:{...r.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-${r.id}`,"--collect","--property=Type=exec",...a?[o]:[process.execPath,o],"--job-file",this.options.jobs.records.filePath(r.id),"--target-version",r.toVersion,"--npm-command",Ha(),"--install-prefix",s.installPrefix,...process.env.TASK_HANDOFF_NODE_AGENT_IPC_PATH?.trim()?["--node-agent-ipc-path",process.env.TASK_HANDOFF_NODE_AGENT_IPC_PATH.trim()]:[],...d?["--control-plane-health-url",d]:[]])}catch(e){const t=e instanceof Error?e.message:String(e);throw this.options.jobs.patch(r.id,{status:"failed",rollout:{...r.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 await this.waitForWorkerClaim(r)}finally{this.applying=!1}}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 qa(this.options.runCommand,this.options.moduleDir);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(Ml(this.options.listInstances()))||this.throwStale();const s=await this.options.resolveRuntimeArtifacts(n.availableVersion);return JSON.stringify(n.runtimeArtifacts)!==JSON.stringify(s)&&this.throwStale(),{check:n,selection:i}}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"})}throwAlreadyRunning(){throw Object.assign(new Error("Another server update is already running on this node."),{statusCode:409,code:"SERVER_UPDATE_ALREADY_RUNNING"})}async waitForWorkerClaim(e){const t=this.options.workerClaimTimeoutMs??5e3,n=this.options.workerClaimPollMs??50,i=Date.now()+t;for(;Date.now()<=i;){const t=this.options.jobs.records.get(e.id);if(!t)throw Object.assign(new Error(`Update job ${e.id} disappeared before the worker claimed it.`),{statusCode:500,code:"UPDATE_JOB_NOT_FOUND"});if("queued"!==t.status)return t;if(Date.now()>=i)break;await new Promise(e=>setTimeout(e,Math.max(1,Math.min(n,i-Date.now()))))}const s=this.options.jobs.records.get(e.id);if("queued"!==s?.status)return s||e;throw this.options.jobs.patch(e.id,{status:"failed",rollout:{...s.rollout,phase:"failed"},error:{code:"NODE_UPDATE_FAILED",message:"The node update worker did not claim the queued job after systemd accepted it.",retryable:!0},completedAt:(new Date).toISOString()}),Object.assign(new Error("The node update worker did not start after systemd accepted the update job."),{statusCode:500,code:"NODE_UPDATE_WORKER_START_TIMEOUT"})}}const Ll=new Set(["provisioning","starting","registering","registered","running"]);function Fl(e){return Ll.has(e.status)&&!ha(e)}function $l(e){return Vs.parse({...e,health:"unknown",connectionStatus:"offline",agentStatus:"offline",targetStatus:"unknown",uiAccessStatus:"unknown",target:{...e.target,status:"unknown"},updatedAt:te()})}class Ul{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);return!["failed","stopping","stopped"].includes(t.status)&&!ha(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(),s=this.unexpectedExitRetries.get(e),r=this.options.crashStableWindowMs??3e4,o=s&&i-s.lastExitAt<r?s.attempt+1:1;this.unexpectedExitRetries.set(e,{attempt:o,lastExitAt:i});const a=this.options.retryBaseDelayMs??1e3,c=1===o?0:Math.min(this.options.retryMaxDelayMs??3e4,a*2**Math.min(o-2,10)),d=t instanceof Error?t.message:String(t);this.restoreErrors.set(e,{message:d,attempt:o,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(Ll.has(t.status)||"failed"===t.status)&&(!e||e.nextAttemptAt<=(this.options.nowMs?.()??Date.now()))}return"docker"===n.type&&Fl(t)});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),s=this.restoreErrors.get(n.id),r=(s?.attempt??0)+1,o=this.options.retryBaseDelayMs??1e3,a=Math.min(this.options.retryMaxDelayMs??3e4,o*2**Math.min(r-1,10)),c=(this.options.nowMs?.()??Date.now())+a;this.restoreErrors.set(n.id,{message:i,attempt:r,nextAttemptAt:c}),s?.message===i&&s.attempt===r||this.options.warn({instanceId:n.id,action:"restore",runtimeId:n.runtimeId,error:i,attempt:r,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(Ll.has(e.status)||"failed"===e.status)&&(!t||t.nextAttemptAt<=(this.options.nowMs?.()??Date.now()))}return"docker"===t.type&&Fl(e)}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)&&!ha(e)&&!["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($l(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 s=t.get(n);return!s||this.restoredInstances.has(n)||this.suppressedInstances.has(n)||"local"!==this.options.state.requireRuntime(s.runtimeId).type?e:Ll.has(s.status)||"failed"===s.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?.()}}}const Vl=new Set(["DELETE","GET","HEAD","PATCH","POST","PUT","OPTIONS"]);function Hl(e){return"string"==typeof e&&Vl.has(e.toUpperCase())?e.toUpperCase():"GET"}function Bl(e,t){const n=new URL(t.tunnelUrl);n.searchParams.set("nodeId",t.nodeId);const i=t.secret?ul({nodeId:t.nodeId,keyId:t.keyId,secret:t.secret,method:"GET",pathWithQuery:`${n.pathname}${n.search}`}):{},s=new p(n,{headers:i}),r=new Map,o=new Map,a=new Map;let c;s.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,s=new URL(`/api/node-agent${n}`,`http://127.0.0.1:${i}`);return s.protocol="ws:",s},l=(e,n,i,s={})=>{const r=e.startsWith("/")?e:`/${e}`;return{...s,...t.secret&&t.keyId?ul({nodeId:t.nodeId,keyId:t.keyId,secret:t.secret,method:n,pathWithQuery:`/api/node-agent${r}`,body:i}):t.token?{authorization:`Bearer ${t.token}`}:{}}},u=e=>t.secret?ul({nodeId:t.nodeId,keyId:t.keyId,secret:t.secret,method:"GET",pathWithQuery:`${e.pathname}${e.search}`}):{},m=(e,t,n)=>{const i=r.get(e);r.delete(e),i?.upstream&&C(i.upstream,t,n),i?.tunnel&&C(i.tunnel,t,n)},h=(e,t,n=!1)=>new Promise((i,s)=>{e.send(t,{binary:n,compress:!1},e=>e?s(e):i())});s.on("open",()=>{s.send(JSON.stringify({type:"node-agent.identify",nodeId:t.nodeId,serverTime:(new Date).toISOString()})),c=e.nodeAgentEventForwarder?.addOutput(s,{legacyFallbackMs:1e3})}),s.on("close",()=>{for(const e of r.keys())m(e,1001,"Reverse tunnel disconnected.");for(const[e,t]of o)o.delete(e),t.controller.abort(),C(t.tunnel,1001,"Reverse tunnel disconnected.");for(const[e,t]of a)a.delete(e),t.abort();c?.(),c=void 0});return s.on("message",i=>{(async i=>{let c;try{c=JSON.parse(String(i))}catch{return void s.send(JSON.stringify({type:"node-agent.error",code:"INVALID_JSON"}))}const g=c&&"object"==typeof c?c:{};if("control-plane.event-subscribe"!==g.type){if("control-plane.http.open"===g.type){const i="string"==typeof g.streamId?g.streamId:"",r="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=Hl(a.method);let m;try{m=Pn(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 s.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 p(y,{headers:u(y)});return o.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}`)})(r),{method:d,headers:l(r,d,m,c),body:Buffer.isBuffer(m)?new Uint8Array(m):m,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===p.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{o.delete(i)}}),I.on("close",()=>{f.abort(),o.delete(i)}),void I.on("error",()=>f.abort())}if("control-plane.http.cancel"===g.type){const e="string"==typeof g.streamId?g.streamId:"",t=o.get(e);if(!t)return;return o.delete(e),t.controller.abort(),void C(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 o=l(t,"GET",void 0),a=i?.length?new p(d(t),i,{headers:o}):new p(d(t),{headers:o}),c=(e=>{const t=new URL(n);return t.pathname=`${t.pathname.replace(/\/$/,"")}/streams/${encodeURIComponent(e)}`,t})(e),m=new p(c,{headers:u(c)});r.set(e,{upstream:a,tunnel:m,close:(e=1e3,t="")=>{C(a,e,t),C(m,e,t)}}),a.on("open",()=>{s.send(JSON.stringify({type:"node-agent.websocket.open",streamId:e,protocol:a.protocol}))}),x(m,a,{pendingFrameLimit:256,upstreamOpenTimeoutMs:1e4,onClientClose:()=>{r.delete(e)},onClientError:t=>{r.delete(e),s.send(JSON.stringify({type:"node-agent.websocket.error",streamId:e,message:t instanceof Error?t.message:String(t)}))},onUpstreamClose:(t,n)=>{r.delete(e);const i=k(t),o=_(n);s.send(JSON.stringify({type:"node-agent.websocket.close",streamId:e,...void 0===i?{}:{code:i},...o?{reason:o}:{}}))},onUpstreamError:t=>{r.delete(e),s.send(JSON.stringify({type:"node-agent.websocket.error",streamId:e,message:t instanceof Error?t.message:String(t)}))}})}catch(t){s.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 m(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:{},r="string"==typeof g.route&&g.route.startsWith("/")?g.route:"/health",o=i.headers&&"object"==typeof i.headers?i.headers:{},c=Hl(i.method);let d;try{d=Pn(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 s.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${r}`,headers:l(r,c,d,o),payload:d,signal:u.signal});if(u.signal.aborted)return;s.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;s.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)}}}else e.nodeAgentEventForwarder?.setOutputSubscription?.(s,g.aiSessionTransient,g.eventEnvelopeVersion)})(i).catch(n=>{e.log.warn({nodeId:t.nodeId,error:n instanceof Error?n.message:String(n)},"node agent reverse tunnel message rejected");try{s.send(JSON.stringify({type:"node-agent.error",code:"INVALID_TUNNEL_MESSAGE"}))}catch{}})}),s}function ql(e,t){return Number.isFinite(e)&&Number(e)>0?Number(e):t}function Kl(e){if(!e.length)return;const t=[...e].sort((e,t)=>e-t);return t[Math.ceil(.95*t.length)-1]}function Gl(e){return e.unref?.(),e}class Wl{connectTimeoutMs;handshakeTimeoutMs;heartbeatIntervalMs;heartbeatTimeoutMs;heartbeatMissThreshold;stableThresholdMs;now;setTimeoutFn;clearTimeoutFn;ping;onTimeout;onStable;onPhase;connectTimer;handshakeTimer;heartbeatTimer;stableTimer;awaitingPongSince;consecutiveHeartbeatMisses=0;stable=!1;stopped=!1;currentPhase="connecting";lastActivityAt;lastPongAt;pingRttMs;recentPingRttMs=[];constructor(e){this.connectTimeoutMs=ql(e.connectTimeoutMs,1e4),this.handshakeTimeoutMs=ql(e.handshakeTimeoutMs,1e4),this.heartbeatIntervalMs=ql(e.heartbeatIntervalMs,25e3),this.heartbeatTimeoutMs=ql(e.heartbeatTimeoutMs,15e3),this.heartbeatMissThreshold=Math.max(1,Math.floor(ql(e.heartbeatMissThreshold,2))),this.stableThresholdMs=ql(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=Gl(this.setTimeoutFn(()=>this.timeout("connect"),this.connectTimeoutMs))}opened(){this.stopped||(this.clearTimer("connectTimer"),this.setPhase("handshaking"),this.handshakeTimer=Gl(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=Gl(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(),this.awaitingPongSince=void 0,this.consecutiveHeartbeatMisses=0,"handshaking"!==this.currentPhase&&"healthy"!==this.currentPhase||this.scheduleHeartbeat(this.heartbeatIntervalMs))}pong(){if(this.stopped)return;const e=this.now();void 0!==this.awaitingPongSince&&(this.pingRttMs=Math.max(0,e-this.awaitingPongSince),this.recentPingRttMs.push(this.pingRttMs),this.recentPingRttMs.length>20&&this.recentPingRttMs.shift()),this.awaitingPongSince=void 0,this.consecutiveHeartbeatMisses=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.pingRttMs?{}:{pingRttMs:this.pingRttMs},...this.recentPingRttMs.length?{pingRttP95Ms:Kl(this.recentPingRttMs)}:{},...void 0===this.lastActivityAt?{}:{lastActivityAt:new Date(this.lastActivityAt).toISOString()},...void 0===this.lastPongAt?{}:{lastPongAt:new Date(this.lastPongAt).toISOString()},...this.consecutiveHeartbeatMisses?{consecutiveHeartbeatMisses:this.consecutiveHeartbeatMisses}:{}}}scheduleHeartbeat(e){this.stopped||(this.clearTimer("heartbeatTimer"),this.heartbeatTimer=Gl(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?(this.consecutiveHeartbeatMisses+=1,this.awaitingPongSince=void 0,this.consecutiveHeartbeatMisses>=this.heartbeatMissThreshold?void this.timeout("heartbeat"):void this.sendHeartbeatProbe()):void this.scheduleHeartbeat(this.heartbeatTimeoutMs-e)}this.sendHeartbeatProbe()}},e)))}sendHeartbeatProbe(){this.awaitingPongSince=this.now();try{this.ping()}catch{if(this.consecutiveHeartbeatMisses+=1,this.awaitingPongSince=void 0,this.consecutiveHeartbeatMisses>=this.heartbeatMissThreshold)return void this.timeout("heartbeat")}this.scheduleHeartbeat(this.heartbeatTimeoutMs)}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 Jl(e){const t=new URL(cl,e);return t.protocol="https:"===t.protocol?"wss:":"ws:",t.toString()}const Yl=new Set(["linux","darwin","win32","freebsd","openbsd","aix","sunos"]);function Xl(e){return Yl.has(e)?e:"unknown"}function Ql(e){return!0===e.managedArtifacts}class Zl{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)}resolveInstanceWeb(e){return this.executor.resolveInstanceWeb(e)}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),s=e.instance.runtime.labels["task-handoff.bootstrap-backup"];return i&&s&&await this.executor.removeBootstrapBackup(s,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:Xl(this.platform),...t?{serverVersion:t}:{}}}}}catch(t){return{status:"offline",capabilities:{...e.capabilities,daemon:{status:"offline",hostPlatform:Xl(this.platform),error:t instanceof Error?t.message:String(t)}}}}}}class eu{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(Ql)}async stopAll(){await(this.local.stopAll?.())}}const tu="task-handoff.local-process-nonce",nu=1e3,iu=1e4,su=2e3;function ru(e,t){try{e?.(t)}catch{}}function ou(e){return e.runtime.port?`http://127.0.0.1:${e.runtime.port}`:void 0}async function au(e,t){try{const n=await fetch(`${e}/api/internal/node-agent/process-identity`,{headers:{authorization:`Bearer ${t}`},signal:AbortSignal.timeout(nu)});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 cu(e,t){if(D.processStartIdentity(e)!==t)return!1;try{process.kill(e,"SIGTERM")}catch{return!0}const n=Date.now()+iu;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()+su;for(;Date.now()<i;){try{process.kill(e,0)}catch{return!0}await new Promise(e=>setTimeout(e,50))}return!1}function du(e,t){return Object.assign(new Error(t),{statusCode:503,code:"LOCAL_INSTANCE_STOP_UNCONFIRMED",instanceId:e.id})}async function lu(e){return!await function(e){return new Promise(t=>{const n=m.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=m.createServer();n.once("error",()=>t(!1)),n.listen({host:"127.0.0.1",port:e,exclusive:!0},()=>n.close(()=>t(!0)))})}const uu=lu;function pu(e,t){return null!==e.exitCode||null!==e.signalCode?Promise.resolve(!0):new Promise(n=>{const i=setTimeout(()=>{e.off("exit",s),n(null!==e.exitCode||null!==e.signalCode)},t);i.unref();const s=()=>{clearTimeout(i),n(!0)};e.once("exit",s)})}async function mu(e,t=1e4,n=2e3,i){if(await pu(e,t))return;ru(i,{stage:"graceful-timeout",pid:e.pid,timeoutMs:t});let s=!1;if(null===e.exitCode&&null===e.signalCode&&(e.kill("SIGKILL"),s=!0,ru(i,{stage:"force-signal-sent",pid:e.pid,signal:"SIGKILL"})),!await pu(e,n))throw ru(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});s&&ru(i,{stage:"force-exit-confirmed",pid:e.pid,signal:"SIGKILL"})}class hu{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 s={instanceId:e,pid:t.pid,code:n,signal:i},r=e=>{try{this.onUnexpectedExitError?.(e,s)}catch{}};try{Promise.resolve(this.onUnexpectedExit?.(s)).catch(r)}catch(e){r(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"),ru(n,{stage:"graceful-signal-sent",pid:t.pid,signal:"SIGTERM"})),this.children.delete(e.id),void await mu(t,iu,su,n)}const i=await async function(e){const t=ou(e),n=e.runtime.labels?.[tu];if(!t||!n||!e.registrationToken)return;const i=await au(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(nu)})).ok?i:void 0}catch{return}}(e);if(i){const t=ou(e),n=Date.now()+iu;for(;t&&Date.now()<n;){if(!await au(t,e.registrationToken))return;await new Promise(e=>setTimeout(e,50))}const s=t?await au(t,e.registrationToken):void 0;if(s&&s.instanceId===i.instanceId&&s.pid===i.pid&&s.processNonce===i.processNonce&&s.startIdentity===i.startIdentity&&s.startIdentity&&await cu(s.pid,s.startIdentity))return;throw du(e,`Controlled instance ${e.id} accepted shutdown but its exit could not be confirmed.`)}const s=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 U(e)}(this.lockPath),r=await async function(e){const t=ou(e);if(t)try{const[n,i]=await Promise.all([fetch(`${t}/api/instance/status`,{signal:AbortSignal.timeout(nu)}),fetch(`${t}/api/diagnostics`,{signal:AbortSignal.timeout(nu)})]);if(!n.ok||!i.ok)return;const s=await n.json(),r=await i.json(),o=r.data?.runtime?.pid;if(s.data?.id!==e.id||"controlled"!==s.data.controlMode||"number"!=typeof o||!Number.isInteger(o)||o<=0)return;const a=D.processStartIdentity(o);return a?{pid:o,startIdentity:a}:void 0}catch{return}}(e);if(r){if(await cu(r.pid,r.startIdentity))return;throw du(e,`Legacy controlled instance ${e.id} did not exit after termination.`)}if(s?.instanceId===e.id&&B(s))throw du(e,`Local controlled instance ${e.id} is still owned by pid ${s.pid}, but its process identity could not be verified.`)}async waitUntilHealthy(e,t,n,i,s=function(e=process.env.TASK_HANDOFF_LOCAL_PROCESS_READY_TIMEOUT_MS){const t=Number(e);return Number.isFinite(t)&&t>0?t:3e4}()){const r=Date.now()+s;for(;Date.now()<r;){if(null!==n.exitCode||null!==n.signalCode)return!1;const s=await au(e,i);if(s&&s.instanceId===t.instanceId&&s.pid===t.pid&&s.processNonce===t.processNonce&&s.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"),ru(e,{stage:"graceful-signal-sent",pid:t.pid,signal:"SIGTERM"}))}this.children.clear(),await Promise.all(e.map(e=>mu(e,iu,su,this.lifecycleReporters.get(e))))}}async function gu(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 fu{runCommand;paths;nodeAgentUrl;processSupervisor;async resolveInstanceWeb(e){const t=e.instance.runtime.port;if(!t)throw Object.assign(new Error(`Instance ${e.instance.id} does not have a node-owned local runtime port.`),{statusCode:409,code:"INSTANCE_RUNTIME_ENDPOINT_UNAVAILABLE"});return`http://127.0.0.1:${t}`}commandOverride;lockPath;constructor(e,t,n,i,s,r,o){this.runCommand=e,this.paths=t,this.nodeAgentUrl=n,this.commandOverride=i,this.lockPath=s,this.processSupervisor=new hu(s,r,o)}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),s=e.instance.runtime.port,r=!!s&&await lu(s),o="allocate"===process.env.TASK_HANDOFF_LOCAL_INSTANCE_PORT_CONFLICT;if(s&&!r&&!o)throw Object.assign(new Error(`Local controlled instance port 127.0.0.1:${s} is already in use.`),{statusCode:409,code:"LOCAL_INSTANCE_PORT_IN_USE"});const a=s&&r?s: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 uu(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"})}(),u=n.join(this.paths.dataDir,"local-instances",e.instance.id),p=n.join(u,"logs");t.mkdirSync(p,{recursive:!0,mode:448}),t.chmodSync(u,448),t.chmodSync(p,448);const[m,...h]=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),g=[...h,"--host","127.0.0.1","--port",String(a)],f=d.randomUUID(),y=n.join(p,"controlled-instance.out.log"),I=n.join(p,"controlled-instance.err.log");Qo(y),Qo(I);const A=t.mkdtempSync(function(e,t=process.platform,i=c.tmpdir()){const s="darwin"===t?"/private/tmp":i,r=d.createHash("sha256").update(e).digest("hex").slice(0,12);return n.join(s,`th-git-${r}-`)}(e.instance.id));t.chmodSync(A,448);const b=t.openSync(y,"a",384),v=t.openSync(I,"a",384),w=l.spawn(m,g,{cwd:i,detached:!1,stdio:["ignore",b,v],env:{...process.env,TASK_HANDOFF_CONTROL_MODE:"controlled",TASK_HANDOFF_RUNTIME_KIND:"local",TASK_HANDOFF_CONTROLLED_INSTANCE_VERSION:Wc(),...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:f,TASK_HANDOFF_WORKSPACE:i,TASK_HANDOFF_WORKSPACE_MODE:"local-bind",TASK_HANDOFF_DATA_DIR:u,TASK_HANDOFF_INSTANCE_PRIVATE_CONFIG_PATH:e.privateConfigPath||"",TASK_HANDOFF_LOG_DIR:p,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",TASK_HANDOFF_GIT_CREDENTIAL_SOCKET:n.join(A,"broker.sock"),...e.modelEnv||{},CODEX_HOME:(e.instance.config?.codexConfigEnabled??1)&&"taskhandoff"===(e.instance.config?.codexHomeMode??"taskhandoff")?n.join(u,"configs","codex"):void 0}});t.closeSync(b),t.closeSync(v);try{await function(e){return new Promise((t,n)=>{const i=()=>{e.off("error",s),t()},s=t=>{e.off("spawn",i),n(t)};e.once("spawn",i),e.once("error",s)})}(w)}catch(e){t.rmSync(A,{recursive:!0,force:!0});const s=e instanceof Error?e.message:String(e);try{t.appendFileSync(n.join(p,"controlled-instance.lifecycle.log"),`[${(new Date).toISOString()}] spawn failed command=${m} cwd=${i} error=${s}\n`)}catch{}throw Object.assign(new Error(`Controlled instance process could not start with command ${m} in ${i}: ${s}`),{statusCode:500,code:"LOCAL_INSTANCE_PROCESS_SPAWN_FAILED"})}const S=n.join(p,"controlled-instance.lifecycle.log");this.processSupervisor.track(e.instance.id,w,e=>{t.appendFileSync(S,`[${(new Date).toISOString()}] shutdown stage=${e.stage} pid=${e.pid??""} signal=${e.signal??""} timeoutMs=${e.timeoutMs??""}\n`)}),w.on("error",e=>{try{t.appendFileSync(S,`[${(new Date).toISOString()}] process error pid=${w.pid??""} error=${e.message}\n`)}catch{}}),w.once("exit",(e,n)=>{t.rmSync(A,{recursive:!0,force:!0});try{t.appendFileSync(S,`[${(new Date).toISOString()}] exited pid=${w.pid??""} code=${e??""} signal=${n??""}\n`)}catch{}});const E=`http://127.0.0.1:${a}`,z=w.pid?D.processStartIdentity(w.pid):void 0;if(!(w.pid&&e.instance.registrationToken&&await this.processSupervisor.waitUntilHealthy(E,{instanceId:e.instance.id,pid:w.pid,processNonce:f,startIdentity:z},w,e.instance.registrationToken)&&this.processSupervisor.markReady(e.instance.id,w)))throw this.processSupervisor.release(e.instance.id,w),null===w.exitCode&&null===w.signalCode&&w.kill("SIGTERM"),await mu(w),Object.assign(new Error(`Controlled instance process did not become ready for instance ${e.instance.id} on ${E}.`),{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:E,api:`${E}/api`},workspace:{mode:"local-bind",status:"pending",path:i},runtime:{kind:"local",workspacePath:i,pid:w.pid,port:a,labels:{...e.instance.runtime.labels,"task-handoff.runtime-kind":"local",[tu]:f}}}}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),ei.parse({instanceId:e.instance.id,containerDeleted:!0,completed:!0,deletedVolumes:[],retainedVolumes:[],volumeResults:[]})}async check(e){const[t,n]=await Promise.all([gu(this.runCommand,"codex"),gu(this.runCommand,"claude")]);return{status:"online",capabilities:od({...e.capabilities,apps:{terminal:!0,codex:t,claude:n}})}}async stopAll(){await this.processSupervisor.stopAll()}}const yu=["codex","claude"],Iu=5e3,Au=D.processStartIdentity(process.pid);function bu(e){const t=process.env[e]?.trim();return t||void 0}function vu(e){const t=e.authorization;return"string"==typeof t&&t.startsWith("Bearer ")?t.slice(7).trim():void 0}function wu(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 Su(e){return!e.ip&&!e.socket.remoteAddress&&!e.socket.remoteFamily}async function Eu(e,t,n){const i=new AbortController,s=setTimeout(()=>i.abort(),2e3);try{return(await e(`${await n(t)}/api/health`,{signal:i.signal})).ok?"reachable":"endpoint-unreachable"}catch{return"endpoint-unreachable"}finally{clearTimeout(s)}}async function zu(e,t,n,i){const s=new AbortController,r=setTimeout(()=>s.abort(),i);try{return await e(t,{...n,signal:s.signal})}finally{clearTimeout(r)}}async function Nu(e,t,n,i,s){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=await s(t),o=Number(process.env.TASK_HANDOFF_CONFIG_AUTO_IMPORT_TIMEOUT_MS||Iu);for(const s of yu)try{const a=await zu(e,`${r}/api/config-sync/import/${encodeURIComponent(s)}`,{method:"POST"},Number.isFinite(o)&&o>0?o:Iu);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 Tu(e,t,n,i,s=async e=>tl(e)){const r=t.requireInstance(n),o=t.resolvedAssignedModelEnvironment(n),a=t.modelRegistry.privateCatalog(n);if(t.instancePrivateConfigs.materialize(r.id,r.registrationToken,o,a),"reachable"!==r.targetStatus)return!1;let c;try{c=await zu(e,`${await s(r)}/api/internal/model-environment`,{method:"PUT",headers:{"content-type":"application/json",authorization:`Bearer ${r.registrationToken}`},body:JSON.stringify(o)},Iu)}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}if(!c.ok)return i?.({instanceId:n,targetWeb:r.target.web,statusCode:c.status},"node instance model environment live sync deferred"),!1;if(!Tn(r.capabilities).features.privateModelCatalog)return!0;try{const t=await zu(e,`${await s(r)}/api/internal/model-catalog`,{method:"PUT",headers:{"content-type":"application/json",authorization:`Bearer ${r.registrationToken}`},body:JSON.stringify(a)},Iu);t.ok||404===t.status||i?.({instanceId:n,statusCode:t.status},"node instance model catalog live sync deferred")}catch(e){i?.({instanceId:n,error:e instanceof Error?e.message:String(e)},"node instance model catalog live sync deferred")}return!0}async function _u(e,t,n,i,s,r,o="request",a){const c=e.requireInstance(i);if(c.imageProvisioning&&"ready"!==c.imageProvisioning.phase&&"docker"===e.requireRuntime(c.runtimeId).type)return s.diagnostic({instanceId:i,action:"start",reason:o,runtimeId:c.runtimeId,imageId:c.imageSelection?.imageId,imagePhase:c.imageProvisioning.phase},"node instance start queued until image provisioning completes"),e.controlledInstances.put(Vs.parse({...c,status:"starting",updatedAt:te()}));s.diagnostic({instanceId:i,action:"start",reason:o,runtimeId:c.runtimeId,imageId:c.imageSelection?.imageId},"node instance start requested");const d=e.applyInstanceLifecycle(i,{type:"start-requested"}),l=t.forRuntime(e.requireRuntime(d.runtimeId)),u=await l.start({...e.context(d),signal:a}),p=u.target?.web?await Eu(n,Vs.parse({...d,...u,target:{...d.target,...u.target},workspace:u.workspace?{...d.workspace,error:void 0,...u.workspace}:d.workspace,runtime:u.runtime?{...d.runtime,...u.runtime}:d.runtime,updatedAt:te()}),r):"unknown",m=e.applyInstanceLifecycle(i,{type:"runtime-lifecycle-completed",baseline:d,observation:{...u,target:u.target?{...u.target,status:p}:void 0,workspace:u.workspace?{error:void 0,...u.workspace}:void 0,targetStatus:p,uiAccessStatus:p}});return s.diagnostic({instanceId:i,action:"start",reason:o,status:m.status,connectionStatus:m.connectionStatus,targetStatus:m.targetStatus,targetWeb:m.target.web,containerName:m.runtime.containerName},"node instance start completed"),m}async function ku(e={}){const i=e.token||process.env.TASK_HANDOFF_NODE_AGENT_TOKEN,c=Number(e.port||process.env.TASK_HANDOFF_NODE_AGENT_PORT||"8091"),d=`http://127.0.0.1:${c}`,l=e.containerUrl||process.env.TASK_HANDOFF_NODE_AGENT_CONTAINER_URL,u=Yo(e.dataDir),m=e.remoteSecret||process.env.TASK_HANDOFF_NODE_AGENT_REMOTE_SECRET,g=e.remoteKeyId||process.env.TASK_HANDOFF_NODE_AGENT_REMOTE_KEY_ID,f=new Rl(u),y=f.resolveNodeId(e.nodeId||process.env.TASK_HANDOFF_NODE_ID),I=e.connectionMode||("local-ipc"===process.env.TASK_HANDOFF_NODE_AGENT_CONNECTION_MODE?"local-ipc":"local-loopback"),A=e.ipcPath||process.env.TASK_HANDOFF_NODE_AGENT_IPC_PATH||ea(u.dataDir),b="local-ipc"===I?`ipc://${encodeURIComponent(A)}`:d,v=e.platform||process.platform,S=e.arch||process.arch,E=new cd(u,y,d,l,c,v);E.node.connectionMode=I,E.node.controlEndpoint=b,E.node.endpoint=b,E.init();const z=e.dockerCommandRunner||rr,T=new ar(z,e.dockerTerminalCommandRunner),_=new Ir(z,{publishHost:"127.0.0.1",imageService:T});let k;const C=new eu(new Zl(_,z,v,S),new fu(e.dockerCommandRunner||rr,u,()=>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=>k.handleUnexpectedLocalExit(e.instanceId,new Error(`Local controlled instance exited unexpectedly (pid=${e.pid??"unknown"}, code=${e.code??"none"}, signal=${e.signal??"none"}).`)),(e,t)=>K.log.error({error:e,instanceId:t.instanceId,pid:t.pid},"local controlled instance exit recovery failed"))),O=async e=>tl(e,await C.forRuntime(E.requireRuntime(e.runtimeId)).resolveInstanceWeb(E.context(e))),R=e.updateCommandRunner||e.dockerCommandRunner||rr,P=e.fetchImpl||fetch,D=new Map,M=new Map,j=async e=>{const t=E.requireInstance(e);if(!Tn(t.capabilities).features.aiSessionPersistenceSettings||"reachable"!==t.targetStatus||!t.registrationToken)return!1;const n=function(e){return _n(e).retentionSettings}(t.capabilities),i=function(e){return!0===_n(e).fileSizeLimitSettings}(t.capabilities),s=`${t.processIncarnationId||"unknown"}:${t.config.aiSessionHistoryLimit}:${n?t.config.aiSessionAttachmentRetentionDays:"unsupported"}:${i?t.config.aiSessionMaxFileAttachmentBytes:"unsupported"}`;if(D.get(e)===s)return!0;let r;try{r=await zu(P,`${await O(t)}/api/internal/ai-session-persistence-settings`,{method:"PUT",headers:{"content-type":"application/json",authorization:`Bearer ${t.registrationToken}`},body:JSON.stringify({historyLimit:t.config.aiSessionHistoryLimit,...n?{attachmentRetentionDays:t.config.aiSessionAttachmentRetentionDays}:{},...i?{maxFileAttachmentBytes:t.config.aiSessionMaxFileAttachmentBytes}:{}})},Iu)}catch(t){return oe.warn({instanceId:e,error:t instanceof Error?t.message:String(t)},"node instance AI session persistence settings live sync deferred"),!1}return r.ok?(D.set(e,s),!0):(oe.warn({instanceId:e,statusCode:r.status},"node instance AI session persistence settings live sync deferred"),!1)},L=new da({cacheDir:n.join(u.dataDir,"runtime-artifacts"),fetchImpl:P}),F=e.resolveRuntimeArtifactRelease||((e,t,n)=>la(e,t,n,P)),$=async(t,n,i)=>{const s=await n.artifactTarget(i);if(e.resolveRuntimeArtifact)return e.resolveRuntimeArtifact(t,s.platform,s.arch);const r=await F(t,s.platform,s.arch);if(r.identity.launcherAbi>s.launcherAbi)throw Object.assign(new Error(`Runtime requires launcher ABI ${r.identity.launcherAbi}, but ${s.platform}-${s.arch} provides ABI ${s.launcherAbi}.`),{code:"INSTANCE_BASE_RUNTIME_INCOMPATIBLE",retryable:!1});return L.resolve(r.identity,r.source)},U=e=>C.forRuntime(E.requireRuntime(e.runtimeId)),V=e=>{const t=U(e);return Ql(t)?t:void 0},H=e=>{const t=V(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})},B=e=>Boolean(V(e)),q=(e,t)=>{const n=E.context(e);return $(t,H(e),n)},K=r({logger:e.logger??!0}),G=new Zo(u,{logger:(e,t)=>K.log.warn(t,e)}),W=()=>E.listInstances().map(e=>e.id),J=()=>{try{G.run(W())}catch(e){K.log.warn({error:e},"node-agent persistence maintenance failed")}};J();const Y=setInterval(()=>{J()},216e5);Y.unref();const X=setInterval(()=>{(()=>{try{G.capNodeAgentLogs(),G.capActiveInstanceLogs(W())}catch(e){K.log.warn({error:e},"node-agent open log maintenance failed")}})()},6e4);X.unref();const Q={requests:0,active:0,completed:0,aborted:0,limitRejected:0,responseBytes:0,totalDurationMs:0,maxResponseBytes:Jd()};K.decorate("nodeAgentState",E),await K.register(o,{options:N});const Z=new Eo(E,i,{logger:K.log,safetyIntervalMs:Number(process.env.TASK_HANDOFF_EVENT_CONNECTION_SAFETY_INTERVAL_MS)||void 0}),ee=new ua(E.controlledInstances,Wc,{isInstalled:async(e,t)=>{const n=await q(e,t),i=await H(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(Vs.parse({...t,runtime:{...t.runtime,labels:n},updatedAt:te()}))}return i},beginDrain:async e=>{try{const t=await async function(e,t,n=async e=>tl(e)){const i=await n(t);if(t.registrationToken&&(await zu(e,`${i}/api/internal/node-agent/drain`,{method:"POST",headers:{authorization:`Bearer ${t.registrationToken}`}},1e4)).ok)return{requested:t.apps.runningCount,failures:[]};const s=await zu(e,`${i}/api/apps/sessions`,{method:"GET",headers:{"cache-control":"no-cache"}},5e3);if(!s.ok)throw new Error(`Could not list app sessions for runtime drain (HTTP ${s.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 s.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 n=await zu(e,`${i}/api/apps/sessions/${encodeURIComponent(t)}/stop`,{method:"POST"},5e3);return n.ok?void 0:{sessionId:t,error:`HTTP ${n.status}`}}catch(e){return{sessionId:t,error:e instanceof Error?e.message:String(e)}}}));return{requested:r.length,failures:o.filter(e=>Boolean(e))}}(P,e,O);t.failures.length?K.log.warn({instanceId:e.id,requested:t.requested,failures:t.failures},"runtime convergence could not stop every app session"):K.log.info({instanceId:e.id,requested:t.requested},"runtime convergence requested app session drain")}catch(t){K.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,n=async e=>tl(e)){return!!t.registrationToken&&(await zu(e,`${await n(t)}/api/internal/node-agent/resume`,{method:"POST",headers:{authorization:`Bearer ${t.registrationToken}`}},5e3)).ok}(P,e,O)&&K.log.info({instanceId:e.id},"runtime convergence released app session drain")}catch(t){K.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=H(e);await n.installRuntime(E.context(e),await q(e,t))},restart:async e=>{const t=U(e),n=E.applyInstanceLifecycle(e.id,{type:"convergence-restart-requested"}),i=await t.restart(E.context(n)),s=Vs.parse({...n,...i,target:i.target?{...n.target,...i.target}:n.target,runtime:i.runtime?{...n.runtime,...i.runtime}:n.runtime,updatedAt:te()}),r=await Eu(P,s,O);E.applyInstanceLifecycle(e.id,{type:"runtime-lifecycle-completed",baseline:n,observation:{...i,target:i.target?{...i.target,status:r}:void 0,targetStatus:r,uiAccessStatus:r}})},onForcedDrain:e=>K.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=>{Z.publishInstanceLifecycle(e),E.updateJobs.reconcileRollouts(E.listInstances(),Wc())}),Z.start(),K.decorate("nodeAgentEventForwarder",Z);const ne=new Ro(z,()=>E.listInstances().filter(e=>"docker"===E.requireRuntime(e.runtimeId).type),e=>Z.publish("instance.metrics.snapshot",e,{instanceId:e.instanceId}));ne.start(),K.decorate("nodeAgentRuntimeMetrics",ne);const ie=(pe=process.env.TASK_HANDOFF_DIAGNOSTIC_LOGS,["1","true","yes","on"].includes(String(pe||"").trim().toLowerCase())),se=new pl(f,y,m,g),re=(e,t)=>{ie&&K.log.info(e,t)},oe={diagnostic:re,warn:(e,t)=>K.log.warn(e,t)},ae=new Fd,ce=new Bd(E.environmentTemplates,E.instancePrivateConfigs,_,e=>E.requireInstance(e),e=>E.requireRuntime(e),(e,t)=>ae.run(e,t),e=>E.listInstances().some(t=>t.environmentTemplateOrigin?.imageId===e)),de=async(e,t,n=()=>!0,i)=>{try{if(!n())return E.requireInstance(e);let s=E.requireInstance(e);"failed"===s.runtimeVersion?.phase&&B(s)&&(s=E.controlledInstances.put(Vs.parse({...s,ready:!1,runtimeVersion:Yc(pa(s)),updatedAt:te()})));const r=E.requireRuntime(s.runtimeId);await _u(E,C,P,e,oe,O,t,i);const o=E.requireInstance(e);if("docker"===r.type&&o.imageProvisioning&&"ready"!==o.imageProvisioning.phase)return Z.syncNow(),o;if(!n())return E.requireInstance(e);k.markRestored(e);let a=E.requireInstance(e);if(B(a)){try{a=await ee.schedule(e,{startRequested:!0})}catch(n){a=E.requireInstance(e),oe.warn({instanceId:e,action:"runtime.converge",reason:t,error:n instanceof Error?n.message:String(n)},"node instance runtime convergence failed after start")}"matched"!==a.runtimeVersion?.phase&&a.runtimeVersion?.error&&oe.warn({instanceId:e,action:"runtime.converge",reason:t,error:a.runtimeVersion.error},"node instance started with pending runtime convergence")}return n()?(await Nu(P,a,"start",oe,O),Z.syncNow(),a):E.requireInstance(e)}catch(n){throw E.applyInstanceLifecycle(e,{type:"start-failed",error:n}),Z.syncNow(),oe.warn({instanceId:e,action:"start",reason:t,error:n instanceof Error?n.message:String(n)},"node instance start failed"),n}},le=new Ud(E,T,{sync:()=>Z.syncNow(),diagnostic:oe.diagnostic,warn:oe.warn,publish:(e,t,n)=>Z.publish(e,t,{instanceId:n}),runInstanceOperation:(e,t)=>ae.run(e,t)}),ue=e=>{const t=ae.intent(e.id);le.provision(e,async()=>{await de(e.id,"image-ready",()=>ae.isIntentCurrent(e.id,t),ae.signal(e.id,t)).catch(()=>{})})};var pe;k=new Ul({state:E,runtimeAdapters:C,convergence:ee,restoreInstance:e=>_u(E,C,P,e,oe,O,"restore"),autoImport:e=>Nu(P,e,"start",oe,O),provisionImage:ue,stopImageProvisioning:()=>le.stop(),usesManagedArtifact:B,warn:oe.warn,error:(e,t)=>K.log.error(e,t),runInstanceOperation:(e,t)=>ae.run(e,t)});const me=new jl({nodeId:y,jobs:E.updateJobs,runCommand:R,currentRuntimeVersion:Wc,listInstances:()=>E.listInstances(),resolveRuntimeArtifacts:async e=>(await(async e=>{const t=new Map;for(const e of C.managedAdapters()){const n=await e.artifactTarget();t.set(`${n.platform}-${n.arch}`,{adapter:e})}for(const e of E.listInstances()){const n=V(e);if(!n)continue;const i=E.context(e),s=await n.artifactTarget(i);t.set(`${s.platform}-${s.arch}`,{adapter:n,context:i})}return(await Promise.all([...t.values()].map(({adapter:t,context:n})=>$(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:w&&"SCRIPT"===w.tagName.toUpperCase()&&w.src||new URL("cli.js",document.baseURI).href)?n.dirname(s.fileURLToPath("undefined"==typeof document?require("url").pathToFileURL(__filename).href:w&&"SCRIPT"===w.tagName.toUpperCase()&&w.src||new URL("cli.js",document.baseURI).href)):__dirname,managedUpdateSupport:e.managedUpdateSupport||(n=>"linux"!==(e.platform||process.platform)?{supported:!1,reason:"Managed server updates require Linux and systemd."}:"function"==typeof process.getuid&&0!==process.getuid()?{supported:!1,reason:"Managed server updates require the node agent to run as root."}:t.existsSync("/run/systemd/system")?"@task-handoff/server"!==n.packageName||process.env.TASK_HANDOFF_CONTROL_PLANE_HEALTH_URL?.trim()?process.env.TASK_HANDOFF_NODE_AGENT_IPC_PATH?.trim()?{supported:!0}:{supported:!1,reason:"Managed server updates require the node-agent IPC readiness endpoint."}:{supported:!1,reason:"Managed server updates require a local control-plane health URL."}:{supported:!1,reason:"Managed server updates require an active systemd host."})});return K.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);(ie||i.statusCode>=500)&&(i.statusCode>=500?K.log.error.bind(K.log):K.log.warn.bind(K.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}:{}}})}),K.addHook("preHandler",async e=>{const t=se.verify(e);if(t){if(f.isRevokedPairing(t)&&"/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=t}else if(Su(e)){if(i&&vu(e.headers)!==i){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)||/^\/api\/node-agent\/instances\/[^/]+\/git-credentials\//.test(t)}(e.url)){if(se.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 wu(e.ip)||wu(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(i&&vu(e.headers)!==i){const e=new Error("Invalid node agent token.");throw Object.assign(e,{statusCode:401,code:"NODE_AGENT_UNAUTHORIZED"}),e}}}),K.addHook("onClose",async()=>{clearInterval(Y),clearInterval(X),ne.stop(),Z.stop(),await k.stop()}),K.decorate("nodeAgentRestoreManagedInstances",()=>k.restoreManagedInstances()),K.decorate("nodeAgentRecoverManagedInstances",()=>k.recoverManagedInstances()),K.decorate("nodeAgentStartRecoverySupervisor",()=>k.start()),K.get("/api/node-agent/health",async()=>{return{data:{ok:!0,role:"node-agent",process:{pid:process.pid,...Au?{startIdentity:Au}:{}},listener:{host:"127.0.0.1",port:E.currentListenerPort},nodeId:y,platform:Xl(v),arch:process.arch,protocolVersion:In,capabilities:{modelEndpointProbe:!0,managedModels:{multiEntityAssignment:!0,privateModelCatalog:!0},aiSessionHistoryLimit:!0,aiSessionAttachmentRetention:!0,aiSessionFileAttachmentLimit:!0,folderPlaces:!0,localFolderNameUpdate:!0,managedGitCredentials:{registry:!0,runtimeBroker:!0,workspaceProvisioning:{docker:!0,kubernetes:!1,local:!1}}},build:(e="node-agent",{component:e,packageName:"@task-handoff/node-agent",packageVersion:Wc(),protocolVersion:In,buildId:bu("TASK_HANDOFF_BUILD_ID"),builtAt:bu("TASK_HANDOFF_BUILT_AT"),gitCommit:bu("TASK_HANDOFF_GIT_COMMIT"),imageRef:bu("TASK_HANDOFF_IMAGE_REF"),imageDigest:bu("TASK_HANDOFF_IMAGE_DIGEST")}),instanceProxy:{...Q},eventTransport:Z.eventTransportHealth(),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)}))}(K,e=>{if(!Su(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(!K.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 K.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)}))}(K,me,E.updateJobs),function(e,t){const{identity:n,nodeId:i,fetchImpl:s}=t;e.post("/api/node-agent/pairing/invites",async(e,t)=>{const s=n.createPairingInvite(Al.parse(e.body||{}));return t.code(201).send({data:{nodeId:i,joinToken:s.token,expiresAt:s.expiresAt}})}),e.post("/api/node-agent/pairing/complete",async(e,t)=>{const s=n.completePairingInvite(bl.parse(e.body));return t.code(201).send({data:{nodeId:i,keyId:s.keyId,secret:s.secret,pairedAt:s.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=Pl.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=Pl.parse(e.params.connectionId),s=n.deleteControlPlaneConnection(i);return s&&t.reverseTunnels()?.connectConfigured(),{data:{deleted:s}}}),e.post("/api/node-agent/control-plane-connections",async(e,r)=>{const o=vl.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(/\/$/,"")}(o.controlPlaneUrl);return n.runControlPlaneConnectionOperation(a,async()=>{const e=n.stageControlPlaneConnection({url:a,...o.controlPlaneName?{name:o.controlPlaneName}:{},enabled:!1!==o.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)}),s=await i.json().catch(()=>({}));if(!i.ok){const e=new Error(s.error?.message||`Control-plane node join failed with HTTP ${i.status}.`);throw Object.assign(e,{statusCode:i.status,code:s.error?.code||"NODE_AGENT_REMOTE_JOIN_FAILED"}),e}return s.data||{}}(s,a,{joinToken:o.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:o.controlPlaneName||("string"==typeof c.name&&c.name?c.name:void 0)});let l,u=d.connection.enabled?"saved":"disabled";const p=t.reverseTunnels();if(p)try{p.connectConfigured(),d.connection.enabled&&(u="connecting")}catch(e){u="failed",l=e instanceof Error?e.message:String(e)}return r.code(201).send({data:{pairing:n.listControlPlanePairings().find(e=>e.keyId===d.pairing.keyId),connection:d.connection,tunnel:{status:u,...l?{error:l}:{}}}})})})}(K,{identity:f,nodeId:y,nodeName:()=>E.node.name,fetchImpl:P,reverseTunnels:()=>K.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(Md.parse(e.body))})),e.patch("/api/node-agent/runtimes/:id",async e=>({data:t.updateRuntime(e.params.id,jd.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/places",async()=>({data:t.listFolderPlaces()})),e.get("/api/node-agent/folders/tree",async e=>({data:t.listFolderTree(Rd.parse(e.query))})),e.post("/api/node-agent/local-folders",async(e,n)=>n.code(201).send({data:t.createLocalFolder(Od.parse(e.body))})),e.patch("/api/node-agent/local-folders/:id",async e=>({data:t.updateLocalFolder(e.params.id,xd.parse(e.body))})),e.delete("/api/node-agent/local-folders/:id",async e=>({data:{deleted:t.deleteLocalFolder(e.params.id)}}))}(K,{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,C.forRuntime(t))},listLocalFolders:()=>E.localFolders.list(),listFolderPlaces:Ko,listFolderTree:Wo,createLocalFolder:e=>E.createLocalFolder(e),updateLocalFolder:(e,t)=>E.updateLocalFolder(e,t),deleteLocalFolder:e=>E.localFolders.delete(e)}),function(e,t,n,i){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(Zi.parse(e.body))})),e.post("/api/node-agent/models/discover",async e=>{const n=bd.parse(e.body);return{data:await dd(i,{...n,key:t.resolveProbeKey(n.existingModelId,n.key)})}}),e.post("/api/node-agent/models/test",async e=>{const n=vd.parse(e.body);return{data:await ld(i,{...n,key:t.resolveProbeKey(n.existingModelId,n.key)})}}),e.put("/api/node-agent/models/:id/deploy",async e=>{const n=e.params.id,i=ts.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,es.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 i=e.params.id,s=e.body&&"object"==typeof e.body&&!Array.isArray(e.body)&&Object.prototype.hasOwnProperty.call(e.body,"modelEntityIds"),r=t.assign(i,ns.parse(e.body));if(await n(i),s)return{data:r};const{modelEntityIds:o,...a}=r.assignment;return{data:{...r,assignment:a}}})}(K,E.modelRegistry,e=>Tu(P,E,e,oe.warn,O),P),function(e,t){const n=new wd(t.gitCredentials);e.addHook("onClose",async()=>n.close()),e.put("/api/node-agent/git-credentials/:credentialId",async e=>{const n=Nd.parse(e.params),i=yc.parse(e.body);if(i.credential.id!==n.credentialId)throw Object.assign(new Error("Credential payload identity mismatch."),{code:"GIT_CREDENTIAL_IDENTITY_MISMATCH",statusCode:409});return{data:t.gitCredentials.putPayload(i).credential}}),e.delete("/api/node-agent/git-credentials/:credentialId",async e=>({data:{deleted:t.gitCredentials.removePayload(Nd.parse(e.params).credentialId)}})),e.get("/api/node-agent/instances/:id/git-credential-authorizations",async e=>{const{id:n}=Td.parse(e.params);return t.requireInstance(n),{data:t.gitCredentials.getAuthorizationSet(n)}}),e.put("/api/node-agent/instances/:id/git-credential-authorizations",async e=>{const{id:n}=Td.parse(e.params);t.requireInstance(n);const i=Ic.parse(e.body);if(i.instanceId!==n)throw Object.assign(new Error("Git credential authorization identity mismatch."),{code:"GIT_CREDENTIAL_AUTHORIZATION_IDENTITY_MISMATCH",statusCode:409});return{data:t.gitCredentials.putAuthorizationSet(i)}}),e.post("/api/node-agent/instances/:id/git-credentials/https",async e=>{const{id:i}=Td.parse(e.params);t.authenticateInstance(i,kd(e.headers));const s=Ac.parse(e.body);return{data:bc.parse(n.resolveHttps(i,s.remoteUrl))}}),e.post("/api/node-agent/instances/:id/git-credentials/ssh/prepare",async e=>{const{id:i}=Td.parse(e.params);t.authenticateInstance(i,kd(e.headers));const s=vc.parse(e.body);return{data:wc.parse(await n.prepareSsh(i,s.remoteUrl))}}),e.post("/api/node-agent/instances/:id/git-credentials/ssh/agent",async e=>{const{id:i}=Td.parse(e.params);t.authenticateInstance(i,kd(e.headers));const s=Sc.parse(e.body);return{data:Ec.parse(await n.exchangeAgentFrame(i,s.invocationId,s.frame))}}),e.delete("/api/node-agent/instances/:id/git-credentials/ssh/:invocationId",async e=>{const{id:i,invocationId:s}=_d.parse(e.params);return t.authenticateInstance(i,kd(e.headers)),{data:{deleted:n.release(s,i)}}})}(K,E),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:ai.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)}))}(K,ce),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(Pd.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,Dd.parse(e.body));return await t.afterUpdate(n),{data:n}}),e.post("/api/node-agent/instances/:id/register",async(e,n)=>{const i=e.params.id,s=t.sanitizeReport(i,"register",e.body),r=t.register(i,Xs.parse(s),Ld(e.headers));return t.afterReport(r,"register"),n.code(201).send({data:r})}),e.post("/api/node-agent/instances/:id/heartbeat",async e=>{const n=e.params.id,i=t.sanitizeReport(n,"heartbeat",e.body),s=t.heartbeat(n,Qs.parse(i),Ld(e.headers));return t.afterReport(s,"heartbeat"),{data:s}})}(K,{list:()=>E.listInstances(),create:e=>"template"===e.environmentSource?.type?ce.runTemplateOperation(e.environmentSource.environmentTemplateId,()=>E.createInstance(e)):E.createInstance(e),retryImageProvisioning:e=>le.retry(e),update:(e,t)=>{const n=E.requireInstance(e);return E.controlledInstances.put(Vs.parse({...n,...t,...t.config?{config:{...n.config,...t.config}}:{},updatedAt:te()}))},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===In)return n;const s=({field:n,action:s})=>K.log.warn({instanceId:e,report:t,protocolVersion:i,expectedProtocolVersion:In,field:n,action:s},"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"],s=new Set([...i,"imageId"]);for(const e of Object.keys(n))s.has(e)||t?.({field:e,action:"ignored"});return Object.prototype.hasOwnProperty.call(n,"imageId")&&t?.({field:"imageId",action:"migrated"}),{...Ys(n,i),imageSelection:ni(n.imageSelection,n.imageId)}}(n,s):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 Ys(e,n)}(n,s)},afterCreate:e=>{Z.syncNow(),e.imageProvisioning&&ue(e)},afterImageRetry:e=>{Z.syncNow(),ue(e)},afterUpdate:async e=>{Z.syncNow(),await j(e.id)},afterReport:(e,t)=>{Z.syncNow(),(e=>{if("endpoint-unreachable"!==e.targetStatus||"online"!==e.connectionStatus||"online"!==e.agentStatus||!e.target.web||M.has(e.id))return;const t=e.processIncarnationId,n=(async()=>{if("reachable"!==await Eu(P,e,O))return;const n=E.requireInstance(e.id);n.processIncarnationId===t&&"online"===n.connectionStatus&&"online"===n.agentStatus&&(E.controlledInstances.put(Vs.parse({...n,target:{...n.target,status:"reachable"},targetStatus:"reachable",uiAccessStatus:"reachable",updatedAt:te()})),Z.syncNow())})().catch(t=>{K.log.debug({instanceId:e.id,error:t},"node instance endpoint reconciliation probe failed")}).finally(()=>{M.delete(e.id)});M.set(e.id,n)})(e),j(e.id),"register"===t?re({instanceId:e.id,action:t,protocolVersion:e.protocolVersion,build:e.build,targetStatus:e.targetStatus,targetStrategy:e.target.strategy},"node instance registered"):re({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"),!B(e)||e.ready&&"matched"===e.runtimeVersion?.phase||ee.schedule(e.id).catch(n=>K.log.error({instanceId:e.id,error:n},`runtime convergence after ${t} failed`))}}),K.get("/api/node-agent/events",{websocket:!0},(e,t)=>{const n=e;n.send(JSON.stringify({type:"node-agent.events.connected",nodeId:y,serverTime:(new Date).toISOString()}));const i=t.query,s=Z.addOutput(n,{expectsTransientSubscription:"1"===i.aiSessionTransient});n.on("message",e=>{try{const t=JSON.parse(String(e));"subscribe"===t.type&&void 0!==t.aiSessionTransient&&Z.setOutputSubscription(n,t.aiSessionTransient,t.eventEnvelopeVersion)}catch{}}),n.on("close",s),n.on("error",s)}),K.get("/api/node-agent/docker/images",async()=>({data:await Or(e.dockerCommandRunner)})),K.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 ne.snapshot(t)}}),function(e,t,n,i,s,r=new Fd){const o=e=>r.intent(e),a=e=>Promise.resolve(i.cancel(e)).then(()=>({ok:!0}),e=>({ok:!1,error:e})),c=(e,t)=>{if(!r.isIntentCurrent(e,t))throw Object.assign(new Error(`Instance operation for ${e} was superseded by stop or delete.`),{statusCode:409,code:"INSTANCE_OPERATION_SUPERSEDED"})},d=(e,t)=>{const n=r.signal;return"function"==typeof n?n.call(r,e,t):void 0},l=(e,n)=>{if(n){if(n.instanceId!==e)throw Object.assign(new Error(`Git provisioning belongs to ${n.instanceId}, not ${e}.`),{code:"GIT_WORKSPACE_PROVISIONING_INSTANCE_MISMATCH",statusCode:409});t.setGitWorkspaceProvisioning(n)}},u=(e,n)=>{if(!n)return e;const i=t.gitWorkspaceProvisioningStatus(e.id);return"consumed"===i?.status&&i.operationId===n.operationId?{instance:e,gitWorkspaceProvisioningOperationId:n.operationId}:e};e.post("/api/node-agent/instances/:id/start",async e=>{const t=$d.parse(e.body),n=e.params.id,i=o(n);return r.run(n,async()=>(c(n,i),l(n,t.gitWorkspaceProvisioning),s.allowRecovery(n),{data:u(await s.start(n,()=>r.isIntentCurrent(n,i),d(n,i)),t.gitWorkspaceProvisioning)}))}),e.post("/api/node-agent/instances/:id/runtime/reconcile",async e=>{const n=e.params.id;$d.parse(e.body);const a=o(n);return r.run(n,async()=>{c(n,a);const e=t.requireInstance(n);t.putInstance(Vs.parse({...e,ready:!1,runtimeVersion:Yc(pa(e)),updatedAt:te()})),c(n,a);const r=await i.schedule(n,{startRequested:!["created","stopped"].includes(e.status),resumeCancelled:!0});return c(n,a),s.sync(),{data:r}})}),e.post("/api/node-agent/instances/:id/stop",async e=>{const i=e.params.id;t.requireInstance(i),t.discardGitWorkspaceProvisioning(i),r.invalidate(i);const o=a(i);return r.run(i,async()=>{const e=t.requireInstance(i);t.applyLifecycle(i,{type:"stop-requested"});try{await s.suppressRecovery(i);const e=await o;if("error"in e)throw e.error;const r=t.requireInstance(i);s.diagnostic({instanceId:i,action:"stop",runtimeId:r.runtimeId,containerName:r.runtime.containerName},"node instance stop requested"),await n.forRuntime(t.requireRuntime(r.runtimeId)).stop(t.context(r))}catch(n){try{t.applyLifecycle(i,{type:"stop-failed",baseline:e}),s.sync()}finally{s.allowRecovery(i)}throw n}const r=t.applyLifecycle(i,{type:"stop-completed"});return s.completeSuppressedRecovery(i),s.sync(),s.diagnostic({instanceId:i,action:"stop",status:r.status,connectionStatus:r.connectionStatus,containerName:r.runtime.containerName},"node instance stop completed"),{data:r}})}),e.post("/api/node-agent/instances/:id/restart",async e=>{const a=e.params.id,d=$d.parse(e.body),p=o(a);return r.run(a,async()=>{c(a,p),l(a,d.gitWorkspaceProvisioning),s.allowRecovery(a);let e=t.requireInstance(a);if(s.isManaged(e)&&(!e.ready||"matched"!==e.runtimeVersion?.phase)){"failed"===e.runtimeVersion?.phase&&(e=t.putInstance(Vs.parse({...e,runtimeVersion:Yc(pa(e)),updatedAt:te()}))),c(a,p);const n=await i.schedule(a,{startRequested:!0});return c(a,p),s.sync(),{data:u(n,d.gitWorkspaceProvisioning)}}s.diagnostic({instanceId:a,action:"restart",runtimeId:e.runtimeId,imageId:e.imageSelection?.imageId,containerName:e.runtime.containerName},"node instance restart requested");const r=await n.forRuntime(t.requireRuntime(e.runtimeId)).restart(t.context(e));let o=t.applyLifecycle(a,{type:"runtime-lifecycle-completed",baseline:e,observation:{...r,target:r.target?{...e.target,...r.target}:void 0}});s.markRestarted(a),c(a,p);const m=Vs.parse({...o,updatedAt:te()}),h=await s.probe(m);return c(a,p),o=t.applyLifecycle(a,{type:"runtime-lifecycle-completed",baseline:o,observation:{target:{...o.target,status:h},targetStatus:h,uiAccessStatus:h}}),await s.autoImport(o),s.sync(),s.diagnostic({instanceId:a,action:"restart",status:o.status,connectionStatus:o.connectionStatus,targetStatus:o.targetStatus,targetWeb:o.target.web,containerName:o.runtime.containerName},"node instance restart completed"),{data:u(o,d.gitWorkspaceProvisioning)}})}),e.post("/api/node-agent/instances/:id/delete",async e=>{const i=e.params.id,o=Qn.parse(e.body);t.requireInstance(i),r.invalidate(i);const c=a(i);return r.run(i,async()=>{const e=t.requireInstance(i);"deleting"!==e.status&&t.applyLifecycle(i,{type:"stop-requested"});try{await s.suppressRecovery(i);const e=await c;if("error"in e)throw e.error;const a=t.requireInstance(i);t.putInstance(Vs.parse({...a,status:"deleting",ready:!1,updatedAt:te()})),s.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,{}),o);if(!d.completed)return s.diagnostic({instanceId:i,action:"delete",volumeResults:d.volumeResults},"node instance delete requires retry"),s.sync(),{data:d};s.diagnostic({instanceId:i,action:"delete"},"node instance delete completed");const l=t.deleteInstance(i);return l&&(s.forgetRecovery(i),r.clearIntent(i)),s.deleteMetadata(i),l&&s.retireInstanceData(i),l&&a.environmentTemplateOrigin?.imageId&&s.releaseEnvironmentImage&&await s.releaseEnvironmentImage(a.environmentTemplateOrigin.imageId).catch(e=>{s.diagnostic({instanceId:i,action:"release-environment-image",error:e instanceof Error?e.message:String(e)},"environment image cleanup deferred after instance deletion")}),s.sync(),{data:d}}catch(n){try{t.putInstance(Vs.parse({...e,updatedAt:te()})),s.sync()}finally{s.allowRecovery(i)}throw n}})})}(K,{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),setGitWorkspaceProvisioning:e=>E.setGitWorkspaceProvisioning(e),discardGitWorkspaceProvisioning:e=>E.discardGitWorkspaceProvisioning(e),gitWorkspaceProvisioningStatus:e=>E.gitWorkspaceProvisioningStatus(e)},C,ee,{start:(e,t,n)=>de(e,"request",t,n),sync:()=>Z.syncNow(),isManaged:B,probe:e=>Eu(P,e,O),autoImport:e=>Nu(P,e,"restart",oe,O),markRestarted:e=>k.markRestored(e),allowRecovery:e=>k.allowRecovery(e),suppressRecovery:e=>k.suppressRecovery(e),forgetRecovery:e=>k.forgetInstance(e),completeSuppressedRecovery:e=>k.completeSuppressedOperation(e),deleteMetadata:e=>{D.delete(e),E.modelRegistry.deleteInstanceMetadata(e),E.gitCredentials.removeInstance(e),E.gitCredentials.collectUnreferencedPayloads(),E.discardGitWorkspaceProvisioning(e),E.instancePrivateConfigs.delete(e)},retireInstanceData:e=>{G.retire(e)},releaseEnvironmentImage:e=>ce.releaseUnusedImage(e),diagnostic:re},ae),function(e,t){const{fetchImpl:n,metrics:i,diagnostic:s}=t;e.post("/api/node-agent/instances/:id/proxy",async(e,i)=>{const r=performance.now(),o=e.params.id,a=Cd.parse(e.body),c=await t.instanceBase(o),d=Xd(a.path);"POST"===a.method&&"/api/apps/sessions"===d&&await t.syncModelEnvironment(o),s({instanceId:o,action:"proxy",method:a.method,path:d,instanceBase:c},"node instance proxy requested");const l=await Zd(n,`${c}${d}`,{method:a.method,headers:{...a.headers},body:Wd(a)},{instanceId:o,method:a.method,path:d,diagnostic:s}),u=l.headers.get("content-type")||"application/octet-stream",p=await l.text(),m=performance.now()-r,h=l.headers.get(Yd)||a.headers[Yd],g=function(...e){return e.map(e=>String(e||"").trim()).filter(Boolean).join(", ")}(l.headers.get("server-timing"),function(e,t){return`node_proxy;dur=${(Number.isFinite(t)?Math.max(0,t):0).toFixed(1)}`}(0,m));i.header("server-timing",g),h&&i.header(Yd,h),s({instanceId:o,action:"proxy",method:a.method,path:d,statusCode:l.status,contentType:u,durationMs:m,traceId:h},"node instance proxy completed"),i.code(l.status).type(u).send(p)}),e.post("/api/node-agent/instances/:id/proxy/stream",{bodyLimit:Kd},async(e,r)=>{const o=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()-o,i.responseBytes+=c,i[e]+=1)},p=()=>{a.abort(),d&&u("aborted")};e.raw.once("aborted",p),r.raw.once("close",p);try{const o=e.params.id,l=Cd.parse(e.body),p=await t.instanceBase(o),m=Xd(l.path);s({instanceId:o,action:"proxy.stream",method:l.method,path:m,instanceBase:p},"node instance streaming proxy requested");const g=await Zd(n,`${p}${m}`,{method:l.method,headers:{...l.headers},body:Wd(l),signal:a.signal},{instanceId:o,method:l.method,path:m,diagnostic:s}),f=Number(g.headers.get("content-length"));if(Number.isFinite(f)&&f>i.maxResponseBytes)return i.limitRejected+=1,a.abort(),Qd(r,i.maxResponseBytes);r.code(g.status);for(const[e,t]of Object.entries(Gd(g.headers)))r.header(e,t);if(!g.body||"HEAD"===l.method)return u("completed"),r.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")),r.send(h.Readable.fromWeb(g.body).pipe(y))}catch(e){throw u("aborted"),e}finally{e.raw.off("aborted",p),d||u("completed")}}),e.post("/api/node-agent/instances/:id/proxy/raw",{bodyLimit:Kd},async(e,r)=>{const o=e.params.id,a=Cd.parse(e.body),c=await t.instanceBase(o),d=Xd(a.path);s({instanceId:o,action:"proxy.raw",method:a.method,path:d,instanceBase:c},"node instance raw proxy requested");const l=await Zd(n,`${c}${d}`,{method:a.method,headers:{...a.headers},body:Wd(a)},{instanceId:o,method:a.method,path:d,diagnostic:s}),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(()=>{})),Qd(r,i.maxResponseBytes);let p;try{p=await async function(e,t){if(!e.body)return Buffer.alloc(0);const n=[];let i=0;const s=e.body.getReader();for(;;){const{done:e,value:r}=await s.read();if(e)break;if(i+=r.byteLength,i>t)throw await s.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(r))}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,Qd(r,i.maxResponseBytes)}return s({instanceId:o,action:"proxy.raw",method:a.method,path:d,statusCode:l.status,byteLength:p.length},"node instance raw proxy completed"),{data:{status:l.status,headers:Gd(l.headers),bodyBase64:p.toString("base64")}}}),e.get("/api/node-agent/instances/:id/proxy/ws/*",{websocket:!0},async(e,n)=>{const i=n.params.id,r=n.params["*"]||"",o=n.url.indexOf("?"),a=o>=0?n.url.slice(o):"";let c;try{const o=await t.instanceBase(i),d=new URL(`/${r}${a}`,`${o}/`);d.protocol="https:"===d.protocol?"wss:":"ws:";const l=function(e){const t=Object.entries(e).find(([e])=>"sec-websocket-protocol"===e.toLowerCase()),n=t?.[1],i=(Array.isArray(n)?n.join(","):"string"==typeof n?n:"").split(",").map(e=>e.trim()).filter(Boolean);return i.length?i:void 0}(n.headers);s({instanceId:i,action:"proxy.ws",path:`/${r}${a}`,upstreamUrl:d.toString(),protocols:l||[]},"node instance websocket proxy opening"),c=l?new p(d,l,{perMessageDeflate:!1}):new p(d,{perMessageDeflate:!1}),c.on("open",()=>{s({instanceId:i,action:"proxy.ws",path:`/${r}${a}`},"node instance websocket proxy opened")}),c.on("close",()=>{s({instanceId:i,action:"proxy.ws",path:`/${r}${a}`},"node instance websocket proxy closed")}),c.on("error",e=>{s({instanceId:i,action:"proxy.ws",path:`/${r}${a}`,error:e instanceof Error?e.message:String(e)},"node instance websocket proxy failed")}),x(e,c,{upstreamOpenTimeoutMs:1e4})}catch(t){s({instanceId:i,action:"proxy.ws",path:`/${r}${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.")}})}(K,{fetchImpl:P,metrics:Q,instanceBase:e=>O(E.requireInstance(e)),syncModelEnvironment:e=>Tu(P,E,e,oe.warn,O),diagnostic:re}),K}async function Cu(e){const s=Yo(e.dataDir),r=function(e,i={}){return function(e,i={}){t.mkdirSync(n.dirname(e),{recursive:!0});const s=D.processStartIdentity(process.pid),r={pid:process.pid,hostname:c.hostname(),command:process.argv.join(" "),acquiredAt:(new Date).toISOString(),token:d.randomUUID(),...void 0!==i.component?{component:i.component}:{},...s?{startIdentity:s}:{},...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(L(e),`${JSON.stringify({token:r.token,pid:r.pid,startIdentity:r.startIdentity,startedAt:(new Date).toISOString()})}\n`,{encoding:"utf8",mode:384,flag:"wx"}),q(e,r),{lockPath:e,owner:r,updateDetails:t=>K(e,r,t),release(){const n=V(e);n?.token===r.token&&t.rmSync(e,{recursive:!0,force:!0})}}}catch(s){if("EEXIST"!==s.code)throw s;const r=V(e);if(B(r))throw new M(e,r,i.error);if(!r&&(W(e)||X(e)<(i.incompleteLockStaleMs??2e3))){if(n+1<5){Y();continue}throw new M(e,void 0,i.error)}const o=d.randomUUID();if(!Q(e,o)){if(n+1<5){Y();continue}throw new M(e,V(e),i.error)}const a=V(e);if(B(a))throw J(F(e)),new M(e,a,i.error);if(r?.token&&a?.token!==r.token){J(F(e));continue}if(!ee(e,o))continue;t.rmSync(e,{recursive:!0,force:!0})}const o=V(e);throw new M(e,o,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:s.dataDir});try{const c=(o=e.host,a=e.port,xs.parse({bindScope:"0.0.0.0"===o.trim()?"all-ipv4":"loopback",port:a})),d=t.existsSync(s.settingsPath),l=function(e,t){return new ka(e.settingsPath,()=>({version:1,externalListener:t}),{schema:nl,sanitize:sl})}(s,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 rl(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 p=e=>{if(!r.updateDetails({dataDir:s.dataDir,host:e.host,port:e.port,instanceId:void 0}))throw new Error("Node agent singleton ownership changed while publishing listener state.")},m={...e,port:u.port},h=await ku(m),g=h.nodeAgentState;if(!g)throw new Error("Node agent state was not initialized.");const f=new Rl(s).resolveNodeId(e.nodeId||process.env.TASK_HANDOFF_NODE_ID),y=function(e,t,n,i){const s=t.token||process.env.TASK_HANDOFF_NODE_AGENT_TOKEN,r=new Rl(n),o=new Map;let a=!1;const c=(t,n)=>{if(a||n.retry.pending||o.get(t)!==n)return;const s=n.retry.schedule(()=>{a||o.get(t)!==n||n.socket||d(t,n)});s&&(n.status="reconnecting",n.nextRetryAt=new Date(Date.now()+s.delay).toISOString(),e.log.info({nodeId:i,tunnelUrl:new URL(n.config.tunnelUrl).origin,attempt:s.attempt,delay:s.delay},"node agent reverse tunnel reconnect scheduled"))},d=(n,r)=>{let d;r.status=r.lastDisconnectedAt?"reconnecting":"connecting",r.error=void 0,r.failureReason=void 0,r.nextRetryAt=void 0;try{d=Bl(e,{...r.config,nodeId:i,port:()=>e.nodeAgentState.currentListenerPort,token:s})}catch(e){return r.status="failed",r.lastDisconnectedAt=(new Date).toISOString(),r.error=e instanceof Error?e.message:String(e),void c(n,r)}r.socket=d;const l=new Wl({connectTimeoutMs:t.connectTimeoutMs,handshakeTimeoutMs:t.handshakeTimeoutMs,heartbeatIntervalMs:t.heartbeatIntervalMs,heartbeatTimeoutMs:t.heartbeatTimeoutMs,heartbeatMissThreshold:t.heartbeatMissThreshold,stableThresholdMs:t.stableThresholdMs,ping:()=>d.ping(),onTimeout:e=>{o.get(n)===r&&r.socket===d&&(r.status="failed",r.failureReason=`Reverse tunnel ${e} timeout.`,r.error=r.failureReason,d.terminate())},onStable:()=>r.retry.reset()});return r.supervisor=l,l.start(),d.on("open",()=>{o.get(n)===r&&r.socket===d&&(r.status="connecting",l.opened())}),d.on("message",t=>{if(o.get(n)!==r||r.socket!==d)return;if(l.activity(),"connected"===r.status)return;let s;try{s=JSON.parse(String(t))}catch{return}const a=s&&"object"==typeof s?s.type:void 0;"control-plane.hello"!==a&&"control-plane.identified"!==a||(l.activity(),l.healthy(),r.status="connected",r.lastConnectedAt=(new Date).toISOString(),r.nextRetryAt=void 0,r.error=void 0,e.log.info({nodeId:i,tunnelUrl:new URL(r.config.tunnelUrl).origin},"node agent reverse tunnel connected"))}),d.on("pong",()=>l.pong()),d.on("close",(t,s)=>{if(o.get(n)!==r||r.socket!==d)return;l.close(),r.socket=void 0,r.lastDisconnectedAt=(new Date).toISOString();const u=`WebSocket closed${t?` (${t})`:""}${s?`: ${Buffer.isBuffer(s)?s.toString("utf8"):String(s)}`:""}`;r.error=r.failureReason||u,a||(e.log.warn({nodeId:i,tunnelUrl:new URL(r.config.tunnelUrl).origin,code:t,reason:Buffer.isBuffer(s)?s.toString("utf8"):String(s||""),error:r.error,closeOrigin:r.failureReason?"supervisor":"transport"},"node agent reverse tunnel disconnected"),c(n,r))}),d.on("error",e=>{o.get(n)===r&&r.socket===d&&(r.status="failed",r.failureReason=e instanceof Error?e.message:String(e),r.error=r.failureReason,d.terminate())}),d},l=(e,t)=>{const n=o.get(e);n?.retry.cancel(),n?.supervisor?.close();const i={config:t,retry:new bo,status:"connecting"};return o.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,s=r.resolvedControlPlaneAccess(),c=new Set;for(const{connection:t,pairing:r}of s.connections){if(!t.enabled)continue;if(!r){e.log.warn({nodeId:i,connectionId:t.id,pairingKeyId:t.pairingKeyId},"node agent control-plane connection has no pairing");continue}const s=Jl(t.url);n.set(t.id,{tunnelUrl:s,keyId:r.keyId,secret:r.secret}),c.add(s)}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=r.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 p=s.hasPersistedAccess?void 0:function(){const e=process.env.TASK_HANDOFF_CONTROL_PLANE_URL;if(!e)return;const t=new URL(cl,e);return t.protocol="https:"===t.protocol?"wss:":"ws:",t.toString()}();if(p&&!c.has(p)){const e=r.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:${p}`,{tunnelUrl:p,keyId:e?.keyId,secret:e?.secret})}(e=>{for(const[t,n]of o)e.has(t)||(n.retry.cancel(),n.supervisor?.close(),o.delete(t),n.socket?.close(1e3,"Reverse tunnel configuration removed."));for(const[t,n]of e){const e=o.get(t);e&&u(e.config,n)||l(t,n)}})(n)},state:e=>{const t=o.get(e);if(!t)return;const n=t.supervisor?.diagnostics();return{status:t.status,...void 0===n?.pingRttMs?{}:{pingRttMs:n.pingRttMs},...void 0===n?.pingRttP95Ms?{}:{pingRttP95Ms:n.pingRttP95Ms},consecutiveReconnects:t.retry.attempts,...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 o.values())e.retry.cancel(),e.supervisor?.close(),e.socket?.close(1001,"Node agent shutting down.");o.clear()}}}({log:h.log,inject:e=>h.inject(e),nodeAgentEventForwarder:h.nodeAgentEventForwarder,nodeAgentState:g},m,s,f);h.decorate("nodeAgentReverseTunnels",y);const I=new ol({app:h,state:g,settings:l,config:u,source:d?"persisted":"bootstrap",onActiveListener:p});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")},s=()=>{n("SIGTERM")};process.once("SIGINT",i),process.once("SIGTERM",s),e.addHook("onClose",async()=>{process.off("SIGINT",i),process.off("SIGTERM",s)})}(h),h.addHook("onClose",async()=>{A?.close(),r.release()});try{await h.ready();const r=e.ipcPath||process.env.TASK_HANDOFF_NODE_AGENT_IPC_PATH||ea(s.dataDir);A=await async function(e,s){!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}}}(s);const r=i.createServer((t,n)=>{e.server.emit("request",t,n)});return r.on("upgrade",(t,n,i)=>{e.server.emit("upgrade",t,n,i)}),await new Promise((e,t)=>{r.once("error",t),r.listen(s,()=>{r.off("error",t),e()})}),r}(h,r),await I.start(),y.connectConfigured(),h.nodeAgentStartRecoverySupervisor?.()}catch(e){throw await h.close(),e}}catch(e){throw r.release(),e}var o,a}const Ou="task-handoff-node-agent.service",xu=`/etc/systemd/system/${Ou}`,Ru="/etc/task-handoff/node-agent.env",Pu=["@task-handoff/node-agent","@task-handoff/controlled-instance"];function Du(e,t,n){const i=e.run(t,n);if(0!==i.status){const e=function(e){return[e.stdout,e.stderr].filter(Boolean).map(e=>String(e).trim()).filter(Boolean).join("\n")}(i);throw new Error(`${t} ${n.join(" ")} failed${e?`:\n${e}`:""}`)}}function Mu(e,t){for(const n of e.split(/\r?\n/)){const e=n.indexOf("=");if(!(e<0||n.slice(0,e).trim()!==t))return n.slice(e+1).trim()}}const ju={getuid:()=>process.getuid?.(),exists:t.existsSync,readText:e=>t.readFileSync(e,"utf8"),remove:(e,n)=>t.rmSync(e,n),run:(e,t)=>l.spawnSync(e,t,{encoding:"utf8"}),confirmDeleteData:async function(e){if(!v.stdin.isTTY||!v.stdout.isTTY)return!1;const t=b.createInterface({input:v.stdin,output:v.stdout});try{const n=await t.question(`Delete Node Agent data at ${e}? This removes identity, configuration, logs, and managed-instance metadata. Docker volumes are preserved. [y/N] `);return/^(?:y|yes)$/i.test(n.trim())}finally{t.close()}},log:e=>console.log(e)};function Lu(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 Fu(e){if("local-ipc"!==e&&"local-loopback"!==e)throw new Error("Connection mode must be local-ipc or local-loopback.");return e}function $u(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(z("@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",Lu,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",Fu).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 Cu({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",$u).option("--json","Print raw JSON output").action(async e=>{const n=t.opts(),i=e.ipcPath||n.ipcPath||process.env.TASK_HANDOFF_NODE_AGENT_IPC_PATH,s=e.dataDir||n.dataDir||process.env.TASK_HANDOFF_NODE_AGENT_DATA_DIR,r=e.endpoint?void 0:i||ea(s||Jo()),o=await async function(e){const t={"content-type":"application/json",...e.token?{authorization:`Bearer ${e.token}`}:{}},n=JSON.stringify({...e.expiresInMs?{expiresInMs:e.expiresInMs}:{}}),i=e.endpoint?await fetch(`${e.endpoint.replace(/\/$/,"")}/api/node-agent/pairing/invites`,{method:"POST",headers:t,body:n}):await ta(e.ipcPath,"/pairing/invites",{method:"POST",headers:t,body:n}),s=await i.json().catch(()=>({}));if(!i.ok)throw new Error(s.error?.message||`Node agent pairing invite failed with HTTP ${i.status}`);const r="string"==typeof s.data?.joinToken?s.data.joinToken:"";if(!r)throw new Error("Node agent pairing invite response did not include a join token.");return{nodeId:"string"==typeof s.data?.nodeId?s.data.nodeId:"",joinToken:r,expiresAt:"string"==typeof s.data?.expiresAt?s.data.expiresAt:""}}({endpoint:e.endpoint,ipcPath:r,token:e.token,expiresInMs:e.expiresInMs});e.json?console.log(JSON.stringify(o,null,2)):(o.nodeId&&console.log(`Node: ${o.nodeId}`),console.log(`Join token: ${o.joinToken}`),o.expiresAt&&console.log(`Expires: ${o.expiresAt}`))}),t.command("connect").description("Connect this Node Agent to a reachable Control Plane.").requiredOption("--control-plane <url>","Public Control Plane base URL").requiredOption("--join-token <token>","One-time join token issued by the Control Plane").option("--control-plane-name <name>","Control Plane display name").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("--json","Print raw JSON output").action(async e=>{const n=t.opts(),i=e.ipcPath||n.ipcPath||process.env.TASK_HANDOFF_NODE_AGENT_IPC_PATH,s=e.dataDir||n.dataDir||process.env.TASK_HANDOFF_NODE_AGENT_DATA_DIR,r=e.endpoint?void 0:i||ea(s||Jo()),o=await async function(e){const t={"content-type":"application/json",...e.token?{authorization:`Bearer ${e.token}`}:{}},n=JSON.stringify({controlPlaneUrl:e.controlPlane,joinToken:e.joinToken,...e.controlPlaneName?{controlPlaneName:e.controlPlaneName}:{},activate:!0}),i=e.endpoint?await fetch(`${e.endpoint.replace(/\/$/,"")}/api/node-agent/control-plane-connections`,{method:"POST",headers:t,body:n}):await ta(e.ipcPath,"/control-plane-connections",{method:"POST",headers:t,body:n}),s=await i.json().catch(()=>({}));if(!i.ok)throw new Error(s.error?.message||`Node Agent connection failed with HTTP ${i.status}`);return s.data}({controlPlane:e.controlPlane,joinToken:e.joinToken,controlPlaneName:e.controlPlaneName,endpoint:e.endpoint,ipcPath:r,token:e.token});e.json?console.log(JSON.stringify(o,null,2)):(console.log(`Control Plane: ${String(o?.connection?.url||e.controlPlane)}`),console.log(`Connection: ${String(o?.tunnel?.status||"saved")}`))}),t.command("uninstall").description("Uninstall the Node Agent service and packages; data is preserved by default.").option("--data-dir <path>","Override the installed Node Agent data directory").option("--delete-data","Delete Node Agent data without prompting").option("--keep-data","Preserve Node Agent data without prompting").action(async e=>{await async function(e,t=ju){if(e.deleteData&&e.keepData)throw new Error("--delete-data and --keep-data cannot be used together.");if(0!==t.getuid())throw new Error("Run this command as root so the Node Agent service and packages can be removed.");const i=t.exists(Ru)?t.readText(Ru):"",s=function(e,t){if(e.dataDir?.trim())return n.resolve(e.dataDir.trim());if(t.exists(Ru)){const e=Mu(t.readText(Ru),"TASK_HANDOFF_NODE_AGENT_DATA_DIR");if(e)return n.resolve(e)}return n.resolve(Jo())}(e,{exists:e=>e===Ru&&Boolean(i),readText:()=>i});if(s===n.parse(s).root)throw new Error(`Refusing to use a filesystem root as the Node Agent data directory: ${s}`);const r=Mu(i,"TASK_HANDOFF_NPM_COMMAND")||process.env.TASK_HANDOFF_NPM_COMMAND||"npm";if(t.exists(xu)){const e=t.readText(xu);if(!/^ExecStart=\S*task-handoff-node-agent(?:\s|$)/m.test(e))throw new Error(`Refusing to remove ${Ou} because it is not owned by a standalone Node Agent installation.`);Du(t,"systemctl",["disable","--now",Ou]),t.remove(xu,{force:!0}),Du(t,"systemctl",["daemon-reload"])}Du(t,r,["uninstall","--global",...Pu]),t.remove(Ru,{force:!0}),t.log("TaskHandoff Node Agent service and packages were removed.");const o=!!e.deleteData||!e.keepData&&await t.confirmDeleteData(s);return o?(t.remove(s,{recursive:!0,force:!0}),t.log(`Node Agent data was deleted from ${s}.`)):t.log(`Node Agent data was preserved at ${s}.`),{dataDir:s,dataDeleted:o}}(e)}),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"),s=require("node:url"),r=require("fastify"),o=require("@fastify/websocket"),a=require("zod"),c=require("node:os"),d=require("node:crypto"),l=require("node:child_process"),u=require("node-pty"),p=require("ws"),m=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=require("node:readline/promises"),v=require("node:process"),w="undefined"!=typeof document?document.currentScript:null;function S(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 E(e){if(e)try{return n.dirname(t.realpathSync(e))}catch{return}}function z(e,t=process.env,i=e){const s=t.TASK_HANDOFF_VERSION?.trim();if(s)return s;const r=i.split("/").at(-1),o=process.argv[1]?n.resolve(process.argv[1]):void 0,a=o?n.dirname(o):void 0,c=[E(o),a,process.cwd()].filter(e=>Boolean(e));for(const t of new Set(c)){let i=t;for(;;){const t=S(n.join(i,"package.json"),e);if(t)return t;const s=n.dirname(i);if(s===i)break;i=s}}let d;for(const e of new Set(c)){let t=e;for(;;){if(r){const e=S(n.join(t,"packages",r,"package.json"),i);if(e)return e}d||=S(n.join(t,"package.json"));const e=n.dirname(t);if(e===t)break;t=e}}return d||"unknown"}const N={perMessageDeflate:{threshold:256,serverNoContextTakeover:!0,clientNoContextTakeover:!0,concurrencyLimit:4,zlibDeflateOptions:{level:1}}};function T(e){return e.readyState===(e.OPEN??1)}function _(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 k(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 C(e,t,n){e.close(k(t),_(n)||void 0)}function O(e,t,n,i){if(T(e))for(const e of t.splice(0))if(i(e),!n(e))return}function x(e,t,n={}){const i=n.pendingFrameLimit??256,s=n.maxFrameBytes??8388608,r=n.maxTotalBytes??1073741824,o=n.maxBufferedBytes??16777216;let a=!1,c=T(t);const d=[],l=[];let u,p=0,m=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,o)=>{const a=g(o);return h+=a,n.onFrame?.(i,a),!(a>s||h>r)||(C(e,1009,"WebSocket bridge traffic limit exceeded."),C(t,1009,"WebSocket bridge traffic limit exceeded."),!1)},y=()=>{u&&(clearTimeout(u),u=void 0)},I=(n,i)=>{const s=i.bytes;if((n.bufferedAmount??0)+s>o)return C(e,1013,"WebSocket bridge consumer is too slow."),C(t,1013,"WebSocket bridge consumer is too slow."),!1;try{return function(e,t){e.send(t.data,{binary:t.isBinary,compress:!1})}(n,i),!0}catch{return C(e,1011,"WebSocket bridge send failed."),C(t,1011,"WebSocket bridge send failed."),!1}},A=(n,s,r)=>{if(s.length>=i)return C(e,1011,"WebSocket bridge pending frame limit exceeded."),void C(t,1011,"WebSocket bridge pending frame limit exceeded.");const a="upstream"===n?p:m;if((("upstream"===n?t:e).bufferedAmount??0)+a+r.bytes>o)return C(e,1013,"WebSocket bridge consumer is too slow."),void C(t,1013,"WebSocket bridge consumer is too slow.");s.push(r),"upstream"===n?p+=r.bytes:m+=r.bytes};return n.upstreamOpenTimeoutMs&&!c&&(u=setTimeout(()=>{c||a||(C(e,1011,"Upstream websocket did not open."),C(t))},n.upstreamOpenTimeoutMs)),e.on("open",()=>O(e,l,t=>I(e,t),e=>{m-=e.bytes})),t.on("open",()=>{y(),c=!0,n.onUpstreamOpen?.(),O(t,d,e=>I(t,e),e=>{p-=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)};T(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)};T(e)?I(e,i):A("client",l,i)}),t.on("close",(t,i)=>{y(),n.onUpstreamClose?.(t,i),(c||a||!n.onUpstreamCloseBeforeOpen?.())&&C(e,t,i)}),t.on("error",t=>{n.onUpstreamError?.(t),(c||a||!n.onUpstreamErrorBeforeOpen?.(t))&&C(e)}),e.on("close",(e,i)=>{y(),a=!0,n.onClientClose?.(e,i),C(t,e,i)}),e.on("error",e=>{y(),a=!0,n.onClientError?.(e),C(t,1011,"WebSocket bridge client failed.")}),{close:(n,i)=>{y(),C(t,n,i),C(e,n,i)}}}var R,P,D=function(){if(P)return R;P=1;const e=t,{spawnSync:n}=l;return R={processStartIdentity:function(t,i=process.platform){if(Number.isInteger(t)&&!(t<=0)){if("linux"===i)try{const n=e.readFileSync(`/proc/${t}/stat`,"utf8"),i=n.lastIndexOf(")");if(i<0)return;const s=n.slice(i+2).trim().split(/\s+/)[19];return s?`linux:${s}`:void 0}catch{return}if(["darwin","freebsd","openbsd","aix","sunos"].includes(i)){const e=n("ps",["-o","lstart=","-p",String(t)],{encoding:"utf8",timeout:1e3}),s=0===e.status?e.stdout.trim().replace(/\s+/g," "):"";return s?`${i}:${s}`:void 0}if("win32"===i){const e=n("powershell.exe",["-NoProfile","-NonInteractive","-Command",`(Get-Process -Id ${t} -ErrorAction Stop).StartTime.ToUniversalTime().Ticks`],{encoding:"utf8",timeout:2e3}),i=0===e.status?e.stdout.trim():"";return/^\d+$/.test(i)?`win32:${i}`:void 0}}}}}();class M 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 j(e){return n.join(e,"owner.json")}function L(e){return n.join(e,"initializing.json")}function F(e){return n.join(e,"recovering.json")}function $(e){return Number.isInteger(e)&&Number(e)>0}function U(e){try{const n=JSON.parse(t.readFileSync(j(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 H=U;function V(e){if(!$(e))return!1;try{return process.kill(Number(e),0),!0}catch(e){return"EPERM"===e.code}}function B(e){if(!e||!V(e.pid))return!1;if(!e.startIdentity)return!0;const t=D.processStartIdentity(e.pid);return void 0===t||t===e.startIdentity}function q(e,i){const s=n.join(e,`.owner-${i.token}.tmp`);t.writeFileSync(s,`${JSON.stringify(i,null,2)}\n`,{encoding:"utf8",mode:384,flag:"wx"});const r=G(e);if(r?.token!==i.token)throw J(s),new Error(`Process lock initialization was superseded: ${e}`);t.renameSync(s,j(e)),J(L(e))}function K(e,i,s){const r=H(e);if(r?.token!==i.token)return!1;const o={...i};for(const[e,t]of Object.entries(s))void 0===t?delete o[e]:Object.assign(o,{[e]:t});const a=n.join(e,`.owner-update-${i.token}-${d.randomUUID()}.tmp`);try{if(t.writeFileSync(a,`${JSON.stringify(o,null,2)}\n`,{encoding:"utf8",mode:384,flag:"wx"}),H(e)?.token!==i.token)return!1;t.renameSync(a,j(e));for(const e of Object.keys(i))delete i[e];return Object.assign(i,o),!0}catch(e){if("ENOENT"===e.code)return!1;throw e}finally{J(a)}}function G(e){try{return JSON.parse(t.readFileSync(L(e),"utf8"))}catch{return}}function W(e){const t=G(e);return $(t?.pid)&&B({pid:t.pid,startIdentity:t.startIdentity})}function J(e){try{t.unlinkSync(e)}catch(e){if("ENOENT"!==e.code)throw e}}function Y(){Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,20)}function X(e){try{const n=G(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 Q(e,i){try{return t.writeFileSync(F(e),`${JSON.stringify({token:i,pid:process.pid,startedAt:(new Date).toISOString()})}\n`,{encoding:"utf8",mode:384,flag:"wx"}),!0}catch(s){if("EEXIST"===s.code)return!!function(e){const i=F(e),s=Z(i),r=Date.parse(s?.startedAt||"");if(V(s?.pid)||Number.isFinite(r)&&Date.now()-r<2e3)return!1;const o=n.join(e,`.recovering-${d.randomUUID()}.stale`);try{t.renameSync(i,o)}catch(e){if(["ENOENT","EEXIST"].includes(e.code||""))return!1;throw e}const a=Z(o);if(a?.token===s?.token)return J(o),!0;try{t.linkSync(o,i)}catch(e){if("EEXIST"!==e.code)throw e}finally{J(o)}return!1}(e)&&Q(e,i);if("ENOENT"===s.code)return!1;throw s}}function Z(e){try{return JSON.parse(t.readFileSync(e,"utf8"))}catch{return}}function ee(e,t){return Z(F(e))?.token===t}function te(){return(new Date).toISOString()}const ne=6048e5;function ie(e,t){const i=n.resolve(e),s=n.resolve(i,t);if(n.dirname(s)!==i||n.basename(s)!==t)throw new Error(`Retention entry is not a direct child of its managed root: ${t}`);return s}function se(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 re=a.z.string().trim().min(1).max(120),oe=20971520,ae=512e3,ce=ae,de=oe,le=41943040,ue="ai.sessions",pe="ai-session.snapshot",me="ai-session.patch",he="ai-session.removed",ge="ai-session.message-delta",fe="ai-session.timeline-item",ye=a.z.string().trim().min(1).max(80),Ie=a.z.enum(["app-session","ai-session"]),Ae=a.z.enum(["image","file"]),be={scopeType:a.z.enum(["session","create-request"]),scopeId:a.z.string().trim().min(1).max(160),kind:Ae,name:a.z.string().trim().min(1).max(240),mime:a.z.string().trim().min(1).max(120)};a.z.object({...be,size:a.z.coerce.number().int().positive().max(oe)}).strict();const ve=a.z.string().regex(/^cia_[a-f0-9]{24}$/);a.z.object({attachmentId:ve,...be,size:a.z.number().int().positive().max(oe)}).strict(),a.z.object({offset:a.z.coerce.number().int().nonnegative()}).strict(),a.z.object({attachmentId:ve,offset:a.z.number().int().nonnegative()}),a.z.object({id:ve,kind:Ae,name:a.z.string().trim().min(1).max(240),mime:a.z.string().trim().min(1).max(120),size:a.z.number().int().positive().max(oe),expiresAt:a.z.string().datetime()});const we=a.z.object({id:a.z.string().trim().min(1).max(120),kind:Ae,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)}),Se=a.z.enum(["available","expired","missing"]),Ee=we.extend({contentState:Se.default("available")}).strict(),ze=a.z.object({id:a.z.string().trim().min(1).max(240),text:a.z.string(),attachments:a.z.array(Ee).max(6).default([])}).strict(),Ne=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 Te=a.z.enum(["thinking","tool","editing","approval","responding","unknown"]),_e=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(),ke=a.z.enum(["running","completed","failed","waiting"]),Ce=a.z.object({id:a.z.string().trim().min(1).max(240),turnId:a.z.string().trim().min(1).max(240)}).strict(),Oe=Ce.extend({type:a.z.literal("user-message"),text:a.z.string(),attachments:a.z.array(Ee).max(6).optional()}).strict(),xe=Ce.extend({type:a.z.literal("ai-message"),text:a.z.string()}).strict(),Re=Ce.extend({type:a.z.literal("activity"),activityKind:a.z.string().trim().min(1).max(120),title:a.z.string().trim().min(1).max(240),status:ke.optional(),summary:a.z.string().max(4e3).optional(),input:a.z.string().max(1e5).optional(),output:a.z.string().max(1e6).optional(),paths:a.z.array(a.z.string().trim().min(1).max(4096)).max(500).optional(),exitCode:a.z.number().int().optional(),durationMs:a.z.number().int().nonnegative().optional()}).strict(),Pe=a.z.discriminatedUnion("type",[Oe,xe,Re]);a.z.object({sessionId:a.z.string().trim().min(1).max(120),providerSessionId:a.z.string().trim().min(1).max(240),items:a.z.array(Pe),generatedAt:a.z.string().datetime()}).strict(),a.z.object({sessionId:a.z.string().trim().min(1).max(120),turnId:a.z.string().trim().min(1).max(240),items:a.z.array(Pe),generatedAt:a.z.string().datetime()}).strict();const De=a.z.enum(["pending-init","running","interrupted","completed","errored","shutdown","not-found"]),Me=a.z.enum(["started","interacted","interrupted"]),je=a.z.object({threadId:a.z.string().trim().min(1).max(240),path:a.z.string().trim().max(4096).optional(),status:De,activity:Me.optional(),message:a.z.string().trim().max(1e3).optional(),updatedAt:a.z.string().datetime()}).strict(),Le=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}),Fe=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(),$e=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(),Ue=a.z.union([we.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?oe:ae;(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.`})}),we.extend({source:a.z.object({type:a.z.literal("runtime-path"),path:a.z.string().trim().min(1).max(4096)}).strict()}).strict()]),He=we.extend({sourceType:a.z.enum(["inline","runtime-path"])}).strict(),Ve=a.z.union([a.z.object({id:a.z.string().trim().min(1).max(120),kind:Ae.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:Ae,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()]),Be=a.z.enum(["auto","queue","steer","immediate"]),qe=a.z.enum(["ask","auto-review","full-access"]),Ke=a.z.enum(["review","rename","goal","compact"]);a.z.object({command:Ke,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:Ke,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 Ge=a.z.object({name:a.z.string().trim().min(1).max(240),path:a.z.string().trim().min(1).max(4096)}),We=a.z.discriminatedUnion("kind",[Ge.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(),Ge.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(),Ge.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()]),Je=a.z.array(We).max(20).default([]),Ye=a.z.enum(["plugin","skill","file","directory","app"]),Xe=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."})}),Qe=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(Xe).max(1e3).default([]),diagnostics:a.z.array(Qe).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(Xe.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 Ze=a.z.object({message:a.z.string().trim().min(1).max(2e4),mode:Be.optional(),permissionMode:qe.optional()}),et=Ze.extend({attachments:a.z.array(Ue).max(6).default([]),references:Je}).strict().superRefine((e,t)=>{e.attachments.reduce((e,t)=>e+("inline"===t.source.type?t.size:0),0)>le&&t.addIssue({code:a.z.ZodIssueCode.custom,path:["attachments"],message:"Inline attachments must be 41943040 bytes or less in total."})}),tt=Ze.extend({attachments:a.z.array(Ve).max(6).default([]),references:Je}).strict(),nt=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(),it=a.z.object({modelEntityId:a.z.string().trim().min(1).max(120),modelName:a.z.string().trim().min(1).max(240)}).strict(),st=a.z.enum(["none","minimal","low","medium","high","xhigh","max","ultra"]);et.extend({agent:ye,cwd:nt,cwdFolderId:a.z.string().trim().min(1).max(120).optional(),clientRequestId:a.z.string().trim().min(1).max(160),modelSelection:it.optional(),reasoningEffort:st.optional(),storyId:re.optional()}).strict();const rt=a.z.object({mode:a.z.enum(["current-folder","worktree"]),branch:a.z.string().trim().min(1).max(1024)}).strict();tt.extend({agent:ye,cwdFolderId:a.z.string().trim().min(1).max(120).optional(),gitSelection:rt.optional(),clientRequestId:a.z.string().trim().min(1).max(160),modelSelection:it.optional(),reasoningEffort:st.optional(),storyId:re.optional()}).strict(),a.z.object({clientRequestId:a.z.string().trim().min(1).max(160),modelSelection:it}).strict(),a.z.object({sessionId:a.z.string().trim().min(1).max(120),accepted:a.z.literal(!0)}).strict(),a.z.object({clientRequestId:a.z.string().trim().min(1).max(160),reasoningEffort:st}).strict(),a.z.object({sessionId:a.z.string().trim().min(1).max(120),accepted:a.z.literal(!0)}).strict(),a.z.object({storyId:re.nullable()}).strict(),a.z.object({sessionId:a.z.string().trim().min(1).max(120),storyId:re.optional()}).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 ot=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:ot.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:Ie}).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:Ie}).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 at=a.z.object({id:a.z.string().trim().min(1).max(120),messageId:a.z.string().trim().min(1).max(240).optional(),message:a.z.string().trim().min(1).max(2e4),attachments:a.z.array(He).max(6).default([]),references:Je,permissionMode:qe.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(),ct=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(at).max(100).default([])}).strict().default({revision:0,pendingCount:0,items:[]}),dt=a.z.enum(["control","realtime","adapter-snapshot","transcript-tail","transcript-scan","process-scan","app-session"]),lt=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(),ut=a.z.object({id:a.z.string().trim().min(1).max(240),providerTurnId:a.z.string().trim().max(240).optional(),source:dt.optional(),userPrompt:a.z.string().trim().optional(),userMessages:a.z.array(ze).max(100).optional(),status:a.z.enum(["queued","running","waiting","completed","failed"]).default("running"),phase:Te.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(lt).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(),pt=ut.pick({id:!0,providerTurnId:!0,userPrompt:!0,userMessages:!0,status:!0,phase:!0,summary:!0,lastMessage:!0,contextCompactions:!0,startedAt:!0,updatedAt:!0,completedAt:!0}).strict(),mt=a.z.object({id:a.z.string().trim().min(1).max(120),agent:ye,creationSource:Ie.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:$e.optional(),providerMeta:a.z.record(a.z.string(),a.z.unknown()).optional(),modelSelection:it.optional(),reasoningEffort:st.optional(),storyId:re.optional(),appBindingKeys:a.z.array(a.z.string().trim().min(1).max(240)).max(20).optional(),actions:Fe.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(ut).max(50).optional(),status:Ne.default("running"),phase:Te.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:_e.optional(),toolCallsSinceLastMessage:a.z.number().int().min(0).default(0),subAgents:a.z.array(je).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:Le,queue:ct}).strict(),ht=mt.pick({id:!0,appBindingKeys:!0,cwd:!0,error:!0,providerMeta:!0,modelSelection:!0,reasoningEffort:!0,queue:!0,subAgents:!0}).strict(),gt=ut.pick({id:!0,providerTurnId:!0,status:!0,phase:!0,revision:!0,startedAt:!0,updatedAt:!0,completedAt:!0}).extend({bodyRevision:a.z.string().trim().min(1).max(64)}).strict(),ft=a.z.object({sessionId:a.z.string().trim().min(1).max(120),revision:a.z.string().trim().min(1).max(64),turns:a.z.array(gt).max(50)}).strict(),yt=a.z.object({sessionId:a.z.string().trim().min(1).max(120),revision:a.z.string().trim().min(1).max(64),turn:ut}).strict(),It=a.z.string().trim().min(1).max(64),At=a.z.object({kind:a.z.literal("not-modified"),revision:It}).strict();a.z.discriminatedUnion("kind",[At,a.z.object({kind:a.z.literal("updated"),revision:It,detail:ht}).strict()]),a.z.discriminatedUnion("kind",[At,a.z.object({kind:a.z.literal("updated"),revision:It,index:ft}).strict()]),a.z.discriminatedUnion("kind",[At,a.z.object({kind:a.z.literal("updated"),revision:It,body:yt}).strict()]);const bt=a.z.object({session:mt,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(),vt=bt.omit({session:!0}).extend({sessionId:a.z.string().trim().min(1).max(120),messageId:a.z.string().trim().min(1).max(240).optional()}).strict();a.z.object({sessionId:a.z.string().trim().min(1).max(120),queueRevision:a.z.number().int().min(0),action:a.z.enum(["retry","remove","edit","reorder"]),queueId:a.z.string().trim().min(1).max(120).optional()}).strict(),a.z.union([vt,bt.transform(function(e){const t=e.session.turns?.at(-1),n=(e.queueId?e.session.queue?.items.find(t=>t.id===e.queueId)?.messageId:void 0)||("send"===e.action||"queue"===e.action||"steer"===e.action?t?.userMessages?.at(-1)?.id:void 0);return vt.parse({sessionId:e.session.id,provider:e.provider,action:e.action,...e.decision?{decision:e.decision}:{},...e.turnId||e.session.activeTurnId||t?.id?{turnId:e.turnId||e.session.activeTurnId||t?.id}:{},...e.providerTurnId||t?.providerTurnId?{providerTurnId:e.providerTurnId||t?.providerTurnId}:{},...e.queueId?{queueId:e.queueId}:{},...n?{messageId:n}:{}})})]);const wt=500,St=a.z.object({id:a.z.string().trim().min(1).max(120),agent:ye,creationSource:Ie,providerSessionId:a.z.string().trim().min(1).max(240),lineage:$e.optional(),modelSelection:it.optional(),reasoningEffort:st.optional(),storyId:re.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(St).max(wt).default([])}).strict(),a.z.object({items:a.z.array(St).max(wt).default([])}).strict(),a.z.object({item:St,turns:a.z.array(pt).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:Ie}).strict();const Et=ut.omit({userMessages:!0}),zt=mt.pick({id:!0,agent:!0,creationSource:!0,appSessionId:!0,appId:!0,providerSessionId:!0,lineage:!0,providerMeta:!0,modelSelection:!0,reasoningEffort:!0,storyId:!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}).extend({turns:a.z.array(Et).max(50).optional(),detailRevision:a.z.string().trim().min(1).max(64).optional(),turnsRevision:a.z.string().trim().min(1).max(64).optional(),latestTurnRef:a.z.object({id:ut.shape.id,bodyRevision:a.z.string().trim().min(1).max(64)}).strict().optional(),turnCount:a.z.number().int().min(0).optional(),subAgentCount:a.z.number().int().min(0).optional(),lastUserMessageAt:a.z.string().datetime().optional()}).strict(),Nt=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(zt).default([]),updatedAt:a.z.string().datetime()}).strict(),Tt=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:Nt}).strict();Nt.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 _t=a.z.enum(["provider-event","app-session-created","app-session-updated","app-session-deleted","discovery-scan","control-action","heartbeat-sync","startup"]),kt=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:_t}).strict(),Ct=a.z.object({meta:kt,snapshot:Nt}).strict(),Ot=a.z.object({meta:kt,upserted:a.z.array(zt).default([]),removed:a.z.array(a.z.string().trim().min(1).max(120)).default([])}).strict(),xt=a.z.object({meta:kt,sessionIds:a.z.array(a.z.string().trim().min(1).max(120)).default([]),expiresAt:a.z.string().datetime()}).strict(),Rt=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).optional(),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(),Pt=Rt.omit({instanceId:!0,nodeId:!0,providerSessionId:!0}).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),item:Pe,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(pe),payload:Ct}).strict(),a.z.object({type:a.z.literal(me),payload:Ot}).strict(),a.z.object({type:a.z.literal(he),payload:xt}).strict()])).default([])}).strict();const Dt=a.z.object({source:dt,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(),Mt=Dt.extend({type:a.z.literal("snapshot"),agent:a.z.string().trim().min(1).max(80),creationSource:Ie.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:$e.optional(),providerMeta:a.z.record(a.z.string(),a.z.unknown()).optional(),modelSelection:it.optional(),reasoningEffort:st.optional(),storyId:re.optional(),appBindingKeys:a.z.array(a.z.string().trim().min(1).max(240)).max(20).optional(),actions:Fe.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(ut).max(50).optional(),status:Ne.optional(),phase:Te.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:_e.optional(),toolCallsSinceLastMessage:a.z.number().int().min(0).optional(),subAgents:a.z.array(je).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(),jt=Dt.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","model-selection","reasoning-effort"]),modelSelection:it.optional(),reasoningEffort:st.optional(),activeTurnId:a.z.string().trim().max(240).optional(),providerTurnId:a.z.string().trim().max(240).optional(),userPrompt:a.z.string().trim().optional(),userMessage:ze.optional(),text:a.z.string().optional(),itemId:a.z.string().trim().max(240).optional(),status:Ne.optional(),phase:Te.optional(),summary:a.z.string().trim().max(1e3).optional(),error:a.z.string().trim().max(4e3).optional(),currentTool:_e.nullable().optional(),toolCallsSinceLastMessage:a.z.number().int().min(0).optional(),subAgents:a.z.array(je).max(50).optional(),contextCompaction:lt.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("model-selection"===e.kind?e.modelSelection||t.addIssue({code:"custom",path:["modelSelection"],message:"model-selection events require modelSelection"}):void 0!==e.modelSelection&&t.addIssue({code:"custom",path:["modelSelection"],message:"modelSelection is only valid for model-selection events"}),"reasoning-effort"===e.kind?e.reasoningEffort||t.addIssue({code:"custom",path:["reasoningEffort"],message:"reasoning-effort events require reasoningEffort"}):void 0!==e.reasoningEffort&&t.addIssue({code:"custom",path:["reasoningEffort"],message:"reasoningEffort is only valid for reasoning-effort events"}),"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"}),"send-ack"!==e.kind&&"user-message"!==e.kind&&void 0!==e.userMessage&&t.addIssue({code:"custom",path:["userMessage"],message:"userMessage is only valid for send-ack and user-message 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",[Mt,jt]);const Lt=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()]),Ft=a.z.union([Lt,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()]),$t=a.z.object({promptTemplate:a.z.string().trim().min(1).max(2e4)}).strict(),Ut=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(),Ht=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:Ft,action:$t,policy:Ut.default({maxConcurrentRuns:1,whenBusy:"skip"}),createdAt:a.z.string().datetime(),updatedAt:a.z.string().datetime()}).strict(),Vt=a.z.object({type:a.z.literal("ai-session"),aiSessionId:a.z.string().trim().min(1).max(160)}).strict(),Bt=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:Vt,localName:a.z.string().trim().min(1).max(160).optional(),createdAt:a.z.string().datetime(),updatedAt:a.z.string().datetime()}).strict(),qt=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(),Kt=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:Vt,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(Ht).default([]),deployments:a.z.array(Bt).default([]),runtime:a.z.array(qt).default([]),recentRuns:a.z.array(Kt).default([])}).strict();const Gt=a.z.object({config:Ht,deployment:Bt,runtime:qt.optional()}).strict();a.z.object({instanceId:a.z.string().trim().min(1).max(160),sessionId:a.z.string().trim().min(1).max(160),mutation:Gt.optional()}).strip(),a.z.object({instanceId:a.z.string().trim().min(1).max(160),sessionId:a.z.string().trim().min(1).max(160),configHash:Ht.shape.configHash}).strip();const Wt=a.z.object({instanceId:a.z.string().trim().min(1).max(160),instanceName:a.z.string().trim().min(1).max(160),deployment:Bt,runtime:qt.optional()}).strip(),Jt=Kt.extend({instanceName:a.z.string().trim().min(1).max(160).optional()}).strip(),Yt=a.z.object({configHash:a.z.string().trim().min(8).max(80),config:Ht,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(Wt),recentRuns:a.z.array(Jt)}).strip();a.z.object({updatedAt:a.z.string().datetime(),triggers:a.z.array(Yt)}).strip(),a.z.object({name:Ht.shape.name,description:Ht.shape.description,source:Ft,action:$t,policy:Ut.partial().optional()}).strict(),a.z.object({scope:a.z.enum(["node","instance"]),nodeId:a.z.string().trim().min(1).max(160).optional(),instanceId:a.z.string().trim().min(1).max(160).optional(),code:a.z.string().trim().min(1).max(160),message:a.z.string().trim().min(1).max(4e3)}).strip();const Xt=a.z.string().regex(/^\d{4}-\d{2}-\d{2}$/,"Proxy protocol version must use YYYY-MM-DD format."),Qt=a.z.string().trim().min(1).max(160).regex(/^[a-zA-Z0-9][a-zA-Z0-9_.:-]*$/),Zt=a.z.string().datetime(),en=a.z.string().trim().min(32).max(4096),tn=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,s;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{s=new URL(t,"https://node-agent.invalid")}catch{throw new Error("Proxy route is invalid.")}if("https://node-agent.invalid"!==s.origin||s.username||s.password)throw new Error("Proxy route cannot select an absolute upstream URL.");return`${s.pathname}${s.search}`}(e)}catch(e){return t.addIssue({code:"custom",message:e instanceof Error?e.message:String(e)}),a.z.NEVER}});const nn=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"})),sn=a.z.object({code:nn,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(),rn=a.z.enum(["active","revoked"]),on=a.z.object({id:Qt,targetNodeId:Qt,status:rn,createdBy:Qt,expiresAt:Zt,revokedAt:Zt.optional(),createdAt:Zt,updatedAt:Zt}).strict();a.z.object({targetNodeId:Qt,expiresInSeconds:a.z.number().int().min(60).max(3600).default(600)}).strict(),a.z.object({invite:on,token:a.z.string().trim().min(24).max(512),proxyOrigin:tn,protocolVersion:Xt}).strict();const an=a.z.enum(["active","revoked"]),cn=a.z.object({id:Qt,claimId:Qt,sourceControlPlaneId:Qt,targetNodeId:Qt,bindingKeyId:Qt,status:an,revision:a.z.number().int().positive(),lastError:sn.optional(),revokedAt:Zt.optional(),createdAt:Zt,updatedAt:Zt}).strict();a.z.object({protocolVersion:Xt,inviteToken:a.z.string().trim().min(24).max(512).optional(),claimId:Qt,sourceControlPlaneId:Qt,targetNodeId:Qt.optional(),bindingKeyId:Qt,credential:en}).strict(),a.z.object({sourceControlPlaneId:Qt,bindingKeyId:Qt,credential:en}).strict();const dn=a.z.object({id:Qt,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:Zt.optional(),capabilities:a.z.record(a.z.string(),a.z.unknown()).default({})}).strict(),ln=a.z.object({protocolVersion:Xt,binding:cn,streamId:Qt,revision:a.z.number().int().nonnegative(),observedAt:Zt,target:dn}).strict(),un=a.z.object({type:a.z.literal("control-plane-proxy.event"),protocolVersion:Xt,streamId:Qt,bindingId:Qt,sourceControlPlaneId:Qt,targetNodeId:Qt,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:dn,event:a.z.object({type:a.z.string().trim().min(1).max(240),topic:a.z.string().trim().min(1).max(240),createdAt:Zt}).strict()}).strict(),pn=a.z.object({type:a.z.literal("control-plane-proxy.events.ready"),protocolVersion:Xt,streamId:Qt,bindingId:Qt,sourceControlPlaneId:Qt,targetNodeId:Qt,latestRevision:a.z.number().int().nonnegative(),earliestRetainedRevision:a.z.number().int().nonnegative()}).strict(),mn=a.z.object({type:a.z.literal("control-plane-proxy.snapshot-required"),protocolVersion:Xt,streamId:Qt,bindingId:Qt,sourceControlPlaneId:Qt,targetNodeId:Qt,sinceRevision:a.z.number().int().nonnegative(),latestRevision:a.z.number().int().nonnegative(),earliestRetainedRevision:a.z.number().int().nonnegative(),error:sn}).strict();a.z.discriminatedUnion("type",[un,pn,mn]),a.z.object({protocolVersion:Xt,binding:cn,target:ln.shape.target}).strict(),a.z.object({id:Qt,claimId:Qt,proxyOrigin:tn,requestedName:a.z.string().trim().min(1).max(160).optional(),sourceControlPlaneId:Qt,targetNodeId:Qt.optional(),bindingKeyId:Qt,credential:en,status:a.z.enum(["pending","compensation-required"]),createdAt:Zt,updatedAt:Zt,expiresAt:Zt}).strict().omit({credential:!0}),a.z.object({id:Qt,nodeId:Qt,proxyOrigin:tn,proxyBindingId:Qt,targetNodeId:Qt,sourceControlPlaneId:Qt,bindingKeyId:Qt,credential:en,createdAt:Zt,updatedAt:Zt}).strict();const hn=a.z.string().trim().min(1).max(120),gn=a.z.object({selectModelAtCreate:a.z.boolean().default(!1),selectProviderAtCreate:a.z.boolean().default(!1),switchModelWithinProvider:a.z.boolean().default(!1),switchProviderDuringSession:a.z.boolean().default(!1)}).strip().default({selectModelAtCreate:!1,selectProviderAtCreate:!1,switchModelWithinProvider:!1,switchProviderDuringSession:!1}),fn=a.z.object({selectAtCreate:a.z.boolean().default(!1),updateDuringSession:a.z.boolean().default(!1)}).strip().default({selectAtCreate:!1,updateDuringSession:!1}),yn=a.z.object({agent:hn,actions:a.z.object({create:a.z.boolean().default(!1),send:a.z.boolean().default(!1),queue:a.z.boolean().default(!1),steer:a.z.boolean().default(!1),interrupt:a.z.boolean().default(!1),archive:a.z.boolean().default(!1),delete:a.z.boolean().default(!1),fork:a.z.boolean().default(!1),approvalDecisions:a.z.array(a.z.enum(["allow","deny","skip"])).max(3).default([])}).passthrough(),timeline:a.z.object({sessionRead:a.z.boolean().default(!1),turnRead:a.z.boolean().default(!1),liveItems:a.z.boolean().default(!1)}).passthrough(),modelSelection:gn.optional(),reasoningEffort:fn.optional()}).passthrough(),In=a.z.array(yn).max(100).default([]),An="2026-08-27",bn=new Set(["2026-08-01","2026-08-16","2026-08-17","2026-08-20",An]),vn=a.z.string().regex(/^\d{4}-\d{2}-\d{2}$/,"Protocol version must use YYYY-MM-DD format."),wn=a.z.string().trim().min(1).max(120);function Sn(){return{features:{appRuntime:!1,tty:!1,gui:!1,browser:!1,browserTunnel:!1,screenshots:!1,logs:!1,aiSessionWorkspaceSelection:!1,aiSessionPersistenceSettings:!1,privateModelCatalog:!1,gitCliCredentialBroker:!1,gitCredentialProxy:!1,aiSessionTimeline:{sessionReadAgents:[],turnReadAgents:[],liveItemAgents:[]},aiSessionConversationAttachments:{metadataAgents:[],contentAgents:[],uploadAgents:[],retentionSettings:!1,fileSizeLimitSettings:!1},aiSessionProviders:[]}}}const En=a.z.object({sessionReadAgents:a.z.array(wn).max(100).default([]),turnReadAgents:a.z.array(wn).max(100).default([]),liveItemAgents:a.z.array(wn).max(100).default([])}).passthrough(),zn=a.z.object({metadataAgents:a.z.array(wn).max(100).default([]),contentAgents:a.z.array(wn).max(100).default([]),uploadAgents:a.z.array(wn).max(100).default([]),retentionSettings:a.z.boolean().default(!1),fileSizeLimitSettings:a.z.boolean().default(!1)}).passthrough(),Nn=a.z.object({appRuntime:a.z.boolean().default(!1),tty:a.z.boolean().default(!1),gui:a.z.boolean().default(!1),browser:a.z.boolean().default(!1),browserTunnel:a.z.boolean().optional(),screenshots:a.z.boolean().default(!1),logs:a.z.boolean().default(!1),aiSessionWorkspaceSelection:a.z.boolean().default(!1),aiSessionPersistenceSettings:a.z.boolean().default(!1),privateModelCatalog:a.z.boolean().optional(),gitCliCredentialBroker:a.z.boolean().optional(),gitCredentialProxy:a.z.boolean().optional(),aiSessionTimeline:En.default(function(){return{sessionReadAgents:[],turnReadAgents:[],liveItemAgents:[]}}),aiSessionConversationAttachments:zn.optional(),aiSessionProviders:In.optional()}).passthrough(),Tn=a.z.object({features:Nn.default(function(){return{appRuntime:!1,tty:!1,gui:!1,browser:!1,browserTunnel:!1,screenshots:!1,logs:!1,aiSessionWorkspaceSelection:!1,aiSessionPersistenceSettings:!1,privateModelCatalog:!1,gitCliCredentialBroker:!1,gitCredentialProxy:!1,aiSessionTimeline:{sessionReadAgents:[],turnReadAgents:[],liveItemAgents:[]},aiSessionConversationAttachments:{metadataAgents:[],contentAgents:[],uploadAgents:[],retentionSettings:!1,fileSizeLimitSettings:!1},aiSessionProviders:[]}})}).passthrough();function _n(e){const t={features:{appRuntime:!1,tty:!1,gui:!1,browser:!1,browserTunnel:!1,screenshots:!1,logs:!1,aiSessionWorkspaceSelection:!1,aiSessionPersistenceSettings:!1,privateModelCatalog:!1,gitCliCredentialBroker:!1,gitCredentialProxy:!1,aiSessionTimeline:{sessionReadAgents:[],turnReadAgents:[],liveItemAgents:[]},aiSessionConversationAttachments:{metadataAgents:[],contentAgents:[],uploadAgents:[],retentionSettings:!1,fileSizeLimitSettings:!1},aiSessionProviders:[]}};if(!e||"object"!=typeof e||Array.isArray(e))return t;const n=e,i=n.features;if(!i||"object"!=typeof i||Array.isArray(i))return t;const s=i,r={appRuntime:!1,tty:!1,gui:!1,browser:!1,browserTunnel:!1,screenshots:!1,logs:!1,aiSessionWorkspaceSelection:!1,aiSessionPersistenceSettings:!1,privateModelCatalog:!1,gitCliCredentialBroker:!1,gitCredentialProxy:!1,aiSessionTimeline:{sessionReadAgents:[],turnReadAgents:[],liveItemAgents:[]},aiSessionConversationAttachments:{metadataAgents:[],contentAgents:[],uploadAgents:[],retentionSettings:!1,fileSizeLimitSettings:!1},aiSessionProviders:[]};for(const e of["appRuntime","tty","gui","browser","browserTunnel","screenshots","logs","aiSessionWorkspaceSelection","aiSessionPersistenceSettings","privateModelCatalog","gitCliCredentialBroker","gitCredentialProxy"]){const t=a.z.boolean().safeParse(s[e]);t.success&&(r[e]=t.data)}const o=En.safeParse(s.aiSessionTimeline);o.success&&(r.aiSessionTimeline=o.data);const c=zn.safeParse(s.aiSessionConversationAttachments);c.success&&(r.aiSessionConversationAttachments=c.data);const d=In.safeParse(s.aiSessionProviders);return d.success&&(r.aiSessionProviders=d.data),Tn.parse({...n,features:{...s,...r}})}function kn(e){return _n(e).features.aiSessionConversationAttachments}const Cn=a.z.string().trim().min(1).max(120).regex(/^[a-zA-Z0-9][a-zA-Z0-9_.:-]*$/),On=a.z.string().datetime(),xn=a.z.record(a.z.string(),a.z.string()).default({}),Rn=a.z.record(a.z.string(),a.z.string()).default({}),Pn=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 Dn(e){if(null==e)return;const t=Pn.parse(e);return"utf8"===t.encoding?t.data:Buffer.from(t.data,"base64")}const Mn=/^[A-Za-z0-9_][A-Za-z0-9_.-]{0,127}$/,jn=/^sha256:([a-fA-F0-9]{64})$/,Ln=/^(?:localhost|[a-z0-9](?:[a-z0-9.-]*[a-z0-9])?)(?::[1-9][0-9]{0,4})?$/,Fn=/^[a-z0-9]+(?:(?:[._]|__|-+)[a-z0-9]+)*$/;function $n(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),s=-1===n?t:t.slice(0,n),r=i?jn.exec(i):void 0;if(i&&!r)throw new Error("Docker image digest must use sha256 followed by 64 hexadecimal characters.");const o=s.lastIndexOf("/"),a=s.lastIndexOf(":"),c=a>o,d=c?s.slice(a+1):void 0,l=c?s.slice(0,a):s;if(d&&!Mn.test(d))throw new Error("Docker image tag is invalid.");if(!d&&!r)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 p=u.length>1&&(u[0].includes(".")||u[0].includes(":")||"localhost"===u[0]),m=p?u.slice(1):u;if(p&&!Ln.test(u[0].toLowerCase()))throw new Error("Docker image registry host or port is invalid.");if(!m.length||m.some(e=>!Fn.test(e)))throw new Error("Docker image repository names must be lowercase and use valid separators.");const h=u.map((e,t)=>p&&0===t?e.toLowerCase():e).join("/"),g=r?`sha256:${r[1].toLowerCase()}`:void 0;return`${h}${d?`:${d}`:""}${g?`@${g}`:""}`}function Un(e){const t=$n(e),n=t.indexOf("@"),i=-1===n?void 0:t.slice(n+1),s=-1===n?t:t.slice(0,n),r=s.lastIndexOf("/"),o=s.lastIndexOf(":"),a=o>r;return{reference:t,repository:a?s.slice(0,o):s,tag:a?s.slice(o+1):void 0,digest:i}}const Hn=a.z.string().trim().min(1).max(512).transform((e,t)=>{try{return $n(e)}catch(e){return t.addIssue({code:"custom",message:e instanceof Error?e.message:String(e)}),a.z.NEVER}}),Vn=a.z.string().trim().transform((e,t)=>{const n=jn.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)}),Bn=a.z.object({modelEntityIds:a.z.array(Cn).max(64).transform(e=>[...new Set(e)]).optional(),codexModelHash:Cn.nullable().optional(),claudeModelHash:Cn.nullable().optional(),opencodeModelHash:Cn.nullable().optional()}).strict().default({}),qn=a.z.object({imageId:Cn,tag:a.z.string().trim().min(1).max(128).regex(Mn).optional()}).strict(),Kn=a.z.discriminatedUnion("type",[a.z.object({type:a.z.literal("image"),imageSelection:qn}).strict(),a.z.object({type:a.z.literal("template"),environmentTemplateId:Cn}).strict()]),Gn=a.z.enum(["creating","ready","failed","deleting"]),Wn=a.z.enum(["linux","darwin","win32","freebsd","openbsd","aix","sunos","unknown"]),Jn=a.z.enum(["x64","arm64","arm","ia32","ppc64","s390x","riscv64","unknown"]),Yn=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(),Xn=a.z.object({templateId:Cn,nodeId:Cn,imageId:Vn,name:a.z.string().trim().min(1).max(160),platform:Wn,architecture:Jn}).strict(),Qn=a.z.enum(["data","agent-home","workspace"]),Zn=a.z.object({deleteVolumes:a.z.boolean()}).strict(),ei=a.z.object({role:Qn,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(),ti=a.z.object({instanceId:Cn,containerDeleted:a.z.boolean(),completed:a.z.boolean(),deletedVolumes:a.z.array(ei),retainedVolumes:a.z.array(ei),volumeResults:a.z.array(ei)}).strict(),ni={img_default:"market_taskhandoff_browser",img_codex:"market_taskhandoff_codex",img_ai:"market_taskhandoff_ai"};function ii(e,t){if(e&&"object"==typeof e&&!Array.isArray(e)){const t=e;return{imageId:"string"==typeof t.imageId&&ni[t.imageId]||t.imageId,..."string"==typeof t.tag?{tag:t.tag}:{}}}if("string"==typeof t)return{imageId:ni[t]||t}}function si(e){if(!e||"object"!=typeof e||Array.isArray(e))return e;const t=e,{defaultImageId:n,...i}=t;return{...i,defaultImageSelection:ii(t.defaultImageSelection,n)}}const ri=a.z.object({id:Cn,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(),oi=a.z.object({code:a.z.enum(["APP_CATALOG_INVALID"]),message:a.z.string().trim().min(1).max(500)}).strict(),ai=a.z.object({items:a.z.array(ri).max(256),observedAt:On,issues:a.z.array(oi).max(32).default([])}).strict(),ci=a.z.object({id:Cn,name:a.z.string().trim().min(1).max(160),sourceInstanceId:Cn,nodeId:Cn,imageId:Vn.optional(),internalTag:a.z.string().trim().min(1).max(512).optional(),platform:Wn.optional(),architecture:Jn.optional(),sizeBytes:a.z.number().int().nonnegative().optional(),status:Gn,error:Yn.optional(),createdAt:On,updatedAt:On}).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."})}),di=a.z.enum(["apt","dnf","brew","npm"]),li=a.z.enum(["user","passwordless-sudo","root"]),ui=a.z.object({platform:Wn,arch:Jn,installers:a.z.array(di).max(8),privilege:li,installerAccess:a.z.object({npmGlobalWritable:a.z.boolean().optional()}).strict().optional()}).strict(),pi=a.z.enum(["installed","not-installed","broken","unsupported"]),mi=a.z.enum(["recipe","bundled","external","none"]),hi=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(),gi=a.z.object({id:Cn,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:pi,managementSource:mi,version:a.z.string().trim().max(120).optional(),canInstall:a.z.boolean(),canUninstall:a.z.boolean(),installReason:hi.optional(),uninstallReason:hi.optional(),activeJobId:Cn.optional()}).strict(),fi=a.z.enum(["install","uninstall"]),yi=a.z.enum(["queued","running","succeeded","failed","cancelled","interrupted"]),Ii=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"]}),Ai=a.z.object({executable:a.z.string().trim().min(1).max(4096),args:a.z.array(a.z.string().max(4096)).max(128)}).strict(),bi=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(Cn).max(64).optional()}).strict(),vi=a.z.object({id:Cn,requestId:Cn.optional(),appId:Cn,operation:fi,state:yi,phase:a.z.string().trim().min(1).max(120).optional(),progress:Ii.optional(),command:Ai.optional(),logTail:a.z.string().max(32768).optional(),logTruncated:a.z.boolean().optional(),error:bi.optional(),requestedAt:On,startedAt:On.optional(),finishedAt:On.optional(),updatedAt:On}).strict(),wi=a.z.object({streamId:Cn,sequence:a.z.number().int().nonnegative(),capabilities:ui,apps:a.z.array(gi).max(256),activeJobs:a.z.array(vi).max(256),recentJobs:a.z.array(vi).max(256),observedAt:On}).strict();a.z.object({requestId:Cn.optional()}).strict(),a.z.object({job:vi}).strict(),a.z.object({type:a.z.literal("app-management"),streamId:Cn,sequence:a.z.number().int().nonnegative(),observedAt:On,job:vi.optional(),snapshot:wi.optional()}).strict().refine(e=>void 0!==e.job||void 0!==e.snapshot,{message:"An app management event requires a job or snapshot."});const Si=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:vn.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:vn,build:Si.extend({component:a.z.literal("control-plane"),packageVersion:a.z.string().trim().min(1).max(80)}).loose(),serverTime:On}).loose()}).loose();const Ei=a.z.enum(["stable","beta","alpha"]),zi=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(),Ni=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(),Ti=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:On.optional(),matchedAt:On.optional(),error:Ni.optional()}).strict(),_i=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(Cn).max(1024).default([]),stoppedInstanceIds:a.z.array(Cn).max(1024).default([]),activeInstanceIds:a.z.array(Cn).max(1024).default([])}).strict(),ki=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(Cn).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(),Ci=a.z.object({channel:Ei.default("stable")}).strict(),Oi=a.z.object({source:a.z.literal("npm"),channel:Ei,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(zi).default([]),impact:_i,updateAvailable:a.z.boolean(),supported:a.z.boolean().default(!0),reason:a.z.string().trim().max(2048).optional(),checkedAt:On,preflightToken:a.z.string().trim().min(16).max(240).optional()}).strict(),xi=a.z.object({id:Cn,nodeId:Cn,source:a.z.literal("npm"),channel:Ei,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(zi).default([]),impact:_i,rollout:ki,status:a.z.enum(["queued","updating-node","restarting-node","converging-instances","succeeded","degraded","failed"]),error:Ni.optional(),startedAt:On.optional(),completedAt:On.optional(),createdAt:On,updatedAt:On}).strict(),Ri=a.z.object({channel:Ei,targetVersion:a.z.string().trim().min(1).max(240),preflightToken:a.z.string().trim().min(16).max(240)}).strict(),Pi=a.z.object({type:a.z.enum(["branch","tag"]),name:a.z.string().trim().min(1).max(240)}).strict(),Di=a.z.object({type:a.z.literal("commit"),commit:a.z.string().trim().regex(/^[0-9a-fA-F]{4,64}$/,"commit must be a hexadecimal Git object id")}).strict(),Mi=a.z.discriminatedUnion("type",[Pi,Di]),ji=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(),Li=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).refine(e=>!e.startsWith("/")&&!e.split("/").some(e=>".."===e),"subdirectory must be a relative path within the repository").transform(e=>e.split("/").filter(e=>e&&"."!==e).join("/")).default("")}).strict();a.z.object({id:Cn,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:Mi.default({type:"branch",name:"main"}),auth:ji.default({type:"none"}),clone:Li.default({submodules:!1,lfs:!1,subdirectory:""}),defaultImageSelection:qn.optional(),labels:xn,createdAt:On,updatedAt:On}).strict();const Fi=a.z.object({id:Cn,nodeId:Cn,name:a.z.string().trim().min(1).max(160),path:a.z.string().trim().min(1).max(4096),defaultImageSelection:qn.optional(),labels:xn,createdAt:On,updatedAt:On}).strict(),$i=a.z.discriminatedUnion("type",[a.z.object({type:a.z.literal("git-repository"),repositoryId:Cn.optional(),url:a.z.string().trim().min(1).max(2048),provider:a.z.string().trim().max(80).optional(),ref:Mi.default({type:"branch",name:"main"}),auth:ji.default({type:"none"}),clone:Li.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:Mi.default({type:"branch",name:"main"}),auth:ji.default({type:"none"}),clone:Li.default({submodules:!1,lfs:!1,subdirectory:""})}).strict(),a.z.object({type:a.z.literal("local-folder"),localFolderId:Cn.optional(),path:a.z.string().trim().min(1).max(4096),ownerNodeId:Cn.optional()}).strict()]),Ui=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(),Hi=a.z.enum(["codex","claude","opencode"]),Vi=a.z.enum(["openai-responses","openai-chat-completions","anthropic-messages"]),Bi=a.z.object({name:a.z.string().trim().min(1).max(240),order:a.z.number().int().min(0).max(1e6).default(0)}).strict(),qi=a.z.object({id:Cn,name:a.z.string().trim().min(1).max(160),source:$i,defaultImageSelection:qn.optional(),defaultNodeId:Cn.optional(),workspacePolicy:Ui,labels:xn,createdAt:On,updatedAt:On}).strict(),Ki=a.z.object({id:Cn,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),modelNames:a.z.array(Bi).max(256).default([]),protocols:a.z.array(Vi).max(3).default([]),app:Hi,enabled:a.z.boolean().default(!0),order:a.z.number().int().min(0).max(1e6).default(0),labels:xn,createdAt:On,updatedAt:On}).strict(),Gi=Ki,Wi=Ki.omit({key:!0}).extend({keyPreview:a.z.string().trim().min(1).max(160),keySet:a.z.boolean()}).strict(),Ji=Wi.extend({referenceCount:a.z.number().int().min(0)}).strict(),Yi=a.z.object({instanceId:Cn,modelEntityIds:a.z.array(Cn).max(64).transform(e=>[...new Set(e)]).optional(),codexModelHash:Cn.optional(),claudeModelHash:Cn.optional(),opencodeModelHash:Cn.optional(),updatedAt:On}).strict().transform(e=>({...e,modelEntityIds:e.modelEntityIds?.length?e.modelEntityIds:[...new Set([e.codexModelHash,e.claudeModelHash,e.opencodeModelHash].filter(e=>Boolean(e)))]})),Xi=a.z.discriminatedUnion("type",[a.z.object({type:a.z.literal("control-plane"),name:Ki.shape.name,enabled:Ki.shape.enabled,order:Ki.shape.order}).strict(),a.z.object({type:a.z.literal("node"),nodeId:Cn,name:Ki.shape.name,enabled:Ki.shape.enabled,order:Ki.shape.order,referenceCount:a.z.number().int().min(0)}).strict()]),Qi=a.z.object({id:Cn,model:Wi,locations:a.z.array(Xi).min(1),referenceCount:a.z.number().int().min(0).default(0)}).strict(),Zi=a.z.object({nodeId:Cn,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(Qi),nodeDiagnostics:a.z.array(Zi).default([]),updatedAt:On}).strict();const es=Ki.omit({id:!0,createdAt:!0,updatedAt:!0}).strict(),ts=es.partial().strict(),ns=Ki,is=a.z.object({modelSelection:Bn,modelEntityIds:a.z.array(Cn).max(64).transform(e=>[...new Set(e)]).optional(),codexModelHash:Cn.optional(),claudeModelHash:Cn.optional(),opencodeModelHash:Cn.optional()}).strict().transform(e=>({...e,modelEntityIds:e.modelEntityIds||e.modelSelection.modelEntityIds||[...new Set([e.codexModelHash,e.claudeModelHash,e.opencodeModelHash].filter(e=>Boolean(e)))]}));function ss(e){const t={app:Hi.parse(e.app),endpoint:Ki.shape.endpoint.parse(e.endpoint),key:Ki.shape.key.parse(e.key),model:Ki.shape.model.parse(e.model)};return`mdl_${d.createHash("sha256").update(JSON.stringify(t)).digest("hex")}`}const rs=a.z.enum(["market","custom"]),os=a.z.enum(["active","deprecated","yanked"]),as=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:Vn.optional()}).strict()]),cs=a.z.array(a.z.string().trim().min(1).max(80)).default([]),ds=a.z.array(a.z.string().trim().min(1).max(120)).default([]),ls=a.z.record(a.z.string().trim().min(2).max(35),a.z.string().trim().min(1).max(4096)),us=a.z.object({os:a.z.string().trim().min(1).max(40),architecture:a.z.string().trim().min(1).max(40),digest:Vn.optional(),downloadSizeBytes:a.z.number().int().positive().optional(),unpackedSizeBytes:a.z.number().int().positive().optional()}).strict(),ps=a.z.object({name:a.z.string().trim().min(1).max(128).regex(Mn),version:a.z.string().trim().min(1).max(160).optional(),reference:Hn,manifestDigest:Vn.optional(),publishedAt:On.optional(),platforms:a.z.array(us).default([]),status:os.default("active")}).strict(),ms=a.z.object({id:Cn,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:ls.optional(),cover:as.optional(),repository:a.z.string().trim().min(1).max(512),defaultTag:a.z.string().trim().min(1).max(128).regex(Mn),tags:a.z.array(ps).min(1),capabilities:cs,optionalApps:ds,defaultEnv:Rn,labels:xn,status:os.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:vn,catalogId:Cn,revision:a.z.string().trim().min(1).max(240),source:a.z.enum(["embedded","remote","cache"]),generatedAt:On,expiresAt:On.optional(),items:a.z.array(ms)}).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:On,error:a.z.string().trim().max(4096).optional()}).strict(),a.z.object({id:Cn,origin:a.z.literal("custom"),name:a.z.string().trim().min(1).max(160),description:a.z.string().trim().max(4096).optional(),localizedDescriptions:ls.optional(),cover:as.optional(),reference:Hn,repository:a.z.string().trim().min(1).max(512),tag:a.z.string().trim().min(1).max(128).regex(Mn).optional(),pullPolicy:a.z.literal("if-not-present").default("if-not-present"),capabilities:cs,optionalApps:ds,defaultEnv:Rn,labels:xn,createdAt:On,updatedAt:On}).strict();const hs=a.z.object({name:a.z.string().trim().min(1).max(128).regex(Mn),version:a.z.string().trim().min(1).max(160).optional(),reference:Hn,manifestDigest:Vn.optional(),status:os}).strict(),gs=a.z.object({id:Cn,origin:rs,name:a.z.string().trim().min(1).max(160),description:a.z.string().trim().max(4096).optional(),localizedDescriptions:ls.optional(),cover:as,repository:a.z.string().trim().min(1).max(512),tag:a.z.string().trim().min(1).max(128).regex(Mn).optional(),availableTags:a.z.array(hs),reference:Hn,digest:Vn.optional(),downloadSizeBytes:a.z.number().int().positive().optional(),unpackedSizeBytes:a.z.number().int().positive().optional(),capabilities:cs,optionalApps:ds,defaultEnv:Rn,labels:xn,readOnly:a.z.boolean(),lifecycleStatus:os.optional(),market:a.z.object({catalogId:Cn,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(),fs=a.z.object({id:Cn,origin:rs,name:a.z.string().trim().min(1).max(160),description:a.z.string().trim().max(4096).optional(),localizedDescriptions:ls.optional(),cover:as.optional(),repository:a.z.string().trim().min(1).max(512),tag:a.z.string().trim().min(1).max(128).regex(Mn).optional(),requestedReference:Hn,resolvedDigest:Vn.optional(),resolvedReference:Hn.optional(),downloadSizeBytes:a.z.number().int().positive().optional(),pullPolicy:a.z.literal("if-not-present").default("if-not-present"),capabilities:cs,optionalApps:ds,defaultEnv:Rn,labels:xn,market:a.z.object({catalogId:Cn,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:On,updatedAt:On}).strict(),ys=a.z.object({phase:a.z.enum(["checking-image","pulling-image","resolving-image","ready","failed"]),requestedReference:Hn,generation:a.z.number().int().nonnegative().default(0),error:a.z.string().trim().max(4096).optional(),startedAt:On,updatedAt:On}).strict(),Is="image.pull.terminal.output",As="image.pull.terminal.finished",bs=a.z.object({instanceId:Cn,generation:a.z.number().int().nonnegative(),requestedReference:Hn,sequence:a.z.number().int().nonnegative(),observedAt:On}).strict(),vs=bs.extend({data:a.z.string().min(1).max(65536),replay:a.z.boolean().optional()}).strict(),ws=bs.extend({outcome:a.z.enum(["succeeded","failed"])}).strict();bs.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 Ss=a.z.discriminatedUnion("kind",[a.z.object({kind:a.z.literal("direct")}).strict(),a.z.object({kind:a.z.literal("control-plane-proxy"),proxyId:Cn,proxyBindingId:Cn,targetNodeId:Cn}).strict()]),Es=a.z.object({pingRttMs:a.z.number().nonnegative().optional(),pingRttP95Ms:a.z.number().nonnegative().optional(),consecutiveReconnects:a.z.number().int().nonnegative(),nextRetryAt:On.optional()}).strict();a.z.object({nodeId:Cn,inviteId:Cn.optional()}).strict(),a.z.discriminatedUnion("status",[a.z.object({id:Cn,status:a.z.literal("pending")}).strict(),a.z.object({id:Cn,status:a.z.literal("completed"),nodeId:Cn}).strict()]);const zs=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:On.optional(),target:dn.optional(),lastError:sn.optional(),updatedAt:On}).strict(),Ns=a.z.object({id:Cn,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:Ss.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:Cn.optional(),secret:a.z.string().trim().max(4096).optional(),pairedAt:On.optional(),pairing:a.z.object({status:a.z.enum(["pending","paired","expired"]).default("pending"),joinToken:a.z.string().trim().max(4096).optional(),expiresAt:On.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:zs.optional(),appInventory:ai.optional(),labels:xn,lastSeenAt:On.optional(),createdAt:On,updatedAt:On}).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."})});a.z.object({nodeId:Cn,status:a.z.enum(["unknown","online","offline","degraded"]),health:a.z.enum(["unknown","ok","degraded","failed"]),lastSeenAt:On.nullable(),connectionPhase:a.z.enum(["connecting","handshaking","healthy","reconnecting","suspect","offline"]).nullable(),connectionDiagnostics:Es.nullable(),proxyState:zs.nullable()}).strict();const Ts=a.z.object({id:Cn,nodeId:Cn,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:xn,createdAt:On,updatedAt:On}).strict(),_s=a.z.object({instanceId:Cn,runtimeKind:a.z.literal("docker"),state:a.z.enum(["pending","available","stopped","unavailable"]),sampledAt:On,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(),ks=a.z.object({registry:a.z.boolean().default(!1),runtimeBroker:a.z.boolean().default(!1),workspaceProvisioning:a.z.object({docker:a.z.boolean().default(!1),kubernetes:a.z.boolean().default(!1),local:a.z.boolean().default(!1)}).strip().default({docker:!1,kubernetes:!1,local:!1})}).strip(),Cs=a.z.object({multiEntityAssignment:a.z.boolean().default(!1),privateModelCatalog:a.z.boolean().default(!1)}).strip(),Os=a.z.object({enabled:a.z.boolean().default(!1),agentTools:a.z.boolean().default(!1),maxFileBytes:a.z.number().int().positive().default(33554432),maxBatchPaths:a.z.number().int().min(1).max(100).default(20)}).strip(),xs=a.z.object({modelEndpointProbe:a.z.boolean().optional(),aiSessionHistoryLimit:a.z.boolean().optional(),aiSessionAttachmentRetention:a.z.boolean().optional(),aiSessionFileAttachmentLimit:a.z.boolean().optional(),folderPlaces:a.z.boolean().optional(),localFolderNameUpdate:a.z.boolean().optional(),managedGitCredentials:ks.optional(),managedModels:Cs.optional(),stories:Os.optional()}).strip(),Rs=a.z.object({status:a.z.enum(["healthy","congested","recovering"]),activeOutputs:a.z.number().int().nonnegative(),bufferedBytes:a.z.number().int().nonnegative(),peakBufferedBytes:a.z.number().int().nonnegative(),coalescedEvents:a.z.number().int().nonnegative(),oversizedEvents:a.z.number().int().nonnegative().optional(),peakEventBytes:a.z.number().int().nonnegative().optional(),congestedSince:On.optional(),lastCongestedAt:On.optional()}).strip();a.z.object({ok:a.z.boolean().optional(),role:a.z.string().optional(),nodeId:Cn.optional(),platform:Wn.optional(),arch:Jn.optional(),protocolVersion:vn.optional(),capabilities:xs.optional(),build:Si.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(),eventTransport:Rs.optional(),serverTime:On.optional()}).strip();const Ps=a.z.object({bindScope:a.z.enum(["loopback","all-ipv4"]),port:a.z.number().int().min(1).max(65535)}).strict(),Ds=Ps.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(),Ms=Ps;a.z.object({nodeId:Cn,joinToken:a.z.string().trim().min(1),expiresAt:On}).passthrough(),a.z.object({nodeId:Cn,keyId:Cn,secret:a.z.string().regex(/^[A-Za-z0-9_-]{32,128}$/),pairedAt:On}).strict();const js=a.z.object({id:Cn,keyId:Cn,name:a.z.string().trim().min(1).max(160).optional(),pairedAt:On,updatedAt:On,current:a.z.boolean()}).passthrough();a.z.object({keyId:Cn,revoked:a.z.literal(!0),revokedAt:On}).strict(),a.z.object({id:Cn,pairingKeyId:Cn,url:a.z.string().trim().min(1).max(2048),name:a.z.string().trim().min(1).max(160).optional(),enabled:a.z.boolean(),createdAt:On,updatedAt:On,status:a.z.enum(["disabled","connecting","connected","reconnecting","failed"]),pingRttMs:a.z.number().nonnegative().optional(),pingRttP95Ms:a.z.number().nonnegative().optional(),consecutiveReconnects:a.z.number().int().nonnegative().optional(),nextRetryAt:On.optional(),lastConnectedAt:On.optional(),lastDisconnectedAt:On.optional(),error:a.z.string().optional()}).passthrough(),a.z.object({pairing:js,connection:a.z.object({id:Cn,pairingKeyId:Cn,url:a.z.string().trim().min(1).max(2048),name:a.z.string().trim().min(1).max(160).optional(),enabled:a.z.boolean(),createdAt:On,updatedAt:On}).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 Ls=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:gs,status:a.z.enum(["available","pull-required","unknown"]),localImage:Ls.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 Fs=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(Fs)}).passthrough());a.z.object({kind:a.z.enum(["home","root"]),name:a.z.string().trim().min(1),path:a.z.string().trim().min(1).max(4096)}).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 $s=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(),Us=a.z.object({...$s.shape}).strict(),Hs=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"}),Vs=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(),Bs=a.z.object({id:Cn,name:a.z.string().trim().min(1).max(160),projectId:Cn.optional(),source:$i,sourceSnapshot:a.z.record(a.z.string(),a.z.unknown()).default({}),modelSelection:Bn,nodeId:Cn,runtimeId:Cn,imageSelection:qn.optional(),environmentSource:Kn.optional(),environmentTemplateOrigin:Xn.optional(),imageSnapshot:fs.optional(),imageProvisioning:ys.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:vn.optional(),instanceVersion:a.z.string().trim().max(80).optional(),build:Si.optional(),runtimeVersion:Ti.optional(),ready:a.z.boolean().default(!1),capabilities:Tn.default(Sn),appInventory:ai.optional(),config:a.z.object({autoImportAgentConfigs:a.z.boolean().default(!0),codexConfigEnabled:a.z.boolean().default(!0),codexHomeMode:a.z.enum(["default","taskhandoff"]).default("taskhandoff"),defaultCodexPermissionMode:qe.default("ask"),aiSessionHistoryLimit:a.z.number().int().min(1).max(wt).default(50),aiSessionAttachmentRetentionDays:a.z.number().int().min(0).max(365).default(30),aiSessionMaxFileAttachmentBytes:a.z.number().int().positive().max(de).default(ce)}).strict().default({autoImportAgentConfigs:!0,codexConfigEnabled:!0,codexHomeMode:"taskhandoff",defaultCodexPermissionMode:"ask",aiSessionHistoryLimit:50,aiSessionAttachmentRetentionDays:30,aiSessionMaxFileAttachmentBytes:ce}),workspace:Vs.default({status:"unknown"}),target:$s.default({strategy:"direct-port",status:"unknown"}),access:Hs,apps:a.z.object({runningCount:a.z.number().int().min(0).default(0),problemCount:a.z.number().int().min(0).default(0),updatedAt:On.optional(),revision:a.z.number().int().min(0).optional()}).strict().default({runningCount:0,problemCount:0}),aiSessions:Nt.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:Ht,deployments:a.z.array(Bt).default([]),runtime:a.z.array(qt).default([])}).strict()).default([]),recentRuns:a.z.array(Kt).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:On.optional(),createdAt:On,updatedAt:On}).strict(),qs=a.z.union([Bs.transform(e=>({instance:e,gitWorkspaceProvisioningOperationId:void 0})),a.z.object({instance:Bs,gitWorkspaceProvisioningOperationId:Cn.optional()}).strict()]);a.z.preprocess(e=>{if(!e||"object"!=typeof e||Array.isArray(e))return e;const t=e;return t.instance&&"object"==typeof t.instance&&!Array.isArray(t.instance)?{instance:Js(t.instance),..."string"==typeof t.gitWorkspaceProvisioningOperationId?{gitWorkspaceProvisioningOperationId:t.gitWorkspaceProvisioningOperationId}:{}}:Js(t)},qs);const Ks="instance.lifecycle.snapshot",Gs=a.z.object({instanceId:Bs.shape.id,revision:a.z.number().int().min(0),updatedAt:On,status:Bs.shape.status.unwrap(),health:Bs.shape.health.unwrap(),connectionStatus:Bs.shape.connectionStatus.unwrap(),accessStatus:a.z.enum(["reachable","endpoint-unreachable"]),imageProvisioning:ys.optional(),workspace:Vs,runtime:Bs.shape.runtime.unwrap(),runtimeVersion:Ti.optional(),ready:a.z.boolean(),lastHeartbeatAt:On.optional()}).strict();function Ws(e,t){return Bs.safeParse(Js(e,t))}function Js(e,t){if(!e||"object"!=typeof e||Array.isArray(e))return e;const n=e,i=new Set(Object.keys(Bs.shape)),s={};for(const[e,r]of Object.entries(n))i.has(e)?s[e]=r: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),s.capabilities=_n(e)}else s.capabilities=_n(void 0);s.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 s={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=Qs(e,["id","name","kind","source","availability","diagnosticCode"]);return!i||"object"!=typeof i||Array.isArray(i)?i:{...i,capabilities:Qs(e.capabilities,["automation","supportsCwdSelection"])}}):i.items,issues:Array.isArray(i.issues)?i.issues.map(e=>Qs(e,["code","message"])):i.issues},r=ai.safeParse(s);return r.success?r.data:void 0}(n.appInventory,t,"string"==typeof n.id?n.id:void 0),s.source=function(e,t,n){if(!e||"object"!=typeof e||Array.isArray(e))return e;const i=e,s=i.type,r=$i.options.find(e=>e.shape.type.value===s);if(!r)return e;const o="local-folder"===s?["type","localFolderId","path","ownerNodeId"]:"git-template"===s?["type","url","templateId","ref","auth","clone"]:["type","repositoryId","url","provider","ref","auth","clone"],a=Qs(i,o);if("local-folder"!==s){const e=function(e,t,n){const i=e&&"object"==typeof e&&!Array.isArray(e)?e:void 0,s=Mi.safeParse(Qs(i,["type","name","commit"]));if(s.success)return s.data;const r="string"==typeof i?.commit?i.commit.trim():"",o="string"==typeof i?.name?i.name.trim():"",a=r?Mi.safeParse({type:"commit",commit:r}):o?Mi.safeParse({type:"tag"===i?.type?"tag":"branch",name:o}):Mi.safeParse({type:"branch",name:"main"});return a.success?(t?.({instanceId:n,field:"source.ref"}),a.data):void 0}(i.ref,t,n),s=Ys(ji,Qs(i.auth,["type","secretId"]),"source.auth",t,n),r=Ys(Li,Qs(i.clone,["depth","submodules","lfs","subdirectory"]),"source.clone",t,n);e?a.ref=e:delete a.ref,s?a.auth=s:delete a.auth,r?a.clone=r:delete a.clone}const c=Ys(r,a,"source",t,n);return c?(Object.keys(i).some(e=>!o.includes(e))&&t?.({instanceId:n,field:"source"}),c):a}(n.source,t,"string"==typeof n.id?n.id:void 0),s.sourceSnapshot=n.sourceSnapshot&&"object"==typeof n.sourceSnapshot&&!Array.isArray(n.sourceSnapshot)?n.sourceSnapshot:{},s.build=Ys(Si,n.build,"build",t,"string"==typeof n.id?n.id:void 0),s.aiSessions=function(e,t,n){if(!e||"object"!=typeof e||Array.isArray(e))return;const i=e,s=Array.isArray(i.sessions)?i.sessions.flatMap((e,i)=>{const s=Ys(zt,e,`aiSessions.sessions.${i}`,t,n);return s?[s]:[]}):[],r={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:s,updatedAt:On.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"}),Nt.parse(r)}(n.aiSessions,t,"string"==typeof n.id?n.id:void 0),s.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 s=(e,i,s)=>Array.isArray(e)?e.flatMap((e,r)=>{const o=Ys(i,e,`${s}.${r}`,t,n);return o?[o]:[]}):[],r=Array.isArray(i.configs)?i.configs.flatMap((e,i)=>{if(!e||"object"!=typeof e||Array.isArray(e))return[];const r=e;Object.keys(r).some(e=>!["configHash","config","deployments","runtime"].includes(e))&&t?.({instanceId:n,field:`triggers.configs.${i}`});const o=function(e,t,n,i){if(!e||"object"!=typeof e||Array.isArray(e))return;const s=e,r=Qs(s,["configHash","name","description","createdAt","updatedAt"]);if(s.source&&"object"==typeof s.source&&!Array.isArray(s.source)){const e=s.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"];r.source=Qs(e,t)}return r.action=Qs(s.action,["promptTemplate"]),r.policy=Qs(s.policy,["cooldownMs","maxConcurrentRuns","whenBusy"]),Ys(Ht,r,t,n,i)}(r.config,`triggers.configs.${i}.config`,t,n);return"string"==typeof r.configHash&&o?[{configHash:r.configHash,config:o,deployments:s(r.deployments,Bt,`triggers.configs.${i}.deployments`),runtime:s(r.runtime,qt,`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:r,recentRuns:s(i.recentRuns,Kt,"triggers.recentRuns")}}(n.triggers,t,"string"==typeof n.id?n.id:void 0),s.apps=Ys(Bs.shape.apps.unwrap(),Qs(n.apps,["runningCount","problemCount","updatedAt","revision"]),"apps",t,"string"==typeof n.id?n.id:void 0)||{runningCount:0,problemCount:0},s.config=Ys(Bs.shape.config.unwrap(),Qs(n.config,["autoImportAgentConfigs","codexConfigEnabled","codexHomeMode","defaultCodexPermissionMode","aiSessionHistoryLimit","aiSessionAttachmentRetentionDays","aiSessionMaxFileAttachmentBytes"]),"config",t,"string"==typeof n.id?n.id:void 0)||{autoImportAgentConfigs:!0,codexConfigEnabled:!0,codexHomeMode:"taskhandoff",defaultCodexPermissionMode:"ask",aiSessionHistoryLimit:50,aiSessionAttachmentRetentionDays:30,aiSessionMaxFileAttachmentBytes:ce},s.modelSelection=Ys(Bn.unwrap(),Qs(n.modelSelection,["modelEntityIds","codexModelHash","claudeModelHash","opencodeModelHash"]),"modelSelection",t,"string"==typeof n.id?n.id:void 0)||{},s.imageSnapshot=function(e,t,n,i){if(!e||"object"!=typeof e||Array.isArray(e))return e;const s=e,r=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 s,r="string"==typeof t.reference?t.reference:i;if(r)try{r=$n(r)}catch{if(!r.includes("@")&&r.lastIndexOf(":")<=r.lastIndexOf("/"))try{r=$n(`${r}:latest`)}catch{}}try{s=r?Un(r):void 0}catch{}return{id:t.id,origin:"custom",name:t.name,description:t.description,localizedDescriptions:t.localizedDescriptions,cover:Qs(t.cover,["kind","key","url","mediaType","digest"]),reference:s?.reference??r,repository:s?.repository??t.repository,tag:s?.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}}(s),{reference:o,...a}=r,c=s.requestedReference??o;let d;try{d="string"==typeof c?Un(c):void 0}catch{}const l={img_default:"market_taskhandoff_browser",img_codex:"market_taskhandoff_codex",img_ai:"market_taskhandoff_ai"},u="string"==typeof s.id?s.id:"string"==typeof t?t:void 0,p="market"===s.origin||u&&l[u]?"market":"custom";return void 0===s.image&&void 0===s.reference||n?.({instanceId:i,field:"imageSnapshot.reference"}),{...a,id:u&&l[u]?l[u]:u,origin:p,repository:d?.repository??s.repository,tag:d?.tag??s.tag,requestedReference:d?.reference??c,resolvedDigest:s.resolvedDigest,resolvedReference:s.resolvedReference,downloadSizeBytes:s.downloadSizeBytes,market:"market"===p?Qs(s.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 r="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,o=Qs(n.imageSelection,["imageId","tag"]);s.imageSelection=o||(r?{imageId:r,tag:s.imageSnapshot?.tag}:void 0),s.imageProvisioning=Ys(ys,Qs(n.imageProvisioning,["phase","requestedReference","generation","error","startedAt","updatedAt"]),"imageProvisioning",t,"string"==typeof n.id?n.id:void 0),s.runtimeVersion=function(e,t,n){if(!e||"object"!=typeof e||Array.isArray(e))return;const i=e,s=e=>{if("string"!=typeof e)return;const t=e.trim();return t&&t.length<=80?t:void 0},r=s(i.desiredVersion);if(!r)return void t?.({instanceId:n,field:"runtimeVersion.desiredVersion"});const o=new Set(Ti.shape.phase.options),a="string"==typeof i.phase?i.phase:"pending",c=o.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,r="string"==typeof e.message?e.message.trim().slice(0,4096):"";if(r){const i=new Set(Ni.shape.code.options),o="string"==typeof e.code&&i.has(e.code)?e.code:"INSTANCE_RUNTIME_INSTALL_FAILED";o!==e.code&&t?.({instanceId:n,field:"runtimeVersion.error.code"});const a=s(e.expectedVersion),c=s(e.actualVersion);d={code:o,message:r,...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:r,...s(i.actualVersion)?{actualVersion:s(i.actualVersion)}:{},retryable:!1});const l=s(i.actualVersion),u=On.safeParse(i.lastAttemptAt),p=On.safeParse(i.matchedAt);return void 0===i.lastAttemptAt||u.success||t?.({instanceId:n,field:"runtimeVersion.lastAttemptAt"}),void 0===i.matchedAt||p.success||t?.({instanceId:n,field:"runtimeVersion.matchedAt"}),{desiredVersion:r,...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}:{},...p.success?{matchedAt:p.data}:{},...d?{error:d}:{}}}(n.runtimeVersion,t,"string"==typeof n.id?n.id:void 0),s.workspace=Ys(Vs,n.workspace,"workspace",t,"string"==typeof n.id?n.id:void 0)||{status:"unknown"},s.environmentSource=Ys(Kn,n.environmentSource,"environmentSource",t,"string"==typeof n.id?n.id:void 0),s.environmentTemplateOrigin=Ys(Xn,n.environmentTemplateOrigin,"environmentTemplateOrigin",t,"string"==typeof n.id?n.id:void 0),s.runtime=Ys(Bs.shape.runtime.unwrap(),n.runtime,"runtime",t,"string"==typeof n.id?n.id:void 0)||{labels:{}},s.target=Ys($s,Qs(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"},s.access=Ys(Hs,Qs(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(Bs.shape))Object.prototype.hasOwnProperty.call(s,e)&&!i.safeParse(s[e]).success&&i.safeParse(void 0).success&&(delete s[e],t?.({instanceId:"string"==typeof n.id?n.id:void 0,field:e}));return s}function Ys(e,t,n,i,s){if(!t||"object"!=typeof t||Array.isArray(t))return;let r=structuredClone(t),o=!1;for(let t=0;t<20;t+=1){const t=e.safeParse(r);if(t.success)return o&&i?.({instanceId:s,field:n}),t.data;let a=!1;for(const e of t.error.issues){if("unrecognized_keys"!==e.code)continue;const t=Xs(r,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,o=!0)}if(!a){const o=structuredClone(r);let a=!1;for(const e of t.error.issues){if(!e.path.length||"string"!=typeof e.path.at(-1))continue;const t=Xs(o,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(o);if(t.success)return i?.({instanceId:s,field:n}),t.data}break}}i?.({instanceId:s,field:n})}function Xs(e,t){let n=e;for(const e of t){if(!n||"object"!=typeof n)return;n=n[e]}return n}function Qs(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 Zs=a.z.object({instanceId:Cn.optional(),projectId:Cn.optional(),source:$i.optional(),nodeId:Cn.optional(),runtimeId:Cn.optional(),imageSelection:qn.optional(),instanceVersion:a.z.string().trim().max(80).optional(),protocolVersion:vn,build:Si.optional(),controlMode:a.z.enum(["standalone","controlled"]).default("controlled"),capabilities:Tn.default(Sn),appInventory:ai.optional(),target:Us.optional(),workspace:Vs.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)=>{bn.has(e.protocolVersion)&&!e.appInventory&&t.addIssue({code:"custom",path:["appInventory"],message:"Current protocol register payload requires appInventory."})}),er=a.z.object({status:Bs.shape.status.optional(),health:Bs.shape.health.optional(),protocolVersion:vn,build:Si.optional(),capabilities:Bs.shape.capabilities.optional(),appInventory:ai.optional(),apps:Bs.shape.apps.optional(),aiSessions:Bs.shape.aiSessions.optional(),triggers:Bs.shape.triggers.optional(),workspace:Vs.optional(),target:Us.optional(),processIncarnationId:a.z.string().trim().min(1).max(120).optional()}).strict().superRefine((e,t)=>{bn.has(e.protocolVersion)&&!e.appInventory&&t.addIssue({code:"custom",path:["appInventory"],message:"Current protocol heartbeat payload requires appInventory."})}),tr=a.z.enum(["web","telegram","wechat","dingding","lark"]);function nr(e,t){let n=or(t);for(let t=0;t<100;t+=1){const t=e.safeParse(n);if(t.success)return t;const i=ir(t.error.issues);let s=!1;for(const e of i){const t=rr(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],s=!0)}if(!s)return t}return e.safeParse(n)}function ir(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 s=e.reduce((e,t)=>sr(t)<sr(e)?t:e);n.push(...ir(s,[...t,...i.path]))}return n}function sr(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(sr)):1)},0)}function rr(e,t){let n=e;for(const e of t){if(!n||"object"!=typeof n)return;n=n[e]}return n}function or(e){return Array.isArray(e)?e.map(or):e&&"object"==typeof e?Object.getPrototypeOf(e)!==Object.prototype&&null!==Object.getPrototypeOf(e)?e:Object.fromEntries(Object.entries(e).map(([e,t])=>[e,or(t)])):e}function ar(e,t,n={}){return new Promise((i,s)=>{if(n.signal?.aborted)return void s(Object.assign(new Error(`${e} was aborted.`),{code:"RUNTIME_COMMAND_ABORTED"}));const r=l.spawn(e,t,{stdio:["ignore","pipe","pipe"]}),o=[],a=[];let c=!1;const d=n.timeoutMs?setTimeout(()=>{c=!0,r.kill("SIGKILL")},n.timeoutMs):void 0;let u=!1;const p=()=>{u=!0,r.kill("SIGKILL")},m=()=>{d&&clearTimeout(d),n.signal?.removeEventListener("abort",p)};n.signal?.addEventListener("abort",p,{once:!0}),d?.unref?.(),r.stdout.on("data",e=>o.push(Buffer.from(e))),r.stderr.on("data",e=>a.push(Buffer.from(e))),r.on("error",e=>{m(),s(e)}),r.on("close",t=>{m();const r={stdout:Buffer.concat(o).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:r}),void s(t)}if(u)return void s(Object.assign(new Error(`${e} was aborted.`),{code:"RUNTIME_COMMAND_ABORTED",details:r}));if(0===t)return void i(r);const d=new Error(r.stderr||`${e} exited with code ${t}`);Object.assign(d,{statusCode:502,code:"RUNTIME_EXECUTOR_FAILED",details:r}),s(d)})})}a.z.object({id:Cn,channel:tr,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:On,updatedAt:On}).strict(),a.z.object({id:Cn,channel:tr,bridgeId:Cn.optional(),chatSessionId:a.z.string().trim().min(1).max(240),userId:a.z.string().trim().max(240).optional(),activeProjectId:Cn.optional(),activeInstanceId:Cn.optional(),activeAiSessionId:a.z.string().trim().min(1).max(120).optional(),lastUsedAt:On,createdAt:On,updatedAt:On}).strict(),a.z.object({source:a.z.object({type:a.z.literal("chat-gateway").default("chat-gateway"),channel:tr,bridgeId:Cn.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(Ue).max(6).default([])}).strict().superRefine((e,t)=>{e.attachments.reduce((e,t)=>e+("inline"===t.source.type?t.size:0),0)>le&&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:Cn,aiSessionId:a.z.string().trim().min(1).max(120)}).strict().optional()}).strict(),a.z.object({id:Cn,instanceId:Cn,projectId:Cn.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:On}).strict();const cr=(e,t,n={})=>new Promise((i,s)=>{if(n.signal?.aborted)return void s(Object.assign(new Error(`${e} was aborted.`),{code:"RUNTIME_COMMAND_ABORTED"}));const r=[];let o,a=!1,c=!1;try{o=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 s(e)}const d=n.timeoutMs?setTimeout(()=>{a=!0,o.kill("SIGKILL")},n.timeoutMs):void 0,l=()=>{c=!0;try{o.kill("SIGKILL")}catch{}};n.signal?.addEventListener("abort",l,{once:!0}),d?.unref?.(),o.onData(e=>{r.push(e),n.onData?.(e)}),o.onExit(({exitCode:t})=>{d&&clearTimeout(d),n.signal?.removeEventListener("abort",l);const o={stdout:r.join(""),stderr:""};a?s(Object.assign(new Error(`${e} timed out after ${n.timeoutMs}ms`),{statusCode:504,code:"RUNTIME_COMMAND_TIMEOUT",details:o})):c?s(Object.assign(new Error(`${e} was aborted.`),{code:"RUNTIME_COMMAND_ABORTED",details:o})):0!==t?s(Object.assign(new Error(o.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:o})):i(o)})});class dr{inFlight=new Map;runCommand;runTerminalCommand;constructor(e=ar,t){this.runCommand=e,this.runTerminalCommand=t||function(e){return e===ar?cr:async(t,n,i={})=>{const s=await e(t,n,{timeoutMs:i.timeoutMs,signal:i.signal});return s.stdout&&i.onData?.(s.stdout),s.stderr&&i.onData?.(s.stderr),s}}(e)}ensure(e,t,n,i){const s=$n(e),r=this.inFlight.get(s);if(r)return t&&(r.phaseListeners.add(t),r.phase&&t(r.phase)),n&&(r.terminalListeners.add(n),r.terminalTail&&n({sequence:r.terminalSequence,data:r.terminalTail,replay:!0})),this.bindAbort(r,i),r.promise;const o=new Set,a=new Set;t&&o.add(t),n&&a.add(n);const c={promise:Promise.resolve(void 0),controller:new AbortController,abortDisposers:new Set,phaseListeners:o,terminalListeners:a,terminalSequence:0,terminalTail:""};return this.bindAbort(c,i),c.promise=this.ensureOnce(s,e=>{c.phase=e,o.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(s);for(const e of c.abortDisposers)e();c.abortDisposers.clear()}),this.inFlight.set(s,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 s=await this.inspect(e,i).catch(e=>{if(i.aborted)throw e}),r=!1;s||(t("pulling-image"),await this.runTerminalCommand("docker",["pull",e],{cols:120,rows:40,signal:i,onData:n}),r=!0,s=await this.inspect(e,i)),t("resolving-image");const o=(a=s,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=o?.split("@").at(-1)?.toLowerCase();return{requestedReference:e,...c?{resolvedDigest:c}:{},resolvedReference:o||e,pulled:r}}async inspect(e,t){const n=await this.runCommand("docker",["image","inspect",e,"--format","{{json .}}"],{signal:t});return JSON.parse(n.stdout.trim()||"{}")}}function lr(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 ur="/run/task-handoff/bootstrap",pr=`${ur}/entrypoint.sh`,mr="/bin/bash",hr=`${ur}/runtime-installer.mjs`,gr="/opt/task-handoff/instance-runtime";function fr(e,t){return{role:"runtime",name:`${Pr(e)}-runtime`,mountPath:gr,labels:{"task-handoff.owner":"task-handoff","task-handoff.instance-id":e,"task-handoff.node-id":t,"task-handoff.volume-role":"runtime"}}}function yr(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:s,mountPath:r})=>({role:n,name:`${i}-${s}`,mountPath:r,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 Ir=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 Ar(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,s=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),r=-1===n?"":e.slice(n+1);Ir.has(i)&&s.add(`Config.Env.${i}`),t.some(e=>e&&r.includes(e))&&s.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))(Ir.has(e)||"string"==typeof n&&t.some(e=>e&&n.includes(e)))&&s.add(`Config.Labels.${e}`);if(s.size)throw Object.assign(new Error(`Docker configuration contains instance-private values in ${[...s].sort().join(", ")}.`),{statusCode:409,code:"ENVIRONMENT_TEMPLATE_SECRET_IN_DOCKER_CONFIG",findings:[...s].sort()})}class br{runCommand;publishHost;images;launcherAssetsDir;portResolutionRetryDelaysMs;constructor(e=ar,t={}){this.runCommand=e,this.images=t.imageService||new dr(e),this.publishHost=t.publishHost||"127.0.0.1",this.launcherAssetsDir=t.launcherAssetsDir||Nr(),this.portResolutionRetryDelaysMs=t.portResolutionRetryDelaysMs?.length?t.portResolutionRetryDelaysMs:[0,100,250,500,1e3]}async start(e){jr(e);const t=e.instance.runtime.containerName||Pr(e.instance.id),i=await this.inspectContainerForStart(t);if(i){xr(t,i.id,e.instance.runtime.containerId,"before start","RUNTIME_EXECUTOR_FAILED");const s=i.labels["task-handoff.instance-id"];if(s!==e.instance.id)throw _r("RUNTIME_EXECUTOR_FAILED",`Docker container ${t} belongs to ${s||"an unknown instance"}, not ${e.instance.id}.`);const r=i.mounts.find(e=>"bind"===e.type&&e.destination===ur);if("1"!==i.labels["task-handoff.bootstrap-abi"]||i.entrypoint[0]!==mr||i.command[0]!==pr||!r?.source||n.resolve(r.source)!==n.resolve(this.launcherAssetsDir)){const n=new Set(yr(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 _r("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 s;await this.createPersistentVolumes(e),"local-folder"!==e.project.source.type&&await this.provisionGitWorkspace(e);try{s=await this.runCommand("docker",Mr(e,t,{publishHost:this.publishHost,launcherAssetsDir:this.launcherAssetsDir}))}catch(e){throw _r("RUNTIME_EXECUTOR_FAILED",`Could not create Docker container ${t}.`,e)}return e.completeGitWorkspaceProvisioning?.(),this.bootstrapResult(e,t,s.stdout||void 0)}async provisionGitWorkspace(e){const i=e.gitWorkspaceProvisioning;if(!i)throw _r("GIT_WORKSPACE_PROVISIONING_MISSING",`Git workspace provisioning input is missing for ${e.instance.id}.`);const s=`${Pr(e.instance.id)}-git-provision`,r=t.mkdtempSync(n.join(c.tmpdir(),"task-handoff-git-auth-"));t.chmodSync(r,448);try{await this.runCommand("docker",["rm","-f",s],{timeoutMs:3e4}).catch(()=>({stdout:"",stderr:""})),this.materializeGitProvisioningAuth(r,i);const t=function(e,t,i,s={}){const r=e.gitWorkspaceProvisioning;if(!r||"local-folder"===e.project.source.type)throw Object.assign(new Error("Git provisioning requires a Git source and operation input."),{code:"GIT_WORKSPACE_PROVISIONING_INVALID",statusCode:400});const o=n.resolve(s.launcherAssetsDir||Nr()),a=yr(e).find(e=>"workspace"===e.role);if(!a)throw Object.assign(new Error("Git workspace volume was not found."),{code:"GIT_WORKSPACE_VOLUME_MISSING",statusCode:409});const c=["run","--rm","--name",t,"--label","task-handoff.role=git-provisioning","--label",`task-handoff.instance-id=${e.instance.id}`,"--user","0:0","--network","bridge","--security-opt","no-new-privileges","--cap-drop","ALL","--cap-add","CHOWN","--cap-add","SETUID","--cap-add","SETGID","--cap-add","DAC_OVERRIDE","--mount",`type=volume,src=${a.name},dst=/workspace`,"--mount",`type=bind,src=${o},dst=${ur},readonly`,"--tmpfs","/run/task-handoff/git-runtime:rw,nosuid,nodev,exec,mode=0700"];r.credentials.length&&c.push("--mount",`type=bind,src=${n.resolve(i)},dst=/run/task-handoff/git-auth,readonly`);const d=(e,t)=>c.push("-e",`${e}=${t}`);return d("TASK_HANDOFF_GIT_URL",r.remoteUrl),d("TASK_HANDOFF_INSTANCE_ID",e.instance.id),"commit"===r.ref.type?d("TASK_HANDOFF_GIT_COMMIT",r.ref.commit):d("TASK_HANDOFF_GIT_REF",r.ref.name),r.clone.depth&&d("TASK_HANDOFF_GIT_DEPTH",String(r.clone.depth)),d("TASK_HANDOFF_GIT_SUBMODULES",r.clone.submodules?"true":"false"),d("TASK_HANDOFF_GIT_LFS",r.clone.lfs?"true":"false"),r.clone.subdirectory&&d("TASK_HANDOFF_WORKSPACE_SUBDIRECTORY",r.clone.subdirectory),c.push("--entrypoint","/bin/bash",e.instance.environmentTemplateOrigin?.imageId||e.image.resolvedReference||e.image.requestedReference,`${ur}/git-provision.sh`),c}(e,s,r,{launcherAssetsDir:this.launcherAssetsDir});await this.runCommand("docker",t,{timeoutMs:9e5,signal:e.signal})}catch(t){throw function(e,t){const n=t&&"object"==typeof t?t:void 0,i="string"==typeof n?.code?n.code:"";if("RUNTIME_COMMAND_TIMEOUT"===i)return _r("GIT_WORKSPACE_PROVISIONING_TIMEOUT",`Git workspace provisioning timed out for ${e}.`);if("RUNTIME_COMMAND_ABORTED"===i)return _r("GIT_WORKSPACE_PROVISIONING_CANCELLED",`Git workspace provisioning was cancelled for ${e}.`);const s=Cr(t)||"",r=s.match(/TASK_HANDOFF_GIT_PROVISIONING_ERROR=([A-Z_]+)/)?.[1];return _r(`GIT_WORKSPACE_PROVISIONING_${r&&kr.has(r)?r:"FAILED"}`,`Could not provision Git workspace for ${e}.`)}(e.instance.id,t)}finally{await this.runCommand("docker",["rm","-f",s],{timeoutMs:3e4}).catch(()=>({stdout:"",stderr:""})),t.rmSync(r,{recursive:!0,force:!0})}}materializeGitProvisioningAuth(e,i){const s=(e,i,s)=>{const r=n.join(e,i);t.writeFileSync(r,s,{encoding:"utf8",mode:384}),t.chmodSync(r,384)};i.credentials.forEach((i,r)=>{const o=n.join(e,`credential-${r}`);if(t.mkdirSync(o,{recursive:!0,mode:448}),t.chmodSync(o,448),s(o,"scope.json",JSON.stringify(i.payload.credential.scope)),"https-token"===i.payload.secret.kind)return s(o,"username",i.payload.secret.username),void s(o,"token",i.payload.secret.token);s(o,"private-key",i.payload.secret.privateKey),s(o,"known_hosts",i.payload.secret.pinnedKnownHosts),i.payload.secret.passphrase&&s(o,"passphrase",i.payload.secret.passphrase),s(o,"ssh-askpass.sh",`#!/usr/bin/env bash\ncat /run/task-handoff/git-runtime/credential-${r}/passphrase 2>/dev/null || true\n`)})}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:""})),_r("RUNTIME_EXECUTOR_FAILED",`Could not preserve Docker container ${t} before bootstrap migration.`,e)}try{const s=await this.runCommand("docker",Mr(e,t,{publishHost:this.publishHost,launcherAssetsDir:this.launcherAssetsDir,imageReference:n.image}));return this.bootstrapResult(e,t,s.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:""})),_r("RUNTIME_EXECUTOR_FAILED",`Could not recreate Docker container ${t} with the node-agent bootstrap.`,e)}}async inspectContainerConfigSecurity(e,t){Ar(await this.runCommand("docker",["inspect","--format","{{json .}}",e]).then(e=>JSON.parse(e.stdout||"{}")).catch(t=>{throw _r("ENVIRONMENT_TEMPLATE_CONTAINER_INSPECT_FAILED",`Could not inspect Docker container ${e}.`,t)}),t)}async inspectImageConfigSecurity(e,t){Ar(await this.runCommand("docker",["image","inspect","--format","{{json .}}",e]).then(e=>JSON.parse(e.stdout||"{}")).catch(e=>{throw _r("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 _r("ENVIRONMENT_TEMPLATE_CONTAINER_NOT_FOUND",`Docker container ${e} does not exist.`);xr(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 _r("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:"",s=Er(n.Os),r=zr(n.Architecture),o="number"==typeof n.Size?n.Size:Number.NaN;if(!/^sha256:[a-f0-9]{64}$/.test(i)||!s||!r||!Number.isSafeInteger(o)||o<0)throw new Error("Docker image inspection did not return a valid immutable identity.");return{imageId:i,platform:s,architecture:r,sizeBytes:o}}catch(e){throw _r("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,Tr(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 _r("ENVIRONMENT_TEMPLATE_UNTAG_FAILED","Could not remove the environment template tag.",e)}}async garbageCollectEnvironmentTemplateImage(e){try{try{await this.runCommand("docker",["image","rm",Tr(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 _r("ENVIRONMENT_TEMPLATE_GC_FAILED","Could not garbage collect the environment template image.",e)}}async createPersistentVolumes(e,t=new Set){const n=fr(e.instance.id,e.node?.id||"node_unset");for(const i of[...yr(e),n])await this.createVolume(i),await this.validateOwnedVolume(e.instance.id,i,t.has(i.name))}async createRuntimeVolume(e){await this.createVolume(fr(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 _r("INSTANCE_VOLUME_CREATE_FAILED",`Could not create managed volume ${e.name}.`,t)}}async validatePersistentVolumes(e,t){for(const n of yr(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=fr(e.instance.id,e.node?.id||"node_unset");await this.validateOwnedVolume(e.instance.id,i);const s=t.find(e=>"volume"===e.type&&e.destination===i.mountPath);if(!s||s.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 _r("INSTANCE_VOLUME_INSPECT_FAILED",`Could not inspect managed volume ${t.name}.`,e)}try{const s=JSON.parse(i.stdout||"{}"),r=s.Labels&&"object"==typeof s.Labels&&!Array.isArray(s.Labels)?s.Labels:{},o=s.Name===t.name&&"task-handoff"===r["task-handoff.owner"]&&r["task-handoff.instance-id"]===e&&r["task-handoff.volume-role"]===t.role,a=n&&s.Name===t.name&&0===Object.keys(r).length;if(!o&&!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),s=e.node?.id||"node_unset",r=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":s,"task-handoff.runtime-id":r,"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`}}async resolveInstanceWeb(e){const t=e.instance.runtime.containerName||Pr(e.instance.id),n=await this.inspectContainerId(t);if(!n)throw _r("INSTANCE_RUNTIME_ENDPOINT_UNAVAILABLE",`Docker container ${t} does not exist.`);return xr(t,n,e.instance.runtime.containerId,"while resolving its web endpoint","INSTANCE_RUNTIME_ENDPOINT_UNAVAILABLE"),(await this.publishedEndpoint(t)).web}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(!Or(e))throw _r("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){jr(e);const n=e.instance.runtime.containerName||Pr(e.instance.id),i=await this.inspectContainerId(n);if(!i)throw _r("INSTANCE_RUNTIME_RESTART_FAILED",`Docker container ${n} does not exist.`);xr(n,i,t,"before restart","INSTANCE_RUNTIME_RESTART_FAILED"),await this.runCommand("docker",["restart",n]);const s=await this.inspectContainerId(n);if(!s||s!==i)throw _r("INSTANCE_RUNTIME_RESTART_FAILED",`Docker container identity changed while restarting ${n}.`);return xr(n,s,t,"after restart","INSTANCE_RUNTIME_RESTART_FAILED"),this.runningResult(e,n,s)}async delete(e,t){const n=e.instance.runtime.containerName||Pr(e.instance.id),i=await this.inspectContainerForStart(n),s=new Set;if(i){xr(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 _r("RUNTIME_EXECUTOR_FAILED",`Docker container ${n} belongs to ${t||"an unknown instance"}, not ${e.instance.id}.`);for(const t of yr(e))i.mounts.some(e=>"volume"===e.type&&e.name===t.name&&e.destination===t.mountPath)&&s.add(t.name);try{await this.runCommand("docker",["rm","-f",i.id])}catch(e){if(!Or(e))throw _r("RUNTIME_EXECUTOR_FAILED",`Could not delete Docker container ${n}.`,e)}}const r=[];for(const n of yr(e))if(t.deleteVolumes)try{const t=await this.inspectVolumeForDelete(n.name);if(!t){r.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,o=s.has(n.name)&&t.name===n.name&&0===Object.keys(t.labels).length;if(!i&&!o)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]),r.push({role:n.role,name:n.name,mountPath:n.mountPath,status:"deleted"})}catch(e){r.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 r.push({role:n.role,name:n.name,mountPath:n.mountPath,status:"retained"});return await this.deleteRuntimeVolume(e),ti.parse({instanceId:e.instance.id,containerDeleted:!0,completed:r.every(e=>"failed"!==e.status),deletedVolumes:r.filter(e=>"deleted"===e.status||"missing"===e.status),retainedVolumes:r.filter(e=>"retained"===e.status),volumeResults:r})}async deleteRuntimeVolume(e){const t=fr(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 _r("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 _r("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 _r("INSTANCE_VOLUME_INSPECT_FAILED",`Could not inspect managed volume ${e}.`,t)}}async installRuntime(e){const t=await this.installRuntimeRelease(e);xr(e.containerName,t,e.expectedContainerId,"before runtime restart","INSTANCE_RUNTIME_RESTART_FAILED");try{await this.runCommand("docker",["restart",t])}catch(t){throw _r("INSTANCE_RUNTIME_RESTART_FAILED",`Could not restart Docker container ${e.containerName}.`,t)}const n=await this.inspectContainerId(e.containerName);if(!n||n!==t)throw _r("INSTANCE_RUNTIME_RESTART_FAILED",`Docker container identity changed while updating ${e.containerName}.`);return xr(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 _r("INSTANCE_RUNTIME_INSTALL_FAILED",`Docker container ${e.containerName} does not exist.`);xr(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",hr,"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 _r("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 s=await this.inspectContainerId(e.containerName);if(!s||s!==t)throw _r("INSTANCE_RUNTIME_INSTALL_FAILED",`Docker container identity changed while installing ${e.containerName}.`);return xr(e.containerName,s,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",hr,"verify-active"]).catch(()=>{});if(!n?.stdout)return{containerId:t};try{const e=nr(zi,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 _r("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 _r("INSTANCE_BASE_RUNTIME_INCOMPATIBLE","Could not inspect the Docker runtime target.",e)});t||=e.OSType,n||=e.Architecture}const i=Er(t),s=zr(n);if(!i||!s)throw _r("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Docker reported an unsupported runtime target ${String(t||"unknown")}/${String(n||"unknown")}.`);return{platform:i,arch:s,launcherAbi:1}}async installRuntimeReleaseWithRecovery(e){const t=e.containerName,i=await this.inspectContainerForStart(t);if(!i)throw _r("INSTANCE_RUNTIME_INSTALL_FAILED",`Docker container ${t} does not exist.`);if(xr(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 _r("INSTANCE_RUNTIME_INSTALL_FAILED",`Docker container ${t} does not expose its immutable image identity.`);const s="/run/task-handoff/runtime-rescue-artifact.tar.gz",r=[`test -r ${pr}`,`test -r ${ur}/instance-launcher.sh`,`test -r ${hr}`,`install -d -o root -g root -m 0755 ${gr} ${gr}/releases ${gr}/staging ${gr}/incoming`,`chown -R root:root ${gr}`,`chmod -R go-w ${gr}`,`node ${hr} 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=${s},readonly`,"--entrypoint",mr,i.image,"-ceu",r,"task-handoff-runtime-rescue",s,e.identity.version,e.identity.sha256,e.identity.platform,e.identity.arch,String(e.identity.launcherAbi)])}catch(n){throw _r("INSTANCE_RUNTIME_INSTALL_FAILED",`Could not rescue controlled-instance ${e.identity.version} in stopped container ${t}.`,n)}const o=await this.inspectContainerForStart(t);if(!o)throw _r("INSTANCE_RUNTIME_INSTALL_FAILED",`Docker container ${t} disappeared during runtime install recovery.`);if(xr(t,o.id,i.id,"after runtime install recovery","INSTANCE_RUNTIME_INSTALL_FAILED"),o.running)throw _r("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 _r("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Docker container ${e} does not exist.`);xr(e,n,t,"before runtime launcher install","INSTANCE_BASE_RUNTIME_INCOMPATIBLE");try{await this.runCommand("docker",["exec","--user","0",n,"bash","-ceu",`test -r ${pr}; test -r ${ur}/instance-launcher.sh; test -r ${hr}; 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 _r("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Could not install the runtime launcher in ${e}.`,t)}const i=await this.inspectContainerId(e);if(i!==n)throw _r("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Docker container identity changed while installing the runtime launcher in ${e}.`);xr(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(Or(t))return;throw _r("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(Or(t))return;throw _r("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}]:[]}):[],s=Array.isArray(e.Config?.Entrypoint)?e.Config.Entrypoint.filter(e=>"string"==typeof e):"string"==typeof e.Config?.Entrypoint?[e.Config.Entrypoint]:[],r=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:s,command:r,labels:n,mounts:i}}catch(t){throw _r("RUNTIME_EXECUTOR_FAILED",`Docker returned invalid inspection data for ${e}.`,t)}}async containerPort(e,t){let n,i=!1;for(const s of this.portResolutionRetryDelaysMs){s>0&&await Sr(s);try{const n=vr((await this.runCommand("docker",["port",e,t])).stdout);if(n)return n}catch(e){n=e}try{const n=wr((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 _r("RUNTIME_EXECUTOR_FAILED",`Docker container ${e} does not publish ${t}.`);throw _r("RUNTIME_EXECUTOR_FAILED",`Could not resolve the published port for Docker container ${e}.`,n)}}function vr(e){const t=e.split(/\r?\n/).find(Boolean);return t?.match(/:(\d+)$/)?.[1]}function wr(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 Sr(e){return new Promise(t=>setTimeout(t,e))}function Er(e){return"linux"===e||"darwin"===e?e:"windows"===e||"win32"===e?"win32":void 0}function zr(e){return"amd64"===e||"x86_64"===e||"x64"===e?"x64":"arm64"===e||"aarch64"===e?"arm64":void 0}function Nr(){const e=("undefined"==typeof document?require("url").pathToFileURL(__filename).href:w&&"SCRIPT"===w.tagName.toUpperCase()&&w.src||new URL("cli.js",document.baseURI).href)?n.dirname(s.fileURLToPath("undefined"==typeof document?require("url").pathToFileURL(__filename).href:w&&"SCRIPT"===w.tagName.toUpperCase()&&w.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 Tr(e){return`task-handoff/environment-image:${e.replace(/^sha256:/,"")}`}function _r(e,t,n){const i=Cr(n),s=new Error(i?`${t} Cause: ${i}`:t,void 0===n?void 0:{cause:n});return Object.assign(s,{statusCode:502,code:e}),s}const kr=new Set(["AUTHENTICATION_REJECTED","CLONE_FAILED","CREDENTIAL_AMBIGUOUS","CREDENTIAL_MISSING","HOST_KEY_REQUIRED","LFS_FAILED","REF_NOT_FOUND","REMOTE_UNSUPPORTED","SSH_AGENT_UNAVAILABLE","SUBDIRECTORY_NOT_FOUND","WORKSPACE_NOT_EMPTY","WORKSPACE_OWNERSHIP_MISMATCH"]);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 Or(e){const t=Cr(e)?.toLowerCase()||"";return t.includes("no such container")||t.includes("no such object")}function xr(e,t,n,i,s){if(n&&t!==n)throw _r(s,`Docker container ${e} identity mismatch ${i}: expected ${n}, got ${t}.`)}async function Rr(e=ar){return async function(e=ar){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>",s=t.ID||t.IDShort||"",r="<none>"!==n&&"<none>"!==i?`${n}:${i}`:s,o="<none>"!==n&&t.Digest&&"<none>"!==t.Digest?[`${n}@${t.Digest}`]:[];return{repository:n,tag:i,id:s,createdSince:t.CreatedSince,size:t.Size,sizeBytes:lr(t.Size),reference:r,repoDigests:o}}).filter(e=>Boolean(e.reference))}(e)}function Pr(e){return`task-handoff-${e.replace(/[^a-zA-Z0-9_.-]/g,"-")}`}function Dr(e,t,n){e.push("-e",`${t}=${n}`)}function Mr(e,t,i={}){const s=i.publishHost||"127.0.0.1",r=n.resolve(i.launcherAssetsDir||Nr()),o=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=${o}`,"--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,nosuid,nodev,exec,mode=1777","-p",`${s}::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=${r},dst=${ur},readonly`,"--entrypoint",mr);for(const t of yr(e))c.push("--mount",`type=volume,src=${t.name},dst=${t.mountPath}`);const d=fr(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:o,TASK_HANDOFF_RUNTIME_ID:a,TASK_HANDOFF_IMAGE_ID:e.image.id,TASK_HANDOFF_INSTANCE_LAUNCHER:`${ur}/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,..."local-folder"===e.project.source.type?{}:{TASK_HANDOFF_SKIP_WORKSPACE_BOOTSTRAP:"true"}};for(const[e,t]of Object.entries(l))Dr(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"}`):(Dr(c,"TASK_HANDOFF_PROJECT_SOURCE",JSON.stringify(e.project.source)),Dr(c,"TASK_HANDOFF_WORKSPACE_POLICY",JSON.stringify(e.project.workspacePolicy)),Dr(c,"TASK_HANDOFF_GIT_URL",e.project.source.url),"commit"===e.project.source.ref.type?Dr(c,"TASK_HANDOFF_GIT_COMMIT",e.project.source.ref.commit):Dr(c,"TASK_HANDOFF_GIT_REF",e.project.source.ref.name),e.project.source.clone?.depth&&Dr(c,"TASK_HANDOFF_GIT_DEPTH",String(e.project.source.clone.depth)),Dr(c,"TASK_HANDOFF_GIT_SUBMODULES",e.project.source.clone?.submodules?"true":"false"),Dr(c,"TASK_HANDOFF_GIT_LFS",e.project.source.clone?.lfs?"true":"false"),e.project.source.clone?.subdirectory&&Dr(c,"TASK_HANDOFF_WORKSPACE_SUBDIRECTORY",e.project.source.clone.subdirectory));for(const[t,n]of Object.entries(e.image.defaultEnv))Dr(c,t,n);return c.push(i.imageReference||e.instance.environmentTemplateOrigin?.imageId||e.image.resolvedReference||e.image.requestedReference,pr,"task-handoff","web"),c}function jr(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}}const Lr="app.sessions";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="app-session.snapshot",$r="app-session.patch",Ur="app-session.removed",Hr=a.z.enum(["created","starting","running","stopping","stopped","exited","failed","closed","terminated","unknown"]),Vr=a.z.enum(["tty","vnc","web"]);a.z.object({mode:Vr,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 Br=new Set(["stopped","failed","exited","closed","terminated"]),qr=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(),Kr=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:Hr.default("unknown"),bindings:a.z.array(qr).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()})),Gr=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(Kr).default([]),updatedAt:a.z.string().datetime()}).strict(),Wr=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:Gr}).strict();Gr.pick({runningCount:!0,problemCount:!0,updatedAt:!0}).extend({revision:a.z.number().int().min(0).optional()});const Jr=a.z.enum(["app-session-created","app-session-updated","app-session-deleted","app-session-recovered","control-action","heartbeat-sync","startup"]),Yr=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:Jr}).strict(),Xr=a.z.object({meta:Yr,snapshot:Gr}).strict(),Qr=a.z.object({meta:Yr,session:Kr}).strict(),Zr=a.z.object({meta:Yr,sessionId:a.z.string().trim().min(1).max(160),tombstone:Kr.optional(),expiresAt:a.z.string().datetime().optional()}).strict();function eo(e,t=(new Date).toISOString()){const n=e.map(e=>function(e){const t=no("string"==typeof e.status?e.status:void 0),n="string"==typeof e.id?e.id:"",i=function(e){const t=ao(e.workspace),n=ao(e.tty),i=ao(e.launch),s=ao(e.ai),r=ao(s.claude),o=co(t.cwd)||co(n.cwd)||co(r.cwd)||co(i.cwd);return o?{cwd:o}:void 0}(e),{workspace:s,...r}=e;return Kr.parse({...r,status:t,bindings:oo([...(o=e.bindings,Array.isArray(o)?o.flatMap(e=>{const t=qr.safeParse(e);return t.success?[t.data]:[]}):[]),...n?[{type:"app-session",id:n}]:[],...ro(e)]),...i?{workspace:i}:{}});var o}(e));return Gr.parse({runningCount:n.filter(e=>"running"===e.status).length,problemCount:n.filter(e=>"failed"===e.status).length,sessions:n,updatedAt:t})}function to(e,t=(new Date).toISOString()){return eo(e.filter(e=>io("string"==typeof e.status?e.status:void 0)),t)}function no(e){const t=(e||"unknown").trim().toLowerCase();return"ended"===t?"closed":"terminating"===t?"stopping":Hr.options.includes(t)?t:"unknown"}function io(e){return!Br.has(no(e))}function so(e){return"app-session"===e.type?`app:${e.id}`:"provider-session"===e.type?`provider:${e.agent||""}:${e.id}`:`adapter:${e.adapter||""}:${e.key||e.id}`}function ro(e){const t=ao(e.ai),n=ao(t.claude),i=ao(t.appServer),s=ao(e.launch),r=[],o=co(ao(s.aiSessionResume).providerSessionId),a="codex"===e.appId||"claude"===e.appId||"opencode"===e.appId?e.appId:void 0;a&&o&&r.push({type:"provider-session",agent:a,id:o});const c=co(n.short);c&&r.push({type:"adapter-key",adapter:"claude",agent:"claude",id:`short:${c}`,key:`short:${c}`});const d=co(n.providerSessionId);d&&r.push({type:"provider-session",agent:"claude",id:d});const l=Array.isArray(t.threadIds)?t.threadIds.filter(e=>"string"==typeof e&&Boolean(e.trim())):[],u=co(t.activeThreadId);for(const e of[...new Set([u,...l].filter(Boolean))])r.push({type:"provider-session",agent:"codex",id:e});const p=co(i.socketPath);return p&&r.push({type:"adapter-key",adapter:"codex-app-server",agent:"codex",id:`socket:${p}`,key:`socket:${p}`}),r}function oo(e){const t=new Map;for(const n of e)t.set(so(n),n);return[...t.values()]}function ao(e){return e&&"object"==typeof e&&!Array.isArray(e)?e:{}}function co(e){return"string"==typeof e&&e.trim()?e.trim():""}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(Fr),payload:Xr}).strict(),a.z.object({type:a.z.literal($r),payload:Qr}).strict(),a.z.object({type:a.z.literal(Ur),payload:Zr}).strict()])).default([])}).strict();const lo="2026-08-25",uo=a.z.object({nodeId:a.z.string().optional(),instanceId:a.z.string().optional()}).passthrough(),po=a.z.object({v:a.z.literal(1),id:a.z.string().min(1),seq:a.z.number().finite(),type:a.z.string().min(1),topic:a.z.string().min(1),createdAt:a.z.string().datetime(),payload:a.z.unknown(),replay:a.z.literal(!0).optional(),scope:uo.optional()}).passthrough(),mo=a.z.object({v:a.z.literal(lo),id:a.z.string().min(1),type:a.z.string().min(1),createdAt:a.z.string().datetime(),payload:a.z.unknown(),topic:a.z.string().min(1).optional(),replay:a.z.literal(!0).optional(),scope:uo.optional()}).passthrough();function ho(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":e.startsWith("story.")?"stories":"system"}a.z.discriminatedUnion("v",[po,mo]),a.z.object({v:a.z.literal(1),type:a.z.literal("ping"),sentAt:a.z.string().datetime()}).strict(),a.z.object({v:a.z.literal(1),type:a.z.literal("pong"),sentAt:a.z.string().datetime(),receivedAt:a.z.string().datetime()}).strict();const go=a.z.object({replaySince:a.z.string().datetime().optional(),messageDeltas:a.z.object({allInstances:a.z.boolean().default(!1),instanceIds:a.z.array(a.z.string().trim().min(1).max(160)).max(1e3).default([])}).default({allInstances:!1,instanceIds:[]}),timelineAllSessions:a.z.boolean().default(!1),timelineSessions:a.z.array(a.z.object({instanceId:a.z.string().trim().min(1).max(160),sessionId:a.z.string().trim().min(1).max(120)})).max(1e3).default([])}),fo=a.z.enum(["ai.sessions","app.sessions"]),yo=a.z.object({topic:fo,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(),Io=a.z.object({protocolVersion:a.z.literal(1),streams:a.z.array(yo)}).strict();function Ao(e,t=Math.random){const n=Math.max(1,Math.floor(e));if(1===n)return 0;if(2===n)return 250;const i=Math.min(6e4,250*2**(n-2));return Math.min(6e4,Math.round(i*(.75+.5*t())))}class bo{retryNumber=0;random;constructor(e=Math.random){this.random=e}get attempts(){return this.retryNumber}next(){return this.retryNumber+=1,{attempt:this.retryNumber,delay:Ao(this.retryNumber,this.random)}}reset(){this.retryNumber=0}}class vo{backoff;timer;constructor(e=Math.random){this.backoff=new bo(e)}get pending(){return Boolean(this.timer)}get attempts(){return this.backoff.attempts}schedule(e,t={}){if(this.timer)return;const n=this.backoff.next(),i=t.setTimeoutFn||setTimeout;return this.timer=i(()=>{this.timer=void 0,e()},n.delay),n}reset(e=clearTimeout){this.timer&&e(this.timer),this.timer=void 0,this.backoff.reset()}cancel(e=clearTimeout){this.timer&&e(this.timer),this.timer=void 0}}class wo extends vo{}function So(e,t=6e4){const n=[];for(let i=0;i<e.length;i+=t)n.push(e.slice(i,i+t));return n}const Eo=262144,zo=262144;class No{sockets=new Map;socketUrls=new Map;retries=new Map;outputs=new Set;outputSubscriptions=new Map;outputEnvelopeVersions=new Map;outputDiagnostics=new Map;aiSessionProjectionByInstance=new Map;appSessionProjectionByInstance=new Map;sessionStreamsHelloByInstance=new Map;sessionAuthorityReplayedOutputs=new Set;pendingAiSessionAuthorityByOutput=new Map;pendingAiSessionAuthorityFlush=new Map;eventTransportCongestion;imagePullTerminalByInstance=new Map;state;token;logger;safetyIntervalMs;lastAiSessionEventByInstance=new Map;lastAppSessionEventByInstance=new Map;timer;reconnectAttempts=0;safetyReconciliations=0;localSequence=0;outputSequence=0;createSocket;setIntervalFn;clearIntervalFn;setTimeoutFn;clearTimeoutFn;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 p(e,t)),this.setIntervalFn=n.setIntervalFn||setInterval,this.clearIntervalFn=n.clearIntervalFn||clearInterval,this.setTimeoutFn=n.setTimeoutFn||setTimeout,this.clearTimeoutFn=n.clearTimeoutFn||clearTimeout}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(),this.outputSubscriptions.clear(),this.outputEnvelopeVersions.clear(),this.outputDiagnostics.clear();for(const e of this.pendingAiSessionAuthorityFlush.values())this.clearTimeoutFn(e);this.pendingAiSessionAuthorityFlush.clear(),this.pendingAiSessionAuthorityByOutput.clear(),this.aiSessionProjectionByInstance.clear(),this.appSessionProjectionByInstance.clear(),this.sessionStreamsHelloByInstance.clear(),this.sessionAuthorityReplayedOutputs.clear()}addOutput(e,t={}){let n;this.outputs.add(e),this.outputDiagnostics.set(e,{outputId:"event_output_"+ ++this.outputSequence,kind:t.expectsTransientSubscription?"events-websocket":void 0!==t.legacyFallbackMs?"reverse-tunnel":"legacy"}),this.outputSubscriptions.set(e,t.expectsTransientSubscription?go.parse({}):void 0),this.outputEnvelopeVersions.set(e,1),t.expectsTransientSubscription||void 0===t.legacyFallbackMs||(n=this.setTimeoutFn(()=>{n=void 0,this.outputs.has(e)&&void 0===this.outputSubscriptions.get(e)&&(this.replaySessionAuthority(e),this.syncNow())},t.legacyFallbackMs));let i=!1;const s=()=>{if(i)return;i=!0,this.outputs.delete(e),this.outputSubscriptions.delete(e),this.outputEnvelopeVersions.delete(e),this.outputDiagnostics.delete(e),this.sessionAuthorityReplayedOutputs.delete(e);const t=this.pendingAiSessionAuthorityFlush.get(e);t&&this.clearTimeoutFn(t),this.pendingAiSessionAuthorityFlush.delete(e),this.pendingAiSessionAuthorityByOutput.delete(e),this.refreshEventTransportRecovery(),n&&clearTimeout(n),this.syncNow()};e.on("close",s),e.on("error",s);for(const t of this.state.listInstances()){const n=To(t);n?this.sendForwarded(e,this.createEvent(Ks,n,{instanceId:t.id})):this.logger?.warn?.({instanceId:t.id},"instance.lifecycle.snapshot.invalid")}for(const[t,n]of this.imagePullTerminalByInstance)So(n.tail).forEach((i,s)=>this.sendForwarded(e,this.createEvent(Is,{...n.output,sequence:n.output.sequence+s,data:i,...0===s?{replay:!0}:{}},{instanceId:t}))),n.finished&&this.sendForwarded(e,this.createEvent(As,n.finished,{instanceId:t}));return(t.expectsTransientSubscription||void 0===t.legacyFallbackMs)&&(this.replaySessionAuthority(e),this.syncNow()),s}setOutputSubscription(e,t,n){if(!this.outputs.has(e))return!1;const i=go.safeParse(t);if(!i.success)return!1;this.outputSubscriptions.set(e,i.data),this.outputEnvelopeVersions.set(e,n===lo?lo:1),this.replaySessionAuthority(e),this.syncNow();for(const[e,t]of this.sockets)this.sendInstanceSubscription(e,t);return!0}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===Is){const e=nr(vs,t);if(!e.success)return;const n=e.data,i=this.imagePullTerminalByInstance.get(n.instanceId);if(i&&n.generation<i.output.generation)return;const s=i?.output.generation===n.generation,r=n.replay||!s?n.data:`${i.tail}${n.data}`.slice(-262144);return void this.imagePullTerminalByInstance.set(n.instanceId,{output:n,tail:r})}if(e===As){const e=nr(ws,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(Ks,function(e){return Gs.parse(_o(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:ho(e),createdAt:(new Date).toISOString(),payload:t,scope:n}}sendForwarded(e,t){const n=t.type===ge?Rt.safeParse(t.payload):void 0,i=this.outputEnvelopeVersions.get(e)===lo?function(e,t,n={}){const i=e.scope?n.publicScope&&e.scope.instanceId?{instanceId:e.scope.instanceId}:e.scope:void 0;return{v:lo,id:e.id,type:e.type,createdAt:e.createdAt,payload:void 0===n.payload?e.payload:n.payload,...e.topic!==ho(e.type)?{topic:e.topic}:{},...e.replay?{replay:!0}:{},...i&&Object.keys(i).length?{scope:i}:{}}}(t,0,{...n?.success?{payload:(s=n.data,Pt.parse({sessionId:s.sessionId,turnId:s.turnId,itemId:s.itemId,delta:s.delta,generatedAt:s.generatedAt}))}:{}}):t;var s;const r=JSON.stringify({type:"node-agent.event.forwarded",event:i});this.sendOutput(e,r,t)}sendOutput(e,t,n){const i=Buffer.byteLength(t,"utf8"),s=n?.topic===Lr?"app-session":n?.topic===ue?"ai-session":void 0,r=s?{...this.outputDiagnostics.get(e),instanceId:n.scope?.instanceId,eventType:n.type,...ko(n.payload)}:void 0;if(e.readyState!==p.OPEN)return r&&this.logger?.warn?.({...r,readyState:e.readyState,outcome:"not-open"},`${s}.event.output.rejected`),!1;if(n&&this.shouldCoalesceAiSessionAuthority(e,n)&&this.deferAiSessionAuthority(e,n))return!0;if(n&&Oo(n)&&i>zo){if(n.type!==pe&&this.deferAiSessionAuthority(e,n))return!0;this.observeEventTransportCongestion(e,!1,i),r&&this.logger?.warn?.({...r,bufferedAmount:e.bufferedAmount,bytes:i,maxBytes:zo,outcome:"payload-too-large"},`${s}.event.output.rejected`);try{e.close(1009,"AI Session authority event exceeds the transport limit.")}catch{}return!1}if(e.bufferedAmount+i>16777216){this.observeEventTransportCongestion(e,!1),r&&this.logger?.warn?.({...r,bufferedAmount:e.bufferedAmount,outcome:"backpressure"},`${s}.event.output.rejected`);try{e.close(1013,"Event consumer is too slow.")}catch{}return!1}try{return e.send(t),r&&this.logger?.info?.({...r,bufferedAmount:e.bufferedAmount,bytes:i,outcome:"queued"},`${s}.event.output.queued`),!0}catch(t){r&&this.logger?.warn?.({...r,error:t instanceof Error?t.message:String(t),outcome:"send-failed"},`${s}.event.output.rejected`);try{e.close(1011,"Event delivery failed.")}catch{}return!1}}shouldCoalesceAiSessionAuthority(e,t){if(!Oo(t))return!1;const n=t.scope?.instanceId;return!!n&&(!!this.pendingAiSessionAuthorityByOutput.get(e)?.has(n)||e.bufferedAmount>=Eo)}deferAiSessionAuthority(e,t){const n=t.scope?.instanceId,i=n?this.aiSessionProjectionByInstance.get(n):void 0;if(!n||!i)return!1;const s=function(e,t){const n=Co(e);return n?n.payload.meta.streamId!==t.streamId||n.payload.meta.revision!==t.revision?void 0:Ct.parse({meta:n.payload.meta,snapshot:t.snapshot}):void 0}(t,i);if(!s)return!1;const r=this.pendingAiSessionAuthorityByOutput.get(e)||new Map;return r.set(n,{...t,type:pe,topic:ue,payload:s}),this.pendingAiSessionAuthorityByOutput.set(e,r),this.observeEventTransportCongestion(e,!0),this.logger?.info?.({...this.outputDiagnostics.get(e),instanceId:n,eventType:t.type,...ko(s),bufferedAmount:e.bufferedAmount,outcome:"coalesced-latest"},"ai-session.event.output.coalesced"),this.scheduleAiSessionAuthorityFlush(e),!0}scheduleAiSessionAuthorityFlush(e){if(this.pendingAiSessionAuthorityFlush.has(e))return;const t=this.setTimeoutFn(()=>{this.pendingAiSessionAuthorityFlush.delete(e),this.flushAiSessionAuthority(e)},25);t.unref?.(),this.pendingAiSessionAuthorityFlush.set(e,t)}flushAiSessionAuthority(e){const t=this.pendingAiSessionAuthorityByOutput.get(e);if(!t?.size)return void this.pendingAiSessionAuthorityByOutput.delete(e);if(e.readyState!==p.OPEN)return void this.pendingAiSessionAuthorityByOutput.delete(e);const[n,i]=t.entries().next().value;e.bufferedAmount>=Eo?this.scheduleAiSessionAuthorityFlush(e):(t.delete(n),t.size||this.pendingAiSessionAuthorityByOutput.delete(e),this.sendForwarded(e,i),this.refreshEventTransportRecovery(),t.size&&this.scheduleAiSessionAuthorityFlush(e))}observeEventTransportCongestion(e,t,n=0){const i=(new Date).toISOString(),s=Math.max(0,Math.floor(e.bufferedAmount)),r=this.eventTransportCongestion;this.eventTransportCongestion={congestedSince:r?.recoveredAt?i:r?.congestedSince||i,lastCongestedAt:i,peakBufferedBytes:Math.max(r?.recoveredAt?0:r?.peakBufferedBytes||0,s),coalescedEvents:(r?.recoveredAt?0:r?.coalescedEvents||0)+(t?1:0),oversizedEvents:(r?.recoveredAt?0:r?.oversizedEvents||0)+(n>0?1:0),peakEventBytes:Math.max(r?.recoveredAt?0:r?.peakEventBytes||0,n)}}eventTransportIsCongested(){return!![...this.pendingAiSessionAuthorityByOutput.values()].some(e=>e.size>0)||[...this.outputs].some(e=>e.readyState===p.OPEN&&e.bufferedAmount>=Eo)}refreshEventTransportRecovery(){const e=this.eventTransportCongestion;!e||e.recoveredAt||this.eventTransportIsCongested()||(e.recoveredAt=(new Date).toISOString())}eventTransportHealth(){this.refreshEventTransportRecovery();const e=[...this.outputs].filter(e=>e.readyState===p.OPEN),t=e.reduce((e,t)=>Math.max(e,Math.max(0,Math.floor(t.bufferedAmount))),0),n=this.eventTransportIsCongested();let i=this.eventTransportCongestion;return i?.recoveredAt&&Date.now()-Date.parse(i.recoveredAt)>3e5&&(this.eventTransportCongestion=void 0,i=void 0),{status:n?"congested":i?"recovering":"healthy",activeOutputs:e.length,bufferedBytes:t,peakBufferedBytes:i?.peakBufferedBytes||t,coalescedEvents:i?.coalescedEvents||0,oversizedEvents:i?.oversizedEvents||0,peakEventBytes:i?.peakEventBytes||0,...n&&i?{congestedSince:i.congestedSince}:{},...i?{lastCongestedAt:i.lastCongestedAt}:{}}}syncNow(){this.sync()}diagnostics(){const e=[...this.outputSubscriptions.values()];return{reconnectAttempts:this.reconnectAttempts,safetyReconciliations:this.safetyReconciliations,activeConnections:this.sockets.size,pendingRetries:[...this.retries.values()].filter(e=>e.timer.pending).length,safetyIntervalMs:this.safetyIntervalMs,eventTransport:this.eventTransportHealth(),transientDemand:{legacyOutputs:e.filter(e=>void 0===e).length,scopedOutputs:e.filter(e=>void 0!==e).length,messageDeltaAllInstances:e.some(e=>e?.messageDeltas.allInstances),messageDeltaInstanceCount:new Set(e.flatMap(e=>e?.messageDeltas.instanceIds||[])).size,timelineAllSessions:e.some(e=>e?.timelineAllSessions),timelineSessionCount:new Set(e.flatMap(e=>e?.timelineSessions.map(e=>JSON.stringify([e.instanceId,e.sessionId]))||[])).size}}}sync(){const e=new Set(this.state.listInstances().map(e=>e.id));for(const t of this.aiSessionProjectionByInstance.keys())e.has(t)||this.aiSessionProjectionByInstance.delete(t);for(const t of this.appSessionProjectionByInstance.keys())e.has(t)||this.appSessionProjectionByInstance.delete(t);for(const t of this.sessionStreamsHelloByInstance.keys())e.has(t)||this.sessionStreamsHelloByInstance.delete(t);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=xo(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);this.retries.set(e,{timer:n?.timer||new wo,url:t}),i.readyState===p.OPEN&&(this.sendInstanceSubscription(e,i),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=function(e,t={}){if(!e||"object"!=typeof e||Array.isArray(e))return;const n=e,i="string"==typeof n.type?n.type:"";if(!i)return;const s=n.scope&&"object"==typeof n.scope&&!Array.isArray(n.scope)?n.scope:{};return{v:1,id:"string"==typeof n.id?n.id:`event_${Date.now().toString(36)}`,seq:"number"==typeof n.seq&&Number.isFinite(n.seq)?n.seq:0,type:i,topic:"string"==typeof n.topic?n.topic:ho(i),createdAt:"string"==typeof n.createdAt?n.createdAt:(new Date).toISOString(),payload:"payload"in n?n.payload:{},...!0===n.replay?{replay:!0}:{},scope:{...t,...s}}}(JSON.parse(String(e)),{instanceId:t});if(!n||"events.connected"===n.type)return;if(n.type===ge){const e=function(e,t){const n=Pt.safeParse(e);return n.success?Rt.parse({instanceId:t,...n.data}):Rt.parse(e)}(n.payload,t);return{...n,payload:e,scope:{...n.scope,instanceId:t}}}return{...n,scope:{...n.scope,instanceId:t}}}catch{return}}(t,e);if(n){if("streams.hello"===n.type){const t=nr(Io,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.");this.retries.get(e)?.timer.reset(),this.sessionStreamsHelloByInstance.set(e,t.data);const s=JSON.stringify({type:"node-agent.streams.hello",instanceId:e,payload:t.data});for(const e of this.outputs)this.sendOutput(e,s);return}this.recordAiSessionEvent(e,n),this.recordAppSessionEvent(e,n);for(const e of this.outputs)this.outputAccepts(e,n)&&this.sendForwarded(e,n)}}),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()})}sendInstanceSubscription(e,t){if(t.readyState!==p.OPEN)return;const n=[...this.outputs].map(e=>this.outputSubscriptions.get(e));if(n.some(e=>void 0===e))return void t.send(JSON.stringify({v:1,type:"subscribe",eventEnvelopeVersion:lo,topics:[ue,"app.sessions","apps","instances"]}));const i=n.some(t=>t.messageDeltas.allInstances||t.messageDeltas.instanceIds.includes(e)),s=n.some(e=>e.timelineAllSessions),r=[...new Set(n.flatMap(t=>t.timelineSessions.filter(t=>t.instanceId===e).map(e=>e.sessionId)))],o=n.map(e=>e.replaySince).filter(e=>Boolean(e)).sort()[0];t.send(JSON.stringify({v:1,type:"subscribe",eventEnvelopeVersion:lo,topics:[pe,me,he,...i?[ge]:[],...s||r.length?[fe]:[],"app.sessions","apps","instances"],aiSessionTransient:{...o?{replaySince:o}:{},messageDeltas:{allInstances:i,instanceIds:[]},timelineAllSessions:s,timelineSessions:r.map(t=>({instanceId:e,sessionId:t}))}}))}outputAccepts(e,t){const n=this.outputSubscriptions.get(e);return!n||function(e,t){if(!e)return!0;if("ai-session.message-delta"!==t.type&&"ai-session.timeline-item"!==t.type)return!0;const n=t.payload&&"object"==typeof t.payload&&!Array.isArray(t.payload)?t.payload:{},i=String(n.instanceId||t.scope?.instanceId||"");return"ai-session.message-delta"===t.type?e.messageDeltas.allInstances||e.messageDeltas.instanceIds.includes(i):e.timelineAllSessions||e.timelineSessions.some(e=>e.instanceId===i&&e.sessionId===n.sessionId)}(n,t)}scheduleReconnect(e){const t=this.state.listInstances().find(t=>t.id===e),n=t&&xo(t);if(!n||!this.outputs.size)return;const i=this.retries.get(e)??{timer:new wo};if(i.timer.pending)return;i.url=n;const s=i.timer.schedule(()=>{this.sockets.has(e)||this.connect(e,n)},{setTimeoutFn:this.setTimeoutFn});s&&(this.reconnectAttempts+=1,this.logger?.info?.({instanceId:e,url:n,attempt:s.attempt,delay:s.delay,reconnectAttempts:this.reconnectAttempts},"session-stream.connection.reconnect-scheduled")),this.retries.set(e,i)}recordAiSessionEvent(e,t){if(t.topic!==ue)return;if(t.type===ge||t.type===fe)return;const n=Co(t);if(n){const t=function(e,t){const{meta:n}=t.payload;if(t.type===pe)return e?.streamId===n.streamId&&n.revision===e.revision?{kind:"duplicate",projection:e}:e?.streamId===n.streamId&&n.revision<e.revision?{kind:"stale",projection:e}:{kind:"applied",projection:Tt.parse({streamId:n.streamId,revision:n.revision,lastEventAt:n.generatedAt,snapshot:t.payload.snapshot})};if(!e||e.streamId!==n.streamId)return{kind:"snapshot-required",projection:e,streamId:n.streamId};if(n.revision===e.revision)return{kind:"duplicate",projection:e};if(n.revision<e.revision)return{kind:"stale",projection:e};if(n.revision!==e.revision+1||n.previousRevision!==e.revision)return{kind:"gap",projection:e,expectedRevision:e.revision+1,receivedRevision:n.revision};const i=new Map(e.snapshot.sessions.map(e=>[e.id,e]));if(t.type===me){for(const e of t.payload.upserted)i.set(e.id,e);for(const e of t.payload.removed)i.delete(e)}else for(const e of t.payload.sessionIds)i.delete(e);const s=[...i.values()],r=Nt.parse({runningCount:s.filter(e=>"running"===e.status).length,waitingCount:s.filter(e=>"waiting"===e.status).length,staleCount:e.snapshot.staleCount,sessions:s,updatedAt:n.generatedAt});return{kind:"applied",projection:Tt.parse({streamId:n.streamId,revision:n.revision,lastEventAt:n.generatedAt,snapshot:r})}}(this.aiSessionProjectionByInstance.get(e),n);"applied"!==t.kind&&"duplicate"!==t.kind&&"stale"!==t.kind||this.aiSessionProjectionByInstance.set(e,t.projection)}const i=ko(t.payload),s=this.lastAiSessionEventByInstance.get(e);s?.streamId===i.streamId&&void 0!==s.revision&&void 0!==i.revision&&i.revision>s.revision+1&&this.logger?.warn?.({instanceId:e,traceId:i.traceId,streamId:i.streamId,previousRevision:s.revision,revision:i.revision},"ai-session.event.forward.gap"),this.lastAiSessionEventByInstance.set(e,{streamId:i.streamId??s?.streamId,revision:i.revision??s?.revision}),this.logger?.info?.({instanceId:e,traceId:i.traceId,eventType:t.type,streamId:i.streamId,revision:i.revision},"ai-session.event.forward.message")}recordAppSessionEvent(e,t){if(t.topic!==Lr)return;const n=function(e){const t=e.type===Fr?Xr:e.type===$r?Qr:e.type===Ur?Zr:void 0;if(!t)return;const n=nr(t,e.payload);return n.success?{type:e.type,payload:n.data}:void 0}(t);if(n){const t=function(e,t){const{meta:n}=t.payload;if(t.type===Fr)return e?.streamId===n.streamId&&n.revision===e.revision?{kind:"duplicate",projection:e}:e?.streamId===n.streamId&&n.revision<e.revision?{kind:"stale",projection:e}:{kind:"applied",projection:Wr.parse({streamId:n.streamId,revision:n.revision,lastEventAt:n.generatedAt,snapshot:to(t.payload.snapshot.sessions,t.payload.snapshot.updatedAt)})};if(!e||e.streamId!==n.streamId)return{kind:"snapshot-required",projection:e,streamId:n.streamId};if(n.revision===e.revision)return{kind:"duplicate",projection:e};if(n.revision<e.revision)return{kind:"stale",projection:e};if(n.revision!==e.revision+1||n.previousRevision!==e.revision)return{kind:"gap",projection:e,expectedRevision:e.revision+1,receivedRevision:n.revision};const i=[...e.snapshot.sessions];if(t.type===$r){const e=i.findIndex(e=>e.id===t.payload.session.id);io(t.payload.session.status)?e<0?i.push(t.payload.session):i[e]=t.payload.session:e>=0&&i.splice(e,1)}else{const e=i.findIndex(e=>e.id===t.payload.sessionId);e>=0&&i.splice(e,1)}const s=eo(i,n.generatedAt);return{kind:"applied",projection:Wr.parse({streamId:n.streamId,revision:n.revision,lastEventAt:n.generatedAt,snapshot:s})}}(this.appSessionProjectionByInstance.get(e),n);"applied"!==t.kind&&"duplicate"!==t.kind&&"stale"!==t.kind||this.appSessionProjectionByInstance.set(e,t.projection)}const i=ko(t.payload),s=this.lastAppSessionEventByInstance.get(e);s?.streamId===i.streamId&&void 0!==s.revision&&void 0!==i.revision&&i.revision>s.revision+1&&this.logger?.warn?.({instanceId:e,traceId:i.traceId,streamId:i.streamId,previousRevision:s.revision,revision:i.revision},"app-session.event.forward.gap"),this.lastAppSessionEventByInstance.set(e,{streamId:i.streamId??s?.streamId,revision:i.revision??s?.revision}),this.logger?.info?.({instanceId:e,traceId:i.traceId,eventType:t.type,streamId:i.streamId,revision:i.revision},"app-session.event.forward.message")}replaySessionAuthority(e){if(!this.sessionAuthorityReplayedOutputs.has(e)&&e.readyState===p.OPEN){this.sessionAuthorityReplayedOutputs.add(e);for(const[t,n]of this.sessionStreamsHelloByInstance){const i=n.streams.map(e=>{const n=e.topic===ue?this.aiSessionProjectionByInstance.get(t):this.appSessionProjectionByInstance.get(t);return n?n.streamId!==e.streamId?{...e,streamId:n.streamId,latestRevision:n.revision,earliestRetainedRevision:n.revision}:{...e,latestRevision:Math.max(e.latestRevision,n.revision)}:e});this.sendOutput(e,JSON.stringify({type:"node-agent.streams.hello",instanceId:t,payload:{...n,streams:i}}))}for(const[t,n]of this.aiSessionProjectionByInstance)this.sendForwarded(e,this.createEvent(pe,{meta:{streamId:n.streamId,instanceId:t,revision:n.revision,traceId:`ais_replay_${Date.now().toString(36)}`,generatedAt:n.lastEventAt,reason:"startup"},snapshot:n.snapshot},{instanceId:t}));for(const[t,n]of this.appSessionProjectionByInstance)this.sendForwarded(e,this.createEvent(Fr,{meta:{streamId:n.streamId,instanceId:t,revision:n.revision,traceId:`aps_replay_${Date.now().toString(36)}`,generatedAt:n.lastEventAt,reason:"startup"},snapshot:n.snapshot},{instanceId:t}))}}}function To(e){const t=Gs.safeParse(_o(e));return t.success?t.data:void 0}function _o(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 ko(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 Co(e){const t=e.type===pe?Ct:e.type===me?Ot:e.type===he?xt:void 0;if(!t)return;const n=nr(t,e.payload);return n.success?{type:e.type,payload:n.data}:void 0}function Oo(e){return e.topic===ue&&(e.type===pe||e.type===me||e.type===he)}function xo(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.searchParams.set("aiSessionTransient","1"),e.searchParams.set("aiSessionAuthoritySnapshot","1"),e.protocol="https:"===e.protocol?"wss:":"ws:",e.toString()}catch{return}}const Ro=new Set(["provisioning","starting","registering","registered","running","unhealthy"]),Po=JSON.stringify({id:"{{.ID}}",name:"{{.Name}}",cpu:"{{.CPUPerc}}",memory:"{{.MemUsage}}",memoryPercent:"{{.MemPerc}}",network:"{{.NetIO}}",blockIo:"{{.BlockIO}}",pids:"{{.PIDs}}"});class Do{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(!Ro.has(t.status))return Uo(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=Mo(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,Mo(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=>Ro.has(e.status)&&(e.runtime.containerId||e.runtime.containerName));for(const t of e.filter(e=>Ro.has(e.status)&&!e.runtime.containerId&&!e.runtime.containerName))this.update(Ho(t.id));for(const t of e.filter(e=>!Ro.has(e.status)))this.update(Uo(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",Po,...n],{timeoutMs:5e3});this.applyDockerOutput(t,e.stdout,i)}catch(e){if(1===t.length)return void this.update(Vo(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",Po,t],{timeoutMs:5e3});this.applyDockerOutput([e],n.stdout,i)}catch(t){this.update(Vo(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 s=$o(e.id),r=$o(e.name),o=s||r;if(!o)continue;const a=jo($o(e.memory)),c=jo($o(e.network)),d=jo($o(e.blockIo)),l=_s.parse({instanceId:o,runtimeKind:"docker",state:"available",sampledAt:t,cpu:Lo(e.cpu,"usagePercent"),memory:a?{usageBytes:a[0],...void 0!==a[1]?{limitBytes:a[1]}:{},...Lo(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:Fo(e.pids)});s&&n.set(s,l),r&&n.set(r,l)}return n}(t,n);for(const t of e){const e=[t.runtime.containerId,t.runtime.containerName].filter(Boolean),s=[...i.entries()].find(([t])=>e.some(e=>e===t||e.startsWith(t)||t.startsWith(e)))?.[1];this.update(s?{...s,instanceId:t.id}:Vo(t.id,n,"Container metrics were not returned by Docker."))}}update(e){const t=_s.parse(e);this.snapshots.set(t.instanceId,t),this.publish?.(t)}}function Mo(e){return[e.status,e.runtime.containerId||"",e.runtime.containerName||""].join("\0")}function jo(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(),s=i.includes("i"),r="b"===i[0]?"":i[0],o=r?"kmgtpe".indexOf(r)+1:0;return Math.round(n*(s?1024:1e3)**o)}(e||""));return void 0===t?void 0:[t,n]}function Lo(e,t){const n=Number($o(e).replace(/%$/,""));return Number.isFinite(n)&&n>=0?{[t]:n}:void 0}function Fo(e){const t=Number($o(e));return Number.isFinite(t)&&t>=0?t:void 0}function $o(e){return"string"==typeof e||"number"==typeof e?String(e).trim():""}function Uo(e){return{instanceId:e,runtimeKind:"docker",state:"stopped",sampledAt:(new Date).toISOString()}}function Ho(e){return{instanceId:e,runtimeKind:"docker",state:"pending",sampledAt:(new Date).toISOString()}}function Vo(e,t,n){return{instanceId:e,runtimeKind:"docker",state:"unavailable",sampledAt:t,error:n.slice(0,2048)}}function Bo(e,t,n){return Object.assign(new Error(e),{statusCode:t,code:n})}function qo(e){const i=n.resolve(e);let s;try{s=t.statSync(i)}catch(e){const t=e&&"object"==typeof e?e.code:void 0;if("ENOENT"===t||"ENOTDIR"===t)throw Bo(`Folder ${i} was not found.`,404,"NODE_FOLDER_PATH_NOT_FOUND");throw Bo(`Folder ${i} is not accessible.`,403,"NODE_FOLDER_PATH_UNREADABLE")}if(!s.isDirectory())throw Bo(`Path ${i} is not a folder.`,400,"NODE_FOLDER_PATH_NOT_DIRECTORY");try{t.accessSync(i,t.constants.R_OK|t.constants.X_OK)}catch{throw Bo(`Folder ${i} is not accessible.`,403,"NODE_FOLDER_PATH_UNREADABLE")}return i}function Ko(e){try{return t.statSync(e).isDirectory()}catch{return!1}}function Go(){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(Ko)}function Wo(){const e=n.resolve(c.homedir()),t=Go().map(e=>n.resolve(e));return[...Ko(e)?[{kind:"home",name:n.basename(e)||e,path:e}]:[],...t.map(e=>({kind:"root",name:e,path:e}))]}function Jo(e,i){let s;try{s=t.statSync(e)}catch{return}if(!s.isDirectory())return;const r=n.resolve(e),o=n.basename(r)||r;let a=[];try{a=i>0?t.readdirSync(r,{withFileTypes:!0}):[]}catch{a=[]}const c=i>0?a.filter(e=>e.isDirectory()||e.isSymbolicLink()&&Ko(n.join(r,e.name))).sort((e,t)=>e.name.localeCompare(t.name)).slice(0,80).flatMap(e=>{const t=Jo(n.join(r,e.name),i-1);return t?[t]:[]}):[];return{name:o,path:r,children:c}}function Yo(e){return(e.path?[qo(e.path)]:Go()).flatMap(t=>{const n=Jo(t,e.depth);return n?[n]:[]})}function Xo(){return process.env.TASK_HANDOFF_NODE_AGENT_DATA_DIR||n.join(c.homedir(),".config","task-handoff","node-agent")}function Qo(e=Xo()){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"),gitCredentialPayloadsDir:n.join(t,"git-credentials","payloads"),gitCredentialAssignmentsDir:n.join(t,"git-credentials","assignments"),gitCredentialAuthorizationSetsDir:n.join(t,"git-credentials","authorization-sets"),gitWorkspaceProvisioningIntentsDir:n.join(t,"git-credentials","workspace-provisioning-intents"),updatesDir:n.join(t,"updates"),logsDir:n.join(t,"logs"),storyRegistryDir:n.join(t,"story-registry"),storyContentDir:n.join(t,"stories")}}function Zo(e,t){const i=n.extname(e);return`${i?e.slice(0,-i.length):e}.${t}${i}`}function ea(e,n=10485760,i=2){if(!t.existsSync(e))return!1;const s=t.lstatSync(e);if(!s.isFile()||s.isSymbolicLink()||s.size<=n)return!1;if(i>0){!function(e,n){if(!(n<=0)){t.rmSync(Zo(e,n),{force:!0});for(let i=n-1;i>=1;i-=1){const n=Zo(e,i);t.existsSync(n)&&t.renameSync(n,Zo(e,i+1))}}}(e,i);const s=function(e,n){const i=t.statSync(e),s=Math.min(i.size,n),r=Buffer.allocUnsafe(s),o=t.openSync(e,"r");let a=0;try{for(;a<s;){const e=t.readSync(o,r,a,s-a,i.size-s+a);if(0===e)break;a+=e}}finally{t.closeSync(o)}return a===s?r:r.subarray(0,a)}(e,n);t.writeFileSync(Zo(e,1),s,{mode:384})}return t.truncateSync(e,0),t.chmodSync(e,384),!0}class ta{logsDir;localInstancesRoot;localInstancesTrashRoot;options;constructor(e,t={}){this.options=t,this.logsDir=e.logsDir,this.localInstancesRoot=n.join(e.dataDir,"local-instances"),this.localInstancesTrashRoot=n.join(e.dataDir,"local-instances-trash")}run(e){this.capNodeAgentLogs();const n=new Set(e);if(t.existsSync(this.localInstancesRoot)){se(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??ne,s=[];for(const r of t.readdirSync(e.trashRoot,{withFileTypes:!0})){const o=ie(e.trashRoot,r.name);try{const e=Number(r.name.split("-",1)[0]);if(!Number.isFinite(e)||e+i>n)continue;const a=t.lstatSync(o);a.isSymbolicLink()?t.unlinkSync(o):a.isDirectory()?t.rmSync(o,{recursive:!0,force:!0}):t.unlinkSync(o),s.push(o)}catch(t){e.logger?.("retired persistence entry cleanup failed",{path:o,error:t instanceof Error?t.message:String(t)})}}return s}({trashRoot:this.localInstancesTrashRoot,retentionMs:this.options.retentionMs??ne,nowMs:this.now(),logger:this.options.logger})}capActiveInstanceLogs(e){for(const t of e)this.capControlledInstanceLogs(t)}capNodeAgentLogs(){const e=[];for(const t of["node-agent.out.log","node-agent.err.log"]){const i=n.join(this.logsDir,t);try{ea(i)&&e.push(i)}catch(e){this.options.logger?.("node-agent log rotation failed",{filePath:i,error:e instanceof Error?e.message:String(e)})}}return e}capControlledInstanceLogs(e){const t=n.resolve(this.localInstancesRoot,e);if(n.dirname(t)!==n.resolve(this.localInstancesRoot))return[];const i=n.join(t,"logs"),s=[];for(const t of["controlled-instance.out.log","controlled-instance.err.log"]){const r=n.join(i,t);try{ea(r)&&s.push(r)}catch(t){this.options.logger?.("controlled instance log rotation failed",{instanceId:e,filePath:r,error:t instanceof Error?t.message:String(t)})}}return s}retire(e){try{return function(e){const n=ie(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}`);se(e.trashRoot);const s=e.nowMs??Date.now();let r=0,o=`${s}-${e.entryName}`;for(;t.existsSync(ie(e.trashRoot,o));)r+=1,o=`${s}-${r}-${e.entryName}`;const a=ie(e.trashRoot,o);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 na(e,t=process.platform){const i=n.resolve(e),s=d.createHash("sha256").update(i).digest("hex").slice(0,16);return"win32"===t?`\\\\.\\pipe\\task-handoff-node-agent-${s}`:n.join("/tmp",`task-handoff-node-agent-${process.getuid?.()??"user"}`,`${s}.sock`)}async function ia(e,t,n={}){const s=n.method||"GET",r="string"==typeof n.body||n.body instanceof Buffer?n.body:void 0===n.body||null===n.body?void 0:String(n.body),o=new Headers(n.headers||{});return void 0===r||o.has("content-length")||o.set("content-length",String(Buffer.byteLength(r))),new Promise((a,c)=>{const d=i.request({socketPath:e,method:s,path:`/api/node-agent${t}`,headers:Object.fromEntries(o.entries())},e=>{const t=e.statusCode||500;a(new Response("HEAD"!==s&&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!==r&&d.write(r),d.end()})}const sa="runtime-manifest.json";class ra 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 oa(e,t=""){const i=[],s=await g.readdir(n.join(e,t),{withFileTypes:!0});for(const r of s){const s=t?n.posix.join(t,r.name):r.name;if(!t&&s===sa)continue;const o=n.join(e,...s.split("/"));if(r.isDirectory()){i.push(...await oa(e,s));continue}if(r.isSymbolicLink()){const t=await g.readlink(o);if(n.isAbsolute(t))throw new ra("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload symlink is absolute: ${s}`);const r=n.resolve(n.dirname(o),t),a=n.relative(n.resolve(e),r);if(!a||".."===a||a.startsWith(`..${n.sep}`)||n.isAbsolute(a))throw new ra("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload symlink escapes the artifact: ${s}`);if(!await g.lstat(r).catch(()=>{}))throw new ra("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload symlink is broken: ${s}`);i.push({absolutePath:o,relativePath:s,kind:"symlink",target:t,size:Buffer.byteLength(t)});continue}if(!r.isFile())throw new ra("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload contains unsupported entry: ${s}`);const a=await g.lstat(o);i.push({absolutePath:o,relativePath:s,kind:"file",size:a.size})}return i}async function aa(e){const n=(await oa(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 ca(e){for(const[t,n]of[["version",e.version],["platform",e.platform],["arch",e.arch]])if(!/^[0-9A-Za-z._-]+$/.test(n))throw new ra("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Invalid runtime artifact ${t}: ${n}`);return`${e.version}-${e.platform}-${e.arch}`}function da(e,t){return`${ca(e)}-${e.sha256}-${t}`}async function la(e){const n=d.createHash("sha256");for await(const i of t.createReadStream(e))n.update(i);return n.digest("hex")}class ua{#e;#t;#n=new Map;constructor(e){this.#e=e.cacheDir,this.#t=e.fetchImpl??fetch}resolve(e,t){const n=zi.parse(e);if(!/^[a-f0-9]{64}$/.test(t.archiveSha256))throw new ra("INSTANCE_RUNTIME_ARTIFACT_INVALID","Runtime archive SHA-256 is invalid.");if((t.archiveUrl?1:0)+(t.archivePath?1:0)!=1)throw new ra("INSTANCE_RUNTIME_ARTIFACT_INVALID","Runtime artifact source must specify exactly one archive location.");const i=da(n,t.archiveSha256),s=this.#n.get(i);if(s)return s;const r=this.#i(n,t).finally(()=>this.#n.delete(i));return this.#n.set(i,r),r}async#i(e,i){if(!/^[a-f0-9]{64}$/.test(i.archiveSha256))throw new ra("INSTANCE_RUNTIME_ARTIFACT_INVALID","Runtime archive SHA-256 is invalid.");const s=da(e,i.archiveSha256),r=n.join(this.#e,"archives"),o=n.join(r,`${s}.tar.gz`);if(await g.mkdir(r,{recursive:!0}),await this.#s(o,e,i.archiveSha256))return{identity:e,archivePath:o,cacheHit:!0};await g.rm(o,{force:!0});const a=n.join(r,`.${s}.${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 ra("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 la(a)!==i.archiveSha256)throw new ra("INSTANCE_RUNTIME_ARTIFACT_INVALID","Downloaded runtime archive SHA-256 does not match release metadata.");return await this.#r(a,e),await g.rename(a,o),{identity:e,archivePath:o,cacheHit:!1}}catch(e){if(e instanceof ra)throw e;throw new ra("INSTANCE_RUNTIME_ARTIFACT_UNAVAILABLE","Could not download runtime artifact.",{cause:e,retryable:!0})}finally{await g.rm(a,{force:!0})}}async#s(e,t,n){try{return await la(e)===n&&(await this.#r(e,t),!0)}catch{return!1}}async#r(e,t){const i=n.join(this.#e,"validation",`${ca(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 ra("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime archive entry escapes the artifact root: ${e}`);const s=t.type;if("File"!==s&&"OldFile"!==s&&"Directory"!==s&&"SymbolicLink"!==s)throw new ra("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime archive contains unsupported entry type ${s??"unknown"}: ${e}`);return!0}})}catch(e){throw new ra("INSTANCE_RUNTIME_ARTIFACT_INVALID","Could not extract runtime artifact safely.",{cause:e})}}(e,i),await async function(e,t,i){const s=await async function(e){let t;try{t=JSON.parse(await g.readFile(n.join(e,sa),"utf8"))}catch(e){throw new ra("INSTANCE_RUNTIME_ARTIFACT_INVALID","Runtime artifact manifest is missing or invalid JSON.",{cause:e})}const i=nr(zi,t);if(!i.success)throw new ra("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 ra("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime artifact ${"sha256"===n?"SHA-256":n} mismatch: expected ${t[n]}, got ${e[n]}.`)}(s,t),1!==s.formatVersion)throw new ra("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Unsupported runtime artifact format ${s.formatVersion}.`);if(i?.platform&&"universal"!==s.platform&&s.platform!==i.platform)throw new ra("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime artifact platform ${s.platform} does not match ${i.platform}.`);if(i?.arch&&"universal"!==s.arch&&s.arch!==i.arch)throw new ra("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime artifact architecture ${s.arch} does not match ${i.arch}.`);if(void 0!==i?.launcherAbi&&s.launcherAbi>i.launcherAbi)throw new ra("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Runtime requires launcher ABI ${s.launcherAbi}, but the base runtime provides ${i.launcherAbi}.`);const r=function(e,t){if(!e||e.includes("\\")||n.posix.isAbsolute(e))throw new ra("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 ra("INSTANCE_RUNTIME_ARTIFACT_INVALID",`${t} escapes the runtime root.`);return i}(s.entrypoint,"Runtime entrypoint"),o=await g.lstat(n.join(e,...r.split("/"))).catch(()=>{});if(!o?.isFile())throw new ra("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime entrypoint is missing: ${r}`);const a=await aa(e);if(a!==s.sha256)throw new ra("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload SHA-256 mismatch: expected ${s.sha256}, got ${a}.`);return s}(i,t,{platform:t.platform,arch:t.arch})}finally{await g.rm(i,{recursive:!0,force:!0})}}}async function pa(e,t,i,s=fetch){if("linux"!==t||!["x64","arm64"].includes(i))throw new ra("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Managed controlled-instance updates require a Linux x64 or arm64 target, received ${t}/${i}.`);const r=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[s,r]=await Promise.all([g.readFile(n.join(i,`${t}.manifest.json`),"utf8"),g.readFile(n.join(i,`${t}.tar.gz.sha256`),"utf8")]),o=nr(zi,JSON.parse(s));if(!o.success||o.data.version!==e||"linux"!==o.data.platform||"universal"!==o.data.arch)throw new ra("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Bundled controlled-instance ${e} has an invalid Linux manifest.`);const a=r.trim().split(/\s+/)[0]?.toLowerCase();if(!a||!/^[a-f0-9]{64}$/.test(a))throw new ra("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Bundled controlled-instance ${e} has an invalid archive checksum.`);return{identity:o.data,source:{archivePath:n.join(i,`${t}.tar.gz`),archiveSha256:a}}}catch(t){if("ENOENT"===t.code)return;if(t instanceof ra)throw t;throw new ra("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Could not read bundled controlled-instance ${e}.`,{cause:t})}}(e);if(r)return r;const o=`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}/${o}.manifest.json`,d=`${a}/${o}.tar.gz`,l=`${a}/${o}.tar.gz.sha256`,[u,p]=await Promise.all([s(c),s(l)]).catch(t=>{throw new ra("INSTANCE_RUNTIME_ARTIFACT_UNAVAILABLE",`Could not read release metadata for controlled-instance ${e}.`,{cause:t,retryable:!0})});if(!u.ok||!p.ok)throw new ra("INSTANCE_RUNTIME_ARTIFACT_UNAVAILABLE",`Release metadata for controlled-instance ${e} is unavailable (manifest HTTP ${u.status}, checksum HTTP ${p.status}).`,{retryable:u.status>=500||p.status>=500});let m;try{m=await u.json()}catch(t){throw new ra("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Release manifest for controlled-instance ${e} is not valid JSON.`,{cause:t})}const h=nr(zi,m);if(!h.success)throw new ra("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 ra("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Release identity mismatch: requested ${e}-linux-universal, received ${h.data.version}-${h.data.platform}-${h.data.arch}.`);const f=(await p.text()).trim().split(/\s+/)[0]?.toLowerCase();if(!f||!/^[a-f0-9]{64}$/.test(f))throw new ra("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Release checksum for controlled-instance ${e} is invalid.`);return{identity:h.data,source:{archiveUrl:d,archiveSha256:f}}}class ma{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=wa(i.retryBaseDelayMs??1e3,"retryBaseDelayMs"),this.retryMaxDelayMs=wa(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 s=Promise.resolve().then(()=>this.reconcile(e,n)).finally(()=>{this.inFlight.delete(e),this.requests.delete(e)});return this.inFlight.set(e,s),s}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");if(fa(n))return this.storePhase(n,"pending");const s=n.runtimeVersion?.desiredVersion!==i||t.startRequested||ya(n)?0:this.remainingRetryDelayMs(n.runtimeVersion);if(s>0&&(await this.delay(s),n=this.requireInstance(e),this.cancelled.has(e)))return this.storePhase(n,"pending");const r=ha(n),o=r===i&&(await(this.hooks.isInstalled?.(n,i))??!0);if(this.cancelled.has(e))return this.storePhase(this.requireInstance(e),"pending");if(r===i&&o)return this.storeState(n,{desiredVersion:i,actualVersion:r,phase:"matched",attempt:n.runtimeVersion?.attempt||0,matchedAt:this.timestamp()},!ya(n)&&"failed"!==n.health);if(n=this.storeState(n,function(e,t,n,i=!1){const s=e.runtimeVersion,r=s?.desiredVersion===t&&"matched"!==s.phase;return{desiredVersion:t,...n?{actualVersion:n}:{},phase:"pending",attempt:r?s.attempt:0,error:(r?s.error:void 0)||(n!==t||i?Ia(t,n):Aa("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,r,o)),ya(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 s;try{if(n=this.storePhase(n,"draining"),await(this.hooks.beginDrain?.(n)),a=!0,n=this.requireInstance(e),ga(n)){const t=await this.waitUntil(e,this.drainTimeoutMs,e=>!ga(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)||ya(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 s=await this.waitUntil(e,this.verificationTimeoutMs,e=>ha(e)===i);if(this.cancelled.has(e))return this.storePhase(this.requireInstance(e),"pending");if(!s)throw Aa("INSTANCE_RUNTIME_VERIFICATION_FAILED",`Instance ${e} did not register controlled-instance ${i} after restart.`,i,ha(this.requireInstance(e)),!0);const r=this.requireInstance(e);if(this.hooks.isInstalled&&!await this.hooks.isInstalled(r,i))throw Aa("INSTANCE_RUNTIME_VERIFICATION_FAILED",`Instance ${e} reported controlled-instance ${i}, but its active runtime release is missing.`,i,ha(r),!0);return this.storeState(r,{desiredVersion:i,actualVersion:i,phase:"matched",attempt:r.runtimeVersion?.attempt||1,matchedAt:this.timestamp()},!ya(r)&&"failed"!==r.health)}catch(t){if(this.cancelled.has(e))return this.storePhase(this.requireInstance(e),"pending");s=ba(t,i,ha(this.store.get(e)))}n=this.requireInstance(e);const r=n.runtimeVersion?.attempt||1;if(!s.retryable||c>=this.maxAttempts)return this.storeBatchFailure(n,i,r>=this.maxAttempts&&s.retryable?va(i,ha(n),this.maxAttempts,s):s);n=this.storeState(n,{desiredVersion:i,...ha(n)?{actualVersion:ha(n)}:{},phase:"pending",attempt:r,lastAttemptAt:this.timestamp(),error:s}),await this.delay(this.retryDelayMs(r))}return this.storeBatchFailure(n,i,va(i,ha(n),this.maxAttempts,n.runtimeVersion?.error))}finally{a&&await(this.hooks.endDrain?.(this.requireInstance(e)))}}storeBatchFailure(e,t,n){const i=ha(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(),s=ha(e),r=e.runtimeVersion?.desiredVersion===i?e.runtimeVersion.error:void 0;return this.storeState(e,{desiredVersion:i,...s?{actualVersion:s}:{},phase:t,attempt:(e.runtimeVersion?.attempt||0)+(n?1:0),lastAttemptAt:this.timestamp(),...r?{error:r}:"pending"===t?{error:Ia(i,s)}:{}},"restarting"!==t&&void 0)}storeState(e,t,n){const i=this.store.get(e.id)||e;return this.store.put(Bs.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 ha(e){return e?.build?.packageVersion||e?.instanceVersion}function ga(e){return e.apps.runningCount>0||e.aiSessions.runningCount>0}function fa(e){return Boolean(e.imageProvisioning&&"ready"!==e.imageProvisioning.phase)}function ya(e){return["created","stopped","failed"].includes(e.status)}function Ia(e,t){return Aa("INSTANCE_RUNTIME_VERSION_MISMATCH",`Expected controlled-instance ${e}, received ${t||"an unknown version"}.`,e,t,!0)}function Aa(e,t,n,i,s){return{code:e,message:t,expectedVersion:n,...i?{actualVersion:i}:{},retryable:s}}function ba(e,t,n){if(e&&"object"==typeof e&&"code"in e&&"message"in e){const i=e,s=Ni.shape.code.safeParse(i.code);if(s.success&&"string"==typeof i.message)return Aa(s.data,i.message,t,n,"boolean"!=typeof i.retryable||i.retryable)}return Aa("INSTANCE_RUNTIME_INSTALL_FAILED",e instanceof Error?e.message:String(e),t,n,!0)}function va(e,t,n,i){const s=i?.message?` Last error: ${i.message}`:"";return Aa(i?.code||"INSTANCE_RUNTIME_INSTALL_FAILED",`Runtime convergence paused after ${n} attempts and will retry.${s}`,e,t,!0)}function wa(e,t){if(!Number.isFinite(e)||e<0)throw new TypeError(`${t} must be a nonnegative finite number.`);return e}function Sa(e,n=448){t.mkdirSync(e,{recursive:!0,mode:n}),t.chmodSync(e,n)}function Ea(e,i,s={}){const r=s.directoryMode??448,o=s.fileMode??384;Sa(n.dirname(e),r),I.sync(e,`${JSON.stringify(i,null,2)}\n`,{encoding:"utf8",mode:o}),t.chmodSync(e,o)}function za(e,t){console.warn(JSON.stringify({message:e,...t}))}function Na(e){return e&&"object"==typeof e&&"issues"in e?{issues:e.issues}:{error:e instanceof Error?e.message:String(e)}}function Ta(e,n){const i=n.logger||za;let s;try{s=JSON.parse(t.readFileSync(e,"utf8"))}catch(t){return void i("stored JSON could not be read",{filePath:e,...Na(t)})}if(!n.schema)return s;const r=n.sanitize?n.sanitize(s):s,o=n.schema.safeParse(r);if(o.success)return o.data;const a="strip"in n.schema&&"function"==typeof n.schema.strip?n.schema.strip().safeParse(r):void 0;if(a?.success)return i("unknown stored fields were ignored",{filePath:e,issues:o.error.issues}),a.data;i("stored record failed validation and was isolated",{filePath:e,issues:o.error.issues})}function _a(e){return`${e}_${d.randomUUID().replace(/-/g,"").slice(0,20)}`}function ka(){return d.randomBytes(24).toString("base64url")}class Ca{directory;options;permissionsInitialized=!1;constructor(e,t={}){this.directory=e,this.options=t}init(){if(this.permissionsInitialized&&t.existsSync(this.directory))return;Sa(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=Ta(n.join(this.directory,e),this.options);return t?[t]:[]})}get(e){this.init();const n=this.filePath(e);return t.existsSync(n)?Ta(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 Ea(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 Oa{filePathValue;defaults;options;constructor(e,t,n={}){this.filePathValue=e,this.defaults=t,this.options=n}init(){Sa(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)?Ta(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 Ea(this.filePathValue,n,this.options),n}}const xa=a.z.record(a.z.string(),a.z.string()),Ra=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 Pa{directory;constructor(e){this.directory=e}get(e){try{return xa.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=xa.parse(n);t.mkdirSync(this.directory,{recursive:!0,mode:448});const s=this.filePath(e);return I.sync(s,`${JSON.stringify(i,null,2)}\n`,{encoding:"utf8",mode:384}),t.chmodSync(s,384),i}delete(e){t.rmSync(this.filePath(e),{force:!0})}filePath(e){return n.join(this.directory,`${e}.json`)}}class Da{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=Gi.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")),s=n.basename(e,".json"),r=Gi.safeParse(i);if(r.success&&r.data.id===s&&ss(r.data)===r.data.id)return r.data;const o=Gi.strip().safeParse(i);return o.success&&o.data.id===s&&ss(o.data)===o.data.id?(console.warn(JSON.stringify({message:"unknown stored node model fields were ignored",nodeId:this.nodeId,filePath:e})),o.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 Ma{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")),s=Yi.safeParse(i);if(s.success)return s.data;const r=i&&"object"==typeof i&&!Array.isArray(i)?i:{},o=Yi.safeParse({instanceId:r.instanceId,modelEntityIds:r.modelEntityIds,codexModelHash:r.codexModelHash,claudeModelHash:r.claudeModelHash,opencodeModelHash:r.opencodeModelHash,updatedAt:r.updatedAt});if(o.success)return console.warn(JSON.stringify({message:"unknown stored model assignment fields were ignored",instanceId:e,filePath:n})),o.data;throw s.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=Yi.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`)}}const ja=a.z.enum(["openai-responses","openai-chat-completions","anthropic-messages"]),La=a.z.object({protocolVersion:a.z.literal("2026-08-27"),instanceId:a.z.string().trim().min(1).max(120),entities:a.z.array(a.z.object({id:a.z.string().trim().min(1).max(120),endpoint:a.z.string().trim().min(1).max(2048),key:a.z.string().trim().min(1).max(4096),protocols:a.z.array(ja).min(1).max(3),modelNames:a.z.array(a.z.object({name:a.z.string().trim().min(1).max(240),order:a.z.number().int().min(0).max(1e6)}).strip()).min(1).max(256)}).strip()).max(64),updatedAt:a.z.string().datetime()}).strip();function Fa(e){if(!e||"object"!=typeof e||Array.isArray(e))return e;const t=e;return{protocolVersion:t.protocolVersion,instanceId:t.instanceId,entities:Array.isArray(t.entities)?t.entities.map(e=>{if(!e||"object"!=typeof e||Array.isArray(e))return e;const t=e;return{id:t.id,endpoint:t.endpoint,key:t.key,protocols:t.protocols,modelNames:Array.isArray(t.modelNames)?t.modelNames.map(e=>{if(!e||"object"!=typeof e||Array.isArray(e))return e;const t=e;return{name:t.name,order:t.order}}):t.modelNames}}):t.entities,updatedAt:t.updatedAt}}class $a{models;assignments;legacyEnvironments;nodeId;instances;constructor(e,t,n){this.nodeId=t,this.instances=n,this.models=new Da(e.nodeModelsDir,t),this.assignments=new Ma(e.modelAssignmentsDir),this.legacyEnvironments=new Pa(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 new Set([...n?.modelEntityIds||[],n?.codexModelHash,n?.claudeModelHash,n?.opencodeModelHash]))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=te(),n=Va(e.modelNames,e.model),i={...e,model:n[0].name,modelNames:n,protocols:e.protocols?.length?e.protocols:Ha(e.app)},s=ss(i),r=this.models.get(s),o=Gi.parse({...i,id:s,enabled:e.enabled??!0,order:e.order??this.nextOrder(),labels:e.labels||{},createdAt:r?.createdAt||t,updatedAt:t});return this.toPublic(this.models.put(o),this.referenceIds(s).length)}deploy(e){const t=ss(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=Va(e.modelNames,e.model),i=this.models.get(e.id)||this.models.put(Gi.parse({...e,model:n[0].name,modelNames:n,protocols:e.protocols?.length?e.protocols:Ha(e.app)}));return this.toPublic(i,this.referenceIds(i.id).length)}update(e,t){const n=this.requireModel(e),i=t.modelNames?.length?Va(t.modelNames,t.model||n.model):t.model?Va(void 0,t.model):Va(n.modelNames,n.model),s=t.protocols?.length?t.protocols:n.protocols?.length?n.protocols:Ha(t.app||n.app),r=Gi.parse({...n,...t,key:t.key?.trim()?t.key:n.key,protocols:s,model:i[0].name,modelNames:i,createdAt:n.createdAt,updatedAt:te()}),o=ss(r),a=this.models.put(Gi.parse({...r,id:o}));return this.toPublic(a,this.referenceIds(o).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)}resolveProbeKey(e,t){const n=t?.trim()||(e?this.requireModel(e).key:"");if(!n)throw Object.assign(new Error("An API key is required to contact the model endpoint."),{statusCode:400,code:"MODEL_API_KEY_REQUIRED"});return n}assign(e,t){const n=this.instances.require(e);for(const e of t.modelEntityIds)this.validateEntityRef(e);if(void 0!==t.modelSelection.modelEntityIds&&JSON.stringify(t.modelSelection.modelEntityIds)!==JSON.stringify(t.modelEntityIds))throw Object.assign(new Error("Ordered model entity selection does not match its node assignment."),{statusCode:400,code:"NODE_MODEL_SELECTION_MISMATCH"});if(this.validateRef("codex",t.codexModelHash),this.validateRef("claude",t.claudeModelHash),this.validateRef("opencode",t.opencodeModelHash),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"});if(void 0!==t.modelSelection.opencodeModelHash&&(t.modelSelection.opencodeModelHash??void 0)!==t.opencodeModelHash)throw Object.assign(new Error("OpenCode model selection does not match its node assignment."),{statusCode:400,code:"NODE_MODEL_SELECTION_MISMATCH"});const i=this.assignments.get(e),s=Yi.parse({instanceId:e,modelEntityIds:t.modelEntityIds,codexModelHash:t.codexModelHash,claudeModelHash:t.claudeModelHash,opencodeModelHash:t.opencodeModelHash,updatedAt:te()});this.assignments.put(s);try{return{assignment:s,instance:this.instances.put(Bs.parse({...n,modelSelection:t.modelSelection,updatedAt:te()}))}}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{}}const n=e=>t.modelEntityIds.find(t=>this.modelSupportsApp(this.requireModel(t),e));return{...this.environmentForRef("codex",n("codex")||t.codexModelHash),...this.environmentForRef("claude",n("claude")||t.claudeModelHash),...this.environmentForOpenCode(t)}}privateCatalog(e){const t=this.assignments.get(e);return La.parse({protocolVersion:"2026-08-27",instanceId:e,entities:(t?.modelEntityIds||[]).map(e=>{const t=this.requireModel(e);return this.validateEntityRef(e),{id:t.id,endpoint:t.endpoint,key:t.key,protocols:t.protocols?.length?t.protocols:Ha(t.app),modelNames:Va(t.modelNames,t.model)}}),updatedAt:t?.updatedAt||te()})}deleteInstanceMetadata(e){this.assignments.delete(e),this.legacyEnvironments.delete(e)}validateRef(e,t){if(!t)return;const n=this.requireModel(t);if(!this.modelSupportsApp(n,e))throw Object.assign(new Error(`Model ${n.id} does not support the ${e} runtime protocol.`),{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"})}modelSupportsApp(e,t){const n="claude"===t?"anthropic-messages":"opencode"===t?"openai-chat-completions":"openai-responses";return e.protocols?.length?e.protocols.includes(n):e.app===t}validateEntityRef(e){const t=this.requireModel(e);if(!t.enabled)throw Object.assign(new Error(`Model ${t.id} is disabled.`),{statusCode:409,code:"NODE_MODEL_DISABLED"});if(!t.protocols?.length&&!Ha(t.app).length)throw Object.assign(new Error(`Model ${t.id} does not expose a supported protocol.`),{statusCode:400,code:"NODE_MODEL_PROTOCOL_UNSUPPORTED"})}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}:"claude"===e?{ANTHROPIC_API_KEY:n.key,ANTHROPIC_BASE_URL:n.endpoint,TASK_HANDOFF_CLAUDE_MODEL:n.model}:{TASK_HANDOFF_OPENCODE_CONFIG_CONTENT:JSON.stringify({$schema:"https://opencode.ai/config.json",model:`task-handoff/${n.model}`,provider:{"task-handoff":{npm:"@ai-sdk/openai-compatible",name:"TaskHandoff",options:{baseURL:n.endpoint,apiKey:n.key},models:{[n.model]:{name:n.name,variants:Ua()}}}}})}}environmentForOpenCode(e){if(e.opencodeModelHash)return this.environmentForRef("opencode",e.opencodeModelHash);const t=e.modelEntityIds.map(e=>this.requireModel(e)).filter(e=>this.modelSupportsApp(e,"opencode"));if(!t.length)return{};const n=t[0],i=Va(n.modelNames,n.model)[0].name,s=Object.fromEntries(t.map(e=>[`task-handoff-${e.id}`,{npm:"@ai-sdk/openai-compatible",name:e.name,options:{baseURL:e.endpoint,apiKey:e.key},models:Object.fromEntries(Va(e.modelNames,e.model).map(t=>[t.name,{name:e.name,variants:Ua()}]))}]));return{TASK_HANDOFF_OPENCODE_CONFIG_CONTENT:JSON.stringify({$schema:"https://opencode.ai/config.json",model:`task-handoff-${n.id}/${i}`,provider:s})}}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(ss(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?.modelEntityIds.includes(e)||n?.codexModelHash===e||n?.claudeModelHash===e||n?.opencodeModelHash===e}).map(e=>e.id)}toPublic(e,t){const{key:n,...i}=e;return Ji.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=>!Ra.has(e))){this.warnMigration(e,"unknown-fields");continue}const n=[];try{const i=this.migrateApp(t,"codex",n),s=this.migrateApp(t,"claude",n);if(!i&&!s)throw new Error("no complete model configuration");const r=[...new Set([i,s].filter(e=>Boolean(e)))],o={modelEntityIds:r,...i?{codexModelHash:i}:{},...s?{claudeModelHash:s}:{}};this.assign(e,{modelSelection:o,modelEntityIds:r,codexModelHash:i,claudeModelHash:s}),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"],s="codex"===t?e.TASK_HANDOFF_CODEX_BASE_URL||e.OPENAI_BASE_URL:e.ANTHROPIC_BASE_URL,r="codex"===t?e.TASK_HANDOFF_CODEX_MODEL||e.CODEX_MODEL:e.TASK_HANDOFF_CLAUDE_MODEL||e.CLAUDE_MODEL;if(!i&&!s&&!r)return;if(!i||!s||!r)throw new Error("model configuration incomplete");const o=ss({app:t,endpoint:s,key:i,model:r}),a=this.models.get(o);if(a){if(a.app!==t||a.key!==i||a.endpoint!==s||a.model!==r||!a.enabled)throw new Error("existing model conflicts with legacy environment");return o}const c=te();return this.models.put(Gi.parse({id:o,name:`Migrated ${"codex"===t?"Codex":"Claude"} model`,endpoint:s,key:i,model:r,app:t,enabled:!0,order:this.nextOrder(),labels:{migratedFrom:"instance-model-environment"},createdAt:c,updatedAt:c})),n.push(o),o}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 Ua(){return Object.fromEntries(["none","minimal","low","medium","high","xhigh","max","ultra"].map(e=>[e,{reasoningEffort:e}]))}function Ha(e){return"claude"===e?["anthropic-messages"]:"opencode"===e?["openai-chat-completions"]:["openai-responses"]}function Va(e,t){const n=e?.length?e:[{name:t,order:100}],i=new Set;return n.map(e=>({name:e.name.trim(),order:e.order})).filter(e=>!(!e.name||i.has(e.name)||(i.add(e.name),0))).sort((e,t)=>e.order-t.order||e.name.localeCompare(t.name)).map((e,t)=>({name:e.name,order:100*(t+1)}))}function Ba(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 qa(){return process.env.TASK_HANDOFF_NPM_COMMAND||"npm"}function Ka(e,i){const s=n.join(e,...i.split("/"),"package.json");try{const e=JSON.parse(t.readFileSync(s,"utf8"));if(e.name!==i||"string"!=typeof e.version||!e.version.trim())throw new Error(`Installed package manifest is invalid: ${s}`);return{name:i,version:e.version.trim()}}catch(e){if("ENOENT"===e.code)return;throw e}}async function Ga(e,i){const s=i?function(e){const i=function(e){let t=n.resolve(e);for(;t!==n.dirname(t);){if("node_modules"===n.basename(t)&&"lib"===n.basename(n.dirname(t)))return n.dirname(n.dirname(t));t=n.dirname(t)}}(e);if(!i)return;let s,r=n.resolve(e);for(;r!==n.dirname(r);){try{const e=JSON.parse(t.readFileSync(n.join(r,"package.json"),"utf8"));if("@task-handoff/node-agent"===e.name&&"string"==typeof e.version&&e.version.trim()&&(s=e.version.trim()),"@task-handoff/server"===e.name&&"string"==typeof e.version&&e.version.trim())return{packageName:"@task-handoff/server",currentVersion:e.version.trim(),relatedCurrentVersions:s?[s]:[],installPrefix:i}}catch(e){if("ENOENT"!==e.code)throw e}r=n.dirname(r)}return s?{packageName:"@task-handoff/node-agent",currentVersion:s,relatedCurrentVersions:[],installPrefix:i}:void 0}(i):void 0;if(s)return s;const r=(await e(qa(),["root","--global"])).stdout.trim();if(!r)throw new Error("npm did not return its global module root.");const o=(await e(qa(),["prefix","--global"])).stdout.trim();if(!n.isAbsolute(o))throw new Error(`npm did not return an absolute global prefix: ${o||"empty"}`);const a=Ka(r,"@task-handoff/server"),c=Ka(r,"@task-handoff/node-agent");return a?{packageName:"@task-handoff/server",currentVersion:a.version,relatedCurrentVersions:c?[c.version]:[],installPrefix:o}:{packageName:"@task-handoff/node-agent",currentVersion:c?.version,relatedCurrentVersions:[],installPrefix:o}}function Wa(e){if(!e||"object"!=typeof e||Array.isArray(e))return e;const t=e,n="string"==typeof t.updatedAt?t.updatedAt:te(),i=t.target&&"object"==typeof t.target&&!Array.isArray(t.target)?t.target:void 0,s="controlled-instance"===i?.component,r={updating:"updating-node",downloading:"updating-node",installing:"updating-node",restarting:"restarting-node",completed:"succeeded",success:"succeeded",error:"failed"},o=new Set(["queued","updating-node","restarting-node","converging-instances","succeeded","degraded","failed"]),a="string"==typeof t.status?t.status:"queued",c=s?"failed":o.has(a)?a:r[a]||"failed",d="string"==typeof t.toVersion&&t.toVersion?t.toVersion:"unknown",l=_i.strip().safeParse(t.impact).success?_i.strip().parse(t.impact):{runningInstanceCount:0,stoppedInstanceCount:0,activeInstanceCount:0,restartInstanceCount:0,runningInstanceIds:[],stoppedInstanceIds:[],activeInstanceIds:[]},u=s?{code:"LEGACY_INSTANCE_UPDATE_RETIRED",message:"Independent controlled-instance update jobs were retired in favor of Node reconciliation.",retryable:!1}:"failed"!==c||t.error||o.has(a)||a in r?"string"==typeof t.error?{code:"NODE_UPDATE_FAILED",message:t.error,retryable:!1}:Ni.strip().safeParse(t.error).success?Ni.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:p,error:m,...h}=t,g={phase:"succeeded"===c?"succeeded":"failed"===c?"failed":c||"queued",desiredVersion:d,expectedInstanceIds:[],expectedInstanceCount:0,matchedInstanceCount:0,pendingInstanceCount:0,failedInstanceCount:s||"failed"===c?1:0,deferredInstanceCount:0},f=ki.strip().safeParse(t.rollout);return{...h,source:"npm",status:c,impact:l,runtimeArtifacts:Array.isArray(t.runtimeArtifacts)?t.runtimeArtifacts.flatMap(e=>{const t=zi.strip().safeParse(e);return t.success?[t.data]:[]}):[],rollout:f.success?f.data:g,...u?{error:u}:{},...s?{completedAt:t.completedAt||n}:{}}}class Ja{records;constructor(e){this.records=new Ca(e.updatesDir,{schema:xi,sanitize:Wa})}init(){this.records.init()}list(){return this.records.list().sort((e,t)=>t.createdAt.localeCompare(e.createdAt))}create(e,t){const n=te();return this.records.put(xi.parse({id:_a("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(xi.parse({...n,...t,id:e,createdAt:n.createdAt,updatedAt:te()}))}reconcileRollouts(e,t,n={}){const i=new Map(e.map(e=>[e.id,e]));if(n.processStarted)for(const e of this.list().filter(e=>"queued"===e.status))this.patch(e.id,{status:"failed",rollout:{...e.rollout,phase:"failed"},error:{code:"NODE_UPDATE_FAILED",message:"The node agent restarted before the update worker claimed this job.",retryable:!0},completedAt:te()});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:te()});continue}const s="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"!==s.status)continue;const r=s.rollout.expectedInstanceIds,o=r.map(e=>i.get(e)),a=o.filter(e=>e?.ready&&"matched"===e.runtimeVersion?.phase&&e.runtimeVersion.actualVersion===s.toVersion).length,c=o.filter(e=>e&&["created","stopped","failed"].includes(e.status||"")&&"failed"!==e.runtimeVersion?.phase).length,d=o.filter(e=>!e||"failed"===e.runtimeVersion?.phase).length,l=Math.max(0,r.length-a-d-c),u=d>0?"degraded":0===l?"succeeded":"converging-instances";this.patch(s.id,{status:u,rollout:{...s.rollout,phase:u,nodeVersion:t,expectedInstanceCount:r.length,matchedInstanceCount:a,pendingInstanceCount:l,failedInstanceCount:d,deferredInstanceCount:s.impact.stoppedInstanceCount+c},..."succeeded"===u||"degraded"===u?{completedAt:te()}:{}})}}run(e,t){(async()=>{this.patch(e.id,{status:"updating-node",rollout:{...e.rollout,phase:"updating-node"},startedAt:te(),error:void 0});try{await t(e),this.patch(e.id,{status:"succeeded",completedAt:te()})}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:te()})}})()}}class Ya{records;constructor(e){this.records=new Ca(e.environmentTemplatesDir,{schema:ci,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"]),s="string"==typeof n.id?n.id:void 0;for(const e of Object.keys(n))i.has(e)||t?.({templateId:s,field:e});const r=Qs(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:s,field:`error.${n}`});r.error=Qs(e,["code","message","phase"])}return r}(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(ci.parse({...e,status:"failed",error:{code:"ENVIRONMENT_TEMPLATE_CREATION_INTERRUPTED",message:"Environment template creation was interrupted by a node-agent restart.",phase:"recovery"},updatedAt:te()}))}list(){return this.records.list()}get(e){return this.records.get(e)}put(e){return this.records.put(ci.parse(e))}patch(e,t){return this.records.patch(e,t)}delete(e){return this.records.delete(e)}}const Xa=a.z.record(a.z.string().regex(/^[A-Za-z_][A-Za-z0-9_]*$/),a.z.string()),Qa=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:Xa,modelCatalog:La.optional(),updatedAt:a.z.string().datetime()}).strict();class Za{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")),s=i&&"object"==typeof i&&!Array.isArray(i)?i:{},r=Qa.parse({version:s.version,instanceId:s.instanceId,instanceCredential:s.instanceCredential??s.registrationToken,environment:s.environment,modelCatalog:void 0===s.modelCatalog?void 0:Fa(s.modelCatalog),updatedAt:s.updatedAt});if(r.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===s.instanceCredential&&void 0!==s.registrationToken||void 0!==s.gitCredentials)&&this.put(r),r}put(e){const n=Qa.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,i){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,...i?{modelCatalog:i}:{},updatedAt:(new Date).toISOString()})}delete(e){t.rmSync(this.filePath(e),{force:!0})}}const ec=a.z.string().trim().min(1).max(120).regex(/^[a-zA-Z0-9][a-zA-Z0-9_.:-]*$/),tc=a.z.string().datetime(),nc=a.z.number().int().nonnegative(),ic=a.z.enum(["https-token","ssh-key"]),sc=a.z.enum(["operation-only","instance-retained"]),rc=a.z.enum(["enabled","disabled"]),oc=a.z.enum(["pending","synced","deferred","revoking","revoked"]),ac=a.z.object({scheme:a.z.enum(["https","ssh"]),host:a.z.string().trim().min(1).max(253),port:a.z.number().int().min(1).max(65535).optional(),pathPrefix:a.z.string().min(1).max(2048).default("/")}).strict();function cc(e){throw new Error(`Invalid Git credential scope: ${e}`)}function dc(e){const t=e.trim().replace(/^\[|\]$/g,"");(!t||t.includes("*")||/[/?#@\s]/.test(t))&&cc("host is invalid");try{const e=new URL(t.includes(":")?`http://[${t}]/`:`http://${t}/`).hostname.replace(/^\[|\]$/g,"").toLowerCase();return(!e||e.length>253||e.includes("*"))&&cc("host is invalid"),e}catch{cc("host is invalid")}}function lc(e){try{return decodeURIComponent(e)}catch{cc("path contains invalid percent encoding")}}function uc(e){const t=e?.trim()||"/";(t.includes("?")||t.includes("#")||t.includes("\\")||t.includes("\0"))&&cc("path contains an unsupported delimiter");const n=(t.startsWith("/")?t:`/${t}`).split("/").filter(Boolean);for(const e of n){const t=lc(e);("."===t||".."===t||t.includes("/")||t.includes("\\")||t.includes("\0"))&&cc("path contains an unsafe segment")}return 0===n.length?"/":`/${n.join("/")}/`}function pc(e){const t=ac.parse(e),n="https"===t.scheme?443:22;return ac.parse({scheme:t.scheme,host:dc(t.host),...void 0===t.port||t.port===n?{}:{port:t.port},pathPrefix:uc(t.pathPrefix)})}function mc(e){return uc(e.replace(/\.git\/?$/,""))}const hc=a.z.object({id:ec,name:a.z.string().trim().min(1).max(160),kind:ic,scope:ac,secretSet:a.z.literal(!0),status:rc,revision:nc,createdAt:tc,updatedAt:tc}).strict(),gc=a.z.object({kind:a.z.literal("https-token"),username:a.z.string().trim().min(1).max(240),token:a.z.string().min(1).max(8192)}).strict(),fc=a.z.object({kind:a.z.literal("ssh-key"),privateKey:a.z.string().min(1).max(131072),passphrase:a.z.string().max(8192).optional(),pinnedKnownHosts:a.z.string().min(1).max(131072)}).strict(),yc=a.z.discriminatedUnion("kind",[gc,fc]);a.z.object({name:a.z.string().trim().min(1).max(160),scope:ac,secret:yc}).strict().superRefine((e,t)=>{"https"===e.scope.scheme!=("https-token"===e.secret.kind)&&t.addIssue({code:"custom",path:["scope","scheme"],message:"Credential kind must match the remote scheme."});try{pc(e.scope)}catch(e){t.addIssue({code:"custom",path:["scope"],message:e instanceof Error?e.message:"Invalid Git scope."})}}),a.z.object({name:a.z.string().trim().min(1).max(160).optional(),scope:ac.optional(),secret:yc.optional(),status:rc.optional()}).strict().refine(e=>Object.keys(e).length>0,"At least one credential field must be updated."),a.z.object({items:a.z.array(hc).max(1e4)}).strict();const Ic=a.z.object({instanceId:ec,credentialId:ec,credentialRevision:nc,assignmentRevision:nc,status:oc,authorizedAt:tc,updatedAt:tc}).strict(),Ac=a.z.object({credential:hc,secret:yc}).strict().superRefine((e,t)=>{e.credential.kind!==e.secret.kind&&t.addIssue({code:"custom",path:["secret","kind"],message:"Credential payload kind mismatch."})}),bc=a.z.object({instanceId:ec,generation:nc,credentialIds:a.z.array(ec).max(256).transform(e=>[...new Set(e)].sort()),updatedAt:tc}).strict(),vc=a.z.object({remoteUrl:a.z.string().trim().min(1).max(4096)}).strict(),wc=a.z.discriminatedUnion("status",[a.z.object({status:a.z.literal("ok"),username:a.z.string().min(1).max(240),password:a.z.string().min(1).max(8192)}).strict(),a.z.object({status:a.z.enum(["none","ambiguous","unsupported","missing-host-key","rejected"])}).strict()]),Sc=a.z.object({remoteUrl:a.z.string().trim().min(1).max(4096)}).strict(),Ec=a.z.discriminatedUnion("status",[a.z.object({status:a.z.literal("ok"),invocationId:ec,publicIdentity:a.z.string().min(1).max(131072),pinnedKnownHosts:a.z.string().min(1).max(131072)}).strict(),a.z.object({status:a.z.enum(["none","ambiguous","unsupported","missing-host-key","rejected"])}).strict()]),zc=a.z.object({invocationId:ec,frame:a.z.string().min(1).max(1048576)}).strict(),Nc=a.z.object({frame:a.z.string().min(1).max(1048576)}).strict(),Tc=a.z.object({operationId:ec,retention:sc,payload:Ac}).strict(),_c=a.z.object({operationId:ec,instanceId:ec,remoteUrl:a.z.string().trim().min(1).max(4096),ref:a.z.discriminatedUnion("type",[a.z.object({type:a.z.enum(["branch","tag"]),name:a.z.string().trim().min(1).max(240)}).strict(),a.z.object({type:a.z.literal("commit"),commit:a.z.string().trim().regex(/^[0-9a-fA-F]{4,64}$/,"commit must be a hexadecimal Git object id")}).strict()]),clone: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).refine(e=>!e.startsWith("/")&&!e.split("/").some(e=>".."===e),"subdirectory must be a relative path within the repository").transform(e=>e.split("/").filter(e=>e&&"."!==e).join("/")).default("")}).strict(),credentials:a.z.array(Tc).max(256).default([])}).strict();function kc(e){return e&&"object"==typeof e&&!Array.isArray(e)?e:void 0}function Cc(e,t){if(e)return Object.fromEntries(t.filter(t=>Object.prototype.hasOwnProperty.call(e,t)).map(t=>[t,e[t]]))}function Oc(e){const t=kc(e),n=kc(t?.scope);return hc.safeParse({...Cc(t,["id","name","kind","secretSet","status","revision","createdAt","updatedAt"]),scope:Cc(n,["scheme","host","port","pathPrefix"])})}function xc(e,t){let n;try{n=function(e){const t=e.trim();if(t&&!t.includes("\0")||cc("remote is empty or invalid"),/^https?:\/\//i.test(t)||/^ssh:\/\//i.test(t)){let e;uc(t.replace(/^[a-z][a-z0-9+.-]*:\/\/[^/]+/i,"").split(/[?#]/,1)[0]||"/");try{e=new URL(t)}catch{cc("remote URL is invalid")}"https:"!==e.protocol&&"ssh:"!==e.protocol&&cc("remote scheme is unsupported"),(e.password||"https:"===e.protocol&&e.username)&&cc("HTTPS userinfo is forbidden"),(e.search||e.hash)&&cc("query and fragment are forbidden");const n="https:"===e.protocol?"https":"ssh",i=e.port?Number(e.port):void 0;return{...pc({scheme:n,host:e.hostname,port:i,pathPrefix:mc(e.pathname)}),original:t}}/^[a-z][a-z0-9+.-]*:\/\//i.test(t)&&cc("remote scheme is unsupported");const n=/^(?:([^@/:\s]+)@)?([^/:\s]+):(.+)$/.exec(t);n||cc("remote must use HTTPS, ssh://, or scp-like SSH syntax");const[,,i,s]=n;return(s.includes("?")||s.includes("#"))&&cc("query and fragment are forbidden"),{...pc({scheme:"ssh",host:i,pathPrefix:mc(s)}),original:t}}(e)}catch(e){return{status:"unsupported",reason:e instanceof Error?e.message:"Unsupported Git remote."}}const i=t.filter(e=>"enabled"===e.status).filter(e=>"https"===n.scheme==("https-token"===e.kind)).filter(e=>function(e,t){const n=pc(e);return n.scheme===t.scheme&&n.host===t.host&&n.port===t.port&&("/"===n.pathPrefix||t.pathPrefix.startsWith(n.pathPrefix))}(e.scope,n)).map(e=>({candidate:e,specificity:pc(e.scope).pathPrefix.length}));if(0===i.length)return{status:"none",remote:n};const s=Math.max(...i.map(e=>e.specificity)),r=i.filter(e=>e.specificity===s).map(e=>e.candidate);if(r.length>1)return{status:"ambiguous",remote:n,credentialIds:r.map(e=>e.id).sort()};const o=r[0];return"ssh-key"===o.kind&&!0!==o.pinnedKnownHosts?{status:"missing-host-key",remote:n,credentialId:o.id}:{status:"unique",remote:n,credential:o}}const Rc=a.z.object({id:a.z.string().trim().min(1).max(120),payload:Ac,createdAt:a.z.string().datetime(),updatedAt:a.z.string().datetime()}).strict(),Pc=Ic.extend({id:a.z.string().trim().min(1).max(300),createdAt:a.z.string().datetime()}).strict(),Dc=bc.extend({id:a.z.string().trim().min(1).max(120),createdAt:a.z.string().datetime()}).strict(),Mc=a.z.object({id:a.z.string().trim().min(1).max(120),status:a.z.literal("pending"),input:_c,createdAt:a.z.string().datetime(),updatedAt:a.z.string().datetime(),expiresAt:a.z.string().datetime()}).strict(),jc=a.z.object({id:a.z.string().trim().min(1).max(120),status:a.z.literal("consumed"),operationId:_c.shape.operationId,createdAt:a.z.string().datetime(),updatedAt:a.z.string().datetime(),expiresAt:a.z.string().datetime()}).strict(),Lc=a.z.discriminatedUnion("status",[Mc,jc]),Fc=864e5;function $c(e){return e&&"object"==typeof e&&!Array.isArray(e)?e:void 0}function Uc(e){const t=$c(e),n=$c(t?.payload),i=Oc(n?.credential),s=$c(n?.secret);return{id:t?.id,payload:{credential:i.success?i.data:n?.credential,secret:"https-token"===s?.kind?{kind:s.kind,username:s.username,token:s.token}:{kind:s?.kind,privateKey:s?.privateKey,passphrase:s?.passphrase,pinnedKnownHosts:s?.pinnedKnownHosts}},createdAt:t?.createdAt,updatedAt:t?.updatedAt}}function Hc(e){const t=$c(e);return Object.fromEntries(["id","instanceId","credentialId","credentialRevision","assignmentRevision","status","authorizedAt","createdAt","updatedAt"].flatMap(e=>t&&Object.prototype.hasOwnProperty.call(t,e)?[[e,t[e]]]:[]))}function Vc(e){const t=$c(e);return Object.fromEntries(["id","instanceId","generation","credentialIds","createdAt","updatedAt"].flatMap(e=>t&&Object.prototype.hasOwnProperty.call(t,e)?[[e,t[e]]]:[]))}function Bc(e){const t=$c(e),n="string"==typeof t?.updatedAt?Date.parse(t.updatedAt):Number.NaN;if("consumed"===t?.status)return{id:t.id,status:"consumed",operationId:t.operationId,createdAt:t.createdAt,updatedAt:t.updatedAt,expiresAt:t.expiresAt};const i=function(e){const t=kc(e),n=kc(t?.ref),i=kc(t?.clone),s=Array.isArray(t?.credentials)?t.credentials.map(e=>{const t=kc(e),n=kc(t?.payload),i=Oc(n?.credential),s=kc(n?.secret);return{...Cc(t,["operationId","retention"]),payload:{credential:i.success?i.data:n?.credential,secret:Cc(s,"https-token"===s?.kind?["kind","username","token"]:["kind","privateKey","passphrase","pinnedKnownHosts"])}}}):t?.credentials;return _c.safeParse({...Cc(t,["operationId","instanceId","remoteUrl"]),ref:Cc(n,["type","name","commit"]),clone:Cc(i,["depth","submodules","lfs","subdirectory"]),credentials:s})}(t?.input);return{id:t?.id,status:"pending",input:i.success?i.data:t?.input,createdAt:t?.createdAt,updatedAt:t?.updatedAt,expiresAt:t?.expiresAt||(Number.isFinite(n)?new Date(n+Fc).toISOString():t?.updatedAt)}}function qc(e,t){return Object.assign(new Error(`Refusing stale ${e} revision for ${t}.`),{code:"GIT_CREDENTIAL_REVISION_STALE",statusCode:409})}function Kc(e,t){return Object.assign(new Error(`Refusing conflicting ${e} revision for ${t}.`),{code:"GIT_CREDENTIAL_REVISION_CONFLICT",statusCode:409})}class Gc{payloads;legacyAssignments;authorizationSets;workspaceProvisioning;workspaceProvisioningTtlMs;workspaceProvisioningCleanupTimer;constructor(e,t={}){this.workspaceProvisioningTtlMs=t.workspaceProvisioningTtlMs??Fc,this.payloads=new Ca(e.gitCredentialPayloadsDir,{schema:Rc,sanitize:Uc,directoryMode:448,fileMode:384}),this.legacyAssignments=new Ca(e.gitCredentialAssignmentsDir,{schema:Pc,sanitize:Hc,directoryMode:448,fileMode:384}),this.authorizationSets=new Ca(e.gitCredentialAuthorizationSetsDir,{schema:Dc,sanitize:Vc,directoryMode:448,fileMode:384}),this.workspaceProvisioning=new Ca(e.gitWorkspaceProvisioningIntentsDir,{schema:Lc,sanitize:Bc,directoryMode:448,fileMode:384})}init(){this.payloads.init(),this.legacyAssignments.init(),this.authorizationSets.init(),this.workspaceProvisioning.init();for(const e of this.workspaceProvisioning.list())("pending"===e.status&&!Wc(e.input)||Date.parse(e.expiresAt)<=Date.now())&&this.workspaceProvisioning.delete(e.id);this.scheduleWorkspaceProvisioningCleanup();const e=new Set(this.legacyAssignments.list().map(e=>e.instanceId));for(const t of e){if(this.authorizationSets.get(t))continue;const e=this.legacyAssignments.list().filter(e=>e.instanceId===t),n=(new Date).toISOString();this.putAuthorizationSet({instanceId:t,generation:Math.max(0,...e.map(e=>e.assignmentRevision)),credentialIds:e.filter(e=>"revoking"!==e.status&&"revoked"!==e.status).map(e=>e.credentialId),updatedAt:n})}}putPayload(e){const t=Ac.parse(e),n=this.payloads.get(t.credential.id);if(n&&n.payload.credential.revision>t.credential.revision)throw qc("payload",t.credential.id);if(n&&n.payload.credential.revision===t.credential.revision&&JSON.stringify(n.payload)!==JSON.stringify(t))throw Kc("payload",t.credential.id);const i=(new Date).toISOString();return this.payloads.put({id:t.credential.id,payload:t,createdAt:n?.createdAt||i,updatedAt:i}).payload}getPayload(e){return this.payloads.get(e)?.payload}putAuthorizationSet(e){const t=bc.parse(e),n=this.authorizationSets.get(t.instanceId);if(n&&n.generation>t.generation)throw qc("authorization set",t.instanceId);if(n&&n.generation===t.generation){if(JSON.stringify(n.credentialIds)!==JSON.stringify(t.credentialIds))throw Kc("authorization set",t.instanceId);return this.publicAuthorizationSet(n)}for(const e of t.credentialIds)if(!this.payloads.get(e))throw Object.assign(new Error(`Credential payload ${e} is not deployed.`),{code:"GIT_CREDENTIAL_PAYLOAD_MISSING",statusCode:409});const i=(new Date).toISOString();return this.publicAuthorizationSet(this.authorizationSets.put({id:t.instanceId,...t,createdAt:n?.createdAt||i}))}getAuthorizationSet(e){const t=this.authorizationSets.get(e);return t?this.publicAuthorizationSet(t):{instanceId:e,generation:0,credentialIds:[],updatedAt:new Date(0).toISOString()}}resolve(e,t){const n=this.getAuthorizationSet(e).credentialIds.flatMap(e=>{const t=this.getPayload(e);return t?[t]:[]}),i=xc(t,n.map(e=>({id:e.credential.id,kind:e.credential.kind,scope:e.credential.scope,status:e.credential.status,pinnedKnownHosts:"ssh-key"===e.secret.kind&&Boolean(e.secret.pinnedKnownHosts.trim())}))),s="unique"===i.status?n.find(e=>e.credential.id===i.credential.id):void 0;return{match:i,payload:s}}removePayload(e){if(this.authorizationSets.list().some(t=>t.credentialIds.includes(e)))throw Object.assign(new Error(`Credential payload ${e} is still authorized.`),{code:"GIT_CREDENTIAL_PAYLOAD_IN_USE",statusCode:409});return this.payloads.delete(e)}collectUnreferencedPayloads(){const e=new Set(this.authorizationSets.list().flatMap(e=>e.credentialIds));let t=0;for(const n of this.payloads.list())!e.has(n.id)&&this.payloads.delete(n.id)&&(t+=1);return t}removeInstance(e){const t=this.authorizationSets.delete(e)?1:0;this.workspaceProvisioning.delete(e),this.scheduleWorkspaceProvisioningCleanup();for(const t of this.legacyAssignments.list().filter(t=>t.instanceId===e))this.legacyAssignments.delete(t.id);return t}putWorkspaceProvisioning(e){const t=_c.parse(e);if(!Wc(t))throw Object.assign(new Error("Only operation-only Git provisioning may be persisted."),{code:"GIT_CREDENTIAL_PROVISIONING_RETENTION_INVALID",statusCode:400});const n=this.workspaceProvisioning.get(t.instanceId);if("consumed"===n?.status&&n.operationId===t.operationId)return t;const i=(new Date).toISOString(),s=Mc.parse(this.workspaceProvisioning.put({id:t.instanceId,status:"pending",input:t,createdAt:n?.createdAt||i,updatedAt:i,expiresAt:new Date(Date.now()+this.workspaceProvisioningTtlMs).toISOString()})).input;return this.scheduleWorkspaceProvisioningCleanup(),s}getWorkspaceProvisioning(e){const t=this.workspaceProvisioning.get(e);if(t&&"pending"===t.status)return!Wc(t.input)||Date.parse(t.expiresAt)<=Date.now()?(this.workspaceProvisioning.delete(e),void this.scheduleWorkspaceProvisioningCleanup()):t.input}removeWorkspaceProvisioning(e){const t=this.workspaceProvisioning.delete(e);return this.scheduleWorkspaceProvisioningCleanup(),t}discardPendingWorkspaceProvisioning(e){const t=this.workspaceProvisioning.get(e);return!(!t||"pending"!==t.status)&&this.removeWorkspaceProvisioning(e)}completeWorkspaceProvisioning(e,t){const n=this.workspaceProvisioning.get(e);if(!n||"pending"!==n.status||n.input.operationId!==t)return!1;const i=(new Date).toISOString();return this.workspaceProvisioning.put({id:e,status:"consumed",operationId:t,createdAt:n.createdAt,updatedAt:i,expiresAt:new Date(Date.now()+6048e5).toISOString()}),this.scheduleWorkspaceProvisioningCleanup(),!0}workspaceProvisioningStatus(e){const t=this.workspaceProvisioning.get(e);if(t){if(!(Date.parse(t.expiresAt)<=Date.now()))return"pending"===t.status?{status:t.status,operationId:t.input.operationId}:{status:t.status,operationId:t.operationId};this.removeWorkspaceProvisioning(e)}}scheduleWorkspaceProvisioningCleanup(){this.workspaceProvisioningCleanupTimer&&clearTimeout(this.workspaceProvisioningCleanupTimer),this.workspaceProvisioningCleanupTimer=void 0;const e=Math.min(...this.workspaceProvisioning.list().map(e=>Date.parse(e.expiresAt)));Number.isFinite(e)&&(this.workspaceProvisioningCleanupTimer=setTimeout(()=>{this.workspaceProvisioningCleanupTimer=void 0;const e=Date.now();for(const t of this.workspaceProvisioning.list())Date.parse(t.expiresAt)<=e&&this.workspaceProvisioning.delete(t.id);this.scheduleWorkspaceProvisioningCleanup()},Math.max(0,e-Date.now())),this.workspaceProvisioningCleanupTimer.unref?.())}listAssignments(e){return this.legacyAssignments.list().filter(t=>!e||t.instanceId===e).map(({id:e,createdAt:t,...n})=>Ic.parse(n))}publicAuthorizationSet(e){const{id:t,createdAt:n,...i}=e;return bc.parse(i)}}function Wc(e){return e.credentials.length>0&&e.credentials.every(e=>"operation-only"===e.retention)}const Jc=function(e,t=process.env,n=e){let i;return()=>{const s=t.TASK_HANDOFF_VERSION?.trim();return s||(i||=z(e,t,n),i)}}("@task-handoff/node-agent",process.env,"@task-handoff/control-plane");function Yc(){return Jc()}function Xc(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 Qc(e){const t=Yc();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:Xc(t,e)}}function Zc(e,t,n=!0){if(!n){const n=Yc(),i=e.runtimeVersion;return"matched"===i?.phase&&i.desiredVersion===n&&i.actualVersion===t?i:Qc(t)}const i=Yc(),s=e.runtimeVersion;if(!s||s.desiredVersion!==i)return Qc(t);const r="INSTANCE_RUNTIME_VERSION_MISMATCH"!==s.error?.code?s.error:t===i?void 0:Xc(i,t);return Ti.parse({...s,desiredVersion:i,...t?{actualVersion:t}:{actualVersion:void 0},..."pending"===s.phase?{error:r||(t!==i?Xc(i,t):void 0)}:{}})}const ed="runtime_local_host",td="task-handoff.node-agent.builtin";function nd(e){const t={...e};return delete t[td],t}function id(e){return"local-folder"===e.type?Ui.parse({mode:"local-bind",path:"/workspace",readOnly:!1}):Ui.parse({mode:"git-clone",path:"/workspace",readOnly:!1})}function sd(e){const t=$i.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 qi.parse({id:n,name:"string"==typeof e.sourceSnapshot.name?e.sourceSnapshot.name:e.name,source:t,defaultImageSelection:e.imageSelection,defaultNodeId:e.nodeId,workspacePolicy:id(t),labels:{},createdAt:e.createdAt,updatedAt:e.updatedAt})}function rd(e,t){throw Object.assign(new Error(t),{statusCode:403,code:e})}function od(e,t){e!==An&&console.warn(JSON.stringify({message:"protocol version mismatch",peer:t,expectedProtocolVersion:An,actualProtocolVersion:e||"missing",errorCode:"PROTOCOL_VERSION_MISMATCH"}))}function ad(e){return"none"!==e.capabilities.artifactKind}function cd(e={}){return{...e,requiresImage:!1,supportsControlledInstanceApi:!0,supportsContainerLifecycle:!1,supportsAppSessions:!0,supportsHostSessions:!0,artifactKind:"none",isolation:"none"}}class dd extends Ca{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||{},n?.modelCatalog);const{registrationToken:s,...r}=e,o=super.put(Bs.parse({...r,stateRevision:Math.max(e.stateRevision||0,t)+1})),a=this.hydrate(o);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 Bs.parse({...e,registrationToken:t})}}class ld{nodeId;paths;localFolders;nodeRuntimes;controlledInstances;environmentTemplates;instancePrivateConfigs;modelRegistry;gitCredentials;updateJobs;node;listenerPort;containerUrlOverride;platform;constructor(e,t,n,i,s,r){this.paths=e,this.nodeId=t,this.localFolders=new Ca(e.localFoldersDir,{schema:Fi,sanitize:si}),this.nodeRuntimes=new Ca(e.nodeRuntimesDir,{schema:Ts}),this.instancePrivateConfigs=new Za(e),this.controlledInstances=new dd(e.controlledInstancesDir,{schema:Bs,sanitize:e=>Js(e,e=>{console.warn(JSON.stringify({message:"legacy controlled instance field was ignored",...e}))})},this.instancePrivateConfigs),this.environmentTemplates=new Ya(e),this.gitCredentials=new Gc(e),this.modelRegistry=new $a(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 Ja(e),this.listenerPort=s,this.platform=r,this.containerUrlOverride=i;const o=te();this.node=Ns.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:o,updatedAt:o})}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.gitCredentials.init(),this.modelRegistry.init(),this.updateJobs.init(),this.updateJobs.reconcileRollouts(this.controlledInstances.list(),Yc(),{processStarted:!0}),!this.nodeRuntimes.get("runtime_local_docker")){const e=te();this.nodeRuntimes.put(Ts.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(ed),t=te();this.nodeRuntimes.put(Ts.parse({id:ed,nodeId:this.nodeId,name:"Local Runtime",type:"local",status:e?.status||"unknown",accessStrategy:"node-proxy",capabilities:cd(e?.capabilities),labels:{...e?.labels,[td]:"true"},createdAt:e?.createdAt||t,updatedAt:e?.updatedAt||t}))}for(const e of this.nodeRuntimes.list())e.nodeId!==this.nodeId&&this.nodeRuntimes.put(Ts.parse({...e,nodeId:this.nodeId,updatedAt:te()}));for(const e of this.localFolders.list())e.nodeId!==this.nodeId&&this.localFolders.put(Fi.parse({...e,nodeId:this.nodeId,updatedAt:te()}));this.normalizeInstanceRuntimeVersions()}normalizeInstanceRuntimeVersions(){for(const e of this.controlledInstances.list()){const t=Qc(e.build?.packageVersion||e.instanceVersion),n=ad(this.requireRuntime(e.runtimeId)),i=["created","stopped","failed"].includes(e.status),s=n&&e.runtimeVersion?.desiredVersion===t.desiredVersion?e.runtimeVersion:void 0,r=n?"matched"===t.phase?i?t:{...t,phase:"verifying",matchedAt:void 0}:{...t,phase:"pending",attempt:s?.attempt||0,lastAttemptAt:s?.lastAttemptAt,error:s?.error||t.error}:t;this.controlledInstances.put(Bs.parse({...e,ready:!1,runtimeVersion:r,updatedAt:te()}))}}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=te()}runningInstanceCount(){const e=new Set(["created","stopped","failed"]);return this.listInstances().filter(t=>!e.has(t.status)).length}createLocalFolder(e){const t=te(),i=qo(e.path),s=Fi.parse({...e,name:e.name.trim()||n.basename(i),path:i,id:e.id||_a("folder"),nodeId:this.nodeId,labels:e.labels||{},createdAt:t,updatedAt:t});return this.localFolders.put(s)}updateLocalFolder(e,t){const i=this.localFolders.get(e);if(!i){const t=new Error(`Local folder ${e} was not found.`);throw Object.assign(t,{statusCode:404,code:"NODE_LOCAL_FOLDER_NOT_FOUND"})}return this.localFolders.put(Fi.parse({...i,name:t.name.trim()||n.basename(i.path),updatedAt:te()}))}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=te(),n=Ts.parse({...e,id:e.id||_a("runtime"),nodeId:this.nodeId,accessStrategy:e.accessStrategy||(i=e.type,"docker"===i?"direct-port":"node-proxy"),capabilities:e.capabilities||{},labels:nd(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[td]){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=Ts.parse({...n,...t,id:n.id,nodeId:this.nodeId,accessStrategy:t.accessStrategy||n.accessStrategy,capabilities:t.capabilities||n.capabilities,labels:t.labels?nd(t.labels):n.labels,createdAt:n.createdAt,updatedAt:te()});return this.nodeRuntimes.put(i)}deleteRuntime(e){if("true"===this.requireRuntime(e).labels[td]){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=Ts.parse({...n,...e,id:n.id,nodeId:this.nodeId,createdAt:n.createdAt,updatedAt:te()});return this.nodeRuntimes.put(t)}):this.nodeRuntimes.put(Ts.parse({...n,status:"unknown",updatedAt:te()}))}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=Ws(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 ${An}: ${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 Bs.parse({...e,status:"starting",ready:!1,updatedAt:n});case"stop-requested":return Bs.parse({...e,status:"stopping",ready:!1,updatedAt:n});case"stop-failed":return"stopping"!==e.status?e:Bs.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 Bs.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 s=t.stateRevision>e.stateRevision&&t.lastHeartbeatAt!==e.lastHeartbeatAt&&"online"===t.agentStatus;return Bs.parse({...t,...n,...s?{status:t.status,health:t.health,connectionStatus:t.connectionStatus,agentStatus:t.agentStatus,targetStatus:t.targetStatus,uiAccessStatus:t.uiAccessStatus}:{},ready:!!s&&t.ready,target:n.target?{...t.target,...n.target}:t.target,workspace:n.workspace?s?{...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 Bs.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 Bs.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=Ws(e);return t.success?[t.data]:[]})}resolvedAssignedModelEnvironment(e){return this.modelRegistry.resolvedEnvironment(e)}createInstance(e){const t=this.requireRuntime(e.runtimeId),i=te(),s=e.id||_a("inst"),r=function(e){const t=$i.parse(e);return"local-folder"===t.type?t:$i.parse({...t,auth:{type:"none"}})}(e.source),o=e.environmentSource||(e.imageSelection?{type:"image",imageSelection:e.imageSelection}:void 0);if("template"===o?.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"===o?.type?this.environmentTemplates.get(o.environmentTemplateId):void 0;if("template"===o?.type&&(!a||"ready"!==a.status)){const e=new Error(`Environment template ${o.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)&&(!o||"image"===o.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"!==r.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?fs.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?fs.parse(e.image):void 0,d="local"===t.type&&"local-folder"===r.type?n.resolve(r.path):void 0,l=Bs.parse({id:s,name:e.name||`instance-${s.replace(/^inst_?/,"").slice(0,6)}`,source:r,sourceSnapshot:e.sourceSnapshot||{},modelSelection:e.modelSelection,projectId:e.projectId,nodeId:this.nodeId,runtimeId:t.id,imageSelection:"image"===o?.type?o.imageSelection:void 0,environmentSource:o,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"!==o?.type?{phase:"checking-image",requestedReference:c.requestedReference,generation:0,startedAt:i,updatedAt:i}:void 0,status:c&&"docker"===t.type&&"template"!==o?.type?"provisioning":"created",health:"unknown",connectionStatus:"unknown",agentStatus:"unknown",targetStatus:"unknown",uiAccessStatus:"unknown",controlMode:"controlled",ready:!1,runtimeVersion:Qc(),capabilities:{},config:{autoImportAgentConfigs:e.config?.autoImportAgentConfigs??!0,codexConfigEnabled:e.config?.codexConfigEnabled??!0,codexHomeMode:e.config?.codexHomeMode??("local"===t.type?"taskhandoff":"default"),defaultCodexPermissionMode:e.config?.defaultCodexPermissionMode??("docker"===t.type?"full-access":"ask"),aiSessionHistoryLimit:e.config?.aiSessionHistoryLimit??50,aiSessionAttachmentRetentionDays:e.config?.aiSessionAttachmentRetentionDays??30,aiSessionMaxFileAttachmentBytes:e.config?.aiSessionMaxFileAttachmentBytes??ce},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:ka(),createdAt:i,updatedAt:i}),u=this.controlledInstances.put(l);return this.instancePrivateConfigs.materialize(u.id,u.registrationToken,this.resolvedAssignedModelEnvironment(u.id),this.modelRegistry.privateCatalog(u.id)),e.gitWorkspaceProvisioning?.credentials.every(e=>"operation-only"===e.retention)&&this.gitCredentials.putWorkspaceProvisioning(e.gitWorkspaceProvisioning),u}takeGitWorkspaceProvisioning(e){const t=this.gitCredentials.getWorkspaceProvisioning(e);return this.gitCredentials.removeWorkspaceProvisioning(e),t}setGitWorkspaceProvisioning(e){const t=this.requireInstance(e.instanceId);if("local-folder"===t.source.type||t.source.url!==e.remoteUrl)throw Object.assign(new Error(`Git provisioning does not match instance ${t.id}.`),{code:"GIT_WORKSPACE_PROVISIONING_INSTANCE_MISMATCH",statusCode:409});this.gitCredentials.putWorkspaceProvisioning(e)}gitWorkspaceProvisioningFor(e){if("local-folder"===e.source.type)return;const t=this.gitCredentials.getWorkspaceProvisioning(e.id);if(t)return t;const n=this.gitCredentials.getAuthorizationSet(e.id).credentialIds.flatMap(e=>{const t=this.gitCredentials.getPayload(e);return t?[t]:[]}),i=n.map(e=>({id:e.credential.id,kind:e.credential.kind,scope:e.credential.scope,status:e.credential.status,pinnedKnownHosts:"ssh-key"===e.secret.kind&&Boolean(e.secret.pinnedKnownHosts.trim())})),s=xc(e.source.url,i);if("ambiguous"===s.status||"missing-host-key"===s.status)throw Object.assign(new Error(`Git credential resolution failed for instance ${e.id}: ${s.status}.`),{code:`GIT_CREDENTIAL_${s.status.replace(/-/g,"_").toUpperCase()}`,statusCode:409});return{operationId:`gitop_${e.id}_${e.stateRevision}`,instanceId:e.id,remoteUrl:e.source.url,ref:e.source.ref,clone:e.source.clone,credentials:n.map((t,n)=>({operationId:`gitcredop_${e.id}_${e.stateRevision}_${n}`,retention:"instance-retained",payload:t}))}}discardGitWorkspaceProvisioning(e){return this.gitCredentials.discardPendingWorkspaceProvisioning(e)}gitWorkspaceProvisioningStatus(e){return this.gitCredentials.workspaceProvisioningStatus(e)}registerInstance(e,t,n){const i=Zs.parse(t),s=te(),r=this.controlledInstances.get(e);if(!r){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(r,i,n),i.processIncarnationId&&i.processIncarnationId===r.processIncarnationId)return r;od(i.protocolVersion,`Instance ${e}`);const o=i.build?.packageVersion||i.instanceVersion,a=ad(this.requireRuntime(r.runtimeId)),c=Zc(r,o,a),d=Bs.parse({...r,status:"registered",health:o===Yc()?"ok":"degraded",ready:!a&&o===Yc(),connectionStatus:"online",agentStatus:"online",targetStatus:r.targetStatus,uiAccessStatus:r.uiAccessStatus,controlMode:i.controlMode,protocolVersion:i.protocolVersion,instanceVersion:i.instanceVersion,build:i.build,runtimeVersion:c,processIncarnationId:i.processIncarnationId||r.processIncarnationId,capabilities:i.capabilities,appInventory:i.appInventory,workspace:i.workspace,target:r.target,registrationToken:r.registrationToken||i.registrationToken,lastHeartbeatAt:s,updatedAt:s});return this.controlledInstances.put(d)}heartbeatInstance(e,t,n){const i=this.requireInstance(e);this.validateInstanceToken(i,n);const s=er.parse(t);i.processIncarnationId&&s.processIncarnationId&&s.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.`),od(s.protocolVersion,`Instance ${e}`);const r=te(),o=i.target,a=i.targetStatus,c=Zc(i,s.build?.packageVersion||i.build?.packageVersion||i.instanceVersion,ad(this.requireRuntime(i.runtimeId))),d=s.health||i.health,l="running"===(s.status||i.status)&&"failed"!==d,u=Bs.parse({...i,...s,target:o,ready:l,health:d,runtimeVersion:c,processIncarnationId:s.processIncarnationId||i.processIncarnationId,agentStatus:"online",targetStatus:a,uiAccessStatus:a,connectionStatus:"online",build:s.build||i.build,lastHeartbeatAt:r,updatedAt:r});return this.controlledInstances.put(u)}validateInstanceReport(e,t,n){this.validateInstanceToken(e,n||t.registrationToken),t.instanceId&&t.instanceId!==e.id&&rd("INSTANCE_ID_MISMATCH",`Instance ${t.instanceId} cannot register as ${e.id}.`),t.nodeId&&t.nodeId!==this.nodeId&&rd("INSTANCE_NODE_MISMATCH",`Instance ${e.id} belongs to node ${this.nodeId}.`),t.runtimeId&&t.runtimeId!==e.runtimeId&&rd("INSTANCE_RUNTIME_MISMATCH",`Instance ${e.id} belongs to runtime ${e.runtimeId}.`),t.imageSelection&&t.imageSelection.imageId!==e.imageSelection?.imageId&&rd("INSTANCE_IMAGE_MISMATCH",`Instance ${e.id} belongs to image ${e.imageSelection?.imageId}.`)}validateInstanceToken(e,t){e.registrationToken&&t===e.registrationToken||rd("INSTANCE_REGISTRATION_TOKEN_INVALID",`Invalid registration token for instance ${e.id}.`)}authenticateInstance(e,t){const n=this.requireInstance(e);return this.validateInstanceToken(n,t),n}context(e,t=this.resolvedAssignedModelEnvironment(e.id)){const n=t,i=e.imageSnapshot||fs.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});this.instancePrivateConfigs.get(e.id);const s=this.instancePrivateConfigs.materialize(e.id,e.registrationToken,n,this.modelRegistry.privateCatalog(e.id)),r=this.gitWorkspaceProvisioningFor(e);return{project:sd(e),image:i,node:this.node,runtime:this.requireRuntime(e.runtimeId),instance:e,nodeAgentUrl:this.containerUrl,modelEnv:n,privateConfigPath:this.instancePrivateConfigs.filePath(s.instanceId),...r?{gitWorkspaceProvisioning:r,completeGitWorkspaceProvisioning:()=>this.gitCredentials.completeWorkspaceProvisioning(e.id,r.operationId)}:{}}}}async function ud(e,t){const n=function(e){const t=gd(e),n=[],i=t.pathname.split("/").filter(Boolean).at(-1)||"";return bd(n,md(t.toString(),/^v\d+$/.test(i)?"models":"v1/models")),bd(n,new URL("/v1/models",t.origin).toString()),bd(n,new URL("/models",t.origin).toString()),n}(t.endpoint),i=Date.now();let s;for(const r of n){const n=await fd(e,r,{method:"GET",headers:{accept:"application/json",authorization:`Bearer ${t.key}`}});if(404===n.status||405===n.status){s=n.status;continue}if(!n.ok)throw Id("MODEL_DISCOVERY_FAILED",n.status);const o=await yd(n,"MODEL_DISCOVERY_RESPONSE_INVALID"),a=Array.isArray(o.data)?o.data:void 0;if(!a)throw Ad("MODEL_DISCOVERY_RESPONSE_INVALID","The model endpoint returned an invalid model list.",502);return{models:vd(a.flatMap(e=>{if(!e||"object"!=typeof e||Array.isArray(e))return[];const t=e,n="string"==typeof t.id?t.id.trim():"";if(!n)return[];const i="string"==typeof t.owned_by?t.owned_by.trim():"";return[{id:n,...i?{ownedBy:i}:{}}]}).sort((e,t)=>e.id.localeCompare(t.id))),latencyMs:Date.now()-i}}throw Ad("MODEL_DISCOVERY_UNSUPPORTED","No compatible model-list endpoint was found for this endpoint.",502,s)}async function pd(e,t){const n=Date.now(),i=t.protocol||("claude"===t.app?"anthropic-messages":"opencode"===t.app?"openai-chat-completions":"openai-responses"),s="openai-responses"===i?await fd(e,hd(t.endpoint,"responses"),{method:"POST",headers:{accept:"application/json",authorization:`Bearer ${t.key}`,"content-type":"application/json"},body:JSON.stringify({model:t.model,input:"Reply with OK.",max_output_tokens:32,stream:!1})}):"openai-chat-completions"===i?await fd(e,hd(t.endpoint,"chat/completions"),{method:"POST",headers:{accept:"application/json",authorization:`Bearer ${t.key}`,"content-type":"application/json"},body:JSON.stringify({model:t.model,messages:[{role:"user",content:"Reply with OK."}],max_tokens:32,stream:!1})}):await fd(e,function(e){const t=gd(e);if(/\/messages\/?$/.test(t.pathname))return t.toString();const n=t.pathname.split("/").filter(Boolean).at(-1)||"";return md(t.toString(),/^v\d+$/.test(n)?"messages":"v1/messages")}(t.endpoint),{method:"POST",headers:{accept:"application/json","anthropic-version":"2023-06-01","content-type":"application/json","x-api-key":t.key},body:JSON.stringify({model:t.model,max_tokens:8,messages:[{role:"user",content:"Reply with OK."}]})});if(!s.ok)throw Id("MODEL_TEST_FAILED",s.status);if((await yd(s,"MODEL_TEST_RESPONSE_INVALID")).error)throw Ad("MODEL_TEST_RESPONSE_INVALID","The model endpoint returned an error payload.",502);return{success:!0,latencyMs:Date.now()-n}}function md(e,t){const n=gd(e);return n.pathname=`${n.pathname.replace(/\/+$/,"")}/${t.replace(/^\/+/,"")}`,n.search="",n.hash="",n.toString()}function hd(e,t){const n=gd(e);return n.pathname.replace(/\/+$/,"").endsWith(`/${t}`)?n.toString():md(n.toString(),t)}function gd(e){let t;try{t=new URL(e.trim())}catch{throw Ad("MODEL_ENDPOINT_INVALID","The model endpoint must be a valid HTTP or HTTPS URL.",400)}if("http:"!==t.protocol&&"https:"!==t.protocol||t.username||t.password)throw Ad("MODEL_ENDPOINT_INVALID","The model endpoint must be an HTTP or HTTPS URL without embedded credentials.",400);return t}async function fd(e,t,n){try{return await e(t,{...n,redirect:"error",signal:AbortSignal.timeout(15e3)})}catch(e){const t=e&&"object"==typeof e&&"name"in e&&"TimeoutError"===e.name;throw Ad(t?"MODEL_ENDPOINT_TIMEOUT":"MODEL_ENDPOINT_UNREACHABLE",t?"The model endpoint timed out.":"The model endpoint could not be reached.",t?504:502)}}async function yd(e,t){const n=await e.text();if(n.length>1e6)throw Ad(t,"The model endpoint response was too large.",502);try{const e=JSON.parse(n);if(!e||"object"!=typeof e||Array.isArray(e))throw new Error("not an object");return e}catch{throw Ad(t,"The model endpoint returned invalid JSON.",502)}}function Id(e,t){return Ad(e,401===t||403===t?"The model endpoint rejected the API key.":"The model endpoint rejected the request.",502,t)}function Ad(e,t,n,i){return Object.assign(new Error(t),{code:e,statusCode:n,...i?{details:{upstreamStatus:i}}:{}})}function bd(e,t){e.includes(t)||e.push(t)}function vd(e){const t=new Set;return e.filter(e=>!t.has(e.id)&&(t.add(e.id),!0))}const wd=a.z.object({endpoint:a.z.string().trim().url().max(2048),key:a.z.string().trim().min(1).max(4096).optional(),existingModelId:a.z.string().trim().min(1).max(120).optional()}).strict(),Sd=wd.extend({model:a.z.string().trim().min(1).max(240),app:a.z.enum(["codex","claude","opencode"]).optional(),protocol:a.z.enum(["openai-responses","openai-chat-completions","anthropic-messages"]).optional()}).strict().refine(e=>Boolean(e.protocol||e.app),{message:"A model protocol is required.",path:["protocol"]});class Ed{invocations=new Map;store;idleTtlMs;maxTtlMs;cleanupTimer;constructor(e,t={}){this.store=e,this.idleTtlMs=t.idleTtlMs??6e4,this.maxTtlMs=t.maxTtlMs??3e5}resolveHttps(e,t){const{match:n,payload:i}=this.store.resolve(e,t);return"unique"!==n.status||"https-token"!==i?.secret.kind?{status:n.status}:{status:"ok",username:i.secret.username,password:i.secret.token}}async prepareSsh(e,i){this.cleanupExpired();const{match:s,payload:r}=this.store.resolve(e,i);if("unique"!==s.status||"ssh-key"!==r?.secret.kind)return{status:s.status};const o=`gitssh_${d.randomUUID()}`,a=t.mkdtempSync(n.join(c.tmpdir(),"task-handoff-node-git-ssh-"));t.chmodSync(a,448);const l=n.join(a,"agent.sock"),u=n.join(a,"askpass.sh");let p;t.writeFileSync(u,"#!/bin/sh\nprintf '%s' \"${TASK_HANDOFF_SSH_KEY_PASSPHRASE:-}\"\n",{mode:448});try{const n=await Nd("ssh-agent",["-s","-a",l]);if(p=Number(/SSH_AGENT_PID=(\d+)/.exec(n)?.[1]),!Number.isInteger(p)||p<=0)throw new Error("ssh-agent did not report a process id.");const s={...process.env,SSH_AUTH_SOCK:l,SSH_ASKPASS:u,SSH_ASKPASS_REQUIRE:"force",DISPLAY:process.env.DISPLAY||":0",TASK_HANDOFF_SSH_KEY_PASSPHRASE:r.secret.passphrase||""};await Td("ssh-add",["-"],r.secret.privateKey,s);const c=await Nd("ssh-add",["-L"],s);t.rmSync(u,{force:!0});const d=Date.now();return this.invocations.set(o,{instanceId:e,remoteUrl:i,credentialId:r.credential.id,credentialRevision:r.credential.revision,socketPath:l,agentPid:p,directory:a,idleExpiresAt:d+this.idleTtlMs,absoluteExpiresAt:d+this.maxTtlMs}),this.scheduleCleanup(),{status:"ok",invocationId:o,publicIdentity:c,pinnedKnownHosts:r.secret.pinnedKnownHosts}}catch(e){if(p)try{process.kill(p,"SIGTERM")}catch{}throw t.rmSync(a,{recursive:!0,force:!0}),e}}async exchangeAgentFrame(e,t,n){this.cleanupExpired();const i=this.invocations.get(t);if(!i||i.instanceId!==e)throw zd("GIT_CREDENTIAL_SSH_INVOCATION_INVALID",404);const{match:s,payload:r}=this.store.resolve(e,i.remoteUrl);if("unique"!==s.status||"ssh-key"!==r?.secret.kind||r.credential.id!==i.credentialId||r.credential.revision!==i.credentialRevision)throw this.release(t,e),zd("GIT_CREDENTIAL_SSH_INVOCATION_REVOKED",403);const o=Buffer.from(n,"base64");if(o.length<5||o.length>1048576||o.readUInt32BE(0)!==o.length-4)throw zd("GIT_CREDENTIAL_SSH_AGENT_FRAME_INVALID",400);i.idleExpiresAt=Math.min(i.absoluteExpiresAt,Date.now()+this.idleTtlMs),this.scheduleCleanup();const a=Math.max(1,Math.min(i.idleExpiresAt,i.absoluteExpiresAt)-Date.now());try{const e=await function(e,t,n){return new Promise((i,s)=>{const r=m.createConnection(e),o=[];let a=0,c=!1;const d=(e,t)=>{c||(c=!0,r.destroy(),e?s(e):i(t))};r.setTimeout(n),r.once("timeout",()=>d(new Error("Managed Git SSH agent exchange timed out."))),r.once("error",e=>d(e)),r.once("end",()=>d(new Error("Managed Git SSH agent closed before returning a complete frame."))),r.once("close",()=>d(new Error("Managed Git SSH agent closed before returning a complete frame."))),r.on("data",e=>{o.push(e);const t=Buffer.concat(o);!a&&t.length>=4&&(a=t.readUInt32BE(0)+4,a<5||a>1048576)?d(new Error("Managed Git SSH agent returned an invalid frame length.")):a&&t.length>=a&&d(void 0,t.subarray(0,a))}),r.once("connect",()=>r.write(t,e=>{e&&d(e)}))})}(i.socketPath,o,a);return{frame:e.toString("base64")}}catch{throw this.release(t,e),zd("GIT_CREDENTIAL_SSH_AGENT_UNAVAILABLE",502)}}release(e,n){const i=this.invocations.get(e);if(!i||void 0!==n&&i.instanceId!==n)return!1;this.invocations.delete(e);try{process.kill(i.agentPid,"SIGTERM")}catch{}return t.rmSync(i.directory,{recursive:!0,force:!0}),this.scheduleCleanup(),!0}close(){this.cleanupTimer&&clearTimeout(this.cleanupTimer),this.cleanupTimer=void 0;for(const e of[...this.invocations.keys()])this.release(e)}cleanupExpired(){const e=Date.now();for(const[t,n]of this.invocations)(n.idleExpiresAt<=e||n.absoluteExpiresAt<=e)&&this.release(t)}scheduleCleanup(){this.cleanupTimer&&clearTimeout(this.cleanupTimer),this.cleanupTimer=void 0;const e=Math.min(...[...this.invocations.values()].map(e=>Math.min(e.idleExpiresAt,e.absoluteExpiresAt)));Number.isFinite(e)&&(this.cleanupTimer=setTimeout(()=>{this.cleanupTimer=void 0,this.cleanupExpired(),this.scheduleCleanup()},Math.max(0,e-Date.now())),this.cleanupTimer.unref?.())}}function zd(e,t){return Object.assign(new Error("Managed Git broker request was rejected."),{code:e,statusCode:t})}function Nd(e,t,n=process.env){return Td(e,t,void 0,n)}function Td(e,t,n,i){return new Promise((s,r)=>{const o=l.spawn(e,t,{shell:!1,env:i,stdio:[void 0===n?"ignore":"pipe","pipe","pipe"]}),a=[];o.stdout.on("data",e=>a.push(e)),o.once("error",()=>r(new Error(`Managed Git SSH broker could not start ${e}.`))),o.once("close",t=>0===t?s(Buffer.concat(a).toString("utf8")):r(new Error(`Managed Git SSH broker command ${e} failed.`))),void 0!==n&&o.stdin.end(n)})}const _d=a.z.object({credentialId:a.z.string().trim().min(1).max(120)}).strict(),kd=a.z.object({id:a.z.string().trim().min(1).max(120)}).strict(),Cd=kd.extend({invocationId:a.z.string().trim().min(1).max(120)}).strict();function Od(e){const t=e.authorization;return"string"==typeof t&&t.startsWith("Bearer ")?t.slice(7).trim():void 0}const xd=a.z.string().trim().min(1).max(1024).refine(e=>!e.startsWith("/")&&!e.includes("\\")&&e.split("/").every(e=>e.length>0&&"."!==e&&".."!==e),"Story paths must be normalized relative POSIX paths."),Rd=a.z.string().regex(/^[a-f0-9]{64}$/),Pd=a.z.object({title:a.z.string().trim().min(1).max(240),storyPath:xd,revision:Rd}).strict(),Dd=a.z.object({name:a.z.string().trim().min(1).max(80),label:a.z.string().trim().min(1).max(120),required:a.z.boolean().default(!1),defaultValue:a.z.string().max(4e3).optional()}).strict(),Md=a.z.object({agent:ye.optional(),mode:Be.optional(),permissionMode:qe.optional(),modelSelection:it.optional(),reasoningEffort:st.optional(),cwdFolderId:a.z.string().trim().min(1).max(120).optional(),gitSelection:rt.optional()}).strict(),jd=a.z.object({id:a.z.string().trim().min(1).max(120),title:a.z.string().trim().min(1).max(120),promptTemplate:a.z.string().trim().min(1).max(32e3),targetInstanceId:a.z.string().trim().min(1).max(120).optional(),parameters:a.z.array(Dd).max(20).default([]),sessionPreset:Md.optional()}).strict(),Ld=jd.omit({id:!0}).strict(),Fd=Ld.extend({id:jd.shape.id.optional()}).strict(),$d=a.z.object({id:re,ownerNodeId:a.z.string().trim().min(1).max(120),title:a.z.string().trim().min(1).max(240),description:a.z.string().trim().max(4e3).optional(),documents:a.z.array(Pd).max(500).default([]),actions:a.z.array(jd).max(50).default([]),createdAt:a.z.string().datetime(),updatedAt:a.z.string().datetime(),archivedAt:a.z.string().datetime().optional()}).strict();a.z.object({stories:a.z.array($d).default([])}).strict();const Ud=a.z.object({title:$d.shape.title,description:$d.shape.description,actions:a.z.array(Ld).max(50).optional()}).strict(),Hd=a.z.object({title:$d.shape.title.optional(),description:$d.shape.description.nullable().optional(),actions:a.z.array(Fd).max(50).optional()}).strict().refine(e=>Object.keys(e).length>0,"At least one Story field is required."),Vd=a.z.object({title:Pd.shape.title.optional(),storyPath:xd.optional()}).strict().refine(e=>Object.keys(e).length>0,"At least one document field is required."),Bd=a.z.object({storyPaths:a.z.array(xd).max(500)}).strict();a.z.object({storyPath:xd,title:Pd.shape.title.optional(),expectedRevision:Rd.optional()}).strict();const qd=a.z.object({documents:a.z.array(Pd).max(500)}).strict();a.z.object({storyPath:xd,revision:Rd,content:a.z.string(),size:a.z.number().int().nonnegative()}).strict(),a.z.object({storyPaths:a.z.array(xd).min(1).max(20),destinationPath:a.z.string().trim().min(1).max(4096)}).strict(),a.z.object({storyPath:xd,title:Pd.shape.title.optional(),sourcePath:a.z.string().trim().min(1).max(4096),expectedRevision:Rd.optional()}).strict();const Kd=a.z.object({storyPath:xd,path:a.z.string().trim().min(1).max(4096).optional(),revision:Rd.optional(),error:a.z.object({code:a.z.string().trim().min(1).max(120),message:a.z.string().trim().min(1).max(2e3)}).strict().optional()}).strict();a.z.object({items:a.z.array(Kd).min(1).max(20)}).strict(),a.z.object({storyId:re,nodeId:a.z.string().trim().min(1).max(120),change:a.z.enum(["created","updated","archived","restored","deleted","content.written","document.updated","document.reordered","document.deleted"]).optional(),storyPath:xd.optional()}).strict();const Gd=a.z.object({storyId:re}).strict(),Wd=Gd.extend({storyPath:a.z.string().min(1).max(2048)}).strict(),Jd=a.z.object({id:a.z.string().trim().min(1).max(120),sessionId:a.z.string().trim().min(1).max(120)}).strict(),Yd=a.z.object({storyPath:xd}).strict(),Xd=Yd.extend({title:a.z.string().trim().min(1).max(240).optional(),expectedRevision:a.z.string().regex(/^[a-f0-9]{64}$/).optional()}).strict();function Qd(e){const t=e.authorization;return"string"==typeof t&&t.startsWith("Bearer ")?t.slice(7).trim():void 0}function Zd(e,t,n,i,s){const r=e.authenticateInstance(n,s).aiSessions.sessions.find(e=>e.id===i);if(!r)throw Object.assign(new Error("AI Session was not found in the authoritative instance snapshot."),{code:"AI_SESSION_NOT_FOUND",statusCode:404});if(!r.storyId)throw Object.assign(new Error("AI Session is not assigned to a Story."),{code:"STORY_CONTEXT_REQUIRED",statusCode:409});return t.get(r.storyId)||(()=>{throw Object.assign(new Error("Story was not found."),{code:"STORY_NOT_FOUND",statusCode:404})})()}function el(e,n,i,s){return e.header("content-type","application/octet-stream"),e.header("content-length",String(s)),e.header("x-story-revision",i),e.send(t.createReadStream(n))}const tl=a.z.object({title:a.z.string().trim().min(1).max(240),storyPath:xd}).strict(),nl=a.z.object({id:$d.shape.id,title:$d.shape.title,description:$d.shape.description,documents:a.z.array(tl).max(500).default([]),actions:$d.shape.actions,createdAt:$d.shape.createdAt,updatedAt:$d.shape.updatedAt,archivedAt:$d.shape.archivedAt}).strict();function il(e,t,n){return Object.assign(new Error(t),{code:e,statusCode:n})}class sl{records;paths;ownerNodeId;maxFileBytes;onChange;constructor(e,t,n=33554432,i){this.paths=e,this.ownerNodeId=t,this.maxFileBytes=n,this.onChange=i,this.records=new Ca(e.storyRegistryDir,{schema:nl})}init(){this.records.init(),t.mkdirSync(this.paths.storyContentDir,{recursive:!0,mode:448}),t.chmodSync(this.paths.storyContentDir,448)}setOnChange(e){this.onChange=e}list(){return this.records.list().map(e=>this.project(e))}get(e){const t=this.records.get(e);return t?this.project(t):void 0}require(e){const t=this.records.get(e);if(!t)throw il("STORY_NOT_FOUND","Story was not found.",404);return t}create(e){const n=Ud.parse(e),i=(new Date).toISOString(),s=_a("story"),r=nl.parse({id:s,title:n.title,description:n.description,actions:(n.actions||[]).map(e=>jd.parse({...e,id:_a("story_action")})),documents:[],createdAt:i,updatedAt:i});t.mkdirSync(this.storyRoot(s),{recursive:!0,mode:448});const o=this.project(this.records.put(r));return this.onChange?.("created",o),o}update(e,t){const n=this.require(e),i=Hd.parse(t),s=this.records.put(nl.parse({...n,...void 0!==i.title?{title:i.title}:{},...void 0!==i.description?{description:i.description||void 0}:{},...void 0!==i.actions?{actions:i.actions.map(e=>jd.parse({...e,id:e.id||_a("story_action")}))}:{},updatedAt:(new Date).toISOString()})),r=this.project(s);return this.onChange?.("updated",r),r}archive(e){const t=this.require(e),n=(new Date).toISOString(),i=this.project(this.records.put({...t,archivedAt:n,updatedAt:n}));return this.onChange?.("archived",i),i}restore(e){const t=this.require(e),n=this.project(this.records.put({...t,archivedAt:void 0,updatedAt:(new Date).toISOString()}));return this.onChange?.("restored",n),n}delete(e){const n=this.require(e),i=this.project(n);t.rmSync(this.storyRoot(e),{recursive:!0,force:!0});const s=this.records.delete(e);return this.onChange?.("deleted",i),s}listContent(e){return this.project(this.require(e)).documents}filePath(e,t){this.require(e);const i=xd.parse(t),s=this.storyRoot(e),r=n.resolve(s,...i.split("/"));if(r===s||!r.startsWith(`${s}${n.sep}`))throw il("STORY_PATH_OUTSIDE_ROOT","Story path is outside the Story directory.",400);return r}readContent(e,t){if(!this.require(e).documents.some(e=>e.storyPath===t))throw il("STORY_CONTENT_NOT_INDEXED","Story content is not indexed.",404);const n=this.filePath(e,t);return{filePath:n,size:this.regularFileStat(n).size,revision:this.hashFile(n)}}async writeContent(e,i){const s=this.require(e);if(s.archivedAt)throw il("STORY_ARCHIVED","Archived Story content is read-only.",409);const r=xd.parse(i.storyPath),o=s.documents.find(e=>e.storyPath===r);if(o){if(!i.expectedRevision)throw il("STORY_REVISION_REQUIRED","expectedRevision is required when replacing Story content.",409);if(this.readContent(e,r).revision!==i.expectedRevision)throw il("STORY_REVISION_CONFLICT","Story content changed since it was read.",409)}else if(!i.title?.trim())throw il("STORY_CONTENT_TITLE_REQUIRED","A title is required for new Story content.",400);const a=this.filePath(e,r);t.mkdirSync(n.dirname(a),{recursive:!0,mode:448});const c=`${a}.${process.pid}.${d.randomUUID()}.tmp`;let l=0;const u=new h.Transform({transform:(e,t,n)=>{l+=e.byteLength,l>this.maxFileBytes?n(il("STORY_FILE_TOO_LARGE","Story content exceeds the node limit.",413)):n(null,e)}});try{await f.pipeline(i.stream,u,t.createWriteStream(c,{mode:384})),t.renameSync(c,a)}catch(e){throw t.rmSync(c,{force:!0}),e}const p=o?s.documents.map(e=>e.storyPath===r?{...e,...i.title?.trim()?{title:i.title.trim()}:{}}:e):[...s.documents,{title:i.title.trim(),storyPath:r}],m=this.project(this.records.put({...s,documents:p,updatedAt:(new Date).toISOString()}));return this.onChange?.("content.written",m),{storyPath:r,revision:this.hashFile(a),size:l}}updateDocument(e,i,s){const r=this.require(e),o=xd.parse(i),a=r.documents.findIndex(e=>e.storyPath===o);if(a<0)throw il("STORY_CONTENT_NOT_INDEXED","Story content is not indexed.",404);const c=s.storyPath?xd.parse(s.storyPath):o;if(c!==o&&r.documents.some(e=>e.storyPath===c))throw il("STORY_PATH_CONFLICT","Story path is already indexed.",409);if(c!==o){const i=this.filePath(e,o),s=this.filePath(e,c);this.regularFileStat(i);try{throw t.lstatSync(s),il("STORY_PATH_CONFLICT","Story path already exists on disk.",409)}catch(e){if("ENOENT"!==e.code)throw e}t.mkdirSync(n.dirname(s),{recursive:!0,mode:448}),t.renameSync(i,s)}const d=[...r.documents];d[a]={title:s.title?.trim()||d[a].title,storyPath:c};const l=this.project(this.records.put({...r,documents:d,updatedAt:(new Date).toISOString()}));return this.onChange?.("document.updated",l),l}reorderDocuments(e,t){const n=this.require(e),{storyPaths:i}=Bd.parse(t),s=n.documents.map(e=>e.storyPath);if(i.length!==s.length||new Set(i).size!==i.length||s.some(e=>!i.includes(e)))throw il("STORY_DOCUMENT_ORDER_INVALID","Document order must contain every indexed storyPath exactly once.",400);const r=new Map(n.documents.map(e=>[e.storyPath,e])),o=i.map(e=>r.get(e)),a=this.project(this.records.put({...n,documents:o,updatedAt:(new Date).toISOString()}));return this.onChange?.("document.reordered",a),a}deleteDocument(e,n){const i=this.require(e),s=xd.parse(n);if(!i.documents.some(e=>e.storyPath===s))return!1;t.rmSync(this.filePath(e,s),{force:!0});const r=this.project(this.records.put({...i,documents:i.documents.filter(e=>e.storyPath!==s),updatedAt:(new Date).toISOString()}));return this.onChange?.("document.deleted",r),!0}project(e){const t=e.documents.flatMap(t=>{const n=this.filePathWithoutLookup(e.id,t.storyPath);try{return this.regularFileStat(n),[{...t,revision:this.hashFile(n)}]}catch(e){if("ENOENT"===e.code)return[];throw e}});return t.length!==e.documents.length&&(e=this.records.put({...e,documents:t.map(({revision:e,...t})=>t),updatedAt:(new Date).toISOString()})),$d.parse({...e,ownerNodeId:this.ownerNodeId,documents:t})}storyRoot(e){return n.resolve(this.paths.storyContentDir,$d.shape.id.parse(e))}filePathWithoutLookup(e,t){const i=this.storyRoot(e),s=n.resolve(i,...xd.parse(t).split("/"));if(!s.startsWith(`${i}${n.sep}`))throw il("STORY_PATH_OUTSIDE_ROOT","Story path is outside the Story directory.",400);return s}regularFileStat(e){const n=t.lstatSync(e);if(n.isSymbolicLink()||!n.isFile())throw il("STORY_CONTENT_NOT_FILE","Story content must be a regular file.",409);if(n.size>this.maxFileBytes)throw il("STORY_FILE_TOO_LARGE","Story content exceeds the node limit.",413);return n}hashFile(e){const n=d.createHash("sha256"),i=t.openSync(e,"r"),s=Buffer.allocUnsafe(65536);try{let e=0;do{e=t.readSync(i,s,0,s.length,null),e>0&&n.update(s.subarray(0,e))}while(e>0)}finally{t.closeSync(i)}return n.digest("hex")}}const rl=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(),ol=a.z.object({id:a.z.string().trim().min(1).max(120).optional(),name:a.z.string().trim().max(160),path:a.z.string().trim().min(1).max(4096),defaultImageSelection:qn.optional(),labels:a.z.record(a.z.string(),a.z.string()).default({})}).strict(),al=a.z.object({name:a.z.string().trim().max(160)}).strict(),cl=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(),dl=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:qn.optional(),environmentSource:Kn.optional(),projectId:a.z.string().trim().min(1).max(120).optional(),image:fs.optional(),source:$i,sourceSnapshot:a.z.record(a.z.string(),a.z.unknown()).default({}),config:a.z.object({autoImportAgentConfigs:a.z.boolean().optional(),codexConfigEnabled:a.z.boolean().optional(),codexHomeMode:a.z.enum(["default","taskhandoff"]).optional(),defaultCodexPermissionMode:qe.optional(),aiSessionHistoryLimit:a.z.number().int().min(1).max(wt).optional(),aiSessionAttachmentRetentionDays:a.z.number().int().min(0).max(365).optional(),aiSessionMaxFileAttachmentBytes:a.z.number().int().positive().max(de).optional()}).strict().optional(),modelSelection:Bs.shape.modelSelection,gitWorkspaceProvisioning:_c.optional()}).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."}),e.gitWorkspaceProvisioning&&"local-folder"===e.source.type&&t.addIssue({code:"custom",path:["gitWorkspaceProvisioning"],message:"Git provisioning requires a Git source."})}),ll=a.z.object({name:a.z.string().trim().min(1).max(160).optional(),config:a.z.object({autoImportAgentConfigs:a.z.boolean().optional(),codexConfigEnabled:a.z.boolean().optional(),codexHomeMode:a.z.enum(["default","taskhandoff"]).optional(),defaultCodexPermissionMode:qe.optional(),aiSessionHistoryLimit:a.z.number().int().min(1).max(wt).optional(),aiSessionAttachmentRetentionDays:a.z.number().int().min(0).max(365).optional(),aiSessionMaxFileAttachmentBytes:a.z.number().int().positive().max(de).optional()}).strict().optional(),modelSelection:Bs.shape.modelSelection.optional()}).strict(),ul=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(),pl=ul.omit({id:!0}).partial().strict();function ml(e){const t=e.authorization;return"string"==typeof t&&t.startsWith("Bearer ")?t.slice(7).trim():void 0}class hl{operations=new Map;intents=new Map;intent(e){const t=this.intents.get(e);if(t)return t;const n={controller:new AbortController};return this.intents.set(e,n),n}invalidate(e){this.intents.get(e)?.controller.abort();const t={controller:new AbortController};return this.intents.set(e,t),t}isIntentCurrent(e,t){return this.intents.get(e)===t}signal(e,t){const n=this.intents.get(e);return n===t?n.controller.signal:AbortSignal.abort()}clearIntent(e){this.intents.delete(e)}async run(e,t){const n=this.operations.get(e)||Promise.resolve();let i;const s=new Promise(e=>{i=e});this.operations.set(e,s),await n;try{return await t()}finally{i(),this.operations.get(e)===s&&this.operations.delete(e)}}}const gl=a.z.object({gitWorkspaceProvisioning:_c.optional()}).strict().default({});class fl{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=te();return this.state.controlledInstances.put(Bs.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}`,s=this.inFlight.get(i);if(s)return s;const r=this.provisionGeneration(e,n,t).finally(()=>{this.inFlight.get(i)===r&&this.inFlight.delete(i)});return this.inFlight.set(i,r),r}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 s,r=0,o=!1,a=Promise.resolve();try{const c=await this.images.ensure(i.imageSnapshot.requestedReference,n=>{a=a.then(async()=>{if(!s)try{await this.updatePhase(e.id,t,n,e.createdAt)}catch(e){s={error:e}}})},n=>{this.stopped||(o=!0,r=n.sequence,this.publishTerminalOutput(e,t,n))},this.abortController.signal);if(await a,s)throw s.error;if(this.stopped)return;o&&this.publishFinished(e,t,r+1,"succeeded");const d=async()=>{if(this.stopped)return;const i=this.currentGeneration(e.id,t,!0,e.createdAt);if(!i)return;const s=this.state.controlledInstances.put(Bs.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:te()},updatedAt:te()}));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"===s.status&&await(n?.())};await(this.options.runInstanceOperation?.(e.id,d)??d())}catch(n){if(await a,s&&(n=s.error),this.stopped)return;o&&this.publishFinished(e,t,r+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(Bs.parse({...n,status:"failed",health:"failed",imageProvisioning:{...n.imageProvisioning,phase:"failed",error:i,updatedAt:te()},updatedAt:te()})),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 s=this.state.controlledInstances.get(e);if(!(!s||i&&s.createdAt!==i||s.imageProvisioning?.generation!==t||n&&!s.imageSnapshot))return s}async updatePhase(e,t,n,i){if(this.stopped)return;const s=async()=>{if(this.stopped)return;const s=this.currentGeneration(e,t,!0,i);s&&["provisioning","starting"].includes(s.status)&&(this.state.controlledInstances.put(Bs.parse({...s,status:"starting"===s.status?"starting":"provisioning",imageProvisioning:{...s.imageProvisioning,phase:n,error:void 0,updatedAt:te()},updatedAt:te()})),this.options.sync())};await(this.options.runInstanceOperation?.(e,s)??s())}eventBase(e,t){return{instanceId:e.id,generation:t,requestedReference:e.imageProvisioning.requestedReference,observedAt:te()}}publishTerminalOutput(e,t,n){for(const[i,s]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(Is,{...this.eventBase(e,t),sequence:1e3*n.sequence+i,data:s,...n.replay?{replay:!0}:{}},e.id)}publishFinished(e,t,n,i){this.options.publish(As,{...this.eventBase(e,t),sequence:1e3*n,outcome:i},e.id)}}const yl=a.z.object({name:a.z.string().trim().min(1).max(160)}).strict();function Il(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 Al{templateOperations=new hl;store;privateConfigs;docker;requireInstanceValue;requireRuntimeValue;runInstanceOperationValue;isImageReferencedValue;constructor(e,t,n,i,s,r,o=()=>!1){this.store=e,this.privateConfigs=t,this.docker=n,this.requireInstanceValue=i,this.requireRuntimeValue=s,this.runInstanceOperationValue=r,this.isImageReferencedValue=o}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=yl.parse(t),i=this.requireInstanceValue(e),s=this.requireRuntimeValue(i.runtimeId);if("docker"!==s.type)throw Object.assign(new Error(`Runtime ${s.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 r=te(),o=_a("envtpl"),a=`task-handoff/environment-template:${o.toLowerCase().replace(/[^a-z0-9_.-]/g,"-")}`;return this.store.put(ci.parse({id:o,name:n.name,sourceInstanceId:i.id,nodeId:i.nodeId,internalTag:a,status:"creating",createdAt:r,updatedAt:r})),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 s=this.privateConfigs.get(i.id);if(!s)throw Object.assign(new Error(`Instance ${i.id} private configuration is missing.`),{code:"INSTANCE_PRIVATE_CONFIG_MISSING"});const r=[s.instanceCredential,...Object.values(s.environment)];await this.docker.inspectContainerConfigSecurity(n.runtime.containerName,r),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,r),this.store.put(ci.parse({...this.require(o),...c,status:"ready",error:void 0,updatedAt:te()}))}catch(n){return t&&(await this.docker.untagEnvironmentTemplate(a,e).catch(()=>!1),e&&await this.docker.garbageCollectEnvironmentTemplateImage(e).catch(()=>!1)),this.store.put(ci.parse({...this.require(o),status:"failed",error:Il(n,"ENVIRONMENT_TEMPLATE_CREATE_FAILED","commit"),updatedAt:te()}))}})}async delete(e){return this.runTemplateOperation(e,async()=>{const t=this.require(e);this.store.put(ci.parse({...t,status:"deleting",error:void 0,updatedAt:te()}));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(ci.parse({...t,status:"failed",error:Il(e,"ENVIRONMENT_TEMPLATE_DELETE_FAILED","delete"),updatedAt:te()})),e}})}async releaseUnusedImage(e){return!this.store.list().some(t=>t.imageId===e)&&!this.isImageReferencedValue(e)&&this.docker.garbageCollectEnvironmentTemplateImage(e)}}const bl=new Set(["content-encoding","content-length","transfer-encoding"]),vl=67108864;function wl(e){return Object.fromEntries([...e.entries()].filter(([e])=>!bl.has(e.toLowerCase())))}function Sl(e){return e.bodyBase64?Buffer.from(e.bodyBase64,"base64"):e.body}function El(){const e=Number(process.env.TASK_HANDOFF_INSTANCE_PROXY_MAX_RESPONSE_BYTES);return Number.isSafeInteger(e)&&e>0?e:67108864}const zl="x-task-handoff-trace-id";function Nl(e){return e.startsWith("/")?e:`/${e}`}function Tl(e,t){return e.code(502).send({error:{code:"INSTANCE_PROXY_RESPONSE_TOO_LARGE",message:`Instance response exceeds ${t} bytes.`}})}async function _l(e,t,n,i){try{return await e(t,n)}catch(e){if(n.signal?.aborted)throw e;throw i.diagnostic({instanceId:i.instanceId,action:"proxy.upstream.failed",method:i.method,path:i.path,error:e instanceof Error?e.message:String(e)},"node instance proxy upstream unavailable"),Object.assign(new Error(`Instance ${i.instanceId} web endpoint is not reachable.`),{statusCode:502,code:"INSTANCE_PROXY_UPSTREAM_UNREACHABLE",retryable:!0,cause:e})}}function kl(e,t){return Object.assign(new Error(`Instance ${e.id} has an invalid node-owned web endpoint: ${t}`),{statusCode:409,code:"NODE_INSTANCE_WEB_ENDPOINT_INVALID"})}function Cl(e,t){const n=t||("local"===e.runtime?.kind&&e.runtime.port?`http://127.0.0.1:${e.runtime.port}`:void 0);if(!n){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}let i;try{i=new URL(n)}catch{throw kl(e,"endpoint is not a URL")}if("http:"!==i.protocol||"127.0.0.1"!==i.hostname||!i.port||i.username||i.password||"/"!==i.pathname&&""!==i.pathname||i.search||i.hash)throw kl(e,"endpoint must be an origin-only http://127.0.0.1:<port> URL");return i.origin}const Ol=a.z.object({version:a.z.literal(1),externalListener:Ps}).strict();function xl(e){return"all-ipv4"===e?"0.0.0.0":"127.0.0.1"}function Rl(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),s=Object.keys(n).filter(e=>"bindScope"!==e&&"port"!==e);return(i.length||s.length)&&console.warn(JSON.stringify({message:"unknown stored node agent runtime setting fields were ignored",filePath:"runtime-settings.json",fields:[...i,...s.map(e=>`externalListener.${e}`)]})),{version:t.version,externalListener:{bindScope:n.bindScope,port:n.port}}}async function Pl(e){const t=xl(e.bindScope);return!await new Promise(t=>{const n=m.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=m.createServer();i.once("error",()=>n(!1)),i.listen({host:t,port:e.port,exclusive:!0},()=>i.close(()=>n(!0)))})}class Dl{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 Ds.parse({...this.config,host:xl(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:xl(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 ${xl(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=Ms.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 ${xl(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",s),n(e)},s=()=>{this.app.server.off("error",i),t()};this.app.server.once("error",i),this.app.server.once("listening",s),this.app.server.listen({host:xl(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 Ml="TASK_HANDOFF_NODE_AGENT_V1",jl="/api/node-tunnel";function Ll(e=""){return d.createHash("sha256").update(e).digest("hex")}function Fl(e,t){return d.createHmac("sha256",e).update(function(e){return[Ml,e.keyId,e.method.toUpperCase(),e.pathWithQuery,e.timestamp,e.nonce,e.bodySha256].join("\n")}(t)).digest("hex")}function $l(e){const t=e.timestamp||(new Date).toISOString(),n=e.nonce||d.randomBytes(18).toString("base64url"),i=Ll(e.body||""),s=Fl(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":s}}class Ul{usedNonces=new Map;identity;nodeId;overrideSecret;overrideKeyId;nowMs;constructor(e,t,n,i,s=Date.now){this.identity=e,this.nodeId=t,this.overrideSecret=n,this.overrideKeyId=i,this.nowMs=s}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 s=i.filter(e=>t.keyId===e.keyId);if(!s.length)throw Object.assign(new Error("Invalid node agent HMAC key id."),{statusCode:401,code:"NODE_AGENT_HMAC_KEY_INVALID"});const r=Date.parse(t.timestamp);if(!Number.isFinite(r)||Math.abs(this.nowMs()-r)>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 o=`${t.nodeId}:${t.keyId}:${t.nonce}`;if(this.usedNonces.has(o))throw Object.assign(new Error("Node agent HMAC nonce was already used."),{statusCode:401,code:"NODE_AGENT_HMAC_NONCE_REPLAY"});const a=Ll(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(!s.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,Fl(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(o,r+6e4+1),t.keyId}pruneNonces(){const e=this.nowMs();for(const[t,n]of this.usedNonces)n<=e&&this.usedNonces.delete(t)}}const Hl=a.z.string().trim().min(1).max(160),Vl=a.z.string().datetime(),Bl=a.z.string().min(1).max(4096),ql=a.z.string().trim().url().max(2048),Kl=a.z.object({id:Hl,keyId:Hl,name:a.z.string().trim().min(1).max(160).optional(),secret:Bl,pairedAt:Vl,revokedAt:Vl.optional(),updatedAt:Vl}).strip(),Gl=a.z.object({id:Hl,pairingKeyId:Hl,name:a.z.string().trim().min(1).max(160).optional(),url:ql,enabled:a.z.boolean().default(!0),createdAt:Vl,updatedAt:Vl}).strip(),Wl=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(),Jl=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(),Yl=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(),Xl=new Set(["nodeId","createdAt","updatedAt","pairingInvites","controlPlanePairings","controlPlaneConnections","remoteControlPlanes"]),Ql=new Set(["id","keyId","name","secret","pairedAt","revokedAt","updatedAt"]),Zl=new Set(["id","pairingKeyId","name","url","enabled","createdAt","updatedAt"]),eu=new Set(["id","keyId","name","url","secret","pairedAt","updatedAt","active"]);function tu(e,t){console.warn(JSON.stringify({message:e,...t}))}function nu(e,t){return Object.assign(new Error(e,void 0===t?void 0:{cause:t}),{code:"NODE_AGENT_IDENTITY_INVALID"})}function iu(e,t){return Object.keys(e).filter(e=>!t.has(e))}function su(e,t,n){const i=Vl.safeParse(e);return i.success?i.data:(n("invalid node agent identity timestamp was replaced",{field:t}),te())}function ru(e,t){if(!e||"object"!=typeof e||Array.isArray(e))throw nu("Node agent identity must be a JSON object.");const n=e,i=Hl.safeParse(n.nodeId);if(!i.success)throw nu("Node agent identity has an invalid nodeId.",i.error);const s=i.data,r=iu(n,Xl);r.length&&t("unknown node agent identity fields were ignored",{fields:r}),Array.isArray(n.pairingInvites)&&n.pairingInvites.length&&t("persisted node agent pairing invites were discarded",{count:n.pairingInvites.length});const o=Array.isArray(n.remoteControlPlanes)?n.remoteControlPlanes.flatMap(e=>{if(!e||"object"!=typeof e||Array.isArray(e))return[];const n=e,i=iu(n,eu);i.length&&t("unknown legacy node agent remote control-plane fields were ignored",{fields:i});const s=Kl.safeParse(n);if(!s.success)return t("invalid legacy node agent control-plane pairing was ignored",{issues:s.error.issues}),[];const r=n.url?Gl.safeParse({id:`connection_${s.data.keyId}`,pairingKeyId:s.data.keyId,name:n.name,url:n.url,enabled:!1!==n.active,createdAt:s.data.pairedAt,updatedAt:s.data.updatedAt}):void 0;return[{pairing:s.data,...r?.success?{connection:r.data}:{}}]}):[],a=(e,n,i,s)=>Array.isArray(e)?e.flatMap(e=>{if(!e||"object"!=typeof e||Array.isArray(e))return t(`invalid node agent ${s} was ignored`,{}),[];const r=iu(e,n);r.length&&t(`unknown node agent ${s} fields were ignored`,{fields:r});const o=i.safeParse(e);return o.success?[o.data]:(t(`invalid node agent ${s} was ignored`,{issues:o.error.issues}),[])}):[];return{nodeId:s,createdAt:su(n.createdAt,"createdAt",t),updatedAt:su(n.updatedAt,"updatedAt",t),controlPlanePairings:n.controlPlanePairings?a(n.controlPlanePairings,Ql,Kl,"control-plane pairing"):o.map(e=>e.pairing),controlPlaneConnections:n.controlPlaneConnections?a(n.controlPlaneConnections,Zl,Gl,"control-plane connection"):o.flatMap(e=>e.connection?[e.connection]:[])}}class ou{paths;logger;constructor(e,t={}){this.paths=e,this.logger=t.logger||tu}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 nu(`Node agent identity contains invalid JSON: ${this.paths.identityPath}`,e)}return ru(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=ru({...e,updatedAt:te()},this.logger);I.sync(this.paths.identityPath,`${JSON.stringify(i,null,2)}\n`,{encoding:"utf8",mode:384})}}class au{values=new Map;put(e,t,n=Date.now()){this.prune(n),this.values.set(e,t)}take(e,t=Date.now()){this.prune(t);const n=this.values.get(e);return n&&this.values.delete(e),n}peek(e,t=Date.now()){return this.prune(t),this.values.get(e)}delete(e,t=Date.now()){this.prune(t);const n=this.values.get(e);return n&&this.values.delete(e),n}list(e=Date.now()){return this.prune(e),[...this.values.values()]}prune(e=Date.now()){for(const[t,n]of this.values)Date.parse(n.expiresAt)<=e&&this.values.delete(t)}}class cu{store;pairingInvites=new au;controlPlaneConnectionOperations=new Map;constructor(e){this.store=new ou(e),this.store.init()}async runControlPlaneConnectionOperation(e,t){const n=e.replace(/\/$/,""),i=this.controlPlaneConnectionOperations.get(n)||Promise.resolve();let s;const r=new Promise(e=>{s=e});this.controlPlaneConnectionOperations.set(n,r),await i;try{return await t()}finally{s(),this.controlPlaneConnectionOperations.get(n)===r&&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=_a("node");return this.writeNodeId(n),n}createPairingInvite(e){const t=te(),n=new Date(Date.now()+(e.expiresInMs||6e5)).toISOString(),i=ka(),s={tokenHash:Ll(i),createdAt:t,expiresAt:n,...e.controlPlaneName?{controlPlaneName:e.controlPlaneName}:{}};return this.pairingInvites.put(s.tokenHash,s),{...s,token:i}}completePairingInvite(e){const t=this.store.read()||this.newIdentity(),n=Ll(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 s=te(),r={id:e.controlPlaneId||_a("cp"),keyId:_a("key"),...e.controlPlaneName||i.controlPlaneName?{name:e.controlPlaneName||i.controlPlaneName}:{},secret:ka(),pairedAt:s,updatedAt:s};return this.store.write({...t,controlPlanePairings:[...(t.controlPlanePairings||[]).filter(e=>e.id!==r.id),r]}),r}stageControlPlaneConnection(e){const{pairing:t,connection:n}=this.createControlPlaneConnection(e),i=this.store.read()||this.newIdentity(),s=n.url.replace(/\/$/,""),r=(i.controlPlaneConnections||[]).filter(e=>e.id===n.id||e.url.replace(/\/$/,"")===s);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(/\/$/,"")!==s),n]}),{pairing:t,connection:n,replacedConnections:r}}commitControlPlaneConnection(e,t={}){const n=this.store.read()||this.newIdentity(),i={...e.pairing,...t.name?{name:t.name}:{}},s={...e.connection,...t.name?{name:t.name}:{}},r=new Set((n.controlPlaneConnections||[]).map(e=>e.pairingKeyId)),o=new Set(e.replacedConnections.map(e=>e.pairingKeyId));return this.store.write({...n,controlPlanePairings:[...(n.controlPlanePairings||[]).filter(e=>e.keyId!==i.keyId&&(!o.has(e.keyId)||r.has(e.keyId))),i],controlPlaneConnections:[...(n.controlPlaneConnections||[]).filter(e=>e.id!==s.id),s]}),{pairing:i,connection:s}}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=te(),n={id:_a("cp"),keyId:_a("key"),...e.name?{name:e.name}:{},secret:ka(),pairedAt:t,updatedAt:t};return{pairing:n,connection:{id:_a("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=te();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(),s=(i?.controlPlanePairings||[]).filter(e=>!e.revokedAt);if(!s.length)return;if(e){const t=e.replace(/\/$/,""),n=(i?.controlPlaneConnections||[]).find(e=>e.url.replace(/\/$/,"")===t),r=n&&s.find(e=>e.keyId===n.pairingKeyId);if(r)return{keyId:r.keyId,secret:r.secret}}const r=[...s].sort((e,t)=>t.updatedAt.localeCompare(e.updatedAt))[0];return r?{keyId:r.keyId,secret:r.secret}:void 0}newIdentity(){return{nodeId:this.resolveNodeId(),createdAt:te(),updatedAt:te(),controlPlanePairings:[],controlPlaneConnections:[]}}writeNodeId(e){const t=this.store.read();this.store.write({...t||{createdAt:te()},nodeId:e,updatedAt:te(),controlPlanePairings:t?.controlPlanePairings||[],controlPlaneConnections:t?.controlPlaneConnections||[]})}}const du=a.z.string().trim().min(1).max(160);const lu=Ri.strict();function uu(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 pu{preflights=new Map;options;applying=!1;constructor(e){this.options=e}async check(e){const t=Ci.parse(e),n=uu(this.options.listInstances()),i=await Ga(this.options.runCommand,this.options.moduleDir),s=this.options.currentRuntimeVersion(),r=this.options.managedUpdateSupport?.(i)||{supported:!0};if(!r.supported)return Oi.parse({source:"npm",channel:t.channel,currentVersion:i.currentVersion||s,availableVersion:i.currentVersion||s||"unavailable",impact:n,updateAvailable:!1,supported:!1,reason:r.reason||"Managed updates are unavailable on this node.",checkedAt:(new Date).toISOString()});const o="@task-handoff/server"===i.packageName?[...new Set([...i.relatedCurrentVersions,s])]:i.relatedCurrentVersions,a=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),s=await e(qa(),["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(!s)return;const r=JSON.parse(s.stdout);if("string"!=typeof r)throw new Error(`npm did not resolve ${t}@${i} to one version.`);return r}(e.runCommand,t,e.channel);if(!n)return function(e){return Oi.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:te()})}({channel:e.channel,currentVersion:e.currentVersion,impact:e.impact});const i=Ba(e.currentVersion,n)||(e.relatedCurrentVersions||[]).some(e=>Ba(e,n)),s=i?await async function(e,t,n){const i=await e(qa(),["view",`${t}@${n}`,"dist.integrity","--json"]),s=JSON.parse(i.stdout);if("string"!=typeof s||!/^sha(?:256|384|512)-[A-Za-z0-9+/=]+$/.test(s))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 s}(e.runCommand,t,n):void 0;return Oi.parse({source:"npm",channel:e.channel,currentVersion:e.currentVersion,availableVersion:n,...s?{artifactRef:`npm:${t}@${n}#${s}`}:{},runtimeArtifacts:e.runtimeArtifacts||[],impact:e.impact||{runningInstanceCount:0,stoppedInstanceCount:0,activeInstanceCount:0,restartInstanceCount:0,runningInstanceIds:[],stoppedInstanceIds:[],activeInstanceIds:[]},updateAvailable:i,checkedAt:te()})}({channel:t.channel,currentVersion:i.currentVersion||s,runCommand:this.options.runCommand,packageName:i.packageName,relatedCurrentVersions:o,impact:n});if(!a.updateAvailable)return a;const c={...a,runtimeArtifacts:await this.options.resolveRuntimeArtifacts(a.availableVersion),preflightToken:ka()};return this.preflights.set(c.preflightToken,{result:c,expiresAt:Date.now()+6e5}),c}async apply(e){const i=lu.parse(e),s=this.preflights.get(i.preflightToken);(!s||s.expiresAt<=Date.now())&&await this.consumePreflight(i),this.applying&&this.throwAlreadyRunning(),this.applying=!0;try{const{check:e,selection:s}=await this.consumePreflight(i);if(this.options.jobs.list().some(e=>!["succeeded","degraded","failed"].includes(e.status))&&this.throwAlreadyRunning(),!e.supported)throw Object.assign(new Error(e.reason||"The requested update is not supported."),{statusCode:400,code:"UPDATE_UNSUPPORTED"});if(!e.updateAvailable)throw Object.assign(new Error(e.reason||"No update is available for the selected channel."),{statusCode:409,code:"UPDATE_NOT_AVAILABLE"});const r=this.options.jobs.create(this.options.nodeId,e),{worker:o,packaged:a,expectedWorker:c}=function(e,i=t.existsSync){const s=[n.resolve(e,"..","bin","task-handoff-node-update-worker"),n.resolve(e,"..","..","bin","task-handoff-node-update-worker")],r=s.find(i),o=n.resolve(e,"..","..","..","..","scripts","node-update-worker.cts");return r?{worker:r,packaged:!0,expectedWorker:s[0]}:i(o)?{worker:o,packaged:!1,expectedWorker:s[0]}:{worker:void 0,packaged:!1,expectedWorker:s[0]}}(this.options.moduleDir);if(!o)throw this.options.jobs.patch(r.id,{status:"failed",rollout:{...r.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-${r.id}`,"--collect","--property=Type=exec",...a?[o]:[process.execPath,o],"--job-file",this.options.jobs.records.filePath(r.id),"--target-version",r.toVersion,"--npm-command",qa(),"--install-prefix",s.installPrefix,...process.env.TASK_HANDOFF_NODE_AGENT_IPC_PATH?.trim()?["--node-agent-ipc-path",process.env.TASK_HANDOFF_NODE_AGENT_IPC_PATH.trim()]:[],...d?["--control-plane-health-url",d]:[]])}catch(e){const t=e instanceof Error?e.message:String(e);throw this.options.jobs.patch(r.id,{status:"failed",rollout:{...r.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 await this.waitForWorkerClaim(r)}finally{this.applying=!1}}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 Ga(this.options.runCommand,this.options.moduleDir);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(uu(this.options.listInstances()))||this.throwStale();const s=await this.options.resolveRuntimeArtifacts(n.availableVersion);return JSON.stringify(n.runtimeArtifacts)!==JSON.stringify(s)&&this.throwStale(),{check:n,selection:i}}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"})}throwAlreadyRunning(){throw Object.assign(new Error("Another server update is already running on this node."),{statusCode:409,code:"SERVER_UPDATE_ALREADY_RUNNING"})}async waitForWorkerClaim(e){const t=this.options.workerClaimTimeoutMs??5e3,n=this.options.workerClaimPollMs??50,i=Date.now()+t;for(;Date.now()<=i;){const t=this.options.jobs.records.get(e.id);if(!t)throw Object.assign(new Error(`Update job ${e.id} disappeared before the worker claimed it.`),{statusCode:500,code:"UPDATE_JOB_NOT_FOUND"});if("queued"!==t.status)return t;if(Date.now()>=i)break;await new Promise(e=>setTimeout(e,Math.max(1,Math.min(n,i-Date.now()))))}const s=this.options.jobs.records.get(e.id);if("queued"!==s?.status)return s||e;throw this.options.jobs.patch(e.id,{status:"failed",rollout:{...s.rollout,phase:"failed"},error:{code:"NODE_UPDATE_FAILED",message:"The node update worker did not claim the queued job after systemd accepted it.",retryable:!0},completedAt:(new Date).toISOString()}),Object.assign(new Error("The node update worker did not start after systemd accepted the update job."),{statusCode:500,code:"NODE_UPDATE_WORKER_START_TIMEOUT"})}}const mu=new Set(["provisioning","starting","registering","registered","running"]);function hu(e){return mu.has(e.status)&&!fa(e)}function gu(e){return Bs.parse({...e,health:"unknown",connectionStatus:"offline",agentStatus:"offline",targetStatus:"unknown",uiAccessStatus:"unknown",target:{...e.target,status:"unknown"},updatedAt:te()})}class fu{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);return!["failed","stopping","stopped"].includes(t.status)&&!fa(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(),s=this.unexpectedExitRetries.get(e),r=this.options.crashStableWindowMs??3e4,o=s&&i-s.lastExitAt<r?s.attempt+1:1;this.unexpectedExitRetries.set(e,{attempt:o,lastExitAt:i});const a=this.options.retryBaseDelayMs??1e3,c=1===o?0:Math.min(this.options.retryMaxDelayMs??3e4,a*2**Math.min(o-2,10)),d=t instanceof Error?t.message:String(t);this.restoreErrors.set(e,{message:d,attempt:o,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(mu.has(t.status)||"failed"===t.status)&&(!e||e.nextAttemptAt<=(this.options.nowMs?.()??Date.now()))}return"docker"===n.type&&hu(t)});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),s=this.restoreErrors.get(n.id),r=(s?.attempt??0)+1,o=this.options.retryBaseDelayMs??1e3,a=Math.min(this.options.retryMaxDelayMs??3e4,o*2**Math.min(r-1,10)),c=(this.options.nowMs?.()??Date.now())+a;this.restoreErrors.set(n.id,{message:i,attempt:r,nextAttemptAt:c}),s?.message===i&&s.attempt===r||this.options.warn({instanceId:n.id,action:"restore",runtimeId:n.runtimeId,error:i,attempt:r,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(mu.has(e.status)||"failed"===e.status)&&(!t||t.nextAttemptAt<=(this.options.nowMs?.()??Date.now()))}return"docker"===t.type&&hu(e)}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)&&!fa(e)&&!["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(gu(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 s=t.get(n);return!s||this.restoredInstances.has(n)||this.suppressedInstances.has(n)||"local"!==this.options.state.requireRuntime(s.runtimeId).type?e:mu.has(s.status)||"failed"===s.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?.()}}}const yu=new Set(["DELETE","GET","HEAD","PATCH","POST","PUT","OPTIONS"]);function Iu(e){return"string"==typeof e&&yu.has(e.toUpperCase())?e.toUpperCase():"GET"}function Au(e,t){const n=new URL(t.tunnelUrl);n.searchParams.set("nodeId",t.nodeId);const i=t.secret?$l({nodeId:t.nodeId,keyId:t.keyId,secret:t.secret,method:"GET",pathWithQuery:`${n.pathname}${n.search}`}):{},s=new p(n,{headers:i}),r=new Map,o=new Map,a=new Map;let c;s.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,s=new URL(`/api/node-agent${n}`,`http://127.0.0.1:${i}`);return s.protocol="ws:",s},l=(e,n,i,s={})=>{const r=e.startsWith("/")?e:`/${e}`;return{...s,...t.secret&&t.keyId?$l({nodeId:t.nodeId,keyId:t.keyId,secret:t.secret,method:n,pathWithQuery:`/api/node-agent${r}`,body:i}):t.token?{authorization:`Bearer ${t.token}`}:{}}},u=e=>t.secret?$l({nodeId:t.nodeId,keyId:t.keyId,secret:t.secret,method:"GET",pathWithQuery:`${e.pathname}${e.search}`}):{},m=(e,t,n)=>{const i=r.get(e);r.delete(e),i?.upstream&&C(i.upstream,t,n),i?.tunnel&&C(i.tunnel,t,n)},h=(e,t,n=!1)=>new Promise((i,s)=>{e.send(t,{binary:n,compress:!1},e=>e?s(e):i())});s.on("open",()=>{s.send(JSON.stringify({type:"node-agent.identify",nodeId:t.nodeId,serverTime:(new Date).toISOString()})),c=e.nodeAgentEventForwarder?.addOutput(s,{legacyFallbackMs:1e3})}),s.on("close",()=>{for(const e of r.keys())m(e,1001,"Reverse tunnel disconnected.");for(const[e,t]of o)o.delete(e),t.controller.abort(),C(t.tunnel,1001,"Reverse tunnel disconnected.");for(const[e,t]of a)a.delete(e),t.abort();c?.(),c=void 0});return s.on("message",i=>{(async i=>{let c;try{c=JSON.parse(String(i))}catch{return void s.send(JSON.stringify({type:"node-agent.error",code:"INVALID_JSON"}))}const g=c&&"object"==typeof c?c:{};if("control-plane.event-subscribe"!==g.type){if("control-plane.http.open"===g.type){const i="string"==typeof g.streamId?g.streamId:"",r="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=Iu(a.method);let m;try{m=Dn(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 s.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 p(y,{headers:u(y)});return o.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}`)})(r),{method:d,headers:l(r,d,m,c),body:Buffer.isBuffer(m)?new Uint8Array(m):m,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===p.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{o.delete(i)}}),I.on("close",()=>{f.abort(),o.delete(i)}),void I.on("error",()=>f.abort())}if("control-plane.http.cancel"===g.type){const e="string"==typeof g.streamId?g.streamId:"",t=o.get(e);if(!t)return;return o.delete(e),t.controller.abort(),void C(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 o=l(t,"GET",void 0),a=i?.length?new p(d(t),i,{headers:o}):new p(d(t),{headers:o}),c=(e=>{const t=new URL(n);return t.pathname=`${t.pathname.replace(/\/$/,"")}/streams/${encodeURIComponent(e)}`,t})(e),m=new p(c,{headers:u(c)});r.set(e,{upstream:a,tunnel:m,close:(e=1e3,t="")=>{C(a,e,t),C(m,e,t)}}),a.on("open",()=>{s.send(JSON.stringify({type:"node-agent.websocket.open",streamId:e,protocol:a.protocol}))}),x(m,a,{pendingFrameLimit:256,upstreamOpenTimeoutMs:1e4,onClientClose:()=>{r.delete(e)},onClientError:t=>{r.delete(e),s.send(JSON.stringify({type:"node-agent.websocket.error",streamId:e,message:t instanceof Error?t.message:String(t)}))},onUpstreamClose:(t,n)=>{r.delete(e);const i=k(t),o=_(n);s.send(JSON.stringify({type:"node-agent.websocket.close",streamId:e,...void 0===i?{}:{code:i},...o?{reason:o}:{}}))},onUpstreamError:t=>{r.delete(e),s.send(JSON.stringify({type:"node-agent.websocket.error",streamId:e,message:t instanceof Error?t.message:String(t)}))}})}catch(t){s.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 m(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:{},r="string"==typeof g.route&&g.route.startsWith("/")?g.route:"/health",o=i.headers&&"object"==typeof i.headers?i.headers:{},c=Iu(i.method);let d;try{d=Dn(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 s.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${r}`,headers:l(r,c,d,o),payload:d,signal:u.signal});if(u.signal.aborted)return;s.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;s.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)}}}else e.nodeAgentEventForwarder?.setOutputSubscription?.(s,g.aiSessionTransient,g.eventEnvelopeVersion)})(i).catch(n=>{e.log.warn({nodeId:t.nodeId,error:n instanceof Error?n.message:String(n)},"node agent reverse tunnel message rejected");try{s.send(JSON.stringify({type:"node-agent.error",code:"INVALID_TUNNEL_MESSAGE"}))}catch{}})}),s}function bu(e,t){return Number.isFinite(e)&&Number(e)>0?Number(e):t}function vu(e){if(!e.length)return;const t=[...e].sort((e,t)=>e-t);return t[Math.ceil(.95*t.length)-1]}function wu(e){return e.unref?.(),e}class Su{connectTimeoutMs;handshakeTimeoutMs;heartbeatIntervalMs;heartbeatTimeoutMs;heartbeatMissThreshold;stableThresholdMs;now;setTimeoutFn;clearTimeoutFn;ping;onTimeout;onStable;onPhase;connectTimer;handshakeTimer;heartbeatTimer;stableTimer;awaitingPongSince;consecutiveHeartbeatMisses=0;stable=!1;stopped=!1;currentPhase="connecting";lastActivityAt;lastPongAt;pingRttMs;recentPingRttMs=[];constructor(e){this.connectTimeoutMs=bu(e.connectTimeoutMs,1e4),this.handshakeTimeoutMs=bu(e.handshakeTimeoutMs,1e4),this.heartbeatIntervalMs=bu(e.heartbeatIntervalMs,25e3),this.heartbeatTimeoutMs=bu(e.heartbeatTimeoutMs,15e3),this.heartbeatMissThreshold=Math.max(1,Math.floor(bu(e.heartbeatMissThreshold,2))),this.stableThresholdMs=bu(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=wu(this.setTimeoutFn(()=>this.timeout("connect"),this.connectTimeoutMs))}opened(){this.stopped||(this.clearTimer("connectTimer"),this.setPhase("handshaking"),this.handshakeTimer=wu(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=wu(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(),this.awaitingPongSince=void 0,this.consecutiveHeartbeatMisses=0,"handshaking"!==this.currentPhase&&"healthy"!==this.currentPhase||this.scheduleHeartbeat(this.heartbeatIntervalMs))}pong(){if(this.stopped)return;const e=this.now();void 0!==this.awaitingPongSince&&(this.pingRttMs=Math.max(0,e-this.awaitingPongSince),this.recentPingRttMs.push(this.pingRttMs),this.recentPingRttMs.length>20&&this.recentPingRttMs.shift()),this.awaitingPongSince=void 0,this.consecutiveHeartbeatMisses=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.pingRttMs?{}:{pingRttMs:this.pingRttMs},...this.recentPingRttMs.length?{pingRttP95Ms:vu(this.recentPingRttMs)}:{},...void 0===this.lastActivityAt?{}:{lastActivityAt:new Date(this.lastActivityAt).toISOString()},...void 0===this.lastPongAt?{}:{lastPongAt:new Date(this.lastPongAt).toISOString()},...this.consecutiveHeartbeatMisses?{consecutiveHeartbeatMisses:this.consecutiveHeartbeatMisses}:{}}}scheduleHeartbeat(e){this.stopped||(this.clearTimer("heartbeatTimer"),this.heartbeatTimer=wu(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?(this.consecutiveHeartbeatMisses+=1,this.awaitingPongSince=void 0,this.consecutiveHeartbeatMisses>=this.heartbeatMissThreshold?void this.timeout("heartbeat"):void this.sendHeartbeatProbe()):void this.scheduleHeartbeat(this.heartbeatTimeoutMs-e)}this.sendHeartbeatProbe()}},e)))}sendHeartbeatProbe(){this.awaitingPongSince=this.now();try{this.ping()}catch{if(this.consecutiveHeartbeatMisses+=1,this.awaitingPongSince=void 0,this.consecutiveHeartbeatMisses>=this.heartbeatMissThreshold)return void this.timeout("heartbeat")}this.scheduleHeartbeat(this.heartbeatTimeoutMs)}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 Eu(e){const t=new URL(jl,e);return t.protocol="https:"===t.protocol?"wss:":"ws:",t.toString()}const zu=new Set(["linux","darwin","win32","freebsd","openbsd","aix","sunos"]);function Nu(e){return zu.has(e)?e:"unknown"}function Tu(e){return!0===e.managedArtifacts}class _u{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)}resolveInstanceWeb(e){return this.executor.resolveInstanceWeb(e)}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),s=e.instance.runtime.labels["task-handoff.bootstrap-backup"];return i&&s&&await this.executor.removeBootstrapBackup(s,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:Nu(this.platform),...t?{serverVersion:t}:{}}}}}catch(t){return{status:"offline",capabilities:{...e.capabilities,daemon:{status:"offline",hostPlatform:Nu(this.platform),error:t instanceof Error?t.message:String(t)}}}}}}class ku{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(Tu)}async stopAll(){await(this.local.stopAll?.())}}const Cu="task-handoff.local-process-nonce",Ou=1e3,xu=1e4,Ru=2e3;function Pu(e,t){try{e?.(t)}catch{}}function Du(e){return e.runtime.port?`http://127.0.0.1:${e.runtime.port}`:void 0}async function Mu(e,t){try{const n=await fetch(`${e}/api/internal/node-agent/process-identity`,{headers:{authorization:`Bearer ${t}`},signal:AbortSignal.timeout(Ou)});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 ju(e,t){if(D.processStartIdentity(e)!==t)return!1;try{process.kill(e,"SIGTERM")}catch{return!0}const n=Date.now()+xu;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()+Ru;for(;Date.now()<i;){try{process.kill(e,0)}catch{return!0}await new Promise(e=>setTimeout(e,50))}return!1}function Lu(e,t){return Object.assign(new Error(t),{statusCode:503,code:"LOCAL_INSTANCE_STOP_UNCONFIRMED",instanceId:e.id})}async function Fu(e){return!await function(e){return new Promise(t=>{const n=m.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=m.createServer();n.once("error",()=>t(!1)),n.listen({host:"127.0.0.1",port:e,exclusive:!0},()=>n.close(()=>t(!0)))})}const $u=Fu;function Uu(e,t){return null!==e.exitCode||null!==e.signalCode?Promise.resolve(!0):new Promise(n=>{const i=setTimeout(()=>{e.off("exit",s),n(null!==e.exitCode||null!==e.signalCode)},t);i.unref();const s=()=>{clearTimeout(i),n(!0)};e.once("exit",s)})}async function Hu(e,t=1e4,n=2e3,i){if(await Uu(e,t))return;Pu(i,{stage:"graceful-timeout",pid:e.pid,timeoutMs:t});let s=!1;if(null===e.exitCode&&null===e.signalCode&&(e.kill("SIGKILL"),s=!0,Pu(i,{stage:"force-signal-sent",pid:e.pid,signal:"SIGKILL"})),!await Uu(e,n))throw Pu(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});s&&Pu(i,{stage:"force-exit-confirmed",pid:e.pid,signal:"SIGKILL"})}class Vu{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 s={instanceId:e,pid:t.pid,code:n,signal:i},r=e=>{try{this.onUnexpectedExitError?.(e,s)}catch{}};try{Promise.resolve(this.onUnexpectedExit?.(s)).catch(r)}catch(e){r(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"),Pu(n,{stage:"graceful-signal-sent",pid:t.pid,signal:"SIGTERM"})),this.children.delete(e.id),void await Hu(t,xu,Ru,n)}const i=await async function(e){const t=Du(e),n=e.runtime.labels?.[Cu];if(!t||!n||!e.registrationToken)return;const i=await Mu(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(Ou)})).ok?i:void 0}catch{return}}(e);if(i){const t=Du(e),n=Date.now()+xu;for(;t&&Date.now()<n;){if(!await Mu(t,e.registrationToken))return;await new Promise(e=>setTimeout(e,50))}const s=t?await Mu(t,e.registrationToken):void 0;if(s&&s.instanceId===i.instanceId&&s.pid===i.pid&&s.processNonce===i.processNonce&&s.startIdentity===i.startIdentity&&s.startIdentity&&await ju(s.pid,s.startIdentity))return;throw Lu(e,`Controlled instance ${e.id} accepted shutdown but its exit could not be confirmed.`)}const s=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 U(e)}(this.lockPath),r=await async function(e){const t=Du(e);if(t)try{const[n,i]=await Promise.all([fetch(`${t}/api/instance/status`,{signal:AbortSignal.timeout(Ou)}),fetch(`${t}/api/diagnostics`,{signal:AbortSignal.timeout(Ou)})]);if(!n.ok||!i.ok)return;const s=await n.json(),r=await i.json(),o=r.data?.runtime?.pid;if(s.data?.id!==e.id||"controlled"!==s.data.controlMode||"number"!=typeof o||!Number.isInteger(o)||o<=0)return;const a=D.processStartIdentity(o);return a?{pid:o,startIdentity:a}:void 0}catch{return}}(e);if(r){if(await ju(r.pid,r.startIdentity))return;throw Lu(e,`Legacy controlled instance ${e.id} did not exit after termination.`)}if(s?.instanceId===e.id&&B(s))throw Lu(e,`Local controlled instance ${e.id} is still owned by pid ${s.pid}, but its process identity could not be verified.`)}async waitUntilHealthy(e,t,n,i,s=function(e=process.env.TASK_HANDOFF_LOCAL_PROCESS_READY_TIMEOUT_MS){const t=Number(e);return Number.isFinite(t)&&t>0?t:3e4}()){const r=Date.now()+s;for(;Date.now()<r;){if(null!==n.exitCode||null!==n.signalCode)return!1;const s=await Mu(e,i);if(s&&s.instanceId===t.instanceId&&s.pid===t.pid&&s.processNonce===t.processNonce&&s.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"),Pu(e,{stage:"graceful-signal-sent",pid:t.pid,signal:"SIGTERM"}))}this.children.clear(),await Promise.all(e.map(e=>Hu(e,xu,Ru,this.lifecycleReporters.get(e))))}}async function Bu(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 qu{runCommand;paths;nodeAgentUrl;processSupervisor;async resolveInstanceWeb(e){const t=e.instance.runtime.port;if(!t)throw Object.assign(new Error(`Instance ${e.instance.id} does not have a node-owned local runtime port.`),{statusCode:409,code:"INSTANCE_RUNTIME_ENDPOINT_UNAVAILABLE"});return`http://127.0.0.1:${t}`}commandOverride;lockPath;constructor(e,t,n,i,s,r,o){this.runCommand=e,this.paths=t,this.nodeAgentUrl=n,this.commandOverride=i,this.lockPath=s,this.processSupervisor=new Vu(s,r,o)}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),s=e.instance.runtime.port,r=!!s&&await Fu(s),o="allocate"===process.env.TASK_HANDOFF_LOCAL_INSTANCE_PORT_CONFLICT;if(s&&!r&&!o)throw Object.assign(new Error(`Local controlled instance port 127.0.0.1:${s} is already in use.`),{statusCode:409,code:"LOCAL_INSTANCE_PORT_IN_USE"});const a=s&&r?s: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 $u(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"})}(),u=n.join(this.paths.dataDir,"local-instances",e.instance.id),p=n.join(u,"logs");t.mkdirSync(p,{recursive:!0,mode:448}),t.chmodSync(u,448),t.chmodSync(p,448);const[m,...h]=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),g=[...h,"--host","127.0.0.1","--port",String(a)],f=d.randomUUID(),y=n.join(p,"controlled-instance.out.log"),I=n.join(p,"controlled-instance.err.log");ea(y),ea(I);const A=t.mkdtempSync(function(e,t=process.platform,i=c.tmpdir()){const s="darwin"===t?"/private/tmp":i,r=d.createHash("sha256").update(e).digest("hex").slice(0,12);return n.join(s,`th-git-${r}-`)}(e.instance.id));t.chmodSync(A,448);const b=t.openSync(y,"a",384),v=t.openSync(I,"a",384),w=l.spawn(m,g,{cwd:i,detached:!1,stdio:["ignore",b,v],env:{...process.env,TASK_HANDOFF_CONTROL_MODE:"controlled",TASK_HANDOFF_RUNTIME_KIND:"local",TASK_HANDOFF_CONTROLLED_INSTANCE_VERSION:Yc(),...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:f,TASK_HANDOFF_WORKSPACE:i,TASK_HANDOFF_WORKSPACE_MODE:"local-bind",TASK_HANDOFF_DATA_DIR:u,TASK_HANDOFF_INSTANCE_PRIVATE_CONFIG_PATH:e.privateConfigPath||"",TASK_HANDOFF_LOG_DIR:p,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",TASK_HANDOFF_GIT_CREDENTIAL_SOCKET:n.join(A,"broker.sock"),...e.modelEnv||{},CODEX_HOME:(e.instance.config?.codexConfigEnabled??1)&&"taskhandoff"===(e.instance.config?.codexHomeMode??"taskhandoff")?n.join(u,"configs","codex"):void 0}});t.closeSync(b),t.closeSync(v);try{await function(e){return new Promise((t,n)=>{const i=()=>{e.off("error",s),t()},s=t=>{e.off("spawn",i),n(t)};e.once("spawn",i),e.once("error",s)})}(w)}catch(e){t.rmSync(A,{recursive:!0,force:!0});const s=e instanceof Error?e.message:String(e);try{t.appendFileSync(n.join(p,"controlled-instance.lifecycle.log"),`[${(new Date).toISOString()}] spawn failed command=${m} cwd=${i} error=${s}\n`)}catch{}throw Object.assign(new Error(`Controlled instance process could not start with command ${m} in ${i}: ${s}`),{statusCode:500,code:"LOCAL_INSTANCE_PROCESS_SPAWN_FAILED"})}const S=n.join(p,"controlled-instance.lifecycle.log");this.processSupervisor.track(e.instance.id,w,e=>{t.appendFileSync(S,`[${(new Date).toISOString()}] shutdown stage=${e.stage} pid=${e.pid??""} signal=${e.signal??""} timeoutMs=${e.timeoutMs??""}\n`)}),w.on("error",e=>{try{t.appendFileSync(S,`[${(new Date).toISOString()}] process error pid=${w.pid??""} error=${e.message}\n`)}catch{}}),w.once("exit",(e,n)=>{t.rmSync(A,{recursive:!0,force:!0});try{t.appendFileSync(S,`[${(new Date).toISOString()}] exited pid=${w.pid??""} code=${e??""} signal=${n??""}\n`)}catch{}});const E=`http://127.0.0.1:${a}`,z=w.pid?D.processStartIdentity(w.pid):void 0;if(!(w.pid&&e.instance.registrationToken&&await this.processSupervisor.waitUntilHealthy(E,{instanceId:e.instance.id,pid:w.pid,processNonce:f,startIdentity:z},w,e.instance.registrationToken)&&this.processSupervisor.markReady(e.instance.id,w)))throw this.processSupervisor.release(e.instance.id,w),null===w.exitCode&&null===w.signalCode&&w.kill("SIGTERM"),await Hu(w),Object.assign(new Error(`Controlled instance process did not become ready for instance ${e.instance.id} on ${E}.`),{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:E,api:`${E}/api`},workspace:{mode:"local-bind",status:"pending",path:i},runtime:{kind:"local",workspacePath:i,pid:w.pid,port:a,labels:{...e.instance.runtime.labels,"task-handoff.runtime-kind":"local",[Cu]:f}}}}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),ti.parse({instanceId:e.instance.id,containerDeleted:!0,completed:!0,deletedVolumes:[],retainedVolumes:[],volumeResults:[]})}async check(e){const[t,n]=await Promise.all([Bu(this.runCommand,"codex"),Bu(this.runCommand,"claude")]);return{status:"online",capabilities:cd({...e.capabilities,apps:{terminal:!0,codex:t,claude:n}})}}async stopAll(){await this.processSupervisor.stopAll()}}const Ku=["codex","claude"],Gu=5e3,Wu=D.processStartIdentity(process.pid);function Ju(e){const t=process.env[e]?.trim();return t||void 0}function Yu(e){const t=e.authorization;return"string"==typeof t&&t.startsWith("Bearer ")?t.slice(7).trim():void 0}function Xu(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 Qu(e){return!e.ip&&!e.socket.remoteAddress&&!e.socket.remoteFamily}async function Zu(e,t,n){const i=new AbortController,s=setTimeout(()=>i.abort(),2e3);try{return(await e(`${await n(t)}/api/health`,{signal:i.signal})).ok?"reachable":"endpoint-unreachable"}catch{return"endpoint-unreachable"}finally{clearTimeout(s)}}async function ep(e,t,n,i){const s=new AbortController,r=setTimeout(()=>s.abort(),i);try{return await e(t,{...n,signal:s.signal})}finally{clearTimeout(r)}}async function tp(e,t,n,i,s){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=await s(t),o=Number(process.env.TASK_HANDOFF_CONFIG_AUTO_IMPORT_TIMEOUT_MS||Gu);for(const s of Ku)try{const a=await ep(e,`${r}/api/config-sync/import/${encodeURIComponent(s)}`,{method:"POST"},Number.isFinite(o)&&o>0?o:Gu);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 np(e,t,n,i,s=async e=>Cl(e)){const r=t.requireInstance(n),o=t.resolvedAssignedModelEnvironment(n),a=t.modelRegistry.privateCatalog(n);if(t.instancePrivateConfigs.materialize(r.id,r.registrationToken,o,a),"reachable"!==r.targetStatus)return!1;let c;try{c=await ep(e,`${await s(r)}/api/internal/model-environment`,{method:"PUT",headers:{"content-type":"application/json",authorization:`Bearer ${r.registrationToken}`},body:JSON.stringify(o)},Gu)}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}if(!c.ok)return i?.({instanceId:n,targetWeb:r.target.web,statusCode:c.status},"node instance model environment live sync deferred"),!1;if(!_n(r.capabilities).features.privateModelCatalog)return!0;try{const t=await ep(e,`${await s(r)}/api/internal/model-catalog`,{method:"PUT",headers:{"content-type":"application/json",authorization:`Bearer ${r.registrationToken}`},body:JSON.stringify(a)},Gu);t.ok||404===t.status||i?.({instanceId:n,statusCode:t.status},"node instance model catalog live sync deferred")}catch(e){i?.({instanceId:n,error:e instanceof Error?e.message:String(e)},"node instance model catalog live sync deferred")}return!0}async function ip(e,t,n,i,s,r,o="request",a){const c=e.requireInstance(i);if(c.imageProvisioning&&"ready"!==c.imageProvisioning.phase&&"docker"===e.requireRuntime(c.runtimeId).type)return s.diagnostic({instanceId:i,action:"start",reason:o,runtimeId:c.runtimeId,imageId:c.imageSelection?.imageId,imagePhase:c.imageProvisioning.phase},"node instance start queued until image provisioning completes"),e.controlledInstances.put(Bs.parse({...c,status:"starting",updatedAt:te()}));s.diagnostic({instanceId:i,action:"start",reason:o,runtimeId:c.runtimeId,imageId:c.imageSelection?.imageId},"node instance start requested");const d=e.applyInstanceLifecycle(i,{type:"start-requested"}),l=t.forRuntime(e.requireRuntime(d.runtimeId)),u=await l.start({...e.context(d),signal:a}),p=u.target?.web?await Zu(n,Bs.parse({...d,...u,target:{...d.target,...u.target},workspace:u.workspace?{...d.workspace,error:void 0,...u.workspace}:d.workspace,runtime:u.runtime?{...d.runtime,...u.runtime}:d.runtime,updatedAt:te()}),r):"unknown",m=e.applyInstanceLifecycle(i,{type:"runtime-lifecycle-completed",baseline:d,observation:{...u,target:u.target?{...u.target,status:p}:void 0,workspace:u.workspace?{error:void 0,...u.workspace}:void 0,targetStatus:p,uiAccessStatus:p}});return s.diagnostic({instanceId:i,action:"start",reason:o,status:m.status,connectionStatus:m.connectionStatus,targetStatus:m.targetStatus,targetWeb:m.target.web,containerName:m.runtime.containerName},"node instance start completed"),m}async function sp(e={}){const i=e.token||process.env.TASK_HANDOFF_NODE_AGENT_TOKEN,c=Number(e.port||process.env.TASK_HANDOFF_NODE_AGENT_PORT||"8091"),d=`http://127.0.0.1:${c}`,l=e.containerUrl||process.env.TASK_HANDOFF_NODE_AGENT_CONTAINER_URL,u=Qo(e.dataDir),m=e.remoteSecret||process.env.TASK_HANDOFF_NODE_AGENT_REMOTE_SECRET,g=e.remoteKeyId||process.env.TASK_HANDOFF_NODE_AGENT_REMOTE_KEY_ID,f=new cu(u),y=f.resolveNodeId(e.nodeId||process.env.TASK_HANDOFF_NODE_ID),I=e.connectionMode||("local-ipc"===process.env.TASK_HANDOFF_NODE_AGENT_CONNECTION_MODE?"local-ipc":"local-loopback"),A=e.ipcPath||process.env.TASK_HANDOFF_NODE_AGENT_IPC_PATH||na(u.dataDir),b="local-ipc"===I?`ipc://${encodeURIComponent(A)}`:d,v=e.platform||process.platform,S=e.arch||process.arch,E=new ld(u,y,d,l,c,v);E.node.connectionMode=I,E.node.controlEndpoint=b,E.node.endpoint=b,E.init();const z=new sl(u,y);z.init();const T=e.dockerCommandRunner||ar,_=new dr(T,e.dockerTerminalCommandRunner),k=new br(T,{publishHost:"127.0.0.1",imageService:_});let C;const O=new ku(new _u(k,T,v,S),new qu(e.dockerCommandRunner||ar,u,()=>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=>C.handleUnexpectedLocalExit(e.instanceId,new Error(`Local controlled instance exited unexpectedly (pid=${e.pid??"unknown"}, code=${e.code??"none"}, signal=${e.signal??"none"}).`)),(e,t)=>G.log.error({error:e,instanceId:t.instanceId,pid:t.pid},"local controlled instance exit recovery failed"))),R=async e=>Cl(e,await O.forRuntime(E.requireRuntime(e.runtimeId)).resolveInstanceWeb(E.context(e))),P=e.updateCommandRunner||e.dockerCommandRunner||ar,D=e.fetchImpl||fetch,M=new Map,j=new Map,L=async e=>{const t=E.requireInstance(e);if(!_n(t.capabilities).features.aiSessionPersistenceSettings||"reachable"!==t.targetStatus||!t.registrationToken)return!1;const n=function(e){return kn(e).retentionSettings}(t.capabilities),i=function(e){return!0===kn(e).fileSizeLimitSettings}(t.capabilities),s=`${t.processIncarnationId||"unknown"}:${t.config.aiSessionHistoryLimit}:${n?t.config.aiSessionAttachmentRetentionDays:"unsupported"}:${i?t.config.aiSessionMaxFileAttachmentBytes:"unsupported"}`;if(M.get(e)===s)return!0;let r;try{r=await ep(D,`${await R(t)}/api/internal/ai-session-persistence-settings`,{method:"PUT",headers:{"content-type":"application/json",authorization:`Bearer ${t.registrationToken}`},body:JSON.stringify({historyLimit:t.config.aiSessionHistoryLimit,...n?{attachmentRetentionDays:t.config.aiSessionAttachmentRetentionDays}:{},...i?{maxFileAttachmentBytes:t.config.aiSessionMaxFileAttachmentBytes}:{}})},Gu)}catch(t){return ce.warn({instanceId:e,error:t instanceof Error?t.message:String(t)},"node instance AI session persistence settings live sync deferred"),!1}return r.ok?(M.set(e,s),!0):(ce.warn({instanceId:e,statusCode:r.status},"node instance AI session persistence settings live sync deferred"),!1)},F=new ua({cacheDir:n.join(u.dataDir,"runtime-artifacts"),fetchImpl:D}),$=e.resolveRuntimeArtifactRelease||((e,t,n)=>pa(e,t,n,D)),U=async(t,n,i)=>{const s=await n.artifactTarget(i);if(e.resolveRuntimeArtifact)return e.resolveRuntimeArtifact(t,s.platform,s.arch);const r=await $(t,s.platform,s.arch);if(r.identity.launcherAbi>s.launcherAbi)throw Object.assign(new Error(`Runtime requires launcher ABI ${r.identity.launcherAbi}, but ${s.platform}-${s.arch} provides ABI ${s.launcherAbi}.`),{code:"INSTANCE_BASE_RUNTIME_INCOMPATIBLE",retryable:!1});return F.resolve(r.identity,r.source)},H=e=>O.forRuntime(E.requireRuntime(e.runtimeId)),V=e=>{const t=H(e);return Tu(t)?t:void 0},B=e=>{const t=V(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})},q=e=>Boolean(V(e)),K=(e,t)=>{const n=E.context(e);return U(t,B(e),n)},G=r({logger:e.logger??!0}),W=new ta(u,{logger:(e,t)=>G.log.warn(t,e)}),J=()=>E.listInstances().map(e=>e.id),Y=()=>{try{W.run(J())}catch(e){G.log.warn({error:e},"node-agent persistence maintenance failed")}};Y();const X=setInterval(()=>{Y()},216e5);X.unref();const Q=setInterval(()=>{(()=>{try{W.capNodeAgentLogs(),W.capActiveInstanceLogs(J())}catch(e){G.log.warn({error:e},"node-agent open log maintenance failed")}})()},6e4);Q.unref();const Z={requests:0,active:0,completed:0,aborted:0,limitRejected:0,responseBytes:0,totalDurationMs:0,maxResponseBytes:El()};G.decorate("nodeAgentState",E),await G.register(o,{options:N});const ee=new No(E,i,{logger:G.log,safetyIntervalMs:Number(process.env.TASK_HANDOFF_EVENT_CONNECTION_SAFETY_INTERVAL_MS)||void 0}),ne=new ma(E.controlledInstances,Yc,{isInstalled:async(e,t)=>{const n=await K(e,t),i=await B(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(Bs.parse({...t,runtime:{...t.runtime,labels:n},updatedAt:te()}))}return i},beginDrain:async e=>{try{const t=await async function(e,t,n=async e=>Cl(e)){const i=await n(t);if(t.registrationToken&&(await ep(e,`${i}/api/internal/node-agent/drain`,{method:"POST",headers:{authorization:`Bearer ${t.registrationToken}`}},1e4)).ok)return{requested:t.apps.runningCount,failures:[]};const s=await ep(e,`${i}/api/apps/sessions`,{method:"GET",headers:{"cache-control":"no-cache"}},5e3);if(!s.ok)throw new Error(`Could not list app sessions for runtime drain (HTTP ${s.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 s.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 n=await ep(e,`${i}/api/apps/sessions/${encodeURIComponent(t)}/stop`,{method:"POST"},5e3);return n.ok?void 0:{sessionId:t,error:`HTTP ${n.status}`}}catch(e){return{sessionId:t,error:e instanceof Error?e.message:String(e)}}}));return{requested:r.length,failures:o.filter(e=>Boolean(e))}}(D,e,R);t.failures.length?G.log.warn({instanceId:e.id,requested:t.requested,failures:t.failures},"runtime convergence could not stop every app session"):G.log.info({instanceId:e.id,requested:t.requested},"runtime convergence requested app session drain")}catch(t){G.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,n=async e=>Cl(e)){return!!t.registrationToken&&(await ep(e,`${await n(t)}/api/internal/node-agent/resume`,{method:"POST",headers:{authorization:`Bearer ${t.registrationToken}`}},5e3)).ok}(D,e,R)&&G.log.info({instanceId:e.id},"runtime convergence released app session drain")}catch(t){G.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=B(e);await n.installRuntime(E.context(e),await K(e,t))},restart:async e=>{const t=H(e),n=E.applyInstanceLifecycle(e.id,{type:"convergence-restart-requested"}),i=await t.restart(E.context(n)),s=Bs.parse({...n,...i,target:i.target?{...n.target,...i.target}:n.target,runtime:i.runtime?{...n.runtime,...i.runtime}:n.runtime,updatedAt:te()}),r=await Zu(D,s,R);E.applyInstanceLifecycle(e.id,{type:"runtime-lifecycle-completed",baseline:n,observation:{...i,target:i.target?{...i.target,status:r}:void 0,targetStatus:r,uiAccessStatus:r}})},onForcedDrain:e=>G.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=>{ee.publishInstanceLifecycle(e),E.updateJobs.reconcileRollouts(E.listInstances(),Yc())}),ee.start(),G.decorate("nodeAgentEventForwarder",ee),z.setOnChange((e,t)=>{ee.publish("story.changed",{storyId:t.id,nodeId:t.ownerNodeId,change:e},{nodeId:t.ownerNodeId})});const ie=new Do(T,()=>E.listInstances().filter(e=>"docker"===E.requireRuntime(e.runtimeId).type),e=>ee.publish("instance.metrics.snapshot",e,{instanceId:e.instanceId}));ie.start(),G.decorate("nodeAgentRuntimeMetrics",ie);const se=(he=process.env.TASK_HANDOFF_DIAGNOSTIC_LOGS,["1","true","yes","on"].includes(String(he||"").trim().toLowerCase())),oe=new Ul(f,y,m,g),ae=(e,t)=>{se&&G.log.info(e,t)},ce={diagnostic:ae,warn:(e,t)=>G.log.warn(e,t)},de=new hl,le=new Al(E.environmentTemplates,E.instancePrivateConfigs,k,e=>E.requireInstance(e),e=>E.requireRuntime(e),(e,t)=>de.run(e,t),e=>E.listInstances().some(t=>t.environmentTemplateOrigin?.imageId===e)),ue=async(e,t,n=()=>!0,i)=>{try{if(!n())return E.requireInstance(e);let s=E.requireInstance(e);"failed"===s.runtimeVersion?.phase&&q(s)&&(s=E.controlledInstances.put(Bs.parse({...s,ready:!1,runtimeVersion:Qc(ha(s)),updatedAt:te()})));const r=E.requireRuntime(s.runtimeId);await ip(E,O,D,e,ce,R,t,i);const o=E.requireInstance(e);if("docker"===r.type&&o.imageProvisioning&&"ready"!==o.imageProvisioning.phase)return ee.syncNow(),o;if(!n())return E.requireInstance(e);C.markRestored(e);let a=E.requireInstance(e);if(q(a)){try{a=await ne.schedule(e,{startRequested:!0})}catch(n){a=E.requireInstance(e),ce.warn({instanceId:e,action:"runtime.converge",reason:t,error:n instanceof Error?n.message:String(n)},"node instance runtime convergence failed after start")}"matched"!==a.runtimeVersion?.phase&&a.runtimeVersion?.error&&ce.warn({instanceId:e,action:"runtime.converge",reason:t,error:a.runtimeVersion.error},"node instance started with pending runtime convergence")}return n()?(await tp(D,a,"start",ce,R),ee.syncNow(),a):E.requireInstance(e)}catch(n){throw E.applyInstanceLifecycle(e,{type:"start-failed",error:n}),ee.syncNow(),ce.warn({instanceId:e,action:"start",reason:t,error:n instanceof Error?n.message:String(n)},"node instance start failed"),n}},pe=new fl(E,_,{sync:()=>ee.syncNow(),diagnostic:ce.diagnostic,warn:ce.warn,publish:(e,t,n)=>ee.publish(e,t,{instanceId:n}),runInstanceOperation:(e,t)=>de.run(e,t)}),me=e=>{const t=de.intent(e.id);pe.provision(e,async()=>{await ue(e.id,"image-ready",()=>de.isIntentCurrent(e.id,t),de.signal(e.id,t)).catch(()=>{})})};var he;C=new fu({state:E,runtimeAdapters:O,convergence:ne,restoreInstance:e=>ip(E,O,D,e,ce,R,"restore"),autoImport:e=>tp(D,e,"start",ce,R),provisionImage:me,stopImageProvisioning:()=>pe.stop(),usesManagedArtifact:q,warn:ce.warn,error:(e,t)=>G.log.error(e,t),runInstanceOperation:(e,t)=>de.run(e,t)});const ge=new pu({nodeId:y,jobs:E.updateJobs,runCommand:P,currentRuntimeVersion:Yc,listInstances:()=>E.listInstances(),resolveRuntimeArtifacts:async e=>(await(async e=>{const t=new Map;for(const e of O.managedAdapters()){const n=await e.artifactTarget();t.set(`${n.platform}-${n.arch}`,{adapter:e})}for(const e of E.listInstances()){const n=V(e);if(!n)continue;const i=E.context(e),s=await n.artifactTarget(i);t.set(`${s.platform}-${s.arch}`,{adapter:n,context:i})}return(await Promise.all([...t.values()].map(({adapter:t,context:n})=>U(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:w&&"SCRIPT"===w.tagName.toUpperCase()&&w.src||new URL("cli.js",document.baseURI).href)?n.dirname(s.fileURLToPath("undefined"==typeof document?require("url").pathToFileURL(__filename).href:w&&"SCRIPT"===w.tagName.toUpperCase()&&w.src||new URL("cli.js",document.baseURI).href)):__dirname,managedUpdateSupport:e.managedUpdateSupport||(n=>"linux"!==(e.platform||process.platform)?{supported:!1,reason:"Managed server updates require Linux and systemd."}:"function"==typeof process.getuid&&0!==process.getuid()?{supported:!1,reason:"Managed server updates require the node agent to run as root."}:t.existsSync("/run/systemd/system")?"@task-handoff/server"!==n.packageName||process.env.TASK_HANDOFF_CONTROL_PLANE_HEALTH_URL?.trim()?process.env.TASK_HANDOFF_NODE_AGENT_IPC_PATH?.trim()?{supported:!0}:{supported:!1,reason:"Managed server updates require the node-agent IPC readiness endpoint."}:{supported:!1,reason:"Managed server updates require a local control-plane health URL."}:{supported:!1,reason:"Managed server updates require an active systemd host."})});return G.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);(se||i.statusCode>=500)&&(i.statusCode>=500?G.log.error.bind(G.log):G.log.warn.bind(G.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}:{}}})}),G.addHook("preHandler",async e=>{const t=oe.verify(e);if(t){if(f.isRevokedPairing(t)&&"/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=t}else if(Qu(e)){if(i&&Yu(e.headers)!==i){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)||/^\/api\/node-agent\/instances\/[^/]+\/git-credentials\//.test(t)||/^\/api\/node-agent\/instances\/[^/]+\/ai-sessions\/[^/]+\/story-content(?:\/|$)/.test(t)}(e.url)){if(oe.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 Xu(e.ip)||Xu(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(i&&Yu(e.headers)!==i){const e=new Error("Invalid node agent token.");throw Object.assign(e,{statusCode:401,code:"NODE_AGENT_UNAUTHORIZED"}),e}}}),G.addHook("onClose",async()=>{clearInterval(X),clearInterval(Q),ie.stop(),ee.stop(),await C.stop()}),G.decorate("nodeAgentRestoreManagedInstances",()=>C.restoreManagedInstances()),G.decorate("nodeAgentRecoverManagedInstances",()=>C.recoverManagedInstances()),G.decorate("nodeAgentStartRecoverySupervisor",()=>C.start()),G.get("/api/node-agent/health",async()=>{return{data:{ok:!0,role:"node-agent",process:{pid:process.pid,...Wu?{startIdentity:Wu}:{}},listener:{host:"127.0.0.1",port:E.currentListenerPort},nodeId:y,platform:Nu(v),arch:process.arch,protocolVersion:An,capabilities:{modelEndpointProbe:!0,managedModels:{multiEntityAssignment:!0,privateModelCatalog:!0},aiSessionHistoryLimit:!0,aiSessionAttachmentRetention:!0,aiSessionFileAttachmentLimit:!0,folderPlaces:!0,localFolderNameUpdate:!0,managedGitCredentials:{registry:!0,runtimeBroker:!0,workspaceProvisioning:{docker:!0,kubernetes:!1,local:!1}},stories:{enabled:!0,agentTools:!0,maxFileBytes:33554432,maxBatchPaths:20}},build:(e="node-agent",{component:e,packageName:"@task-handoff/node-agent",packageVersion:Yc(),protocolVersion:An,buildId:Ju("TASK_HANDOFF_BUILD_ID"),builtAt:Ju("TASK_HANDOFF_BUILT_AT"),gitCommit:Ju("TASK_HANDOFF_GIT_COMMIT"),imageRef:Ju("TASK_HANDOFF_IMAGE_REF"),imageDigest:Ju("TASK_HANDOFF_IMAGE_DIGEST")}),instanceProxy:{...Z},eventTransport:ee.eventTransportHealth(),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)}))}(G,e=>{if(!Qu(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(!G.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 G.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)}))}(G,ge,E.updateJobs),function(e,t){const{identity:n,nodeId:i,fetchImpl:s}=t;e.post("/api/node-agent/pairing/invites",async(e,t)=>{const s=n.createPairingInvite(Wl.parse(e.body||{}));return t.code(201).send({data:{nodeId:i,joinToken:s.token,expiresAt:s.expiresAt}})}),e.post("/api/node-agent/pairing/complete",async(e,t)=>{const s=n.completePairingInvite(Jl.parse(e.body));return t.code(201).send({data:{nodeId:i,keyId:s.keyId,secret:s.secret,pairedAt:s.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=du.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=du.parse(e.params.connectionId),s=n.deleteControlPlaneConnection(i);return s&&t.reverseTunnels()?.connectConfigured(),{data:{deleted:s}}}),e.post("/api/node-agent/control-plane-connections",async(e,r)=>{const o=Yl.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(/\/$/,"")}(o.controlPlaneUrl);return n.runControlPlaneConnectionOperation(a,async()=>{const e=n.stageControlPlaneConnection({url:a,...o.controlPlaneName?{name:o.controlPlaneName}:{},enabled:!1!==o.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)}),s=await i.json().catch(()=>({}));if(!i.ok){const e=new Error(s.error?.message||`Control-plane node join failed with HTTP ${i.status}.`);throw Object.assign(e,{statusCode:i.status,code:s.error?.code||"NODE_AGENT_REMOTE_JOIN_FAILED"}),e}return s.data||{}}(s,a,{joinToken:o.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:o.controlPlaneName||("string"==typeof c.name&&c.name?c.name:void 0)});let l,u=d.connection.enabled?"saved":"disabled";const p=t.reverseTunnels();if(p)try{p.connectConfigured(),d.connection.enabled&&(u="connecting")}catch(e){u="failed",l=e instanceof Error?e.message:String(e)}return r.code(201).send({data:{pairing:n.listControlPlanePairings().find(e=>e.keyId===d.pairing.keyId),connection:d.connection,tunnel:{status:u,...l?{error:l}:{}}}})})})}(G,{identity:f,nodeId:y,nodeName:()=>E.node.name,fetchImpl:D,reverseTunnels:()=>G.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(ul.parse(e.body))})),e.patch("/api/node-agent/runtimes/:id",async e=>({data:t.updateRuntime(e.params.id,pl.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/places",async()=>({data:t.listFolderPlaces()})),e.get("/api/node-agent/folders/tree",async e=>({data:t.listFolderTree(cl.parse(e.query))})),e.post("/api/node-agent/local-folders",async(e,n)=>n.code(201).send({data:t.createLocalFolder(ol.parse(e.body))})),e.patch("/api/node-agent/local-folders/:id",async e=>({data:t.updateLocalFolder(e.params.id,al.parse(e.body))})),e.delete("/api/node-agent/local-folders/:id",async e=>({data:{deleted:t.deleteLocalFolder(e.params.id)}}))}(G,{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,O.forRuntime(t))},listLocalFolders:()=>E.localFolders.list(),listFolderPlaces:Wo,listFolderTree:Yo,createLocalFolder:e=>E.createLocalFolder(e),updateLocalFolder:(e,t)=>E.updateLocalFolder(e,t),deleteLocalFolder:e=>E.localFolders.delete(e)}),function(e,t,n,i){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(es.parse(e.body))})),e.post("/api/node-agent/models/discover",async e=>{const n=wd.parse(e.body);return{data:await ud(i,{...n,key:t.resolveProbeKey(n.existingModelId,n.key)})}}),e.post("/api/node-agent/models/test",async e=>{const n=Sd.parse(e.body);return{data:await pd(i,{...n,key:t.resolveProbeKey(n.existingModelId,n.key)})}}),e.put("/api/node-agent/models/:id/deploy",async e=>{const n=e.params.id,i=ns.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,ts.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 i=e.params.id,s=e.body&&"object"==typeof e.body&&!Array.isArray(e.body)&&Object.prototype.hasOwnProperty.call(e.body,"modelEntityIds"),r=t.assign(i,is.parse(e.body));if(await n(i),s)return{data:r};const{modelEntityIds:o,...a}=r.assignment;return{data:{...r,assignment:a}}})}(G,E.modelRegistry,e=>np(D,E,e,ce.warn,R),D),function(e,t){const n=new Ed(t.gitCredentials);e.addHook("onClose",async()=>n.close()),e.put("/api/node-agent/git-credentials/:credentialId",async e=>{const n=_d.parse(e.params),i=Ac.parse(e.body);if(i.credential.id!==n.credentialId)throw Object.assign(new Error("Credential payload identity mismatch."),{code:"GIT_CREDENTIAL_IDENTITY_MISMATCH",statusCode:409});return{data:t.gitCredentials.putPayload(i).credential}}),e.delete("/api/node-agent/git-credentials/:credentialId",async e=>({data:{deleted:t.gitCredentials.removePayload(_d.parse(e.params).credentialId)}})),e.get("/api/node-agent/instances/:id/git-credential-authorizations",async e=>{const{id:n}=kd.parse(e.params);return t.requireInstance(n),{data:t.gitCredentials.getAuthorizationSet(n)}}),e.put("/api/node-agent/instances/:id/git-credential-authorizations",async e=>{const{id:n}=kd.parse(e.params);t.requireInstance(n);const i=bc.parse(e.body);if(i.instanceId!==n)throw Object.assign(new Error("Git credential authorization identity mismatch."),{code:"GIT_CREDENTIAL_AUTHORIZATION_IDENTITY_MISMATCH",statusCode:409});return{data:t.gitCredentials.putAuthorizationSet(i)}}),e.post("/api/node-agent/instances/:id/git-credentials/https",async e=>{const{id:i}=kd.parse(e.params);t.authenticateInstance(i,Od(e.headers));const s=vc.parse(e.body);return{data:wc.parse(n.resolveHttps(i,s.remoteUrl))}}),e.post("/api/node-agent/instances/:id/git-credentials/ssh/prepare",async e=>{const{id:i}=kd.parse(e.params);t.authenticateInstance(i,Od(e.headers));const s=Sc.parse(e.body);return{data:Ec.parse(await n.prepareSsh(i,s.remoteUrl))}}),e.post("/api/node-agent/instances/:id/git-credentials/ssh/agent",async e=>{const{id:i}=kd.parse(e.params);t.authenticateInstance(i,Od(e.headers));const s=zc.parse(e.body);return{data:Nc.parse(await n.exchangeAgentFrame(i,s.invocationId,s.frame))}}),e.delete("/api/node-agent/instances/:id/git-credentials/ssh/:invocationId",async e=>{const{id:i,invocationId:s}=Cd.parse(e.params);return t.authenticateInstance(i,Od(e.headers)),{data:{deleted:n.release(s,i)}}})}(G,E),function(e,t,n,i={}){e.hasContentTypeParser("application/octet-stream")||e.addContentTypeParser("application/octet-stream",(e,t,n)=>n(null,t)),e.get("/api/node-agent/stories",async()=>({data:{stories:n.list()}})),e.post("/api/node-agent/stories",async(e,t)=>t.code(201).send({data:n.create(Ud.parse(e.body))})),e.get("/api/node-agent/stories/:storyId",async e=>{const{storyId:t}=Gd.parse(e.params);return{data:n.get(t)||(()=>{throw Object.assign(new Error("Story was not found."),{code:"STORY_NOT_FOUND",statusCode:404})})()}}),e.patch("/api/node-agent/stories/:storyId",async e=>{const{storyId:t}=Gd.parse(e.params);return{data:n.update(t,Hd.parse(e.body))}}),e.post("/api/node-agent/stories/:storyId/archive",async e=>({data:n.archive(Gd.parse(e.params).storyId)})),e.post("/api/node-agent/stories/:storyId/restore",async e=>({data:n.restore(Gd.parse(e.params).storyId)})),e.delete("/api/node-agent/stories/:storyId",async e=>{const{storyId:i}=Gd.parse(e.params);if(t.listInstances().some(e=>e.aiSessions.sessions.some(e=>e.storyId===i)))throw Object.assign(new Error("Story is still referenced by an AI Session."),{code:"STORY_IN_USE",statusCode:409});return{data:{deleted:n.delete(i)}}}),e.get("/api/node-agent/stories/:storyId/content",async e=>{const{storyId:t}=Gd.parse(e.params);return{data:qd.parse({documents:n.listContent(t)})}}),e.get("/api/node-agent/stories/:storyId/content/file",async(e,t)=>{const{storyId:i}=Gd.parse(e.params),{storyPath:s}=Yd.parse(e.query),r=n.readContent(i,s);return el(t,r.filePath,r.revision,r.size)}),e.put("/api/node-agent/stories/:storyId/content/file",{bodyLimit:33555456},async e=>{const{storyId:t}=Gd.parse(e.params),i=Xd.parse(e.query);return{data:await n.writeContent(t,{...i,stream:e.body})}}),e.patch("/api/node-agent/stories/:storyId/documents/:storyPath",async e=>{const t=Wd.parse(e.params),i=xd.parse(decodeURIComponent(t.storyPath));return{data:n.updateDocument(t.storyId,i,Vd.parse(e.body))}}),e.delete("/api/node-agent/stories/:storyId/documents/:storyPath",async e=>{const t=Wd.parse(e.params);return{data:{deleted:n.deleteDocument(t.storyId,xd.parse(decodeURIComponent(t.storyPath)))}}}),e.post("/api/node-agent/stories/:storyId/documents/order",async e=>{const{storyId:t}=Gd.parse(e.params);return{data:n.reorderDocuments(t,e.body)}}),e.get("/api/node-agent/instances/:id/ai-sessions/:sessionId/story-content",async e=>{const{id:i,sessionId:s}=Jd.parse(e.params),r=Zd(t,n,i,s,Qd(e.headers));return{data:qd.parse({documents:n.listContent(r.id)})}}),e.get("/api/node-agent/instances/:id/ai-sessions/:sessionId/story-content/file",async(e,i)=>{const{id:s,sessionId:r}=Jd.parse(e.params),o=Zd(t,n,s,r,Qd(e.headers)),{storyPath:a}=Yd.parse(e.query),c=n.readContent(o.id,a);return el(i,c.filePath,c.revision,c.size)}),e.put("/api/node-agent/instances/:id/ai-sessions/:sessionId/story-content/file",{bodyLimit:33555456},async e=>{const{id:i,sessionId:s}=Jd.parse(e.params),r=Zd(t,n,i,s,Qd(e.headers)),o=Xd.parse(e.query);return{data:await n.writeContent(r.id,{...o,stream:e.body})}}),e.put("/api/node-agent/instances/:id/ai-sessions/:sessionId/story",async e=>{const{id:s,sessionId:r}=Jd.parse(e.params),o=t.requireInstance(s),c=a.z.object({storyId:re.nullable()}).strict().parse(e.body||{});if(c.storyId){const e=n.get(c.storyId);if(!e)throw Object.assign(new Error("Story belongs to another node or was not found."),{code:"STORY_NODE_MISMATCH",statusCode:409});if(e.archivedAt)throw Object.assign(new Error("Archived Story cannot receive new Session associations."),{code:"STORY_ARCHIVED",statusCode:409})}if(!i.fetchImpl||!i.resolveInstanceWeb||!o.registrationToken)throw Object.assign(new Error("Managed instance Session association is unavailable."),{code:"STORY_SESSION_ASSOCIATION_UNAVAILABLE",statusCode:503});const d=await i.resolveInstanceWeb(o),l=await i.fetchImpl(`${d}/api/ai-sessions/${encodeURIComponent(r)}/story`,{method:"PUT",headers:{"content-type":"application/json",authorization:`Bearer ${o.registrationToken}`},body:JSON.stringify(c)}),u=await l.json().catch(()=>({}));if(!l.ok)throw Object.assign(new Error(u.error?.message||"Controlled instance rejected Story association."),{code:u.error?.code||"STORY_SESSION_ASSOCIATION_FAILED",statusCode:l.status});return u})}(G,E,z,{fetchImpl:D,resolveInstanceWeb:R}),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:ci.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)}))}(G,le),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(dl.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,ll.parse(e.body));return await t.afterUpdate(n),{data:n}}),e.post("/api/node-agent/instances/:id/register",async(e,n)=>{const i=e.params.id,s=t.sanitizeReport(i,"register",e.body),r=t.register(i,Zs.parse(s),ml(e.headers));return t.afterReport(r,"register"),n.code(201).send({data:r})}),e.post("/api/node-agent/instances/:id/heartbeat",async e=>{const n=e.params.id,i=t.sanitizeReport(n,"heartbeat",e.body),s=t.heartbeat(n,er.parse(i),ml(e.headers));return t.afterReport(s,"heartbeat"),{data:s}})}(G,{list:()=>E.listInstances(),create:e=>"template"===e.environmentSource?.type?le.runTemplateOperation(e.environmentSource.environmentTemplateId,()=>E.createInstance(e)):E.createInstance(e),retryImageProvisioning:e=>pe.retry(e),update:(e,t)=>{const n=E.requireInstance(e);return E.controlledInstances.put(Bs.parse({...n,...t,...t.config?{config:{...n.config,...t.config}}:{},updatedAt:te()}))},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===An)return n;const s=({field:n,action:s})=>G.log.warn({instanceId:e,report:t,protocolVersion:i,expectedProtocolVersion:An,field:n,action:s},"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"],s=new Set([...i,"imageId"]);for(const e of Object.keys(n))s.has(e)||t?.({field:e,action:"ignored"});return Object.prototype.hasOwnProperty.call(n,"imageId")&&t?.({field:"imageId",action:"migrated"}),{...Qs(n,i),imageSelection:ii(n.imageSelection,n.imageId)}}(n,s):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 Qs(e,n)}(n,s)},afterCreate:e=>{ee.syncNow(),e.imageProvisioning&&me(e)},afterImageRetry:e=>{ee.syncNow(),me(e)},afterUpdate:async e=>{ee.syncNow(),await L(e.id)},afterReport:(e,t)=>{ee.syncNow(),(e=>{if("endpoint-unreachable"!==e.targetStatus||"online"!==e.connectionStatus||"online"!==e.agentStatus||!e.target.web||j.has(e.id))return;const t=e.processIncarnationId,n=(async()=>{if("reachable"!==await Zu(D,e,R))return;const n=E.requireInstance(e.id);n.processIncarnationId===t&&"online"===n.connectionStatus&&"online"===n.agentStatus&&(E.controlledInstances.put(Bs.parse({...n,target:{...n.target,status:"reachable"},targetStatus:"reachable",uiAccessStatus:"reachable",updatedAt:te()})),ee.syncNow())})().catch(t=>{G.log.debug({instanceId:e.id,error:t},"node instance endpoint reconciliation probe failed")}).finally(()=>{j.delete(e.id)});j.set(e.id,n)})(e),L(e.id),"register"===t?ae({instanceId:e.id,action:t,protocolVersion:e.protocolVersion,build:e.build,targetStatus:e.targetStatus,targetStrategy:e.target.strategy},"node instance registered"):ae({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"),!q(e)||e.ready&&"matched"===e.runtimeVersion?.phase||ne.schedule(e.id).catch(n=>G.log.error({instanceId:e.id,error:n},`runtime convergence after ${t} failed`))}}),G.get("/api/node-agent/events",{websocket:!0},(e,t)=>{const n=e;n.send(JSON.stringify({type:"node-agent.events.connected",nodeId:y,serverTime:(new Date).toISOString()}));const i=t.query,s=ee.addOutput(n,{expectsTransientSubscription:"1"===i.aiSessionTransient});n.on("message",e=>{try{const t=JSON.parse(String(e));"subscribe"===t.type&&void 0!==t.aiSessionTransient&&ee.setOutputSubscription(n,t.aiSessionTransient,t.eventEnvelopeVersion)}catch{}}),n.on("close",s),n.on("error",s)}),G.get("/api/node-agent/docker/images",async()=>({data:await Rr(e.dockerCommandRunner)})),G.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 ie.snapshot(t)}}),function(e,t,n,i,s,r=new hl){const o=e=>r.intent(e),a=e=>Promise.resolve(i.cancel(e)).then(()=>({ok:!0}),e=>({ok:!1,error:e})),c=(e,t)=>{if(!r.isIntentCurrent(e,t))throw Object.assign(new Error(`Instance operation for ${e} was superseded by stop or delete.`),{statusCode:409,code:"INSTANCE_OPERATION_SUPERSEDED"})},d=(e,t)=>{const n=r.signal;return"function"==typeof n?n.call(r,e,t):void 0},l=(e,n)=>{if(n){if(n.instanceId!==e)throw Object.assign(new Error(`Git provisioning belongs to ${n.instanceId}, not ${e}.`),{code:"GIT_WORKSPACE_PROVISIONING_INSTANCE_MISMATCH",statusCode:409});t.setGitWorkspaceProvisioning(n)}},u=(e,n)=>{if(!n)return e;const i=t.gitWorkspaceProvisioningStatus(e.id);return"consumed"===i?.status&&i.operationId===n.operationId?{instance:e,gitWorkspaceProvisioningOperationId:n.operationId}:e};e.post("/api/node-agent/instances/:id/start",async e=>{const t=gl.parse(e.body),n=e.params.id,i=o(n);return r.run(n,async()=>(c(n,i),l(n,t.gitWorkspaceProvisioning),s.allowRecovery(n),{data:u(await s.start(n,()=>r.isIntentCurrent(n,i),d(n,i)),t.gitWorkspaceProvisioning)}))}),e.post("/api/node-agent/instances/:id/runtime/reconcile",async e=>{const n=e.params.id;gl.parse(e.body);const a=o(n);return r.run(n,async()=>{c(n,a);const e=t.requireInstance(n);t.putInstance(Bs.parse({...e,ready:!1,runtimeVersion:Qc(ha(e)),updatedAt:te()})),c(n,a);const r=await i.schedule(n,{startRequested:!["created","stopped"].includes(e.status),resumeCancelled:!0});return c(n,a),s.sync(),{data:r}})}),e.post("/api/node-agent/instances/:id/stop",async e=>{const i=e.params.id;t.requireInstance(i),t.discardGitWorkspaceProvisioning(i),r.invalidate(i);const o=a(i);return r.run(i,async()=>{const e=t.requireInstance(i);t.applyLifecycle(i,{type:"stop-requested"});try{await s.suppressRecovery(i);const e=await o;if("error"in e)throw e.error;const r=t.requireInstance(i);s.diagnostic({instanceId:i,action:"stop",runtimeId:r.runtimeId,containerName:r.runtime.containerName},"node instance stop requested"),await n.forRuntime(t.requireRuntime(r.runtimeId)).stop(t.context(r))}catch(n){try{t.applyLifecycle(i,{type:"stop-failed",baseline:e}),s.sync()}finally{s.allowRecovery(i)}throw n}const r=t.applyLifecycle(i,{type:"stop-completed"});return s.completeSuppressedRecovery(i),s.sync(),s.diagnostic({instanceId:i,action:"stop",status:r.status,connectionStatus:r.connectionStatus,containerName:r.runtime.containerName},"node instance stop completed"),{data:r}})}),e.post("/api/node-agent/instances/:id/restart",async e=>{const a=e.params.id,d=gl.parse(e.body),p=o(a);return r.run(a,async()=>{c(a,p),l(a,d.gitWorkspaceProvisioning),s.allowRecovery(a);let e=t.requireInstance(a);if(s.isManaged(e)&&(!e.ready||"matched"!==e.runtimeVersion?.phase)){"failed"===e.runtimeVersion?.phase&&(e=t.putInstance(Bs.parse({...e,runtimeVersion:Qc(ha(e)),updatedAt:te()}))),c(a,p);const n=await i.schedule(a,{startRequested:!0});return c(a,p),s.sync(),{data:u(n,d.gitWorkspaceProvisioning)}}s.diagnostic({instanceId:a,action:"restart",runtimeId:e.runtimeId,imageId:e.imageSelection?.imageId,containerName:e.runtime.containerName},"node instance restart requested");const r=await n.forRuntime(t.requireRuntime(e.runtimeId)).restart(t.context(e));let o=t.applyLifecycle(a,{type:"runtime-lifecycle-completed",baseline:e,observation:{...r,target:r.target?{...e.target,...r.target}:void 0}});s.markRestarted(a),c(a,p);const m=Bs.parse({...o,updatedAt:te()}),h=await s.probe(m);return c(a,p),o=t.applyLifecycle(a,{type:"runtime-lifecycle-completed",baseline:o,observation:{target:{...o.target,status:h},targetStatus:h,uiAccessStatus:h}}),await s.autoImport(o),s.sync(),s.diagnostic({instanceId:a,action:"restart",status:o.status,connectionStatus:o.connectionStatus,targetStatus:o.targetStatus,targetWeb:o.target.web,containerName:o.runtime.containerName},"node instance restart completed"),{data:u(o,d.gitWorkspaceProvisioning)}})}),e.post("/api/node-agent/instances/:id/delete",async e=>{const i=e.params.id,o=Zn.parse(e.body);t.requireInstance(i),r.invalidate(i);const c=a(i);return r.run(i,async()=>{const e=t.requireInstance(i);"deleting"!==e.status&&t.applyLifecycle(i,{type:"stop-requested"});try{await s.suppressRecovery(i);const e=await c;if("error"in e)throw e.error;const a=t.requireInstance(i);t.putInstance(Bs.parse({...a,status:"deleting",ready:!1,updatedAt:te()})),s.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,{}),o);if(!d.completed)return s.diagnostic({instanceId:i,action:"delete",volumeResults:d.volumeResults},"node instance delete requires retry"),s.sync(),{data:d};s.diagnostic({instanceId:i,action:"delete"},"node instance delete completed");const l=t.deleteInstance(i);return l&&(s.forgetRecovery(i),r.clearIntent(i)),s.deleteMetadata(i),l&&s.retireInstanceData(i),l&&a.environmentTemplateOrigin?.imageId&&s.releaseEnvironmentImage&&await s.releaseEnvironmentImage(a.environmentTemplateOrigin.imageId).catch(e=>{s.diagnostic({instanceId:i,action:"release-environment-image",error:e instanceof Error?e.message:String(e)},"environment image cleanup deferred after instance deletion")}),s.sync(),{data:d}}catch(n){try{t.putInstance(Bs.parse({...e,updatedAt:te()})),s.sync()}finally{s.allowRecovery(i)}throw n}})})}(G,{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),setGitWorkspaceProvisioning:e=>E.setGitWorkspaceProvisioning(e),discardGitWorkspaceProvisioning:e=>E.discardGitWorkspaceProvisioning(e),gitWorkspaceProvisioningStatus:e=>E.gitWorkspaceProvisioningStatus(e)},O,ne,{start:(e,t,n)=>ue(e,"request",t,n),sync:()=>ee.syncNow(),isManaged:q,probe:e=>Zu(D,e,R),autoImport:e=>tp(D,e,"restart",ce,R),markRestarted:e=>C.markRestored(e),allowRecovery:e=>C.allowRecovery(e),suppressRecovery:e=>C.suppressRecovery(e),forgetRecovery:e=>C.forgetInstance(e),completeSuppressedRecovery:e=>C.completeSuppressedOperation(e),deleteMetadata:e=>{M.delete(e),E.modelRegistry.deleteInstanceMetadata(e),E.gitCredentials.removeInstance(e),E.gitCredentials.collectUnreferencedPayloads(),E.discardGitWorkspaceProvisioning(e),E.instancePrivateConfigs.delete(e)},retireInstanceData:e=>{W.retire(e)},releaseEnvironmentImage:e=>le.releaseUnusedImage(e),diagnostic:ae},de),function(e,t){const{fetchImpl:n,metrics:i,diagnostic:s}=t;e.post("/api/node-agent/instances/:id/proxy",async(e,i)=>{const r=performance.now(),o=e.params.id,a=rl.parse(e.body),c=await t.instanceBase(o),d=Nl(a.path);"POST"===a.method&&"/api/apps/sessions"===d&&await t.syncModelEnvironment(o),s({instanceId:o,action:"proxy",method:a.method,path:d,instanceBase:c},"node instance proxy requested");const l=await _l(n,`${c}${d}`,{method:a.method,headers:{...a.headers},body:Sl(a)},{instanceId:o,method:a.method,path:d,diagnostic:s}),u=l.headers.get("content-type")||"application/octet-stream",p=await l.text(),m=performance.now()-r,h=l.headers.get(zl)||a.headers[zl],g=function(...e){return e.map(e=>String(e||"").trim()).filter(Boolean).join(", ")}(l.headers.get("server-timing"),function(e,t){return`node_proxy;dur=${(Number.isFinite(t)?Math.max(0,t):0).toFixed(1)}`}(0,m));i.header("server-timing",g),h&&i.header(zl,h),s({instanceId:o,action:"proxy",method:a.method,path:d,statusCode:l.status,contentType:u,durationMs:m,traceId:h},"node instance proxy completed"),i.code(l.status).type(u).send(p)}),e.post("/api/node-agent/instances/:id/proxy/stream",{bodyLimit:vl},async(e,r)=>{const o=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()-o,i.responseBytes+=c,i[e]+=1)},p=()=>{a.abort(),d&&u("aborted")};e.raw.once("aborted",p),r.raw.once("close",p);try{const o=e.params.id,l=rl.parse(e.body),p=await t.instanceBase(o),m=Nl(l.path);s({instanceId:o,action:"proxy.stream",method:l.method,path:m,instanceBase:p},"node instance streaming proxy requested");const g=await _l(n,`${p}${m}`,{method:l.method,headers:{...l.headers},body:Sl(l),signal:a.signal},{instanceId:o,method:l.method,path:m,diagnostic:s}),f=Number(g.headers.get("content-length"));if(Number.isFinite(f)&&f>i.maxResponseBytes)return i.limitRejected+=1,a.abort(),Tl(r,i.maxResponseBytes);r.code(g.status);for(const[e,t]of Object.entries(wl(g.headers)))r.header(e,t);if(!g.body||"HEAD"===l.method)return u("completed"),r.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")),r.send(h.Readable.fromWeb(g.body).pipe(y))}catch(e){throw u("aborted"),e}finally{e.raw.off("aborted",p),d||u("completed")}}),e.post("/api/node-agent/instances/:id/proxy/raw",{bodyLimit:vl},async(e,r)=>{const o=e.params.id,a=rl.parse(e.body),c=await t.instanceBase(o),d=Nl(a.path);s({instanceId:o,action:"proxy.raw",method:a.method,path:d,instanceBase:c},"node instance raw proxy requested");const l=await _l(n,`${c}${d}`,{method:a.method,headers:{...a.headers},body:Sl(a)},{instanceId:o,method:a.method,path:d,diagnostic:s}),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(()=>{})),Tl(r,i.maxResponseBytes);let p;try{p=await async function(e,t){if(!e.body)return Buffer.alloc(0);const n=[];let i=0;const s=e.body.getReader();for(;;){const{done:e,value:r}=await s.read();if(e)break;if(i+=r.byteLength,i>t)throw await s.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(r))}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,Tl(r,i.maxResponseBytes)}return s({instanceId:o,action:"proxy.raw",method:a.method,path:d,statusCode:l.status,byteLength:p.length},"node instance raw proxy completed"),{data:{status:l.status,headers:wl(l.headers),bodyBase64:p.toString("base64")}}}),e.get("/api/node-agent/instances/:id/proxy/ws/*",{websocket:!0},async(e,n)=>{const i=n.params.id,r=n.params["*"]||"",o=n.url.indexOf("?"),a=o>=0?n.url.slice(o):"";let c;try{const o=await t.instanceBase(i),d=new URL(`/${r}${a}`,`${o}/`);d.protocol="https:"===d.protocol?"wss:":"ws:";const l=function(e){const t=Object.entries(e).find(([e])=>"sec-websocket-protocol"===e.toLowerCase()),n=t?.[1],i=(Array.isArray(n)?n.join(","):"string"==typeof n?n:"").split(",").map(e=>e.trim()).filter(Boolean);return i.length?i:void 0}(n.headers);s({instanceId:i,action:"proxy.ws",path:`/${r}${a}`,upstreamUrl:d.toString(),protocols:l||[]},"node instance websocket proxy opening"),c=l?new p(d,l,{perMessageDeflate:!1}):new p(d,{perMessageDeflate:!1}),c.on("open",()=>{s({instanceId:i,action:"proxy.ws",path:`/${r}${a}`},"node instance websocket proxy opened")}),c.on("close",()=>{s({instanceId:i,action:"proxy.ws",path:`/${r}${a}`},"node instance websocket proxy closed")}),c.on("error",e=>{s({instanceId:i,action:"proxy.ws",path:`/${r}${a}`,error:e instanceof Error?e.message:String(e)},"node instance websocket proxy failed")}),x(e,c,{upstreamOpenTimeoutMs:1e4})}catch(t){s({instanceId:i,action:"proxy.ws",path:`/${r}${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.")}})}(G,{fetchImpl:D,metrics:Z,instanceBase:e=>R(E.requireInstance(e)),syncModelEnvironment:e=>np(D,E,e,ce.warn,R),diagnostic:ae}),G}async function rp(e){const s=Qo(e.dataDir),r=function(e,i={}){return function(e,i={}){t.mkdirSync(n.dirname(e),{recursive:!0});const s=D.processStartIdentity(process.pid),r={pid:process.pid,hostname:c.hostname(),command:process.argv.join(" "),acquiredAt:(new Date).toISOString(),token:d.randomUUID(),...void 0!==i.component?{component:i.component}:{},...s?{startIdentity:s}:{},...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(L(e),`${JSON.stringify({token:r.token,pid:r.pid,startIdentity:r.startIdentity,startedAt:(new Date).toISOString()})}\n`,{encoding:"utf8",mode:384,flag:"wx"}),q(e,r),{lockPath:e,owner:r,updateDetails:t=>K(e,r,t),release(){const n=H(e);n?.token===r.token&&t.rmSync(e,{recursive:!0,force:!0})}}}catch(s){if("EEXIST"!==s.code)throw s;const r=H(e);if(B(r))throw new M(e,r,i.error);if(!r&&(W(e)||X(e)<(i.incompleteLockStaleMs??2e3))){if(n+1<5){Y();continue}throw new M(e,void 0,i.error)}const o=d.randomUUID();if(!Q(e,o)){if(n+1<5){Y();continue}throw new M(e,H(e),i.error)}const a=H(e);if(B(a))throw J(F(e)),new M(e,a,i.error);if(r?.token&&a?.token!==r.token){J(F(e));continue}if(!ee(e,o))continue;t.rmSync(e,{recursive:!0,force:!0})}const o=H(e);throw new M(e,o,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:s.dataDir});try{const c=(o=e.host,a=e.port,Ps.parse({bindScope:"0.0.0.0"===o.trim()?"all-ipv4":"loopback",port:a})),d=t.existsSync(s.settingsPath),l=function(e,t){return new Oa(e.settingsPath,()=>({version:1,externalListener:t}),{schema:Ol,sanitize:Rl})}(s,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 Pl(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 p=e=>{if(!r.updateDetails({dataDir:s.dataDir,host:e.host,port:e.port,instanceId:void 0}))throw new Error("Node agent singleton ownership changed while publishing listener state.")},m={...e,port:u.port},h=await sp(m),g=h.nodeAgentState;if(!g)throw new Error("Node agent state was not initialized.");const f=new cu(s).resolveNodeId(e.nodeId||process.env.TASK_HANDOFF_NODE_ID),y=function(e,t,n,i){const s=t.token||process.env.TASK_HANDOFF_NODE_AGENT_TOKEN,r=new cu(n),o=new Map;let a=!1;const c=(t,n)=>{if(a||n.retry.pending||o.get(t)!==n)return;const s=n.retry.schedule(()=>{a||o.get(t)!==n||n.socket||d(t,n)});s&&(n.status="reconnecting",n.nextRetryAt=new Date(Date.now()+s.delay).toISOString(),e.log.info({nodeId:i,tunnelUrl:new URL(n.config.tunnelUrl).origin,attempt:s.attempt,delay:s.delay},"node agent reverse tunnel reconnect scheduled"))},d=(n,r)=>{let d;r.status=r.lastDisconnectedAt?"reconnecting":"connecting",r.error=void 0,r.failureReason=void 0,r.nextRetryAt=void 0;try{d=Au(e,{...r.config,nodeId:i,port:()=>e.nodeAgentState.currentListenerPort,token:s})}catch(e){return r.status="failed",r.lastDisconnectedAt=(new Date).toISOString(),r.error=e instanceof Error?e.message:String(e),void c(n,r)}r.socket=d;const l=new Su({connectTimeoutMs:t.connectTimeoutMs,handshakeTimeoutMs:t.handshakeTimeoutMs,heartbeatIntervalMs:t.heartbeatIntervalMs,heartbeatTimeoutMs:t.heartbeatTimeoutMs,heartbeatMissThreshold:t.heartbeatMissThreshold,stableThresholdMs:t.stableThresholdMs,ping:()=>d.ping(),onTimeout:e=>{o.get(n)===r&&r.socket===d&&(r.status="failed",r.failureReason=`Reverse tunnel ${e} timeout.`,r.error=r.failureReason,d.terminate())},onStable:()=>r.retry.reset()});return r.supervisor=l,l.start(),d.on("open",()=>{o.get(n)===r&&r.socket===d&&(r.status="connecting",l.opened())}),d.on("message",t=>{if(o.get(n)!==r||r.socket!==d)return;if(l.activity(),"connected"===r.status)return;let s;try{s=JSON.parse(String(t))}catch{return}const a=s&&"object"==typeof s?s.type:void 0;"control-plane.hello"!==a&&"control-plane.identified"!==a||(l.activity(),l.healthy(),r.status="connected",r.lastConnectedAt=(new Date).toISOString(),r.nextRetryAt=void 0,r.error=void 0,e.log.info({nodeId:i,tunnelUrl:new URL(r.config.tunnelUrl).origin},"node agent reverse tunnel connected"))}),d.on("pong",()=>l.pong()),d.on("close",(t,s)=>{if(o.get(n)!==r||r.socket!==d)return;l.close(),r.socket=void 0,r.lastDisconnectedAt=(new Date).toISOString();const u=`WebSocket closed${t?` (${t})`:""}${s?`: ${Buffer.isBuffer(s)?s.toString("utf8"):String(s)}`:""}`;r.error=r.failureReason||u,a||(e.log.warn({nodeId:i,tunnelUrl:new URL(r.config.tunnelUrl).origin,code:t,reason:Buffer.isBuffer(s)?s.toString("utf8"):String(s||""),error:r.error,closeOrigin:r.failureReason?"supervisor":"transport"},"node agent reverse tunnel disconnected"),c(n,r))}),d.on("error",e=>{o.get(n)===r&&r.socket===d&&(r.status="failed",r.failureReason=e instanceof Error?e.message:String(e),r.error=r.failureReason,d.terminate())}),d},l=(e,t)=>{const n=o.get(e);n?.retry.cancel(),n?.supervisor?.close();const i={config:t,retry:new wo,status:"connecting"};return o.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,s=r.resolvedControlPlaneAccess(),c=new Set;for(const{connection:t,pairing:r}of s.connections){if(!t.enabled)continue;if(!r){e.log.warn({nodeId:i,connectionId:t.id,pairingKeyId:t.pairingKeyId},"node agent control-plane connection has no pairing");continue}const s=Eu(t.url);n.set(t.id,{tunnelUrl:s,keyId:r.keyId,secret:r.secret}),c.add(s)}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=r.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 p=s.hasPersistedAccess?void 0:function(){const e=process.env.TASK_HANDOFF_CONTROL_PLANE_URL;if(!e)return;const t=new URL(jl,e);return t.protocol="https:"===t.protocol?"wss:":"ws:",t.toString()}();if(p&&!c.has(p)){const e=r.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:${p}`,{tunnelUrl:p,keyId:e?.keyId,secret:e?.secret})}(e=>{for(const[t,n]of o)e.has(t)||(n.retry.cancel(),n.supervisor?.close(),o.delete(t),n.socket?.close(1e3,"Reverse tunnel configuration removed."));for(const[t,n]of e){const e=o.get(t);e&&u(e.config,n)||l(t,n)}})(n)},state:e=>{const t=o.get(e);if(!t)return;const n=t.supervisor?.diagnostics();return{status:t.status,...void 0===n?.pingRttMs?{}:{pingRttMs:n.pingRttMs},...void 0===n?.pingRttP95Ms?{}:{pingRttP95Ms:n.pingRttP95Ms},consecutiveReconnects:t.retry.attempts,...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 o.values())e.retry.cancel(),e.supervisor?.close(),e.socket?.close(1001,"Node agent shutting down.");o.clear()}}}({log:h.log,inject:e=>h.inject(e),nodeAgentEventForwarder:h.nodeAgentEventForwarder,nodeAgentState:g},m,s,f);h.decorate("nodeAgentReverseTunnels",y);const I=new Dl({app:h,state:g,settings:l,config:u,source:d?"persisted":"bootstrap",onActiveListener:p});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")},s=()=>{n("SIGTERM")};process.once("SIGINT",i),process.once("SIGTERM",s),e.addHook("onClose",async()=>{process.off("SIGINT",i),process.off("SIGTERM",s)})}(h),h.addHook("onClose",async()=>{A?.close(),r.release()});try{await h.ready();const r=e.ipcPath||process.env.TASK_HANDOFF_NODE_AGENT_IPC_PATH||na(s.dataDir);A=await async function(e,s){!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}}}(s);const r=i.createServer((t,n)=>{e.server.emit("request",t,n)});return r.on("upgrade",(t,n,i)=>{e.server.emit("upgrade",t,n,i)}),await new Promise((e,t)=>{r.once("error",t),r.listen(s,()=>{r.off("error",t),e()})}),r}(h,r),await I.start(),y.connectConfigured(),h.nodeAgentStartRecoverySupervisor?.()}catch(e){throw await h.close(),e}}catch(e){throw r.release(),e}var o,a}const op="task-handoff-node-agent.service",ap=`/etc/systemd/system/${op}`,cp="/etc/task-handoff/node-agent.env",dp=["@task-handoff/node-agent","@task-handoff/controlled-instance"];function lp(e,t,n){const i=e.run(t,n);if(0!==i.status){const e=function(e){return[e.stdout,e.stderr].filter(Boolean).map(e=>String(e).trim()).filter(Boolean).join("\n")}(i);throw new Error(`${t} ${n.join(" ")} failed${e?`:\n${e}`:""}`)}}function up(e,t){for(const n of e.split(/\r?\n/)){const e=n.indexOf("=");if(!(e<0||n.slice(0,e).trim()!==t))return n.slice(e+1).trim()}}const pp={getuid:()=>process.getuid?.(),exists:t.existsSync,readText:e=>t.readFileSync(e,"utf8"),remove:(e,n)=>t.rmSync(e,n),run:(e,t)=>l.spawnSync(e,t,{encoding:"utf8"}),confirmDeleteData:async function(e){if(!v.stdin.isTTY||!v.stdout.isTTY)return!1;const t=b.createInterface({input:v.stdin,output:v.stdout});try{const n=await t.question(`Delete Node Agent data at ${e}? This removes identity, configuration, logs, and managed-instance metadata. Docker volumes are preserved. [y/N] `);return/^(?:y|yes)$/i.test(n.trim())}finally{t.close()}},log:e=>console.log(e)};function mp(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 hp(e){if("local-ipc"!==e&&"local-loopback"!==e)throw new Error("Connection mode must be local-ipc or local-loopback.");return e}function gp(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(z("@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",mp,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",hp).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 rp({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",gp).option("--json","Print raw JSON output").action(async e=>{const n=t.opts(),i=e.ipcPath||n.ipcPath||process.env.TASK_HANDOFF_NODE_AGENT_IPC_PATH,s=e.dataDir||n.dataDir||process.env.TASK_HANDOFF_NODE_AGENT_DATA_DIR,r=e.endpoint?void 0:i||na(s||Xo()),o=await async function(e){const t={"content-type":"application/json",...e.token?{authorization:`Bearer ${e.token}`}:{}},n=JSON.stringify({...e.expiresInMs?{expiresInMs:e.expiresInMs}:{}}),i=e.endpoint?await fetch(`${e.endpoint.replace(/\/$/,"")}/api/node-agent/pairing/invites`,{method:"POST",headers:t,body:n}):await ia(e.ipcPath,"/pairing/invites",{method:"POST",headers:t,body:n}),s=await i.json().catch(()=>({}));if(!i.ok)throw new Error(s.error?.message||`Node agent pairing invite failed with HTTP ${i.status}`);const r="string"==typeof s.data?.joinToken?s.data.joinToken:"";if(!r)throw new Error("Node agent pairing invite response did not include a join token.");return{nodeId:"string"==typeof s.data?.nodeId?s.data.nodeId:"",joinToken:r,expiresAt:"string"==typeof s.data?.expiresAt?s.data.expiresAt:""}}({endpoint:e.endpoint,ipcPath:r,token:e.token,expiresInMs:e.expiresInMs});e.json?console.log(JSON.stringify(o,null,2)):(o.nodeId&&console.log(`Node: ${o.nodeId}`),console.log(`Join token: ${o.joinToken}`),o.expiresAt&&console.log(`Expires: ${o.expiresAt}`))}),t.command("connect").description("Connect this Node Agent to a reachable Control Plane.").requiredOption("--control-plane <url>","Public Control Plane base URL").requiredOption("--join-token <token>","One-time join token issued by the Control Plane").option("--control-plane-name <name>","Control Plane display name").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("--json","Print raw JSON output").action(async e=>{const n=t.opts(),i=e.ipcPath||n.ipcPath||process.env.TASK_HANDOFF_NODE_AGENT_IPC_PATH,s=e.dataDir||n.dataDir||process.env.TASK_HANDOFF_NODE_AGENT_DATA_DIR,r=e.endpoint?void 0:i||na(s||Xo()),o=await async function(e){const t={"content-type":"application/json",...e.token?{authorization:`Bearer ${e.token}`}:{}},n=JSON.stringify({controlPlaneUrl:e.controlPlane,joinToken:e.joinToken,...e.controlPlaneName?{controlPlaneName:e.controlPlaneName}:{},activate:!0}),i=e.endpoint?await fetch(`${e.endpoint.replace(/\/$/,"")}/api/node-agent/control-plane-connections`,{method:"POST",headers:t,body:n}):await ia(e.ipcPath,"/control-plane-connections",{method:"POST",headers:t,body:n}),s=await i.json().catch(()=>({}));if(!i.ok)throw new Error(s.error?.message||`Node Agent connection failed with HTTP ${i.status}`);return s.data}({controlPlane:e.controlPlane,joinToken:e.joinToken,controlPlaneName:e.controlPlaneName,endpoint:e.endpoint,ipcPath:r,token:e.token});e.json?console.log(JSON.stringify(o,null,2)):(console.log(`Control Plane: ${String(o?.connection?.url||e.controlPlane)}`),console.log(`Connection: ${String(o?.tunnel?.status||"saved")}`))}),t.command("uninstall").description("Uninstall the Node Agent service and packages; data is preserved by default.").option("--data-dir <path>","Override the installed Node Agent data directory").option("--delete-data","Delete Node Agent data without prompting").option("--keep-data","Preserve Node Agent data without prompting").action(async e=>{await async function(e,t=pp){if(e.deleteData&&e.keepData)throw new Error("--delete-data and --keep-data cannot be used together.");if(0!==t.getuid())throw new Error("Run this command as root so the Node Agent service and packages can be removed.");const i=t.exists(cp)?t.readText(cp):"",s=function(e,t){if(e.dataDir?.trim())return n.resolve(e.dataDir.trim());if(t.exists(cp)){const e=up(t.readText(cp),"TASK_HANDOFF_NODE_AGENT_DATA_DIR");if(e)return n.resolve(e)}return n.resolve(Xo())}(e,{exists:e=>e===cp&&Boolean(i),readText:()=>i});if(s===n.parse(s).root)throw new Error(`Refusing to use a filesystem root as the Node Agent data directory: ${s}`);const r=up(i,"TASK_HANDOFF_NPM_COMMAND")||process.env.TASK_HANDOFF_NPM_COMMAND||"npm";if(t.exists(ap)){const e=t.readText(ap);if(!/^ExecStart=\S*task-handoff-node-agent(?:\s|$)/m.test(e))throw new Error(`Refusing to remove ${op} because it is not owned by a standalone Node Agent installation.`);lp(t,"systemctl",["disable","--now",op]),t.remove(ap,{force:!0}),lp(t,"systemctl",["daemon-reload"])}lp(t,r,["uninstall","--global",...dp]),t.remove(cp,{force:!0}),t.log("TaskHandoff Node Agent service and packages were removed.");const o=!!e.deleteData||!e.keepData&&await t.confirmDeleteData(s);return o?(t.remove(s,{recursive:!0,force:!0}),t.log(`Node Agent data was deleted from ${s}.`)):t.log(`Node Agent data was preserved at ${s}.`),{dataDir:s,dataDeleted:o}}(e)}),await t.parseAsync(process.argv)})().catch(e=>{console.error(e instanceof Error?e.message:String(e)),process.exitCode=1});