@task-handoff/node-agent 0.0.13 → 0.0.14

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"),r=require("node:crypto"),i=require("node:http"),o=require("node:net"),s=require("node:url"),a=require("node:child_process"),c=require("node:stream"),d=require("fastify"),l=require("@fastify/websocket"),u=require("ws"),m=require("zod"),p=require("node:os"),g=require("node-pty"),h=require("write-file-atomic"),f=require("semver"),y=require("node:fs/promises"),I=require("node:stream/promises"),A=require("tar"),b="undefined"!=typeof document?document.currentScript:null;function w(e,n){try{const r=JSON.parse(t.readFileSync(e,"utf8"));if(n&&r.name!==n)return;return"string"==typeof r.version&&r.version.trim()?r.version.trim():void 0}catch{return}}function z(e){if(e)try{return n.dirname(t.realpathSync(e))}catch{return}}function N(e,t=process.env,r=e){const i=t.TASK_HANDOFF_VERSION?.trim();if(i)return i;const o=r.split("/").at(-1),s=process.argv[1]?n.resolve(process.argv[1]):void 0,a=s?n.dirname(s):void 0,c=[z(s),a,process.cwd()].filter(e=>Boolean(e));for(const t of new Set(c)){let r=t;for(;;){const t=w(n.join(r,"package.json"),e);if(t)return t;const i=n.dirname(r);if(i===r)break;r=i}}let d;for(const e of new Set(c)){let t=e;for(;;){if(o){const e=w(n.join(t,"packages",o,"package.json"),r);if(e)return e}d||=w(n.join(t,"package.json"));const e=n.dirname(t);if(e===t)break;t=e}}return d||"unknown"}class v extends Error{code;lockPath;owner;constructor(e,t,n={}){const r=t?.pid?` pid ${t.pid}`:"";super(`${n.label||"Process"} is already running${r}. Lock: ${e}`),this.name="ProcessSingletonError",this.code=n.code||"PROCESS_ALREADY_RUNNING",this.lockPath=e,this.owner=t}}function E(e){return n.join(e,"owner.json")}function S(e){return n.join(e,"initializing.json")}function _(e){return n.join(e,"recovering.json")}function T(e){return Number.isInteger(e)&&Number(e)>0}function k(e,n=process.platform){if(T(e)){if("linux"===n)try{const n=t.readFileSync(`/proc/${e}/stat`,"utf8"),r=n.lastIndexOf(")");if(r<0)return;const i=n.slice(r+2).trim().split(/\s+/)[19];return i?`linux:${i}`:void 0}catch{return}if(["darwin","freebsd","openbsd","aix","sunos"].includes(n)){const t=a.spawnSync("ps",["-o","lstart=","-p",String(e)],{encoding:"utf8",timeout:1e3}),r=0===t.status?t.stdout.trim().replace(/\s+/g," "):"";return r?`${n}:${r}`:void 0}if("win32"===n){const t=`(Get-Process -Id ${e} -ErrorAction Stop).StartTime.ToUniversalTime().Ticks`,n=a.spawnSync("powershell.exe",["-NoProfile","-NonInteractive","-Command",t],{encoding:"utf8",timeout:2e3}),r=0===n.status?n.stdout.trim():"";return/^\d+$/.test(r)?`win32:${r}`:void 0}}}function C(e){try{const n=JSON.parse(t.readFileSync(E(e),"utf8"));if(T(n.pid)&&"string"==typeof n.startTime){const e=n;return{pid:e.pid,hostname:"string"==typeof e.hostname&&e.hostname?e.hostname:p.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(!(T(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 x=C;function O(e){if(!T(e))return!1;try{return process.kill(Number(e),0),!0}catch(e){return"EPERM"===e.code}}function R(e){if(!e||!O(e.pid))return!1;if(!e.startIdentity)return!0;const t=k(e.pid);return void 0===t||t===e.startIdentity}function D(e,r){const i=n.join(e,`.owner-${r.token}.tmp`);t.writeFileSync(i,`${JSON.stringify(r,null,2)}\n`,{encoding:"utf8",mode:384,flag:"wx"});const o=M(e);if(o?.token!==r.token)throw j(i),new Error(`Process lock initialization was superseded: ${e}`);t.renameSync(i,E(e)),j(S(e))}function M(e){try{return JSON.parse(t.readFileSync(S(e),"utf8"))}catch{return}}function P(e){const t=M(e);return T(t?.pid)&&R({pid:t.pid,startIdentity:t.startIdentity})}function j(e){try{t.unlinkSync(e)}catch(e){if("ENOENT"!==e.code)throw e}}function L(){Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,20)}function $(e){try{const n=M(e),r=Date.parse(n?.startedAt||"");return Number.isFinite(r)?Math.max(0,Date.now()-r):Math.max(0,Date.now()-t.statSync(e).mtimeMs)}catch{return 0}}function F(e,i){try{return t.writeFileSync(_(e),`${JSON.stringify({token:i,pid:process.pid,startedAt:(new Date).toISOString()})}\n`,{encoding:"utf8",mode:384,flag:"wx"}),!0}catch(o){if("EEXIST"===o.code)return!!function(e){const i=_(e),o=U(i),s=Date.parse(o?.startedAt||"");if(O(o?.pid)||Number.isFinite(s)&&Date.now()-s<2e3)return!1;const a=n.join(e,`.recovering-${r.randomUUID()}.stale`);try{t.renameSync(i,a)}catch(e){if(["ENOENT","EEXIST"].includes(e.code||""))return!1;throw e}const c=U(a);if(c?.token===o?.token)return j(a),!0;try{t.linkSync(a,i)}catch(e){if("EEXIST"!==e.code)throw e}finally{j(a)}return!1}(e)&&F(e,i);if("ENOENT"===o.code)return!1;throw o}}function U(e){try{return JSON.parse(t.readFileSync(e,"utf8"))}catch{return}}function V(e,t){return U(_(e))?.token===t}const H=41943040,q="ai.sessions",B=m.z.string().trim().min(1).max(80),K=m.z.enum(["running","waiting","idle","failed"]);m.z.object({instanceId:m.z.string().trim().min(1).max(160),sessionId:m.z.string().trim().min(1).max(120),unread:m.z.boolean(),sessionUpdatedAt:m.z.string().datetime(),updatedAt:m.z.string().datetime()}).strict();const G=m.z.enum(["thinking","tool","editing","approval","responding","unknown"]),J=m.z.object({id:m.z.string().trim().min(1).max(240).optional(),kind:m.z.string().trim().min(1).max(80).optional(),name:m.z.string().trim().min(1).max(120),inputPreview:m.z.string().trim().max(500).optional(),startedAt:m.z.string().datetime().optional()}).strict(),W=m.z.enum(["pending-init","running","interrupted","completed","errored","shutdown","not-found"]),X=m.z.enum(["started","interacted","interrupted"]),Y=m.z.object({threadId:m.z.string().trim().min(1).max(240),path:m.z.string().trim().max(4096).optional(),status:W,activity:X.optional(),message:m.z.string().trim().max(1e3).optional(),updatedAt:m.z.string().datetime()}).strict(),Z=m.z.object({toolCalls:m.z.number().int().min(0).default(0),edits:m.z.number().int().min(0).default(0),approvals:m.z.number().int().min(0).default(0)}).strict().default({toolCalls:0,edits:0,approvals:0}),Q=m.z.object({send:m.z.boolean().optional(),interrupt:m.z.boolean().optional(),approval:m.z.boolean().optional()}).strict(),ee=m.z.enum(["image","file"]),te=m.z.object({id:m.z.string().trim().min(1).max(120),kind:ee,name:m.z.string().trim().min(1).max(240),mime:m.z.string().trim().min(1).max(120),size:m.z.number().int().min(0).max(Number.MAX_SAFE_INTEGER)}),ne=m.z.union([te.extend({source:m.z.object({type:m.z.literal("inline"),encoding:m.z.literal("base64"),data:m.z.string().min(1).max(31457280)}).strict()}).strict().superRefine((e,t)=>{const n="image"===e.kind?20971520:512e3;(e.size<=0||("file"===e.kind?e.size>=n:e.size>n))&&t.addIssue({code:m.z.ZodIssueCode.custom,path:["size"],message:`Inline ${e.kind} must be between 1 byte and ${n} bytes.`})}),te.extend({source:m.z.object({type:m.z.literal("runtime-path"),path:m.z.string().trim().min(1).max(4096)}).strict()}).strict()]),re=te.extend({sourceType:m.z.enum(["inline","runtime-path"])}).strict(),ie=m.z.union([m.z.object({id:m.z.string().trim().min(1).max(120),kind:ee.optional(),source:m.z.object({type:m.z.literal("upload-ref")}).strict().default({type:"upload-ref"})}).strict(),m.z.object({id:m.z.string().trim().min(1).max(120),kind:ee,name:m.z.string().trim().min(1).max(240),mime:m.z.string().trim().min(1).max(120),size:m.z.number().int().min(0).max(Number.MAX_SAFE_INTEGER),source:m.z.object({type:m.z.literal("runtime-path"),path:m.z.string().trim().min(1).max(4096)}).strict()}).strict()]),oe=m.z.enum(["auto","queue","steer","immediate"]),se=m.z.enum(["ask","auto-review","full-access"]),ae=m.z.enum(["review","rename","goal","compact"]);m.z.object({command:ae,argument:m.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.`})}),m.z.object({command:ae,value:m.z.string().max(4e3).optional(),turnId:m.z.string().trim().min(1).max(240).optional()}).strict(),m.z.enum(["skill","app","plugin"]);const ce=m.z.object({name:m.z.string().trim().min(1).max(240),path:m.z.string().trim().min(1).max(4096)}),de=m.z.discriminatedUnion("kind",[ce.extend({kind:m.z.literal("skill"),path:m.z.string().trim().min(1).max(4096).refine(e=>e.startsWith("/"),"Skill paths must be absolute.")}).strict(),ce.extend({kind:m.z.literal("app"),path:m.z.string().trim().min(7).max(4096).regex(/^app:\/\/[^\s/]+$/,"App paths must use app://<id>.")}).strict(),ce.extend({kind:m.z.literal("plugin"),path:m.z.string().trim().min(10).max(4096).regex(/^plugin:\/\/[^\s/]+$/,"Plugin paths must use plugin://<id>.")}).strict()]),le=m.z.array(de).max(20).default([]),ue=m.z.enum(["plugin","skill","file","directory","app"]),me=m.z.object({kind:ue,name:m.z.string().trim().min(1).max(240),description:m.z.string().trim().max(1e3).optional(),path:m.z.string().trim().min(1).max(4096),icon:m.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."})}),pe=m.z.object({category:m.z.enum(["skills","plugins","apps","files"]),code:m.z.string().trim().min(1).max(160),message:m.z.string().trim().min(1).max(2e3)}).strict();m.z.object({sessionId:m.z.string().trim().min(1).max(120),providerSessionId:m.z.string().trim().min(1).max(240),cwd:m.z.string().trim().min(1).max(4096),candidates:m.z.array(me).max(1e3).default([]),diagnostics:m.z.array(pe).max(20).default([])}).strict(),m.z.object({query:m.z.string().trim().max(240).default("")}).strict(),m.z.object({sessionId:m.z.string().trim().min(1).max(120),cwd:m.z.string().trim().min(1).max(4096),query:m.z.string().trim().max(240),requestId:m.z.string().trim().min(1).max(160),candidates:m.z.array(me.refine(e=>"file"===e.kind||"directory"===e.kind,"File search only returns files and directories.")).max(200).default([]),complete:m.z.boolean().default(!1)}).strict();const ge=m.z.object({message:m.z.string().trim().min(1).max(2e4),mode:oe.optional(),permissionMode:se.optional()});ge.extend({attachments:m.z.array(ne).max(6).default([]),references:le}).strict().superRefine((e,t)=>{e.attachments.reduce((e,t)=>e+("inline"===t.source.type?t.size:0),0)>H&&t.addIssue({code:m.z.ZodIssueCode.custom,path:["attachments"],message:"Inline attachments must be 41943040 bytes or less in total."})}),ge.extend({attachments:m.z.array(ie).max(6).default([]),references:le}).strict(),m.z.object({decision:m.z.enum(["allow","deny","skip"])}).strict(),m.z.object({queueIds:m.z.array(m.z.string().trim().min(1).max(120)).max(100)}).strict(),m.z.object({code:m.z.string().trim().min(1).max(160),message:m.z.string(),instanceId:m.z.string().trim().min(1).max(160).optional(),nodeId:m.z.string().trim().min(1).max(160).optional(),route:m.z.string().trim().min(1).max(4096).optional()}).strict();const he=m.z.object({id:m.z.string().trim().min(1).max(120),message:m.z.string().trim().min(1).max(2e4),attachments:m.z.array(re).max(6).default([]),references:le,permissionMode:se.optional(),status:m.z.enum(["queued","sending","failed"]).default("queued"),createdAt:m.z.string().datetime(),updatedAt:m.z.string().datetime(),error:m.z.string().trim().max(4e3).optional()}).strict(),fe=m.z.object({pendingCount:m.z.number().int().min(0).default(0),items:m.z.array(he).max(100).default([])}).strict().default({pendingCount:0,items:[]}),ye=m.z.enum(["control","realtime","adapter-snapshot","transcript-tail","transcript-scan","process-scan","app-session"]),Ie=m.z.object({id:m.z.string().trim().min(1).max(240),status:m.z.enum(["running","completed"]),startedAt:m.z.string().datetime().optional(),completedAt:m.z.string().datetime().optional()}).strict(),Ae=m.z.object({id:m.z.string().trim().min(1).max(240),providerTurnId:m.z.string().trim().max(240).optional(),source:ye.optional(),userPrompt:m.z.string().trim().optional(),status:m.z.enum(["queued","running","waiting","completed","failed"]).default("running"),phase:G.optional(),summary:m.z.string().trim().max(1e3).optional(),lastMessage:m.z.string().trim().optional(),lastMessageItemId:m.z.string().trim().max(240).optional(),contextCompactions:m.z.array(Ie).max(20).optional(),revision:m.z.number().int().min(0).default(0),sourcePriority:m.z.number().int().min(0).max(100).optional(),snapshotVersion:m.z.number().int().min(0).optional(),observedAt:m.z.string().datetime().optional(),startedAt:m.z.string().datetime().optional(),updatedAt:m.z.string().datetime().optional(),completedAt:m.z.string().datetime().optional()}).strict(),be=Ae.pick({id:!0,providerTurnId:!0,userPrompt:!0,status:!0,phase:!0,summary:!0,lastMessage:!0,contextCompactions:!0,startedAt:!0,updatedAt:!0,completedAt:!0}).strict(),we=m.z.object({id:m.z.string().trim().min(1).max(120),agent:B,appSessionId:m.z.string().trim().max(120).optional(),appId:m.z.string().trim().max(120).optional(),providerSessionId:m.z.string().trim().max(240).optional(),providerMeta:m.z.record(m.z.string(),m.z.unknown()).optional(),appBindingKeys:m.z.array(m.z.string().trim().min(1).max(240)).max(20).optional(),actions:Q.optional(),activeTurnId:m.z.string().trim().max(240).optional(),title:m.z.string().trim().max(240).optional(),cwd:m.z.string().trim().max(4096).optional(),userPrompt:m.z.string().trim().optional(),turns:m.z.array(Ae).max(50).optional(),status:K.default("running"),phase:G.default("unknown"),summary:m.z.string().trim().max(1e3).optional(),lastMessage:m.z.string().trim().optional(),lastMessageItemId:m.z.string().trim().max(240).optional(),currentTool:J.optional(),toolCallsSinceLastMessage:m.z.number().int().min(0).default(0),subAgents:m.z.array(Y).max(50).default([]),transcriptPath:m.z.string().trim().max(4096).optional(),transcriptSize:m.z.number().int().min(0).optional(),startedAt:m.z.string().datetime(),updatedAt:m.z.string().datetime(),completedAt:m.z.string().datetime().optional(),error:m.z.string().trim().max(4e3).optional(),counters:Z,queue:fe}).strict();m.z.object({session:we,provider:m.z.string().trim().min(1).max(80),action:m.z.enum(["send","queue","steer","interrupt","approval"]),decision:m.z.enum(["allow","deny","skip"]).optional(),turnId:m.z.string().trim().min(1).max(240).optional(),providerTurnId:m.z.string().trim().min(1).max(240).optional(),queueId:m.z.string().trim().min(1).max(120).optional()}).strict();const ze=m.z.object({id:m.z.string().trim().min(1).max(120),agent:m.z.enum(["codex","claude"]),providerSessionId:m.z.string().trim().min(1).max(240),title:m.z.string().trim().max(240).optional(),userPrompt:m.z.string().trim().optional(),lastMessage:m.z.string().trim().optional(),cwd:m.z.string().trim().min(1).max(4096),lastActiveAt:m.z.string().datetime(),archivedAt:m.z.string().datetime()}).strict();m.z.object({schemaVersion:m.z.literal(1).default(1),items:m.z.array(ze).max(50).default([])}).strict(),m.z.object({items:m.z.array(ze).max(50).default([])}).strict(),m.z.object({item:ze,turns:m.z.array(be).max(50).default([])}).strict(),m.z.object({disposition:m.z.enum(["resumed","already-open"]),aiSessionId:m.z.string().trim().min(1).max(120),providerSessionId:m.z.string().trim().min(1).max(240),appSessionId:m.z.string().trim().min(1).max(120)}).strict();const Ne=we.pick({id:!0,agent:!0,appSessionId:!0,appId:!0,providerSessionId:!0,providerMeta:!0,appBindingKeys:!0,actions:!0,activeTurnId:!0,title:!0,cwd:!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}),ve=m.z.object({runningCount:m.z.number().int().min(0).default(0),waitingCount:m.z.number().int().min(0).default(0),staleCount:m.z.number().int().min(0).default(0),sessions:m.z.array(Ne).default([]),updatedAt:m.z.string().datetime()}).strict();m.z.object({streamId:m.z.string().trim().min(1).max(240),revision:m.z.number().int().min(0),lastEventAt:m.z.string().datetime(),snapshot:ve}).strict(),ve.pick({runningCount:!0,waitingCount:!0,staleCount:!0,updatedAt:!0}).extend({idleCount:m.z.number().int().min(0).default(0),problemCount:m.z.number().int().min(0).default(0),revision:m.z.number().int().min(0).optional()});const Ee=m.z.enum(["provider-event","app-session-created","app-session-updated","app-session-deleted","discovery-scan","control-action","heartbeat-sync","startup"]),Se=m.z.object({streamId:m.z.string().trim().min(1).max(240),instanceId:m.z.string().trim().min(1).max(160),nodeId:m.z.string().trim().min(1).max(160).optional(),revision:m.z.number().int().min(0),previousRevision:m.z.number().int().min(0).optional(),traceId:m.z.string().trim().min(1).max(160),generatedAt:m.z.string().datetime(),reason:Ee}).strict(),_e=m.z.object({meta:Se,snapshot:ve}).strict(),Te=m.z.object({meta:Se,upserted:m.z.array(Ne).default([]),removed:m.z.array(m.z.string().trim().min(1).max(120)).default([])}).strict(),ke=m.z.object({meta:Se,sessionIds:m.z.array(m.z.string().trim().min(1).max(120)).default([]),expiresAt:m.z.string().datetime()}).strict();m.z.object({instanceId:m.z.string().trim().min(1).max(160),nodeId:m.z.string().trim().min(1).max(160).optional(),sessionId:m.z.string().trim().min(1).max(120),providerSessionId:m.z.string().trim().min(1).max(240),turnId:m.z.string().trim().min(1).max(240),itemId:m.z.string().trim().min(1).max(240),delta:m.z.string().min(1),generatedAt:m.z.string().datetime()}).strict(),m.z.object({streamId:m.z.string().trim().min(1).max(240),instanceId:m.z.string().trim().min(1).max(160),sinceRevision:m.z.number().int().min(0),latestRevision:m.z.number().int().min(0),earliestRetainedRevision:m.z.number().int().min(0),syncRequired:m.z.boolean().default(!1),events:m.z.array(m.z.discriminatedUnion("type",[m.z.object({type:m.z.literal("ai-session.snapshot"),payload:_e}).strict(),m.z.object({type:m.z.literal("ai-session.patch"),payload:Te}).strict(),m.z.object({type:m.z.literal("ai-session.removed"),payload:ke}).strict()])).default([])}).strict();const Ce=m.z.object({source:ye,sourcePriority:m.z.number().int().min(0).max(100).optional(),observedAt:m.z.string().datetime().optional(),snapshotVersion:m.z.number().int().min(0).optional()}).strict(),xe=Ce.extend({type:m.z.literal("snapshot"),agent:m.z.string().trim().min(1).max(80),appSessionId:m.z.string().trim().max(120).optional(),appId:m.z.string().trim().max(120).optional(),providerSessionId:m.z.string().trim().max(240).optional(),providerMeta:m.z.record(m.z.string(),m.z.unknown()).optional(),appBindingKeys:m.z.array(m.z.string().trim().min(1).max(240)).max(20).optional(),actions:Q.optional(),title:m.z.string().trim().max(240).optional(),cwd:m.z.string().trim().max(4096).optional(),activeTurnId:m.z.string().trim().max(240).optional(),userPrompt:m.z.string().trim().optional(),turns:m.z.array(Ae).max(50).optional(),status:K.optional(),phase:G.optional(),summary:m.z.string().trim().max(1e3).optional(),lastMessage:m.z.string().trim().optional(),lastMessageItemId:m.z.string().trim().max(240).optional(),currentTool:J.optional(),toolCallsSinceLastMessage:m.z.number().int().min(0).optional(),subAgents:m.z.array(Y).max(50).optional(),transcriptPath:m.z.string().trim().max(4096).optional(),transcriptSize:m.z.number().int().min(0).optional(),replaceActivity:m.z.boolean().optional()}).strict(),Oe=Ce.extend({type:m.z.literal("event"),sessionId:m.z.string().trim().min(1).max(120),kind:m.z.enum(["lifecycle","send-ack","turn-started","user-message","assistant-message","approval-requested","turn-completed","tool-activity","sub-agent-activity","context-compaction"]),activeTurnId:m.z.string().trim().max(240).optional(),providerTurnId:m.z.string().trim().max(240).optional(),userPrompt:m.z.string().trim().optional(),text:m.z.string().optional(),itemId:m.z.string().trim().max(240).optional(),status:K.optional(),phase:G.optional(),summary:m.z.string().trim().max(1e3).optional(),error:m.z.string().trim().max(4e3).optional(),currentTool:J.nullable().optional(),toolCallsSinceLastMessage:m.z.number().int().min(0).optional(),subAgents:m.z.array(Y).max(50).optional(),contextCompaction:Ie.optional(),counters:m.z.object({toolCalls:m.z.number().int().min(0).optional(),edits:m.z.number().int().min(0).optional(),approvals:m.z.number().int().min(0).optional()}).strict().optional()}).strict().superRefine((e,t)=>{if("context-compaction"===e.kind?e.contextCompaction||t.addIssue({code:"custom",path:["contextCompaction"],message:"context-compaction events require contextCompaction"}):void 0!==e.contextCompaction&&t.addIssue({code:"custom",path:["contextCompaction"],message:"contextCompaction is only valid for context-compaction events"}),"sub-agent-activity"===e.kind?e.subAgents||t.addIssue({code:"custom",path:["subAgents"],message:"sub-agent-activity events require subAgents"}):void 0!==e.subAgents&&t.addIssue({code:"custom",path:["subAgents"],message:"subAgents is only valid for sub-agent-activity events"}),"tool-activity"!==e.kind)return void 0!==e.currentTool&&t.addIssue({code:"custom",path:["currentTool"],message:"currentTool is only valid for tool-activity events"}),void(void 0!==e.toolCallsSinceLastMessage&&t.addIssue({code:"custom",path:["toolCallsSinceLastMessage"],message:"toolCallsSinceLastMessage is only valid for tool-activity events"}));"currentTool"in e||t.addIssue({code:"custom",path:["currentTool"],message:"tool-activity events require currentTool"}),void 0===e.toolCallsSinceLastMessage&&t.addIssue({code:"custom",path:["toolCallsSinceLastMessage"],message:"tool-activity events require toolCallsSinceLastMessage"})});m.z.discriminatedUnion("type",[xe,Oe]);const Re=m.z.union([m.z.object({type:m.z.literal("schedule"),scheduleKind:m.z.literal("interval").default("interval"),intervalMs:m.z.number().int().min(1e3)}).strict(),m.z.object({type:m.z.literal("schedule"),scheduleKind:m.z.literal("daily"),timeOfDay:m.z.string().regex(/^([01]\d|2[0-3]):[0-5]\d$/),timezone:m.z.string().trim().min(1).max(120)}).strict(),m.z.object({type:m.z.literal("schedule"),scheduleKind:m.z.literal("weekly"),weekdays:m.z.array(m.z.number().int().min(0).max(6)).min(1).max(7),timeOfDay:m.z.string().regex(/^([01]\d|2[0-3]):[0-5]\d$/),timezone:m.z.string().trim().min(1).max(120)}).strict()]),De=m.z.union([Re,m.z.object({type:m.z.literal("file-change"),roots:m.z.array(m.z.string().trim().min(1).max(4096)).min(1).max(50),globs:m.z.array(m.z.string().trim().min(1).max(500)).min(1).max(100),ignore:m.z.array(m.z.string().trim().min(1).max(500)).max(100).optional(),debounceMs:m.z.number().int().min(100).max(6e4).default(1500)}).strict(),m.z.object({type:m.z.literal("ai-session"),agent:m.z.string().trim().min(1).max(80).optional(),statuses:m.z.array(m.z.enum(["running","waiting","idle","failed"])).max(20).optional(),phases:m.z.array(m.z.enum(["thinking","tool","editing","approval","responding","unknown"])).max(20).optional()}).strict()]),Me=m.z.object({promptTemplate:m.z.string().trim().min(1).max(2e4)}).strict(),Pe=m.z.object({cooldownMs:m.z.number().int().min(0).max(864e5).optional(),maxConcurrentRuns:m.z.number().int().min(1).max(20).default(1),whenBusy:m.z.enum(["skip","queue"]).default("skip")}).strict(),je=m.z.object({configHash:m.z.string().trim().min(8).max(80),name:m.z.string().trim().min(1).max(160),description:m.z.string().trim().max(1e3).optional(),source:De,action:Me,policy:Pe.default({maxConcurrentRuns:1,whenBusy:"skip"}),createdAt:m.z.string().datetime(),updatedAt:m.z.string().datetime()}).strict(),Le=m.z.object({type:m.z.literal("ai-session"),aiSessionId:m.z.string().trim().min(1).max(160)}).strict(),$e=m.z.object({configHash:m.z.string().trim().min(8).max(80),deploymentId:m.z.string().trim().min(1).max(240).optional(),instanceId:m.z.string().trim().min(1).max(160),origin:m.z.enum(["control-plane","controlled-instance"]).default("controlled-instance"),enabled:m.z.boolean().default(!0),target:Le,localName:m.z.string().trim().min(1).max(160).optional(),createdAt:m.z.string().datetime(),updatedAt:m.z.string().datetime()}).strict(),Fe=m.z.object({configHash:m.z.string().trim().min(8).max(80),deploymentId:m.z.string().trim().min(1).max(240).optional(),instanceId:m.z.string().trim().min(1).max(160),status:m.z.enum(["idle","running","disabled","error"]).default("idle"),lastTriggeredAt:m.z.string().datetime().optional(),lastCompletedAt:m.z.string().datetime().optional(),lastSkippedAt:m.z.string().datetime().optional(),lastError:m.z.string().trim().max(4e3).optional(),runCount:m.z.number().int().min(0).default(0),skippedCount:m.z.number().int().min(0).default(0)}).strict(),Ue=m.z.object({id:m.z.string().trim().min(1).max(160),configHash:m.z.string().trim().min(8).max(80),deploymentId:m.z.string().trim().min(1).max(240).optional(),instanceId:m.z.string().trim().min(1).max(160),eventType:m.z.enum(["manual","schedule","file-change","ai-session"]),status:m.z.enum(["started","completed","failed","skipped"]),target:Le,promptPreview:m.z.string().trim().max(500),eventSummary:m.z.string().trim().max(1e3).optional(),error:m.z.string().trim().max(4e3).optional(),startedAt:m.z.string().datetime(),completedAt:m.z.string().datetime().optional()}).strict();m.z.object({schemaVersion:m.z.literal(1).default(1),configs:m.z.array(je).default([]),deployments:m.z.array($e).default([]),runtime:m.z.array(Fe).default([]),recentRuns:m.z.array(Ue).default([])}).strict();const Ve="2026-07-30",He=m.z.string(),qe=m.z.string().trim().min(1).max(120).regex(/^[a-zA-Z0-9][a-zA-Z0-9_.:-]*$/),Be=m.z.string().datetime(),Ke=m.z.record(m.z.string(),m.z.string()).default({}),Ge=m.z.record(m.z.string(),m.z.string()).default({}),Je=m.z.string().regex(/^\d{4}-\d{2}-\d{2}$/,"Protocol version must use YYYY-MM-DD format."),We=/^[A-Za-z0-9_][A-Za-z0-9_.-]{0,127}$/,Xe=/^sha256:([a-fA-F0-9]{64})$/,Ye=/^(?:localhost|[a-z0-9](?:[a-z0-9.-]*[a-z0-9])?)(?::[1-9][0-9]{0,4})?$/,Ze=/^[a-z0-9]+(?:(?:[._]|__|-+)[a-z0-9]+)*$/;function Qe(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 r=-1===n?void 0:t.slice(n+1),i=-1===n?t:t.slice(0,n),o=r?Xe.exec(r):void 0;if(r&&!o)throw new Error("Docker image digest must use sha256 followed by 64 hexadecimal characters.");const s=i.lastIndexOf("/"),a=i.lastIndexOf(":"),c=a>s,d=c?i.slice(a+1):void 0,l=c?i.slice(0,a):i;if(d&&!We.test(d))throw new Error("Docker image tag is invalid.");if(!d&&!o)throw new Error("Docker image reference must include an explicit tag or sha256 digest.");const u=l.split("/");if(!u.length||u.some(e=>!e))throw new Error("Docker image repository path is invalid.");const m=u.length>1&&(u[0].includes(".")||u[0].includes(":")||"localhost"===u[0]),p=m?u.slice(1):u;if(m&&!Ye.test(u[0].toLowerCase()))throw new Error("Docker image registry host or port is invalid.");if(!p.length||p.some(e=>!Ze.test(e)))throw new Error("Docker image repository names must be lowercase and use valid separators.");const g=u.map((e,t)=>m&&0===t?e.toLowerCase():e).join("/"),h=o?`sha256:${o[1].toLowerCase()}`:void 0;return`${g}${d?`:${d}`:""}${h?`@${h}`:""}`}function et(e){const t=Qe(e),n=t.indexOf("@"),r=-1===n?void 0:t.slice(n+1),i=-1===n?t:t.slice(0,n),o=i.lastIndexOf("/"),s=i.lastIndexOf(":"),a=s>o;return{reference:t,repository:a?i.slice(0,s):i,tag:a?i.slice(s+1):void 0,digest:r}}const tt=m.z.string().trim().min(1).max(512).transform((e,t)=>{try{return Qe(e)}catch(e){return t.addIssue({code:"custom",message:e instanceof Error?e.message:String(e)}),m.z.NEVER}}),nt=m.z.string().trim().transform((e,t)=>{const n=Xe.exec(e);return n?`sha256:${n[1].toLowerCase()}`:(t.addIssue({code:"custom",message:"Docker image digest must use sha256 followed by 64 hexadecimal characters."}),m.z.NEVER)}),rt=m.z.object({codexModelHash:qe.nullable().optional(),claudeModelHash:qe.nullable().optional()}).strict().default({}),it=m.z.object({imageId:qe,tag:m.z.string().trim().min(1).max(128).regex(We).optional()}).strict(),ot={img_default:"market_taskhandoff_browser",img_codex:"market_taskhandoff_codex",img_ai:"market_taskhandoff_ai"};function st(e,t){if(e&&"object"==typeof e&&!Array.isArray(e)){const t=e;return{imageId:"string"==typeof t.imageId&&ot[t.imageId]||t.imageId,..."string"==typeof t.tag?{tag:t.tag}:{}}}if("string"==typeof t)return{imageId:ot[t]||t}}function at(e){if(!e||"object"!=typeof e||Array.isArray(e))return e;const t=e,{defaultImageId:n,...r}=t;return{...r,defaultImageSelection:st(t.defaultImageSelection,n)}}const ct=m.z.object({id:qe,name:m.z.string().trim().min(1).max(120),kind:m.z.enum(["tty","gui","web"]),source:m.z.enum(["builtin","custom"]),availability:m.z.enum(["available","missing-dependency"]),capabilities:m.z.object({automation:m.z.enum(["cdp"]).optional(),supportsCwdSelection:m.z.boolean().default(!1)}).strict().default({supportsCwdSelection:!1}),diagnosticCode:m.z.enum(["APP_EXECUTABLE_NOT_FOUND"]).optional()}).strict(),dt=m.z.object({code:m.z.enum(["APP_CATALOG_INVALID"]),message:m.z.string().trim().min(1).max(500)}).strict(),lt=m.z.object({items:m.z.array(ct).max(256),observedAt:Be,issues:m.z.array(dt).max(32).default([])}).strict(),ut=m.z.enum(["linux","darwin","win32","freebsd","openbsd","aix","sunos","unknown"]),mt=m.z.enum(["x64","arm64","arm","ia32","ppc64","s390x","riscv64","unknown"]),pt=m.z.enum(["apt","dnf","brew","npm"]),gt=m.z.enum(["user","passwordless-sudo","root"]),ht=m.z.object({platform:ut,arch:mt,installers:m.z.array(pt).max(8),privilege:gt,installerAccess:m.z.object({npmGlobalWritable:m.z.boolean().optional()}).strict().optional()}).strict(),ft=m.z.enum(["installed","not-installed","broken","unsupported"]),yt=m.z.enum(["recipe","bundled","external","none"]),It=m.z.object({code:m.z.enum(["BUNDLED","EXTERNALLY_MANAGED","ALREADY_INSTALLED","NOT_INSTALLED","UNSUPPORTED_PLATFORM","INSTALLER_UNAVAILABLE","INSTALLER_NOT_WRITABLE","INSUFFICIENT_PRIVILEGE","OPERATION_IN_PROGRESS"]),message:m.z.string().trim().min(1).max(500)}).strict(),At=m.z.object({id:qe,name:m.z.string().trim().min(1).max(120),kind:m.z.enum(["tty","gui","web"]),description:m.z.string().trim().max(500).optional(),state:ft,managementSource:yt,version:m.z.string().trim().max(120).optional(),canInstall:m.z.boolean(),canUninstall:m.z.boolean(),installReason:It.optional(),uninstallReason:It.optional(),activeJobId:qe.optional()}).strict(),bt=m.z.enum(["install","uninstall"]),wt=m.z.enum(["queued","running","succeeded","failed","cancelled","interrupted"]),zt=m.z.object({current:m.z.number().finite().nonnegative().optional(),total:m.z.number().finite().positive().optional(),unit:m.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"]}),Nt=m.z.object({executable:m.z.string().trim().min(1).max(4096),args:m.z.array(m.z.string().max(4096)).max(128)}).strict(),vt=m.z.object({code:m.z.string().trim().min(1).max(120).regex(/^[a-z0-9][a-z0-9._-]*$/),message:m.z.string().trim().min(1).max(4096),retryable:m.z.boolean(),sessionIds:m.z.array(qe).max(64).optional()}).strict(),Et=m.z.object({id:qe,requestId:qe.optional(),appId:qe,operation:bt,state:wt,phase:m.z.string().trim().min(1).max(120).optional(),progress:zt.optional(),command:Nt.optional(),logTail:m.z.string().max(32768).optional(),logTruncated:m.z.boolean().optional(),error:vt.optional(),requestedAt:Be,startedAt:Be.optional(),finishedAt:Be.optional(),updatedAt:Be}).strict(),St=m.z.object({streamId:qe,sequence:m.z.number().int().nonnegative(),capabilities:ht,apps:m.z.array(At).max(256),activeJobs:m.z.array(Et).max(256),recentJobs:m.z.array(Et).max(256),observedAt:Be}).strict();m.z.object({requestId:qe.optional()}).strict(),m.z.object({job:Et}).strict(),m.z.object({type:m.z.literal("app-management"),streamId:qe,sequence:m.z.number().int().nonnegative(),observedAt:Be,job:Et.optional(),snapshot:St.optional()}).strict().refine(e=>void 0!==e.job||void 0!==e.snapshot,{message:"An app management event requires a job or snapshot."});const _t=m.z.object({component:m.z.enum(["control-plane","node-agent","controlled-instance"]),packageName:m.z.string().trim().max(160).optional(),packageVersion:m.z.string().trim().max(80).optional(),protocolVersion:He.optional(),buildId:m.z.string().trim().max(160).optional(),builtAt:m.z.string().trim().max(120).optional(),gitCommit:m.z.string().trim().max(120).optional(),imageRef:m.z.string().trim().max(512).optional(),imageDigest:m.z.string().trim().max(240).optional()}).strict(),Tt=m.z.enum(["stable","beta","alpha"]),kt=m.z.object({packageName:m.z.literal("@task-handoff/controlled-instance"),version:m.z.string().trim().min(1).max(80),platform:m.z.string().trim().min(1).max(40),arch:m.z.string().trim().min(1).max(40),formatVersion:m.z.number().int().positive(),launcherAbi:m.z.number().int().positive(),entrypoint:m.z.string().trim().min(1).max(512),sha256:m.z.string().regex(/^[a-f0-9]{64}$/)}).strict(),Ct=m.z.object({code:m.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:m.z.string().trim().min(1).max(4096),expectedVersion:m.z.string().trim().min(1).max(80).optional(),actualVersion:m.z.string().trim().min(1).max(80).optional(),retryable:m.z.boolean().default(!1)}).strict(),xt=m.z.object({desiredVersion:m.z.string().trim().min(1).max(80),actualVersion:m.z.string().trim().min(1).max(80).optional(),phase:m.z.enum(["pending","draining","installing","restarting","verifying","matched","failed"]),attempt:m.z.number().int().nonnegative().default(0),lastAttemptAt:Be.optional(),matchedAt:Be.optional(),error:Ct.optional()}).strict(),Ot=m.z.object({runningInstanceCount:m.z.number().int().nonnegative(),stoppedInstanceCount:m.z.number().int().nonnegative(),activeInstanceCount:m.z.number().int().nonnegative(),restartInstanceCount:m.z.number().int().nonnegative(),runningInstanceIds:m.z.array(qe).max(1024).default([]),stoppedInstanceIds:m.z.array(qe).max(1024).default([]),activeInstanceIds:m.z.array(qe).max(1024).default([])}).strict(),Rt=m.z.object({phase:m.z.enum(["queued","updating-node","restarting-node","converging-instances","succeeded","degraded","failed"]),desiredVersion:m.z.string().trim().min(1).max(80),nodeVersion:m.z.string().trim().min(1).max(80).optional(),expectedInstanceIds:m.z.array(qe).max(1024).default([]),expectedInstanceCount:m.z.number().int().nonnegative(),matchedInstanceCount:m.z.number().int().nonnegative(),pendingInstanceCount:m.z.number().int().nonnegative(),failedInstanceCount:m.z.number().int().nonnegative(),deferredInstanceCount:m.z.number().int().nonnegative().default(0)}).strict(),Dt=m.z.object({channel:Tt.default("stable")}).strict(),Mt=m.z.object({source:m.z.literal("npm"),channel:Tt,currentVersion:m.z.string().trim().max(240).optional(),availableVersion:m.z.string().trim().min(1).max(240),artifactRef:m.z.string().trim().min(1).max(512).optional(),runtimeArtifacts:m.z.array(kt).default([]),impact:Ot,updateAvailable:m.z.boolean(),supported:m.z.boolean().default(!0),reason:m.z.string().trim().max(2048).optional(),checkedAt:Be,preflightToken:m.z.string().trim().min(16).max(240).optional()}).strict(),Pt=m.z.object({id:qe,nodeId:qe,source:m.z.literal("npm"),channel:Tt,fromVersion:m.z.string().trim().max(240).optional(),toVersion:m.z.string().trim().min(1).max(240),artifactRef:m.z.string().trim().min(1).max(512).optional(),runtimeArtifacts:m.z.array(kt).default([]),impact:Ot,rollout:Rt,status:m.z.enum(["queued","updating-node","restarting-node","converging-instances","succeeded","degraded","failed"]),error:Ct.optional(),startedAt:Be.optional(),completedAt:Be.optional(),createdAt:Be,updatedAt:Be}).strict(),jt=m.z.object({channel:Tt,targetVersion:m.z.string().trim().min(1).max(240),preflightToken:m.z.string().trim().min(16).max(240)}).strict(),Lt=m.z.object({type:m.z.enum(["branch","tag","commit"]),name:m.z.string().trim().min(1).max(240).optional(),commit:m.z.string().trim().max(80).optional()}).strict(),$t=m.z.object({type:m.z.enum(["none","ssh-key","https-token"]).default("none"),secretId:m.z.string().trim().min(1).max(120).optional()}).strict(),Ft=m.z.object({depth:m.z.number().int().positive().max(1e5).optional(),submodules:m.z.boolean().default(!1),lfs:m.z.boolean().default(!1),subdirectory:m.z.string().trim().max(240).default("")}).strict();m.z.object({id:qe,name:m.z.string().trim().min(1).max(160),url:m.z.string().trim().min(1).max(2048),provider:m.z.string().trim().max(80).optional(),ref:Lt.default({type:"branch",name:"main"}),auth:$t.default({type:"none"}),clone:Ft.default({submodules:!1,lfs:!1,subdirectory:""}),defaultImageSelection:it.optional(),labels:Ke,createdAt:Be,updatedAt:Be}).strict();const Ut=m.z.object({id:qe,nodeId:qe,name:m.z.string().trim().min(1).max(160),path:m.z.string().trim().min(1).max(4096),defaultImageSelection:it.optional(),labels:Ke,createdAt:Be,updatedAt:Be}).strict(),Vt=m.z.discriminatedUnion("type",[m.z.object({type:m.z.literal("git-repository"),repositoryId:qe.optional(),url:m.z.string().trim().min(1).max(2048),provider:m.z.string().trim().max(80).optional(),ref:Lt.default({type:"branch",name:"main"}),auth:$t.default({type:"none"}),clone:Ft.default({submodules:!1,lfs:!1,subdirectory:""})}).strict(),m.z.object({type:m.z.literal("git-template"),url:m.z.string().trim().min(1).max(2048),templateId:m.z.string().trim().min(1).max(120).optional(),ref:Lt.default({type:"branch",name:"main"}),auth:$t.default({type:"none"}),clone:Ft.default({submodules:!1,lfs:!1,subdirectory:""})}).strict(),m.z.object({type:m.z.literal("local-folder"),localFolderId:qe.optional(),path:m.z.string().trim().min(1).max(4096),ownerNodeId:qe.optional()}).strict()]),Ht=m.z.object({mode:m.z.enum(["local-bind","git-clone","empty-volume","persistent-volume"]),path:m.z.string().trim().min(1).max(4096).default("/workspace"),volumeName:m.z.string().trim().max(240).optional(),readOnly:m.z.boolean().default(!1)}).strict(),qt=m.z.enum(["codex","claude"]),Bt=m.z.object({id:qe,name:m.z.string().trim().min(1).max(160),source:Vt,defaultImageSelection:it.optional(),defaultNodeId:qe.optional(),defaultRuntimeId:qe.optional(),workspacePolicy:Ht,labels:Ke,createdAt:Be,updatedAt:Be}).strict(),Kt=m.z.object({id:qe,name:m.z.string().trim().min(1).max(160),endpoint:m.z.string().trim().min(1).max(2048),key:m.z.string().trim().min(1).max(4096),model:m.z.string().trim().min(1).max(240),app:qt,enabled:m.z.boolean().default(!0),order:m.z.number().int().min(0).max(1e6).default(0),labels:Ke,createdAt:Be,updatedAt:Be}).strict(),Gt=Kt,Jt=Kt.omit({key:!0}).extend({keyPreview:m.z.string().trim().min(1).max(160),keySet:m.z.boolean()}).strict(),Wt=Jt.extend({referenceCount:m.z.number().int().min(0)}).strict(),Xt=m.z.object({instanceId:qe,codexModelHash:qe.optional(),claudeModelHash:qe.optional(),updatedAt:Be}).strict(),Yt=m.z.discriminatedUnion("type",[m.z.object({type:m.z.literal("control-plane"),name:Kt.shape.name,enabled:Kt.shape.enabled,order:Kt.shape.order}).strict(),m.z.object({type:m.z.literal("node"),nodeId:qe,name:Kt.shape.name,enabled:Kt.shape.enabled,order:Kt.shape.order,referenceCount:m.z.number().int().min(0)}).strict()]),Zt=m.z.object({id:qe,model:Jt,locations:m.z.array(Yt).min(1),referenceCount:m.z.number().int().min(0).default(0)}).strict(),Qt=m.z.object({nodeId:qe,code:m.z.string().trim().min(1).max(120),message:m.z.string().trim().min(1).max(2e3)}).strict();m.z.object({models:m.z.array(Zt),nodeDiagnostics:m.z.array(Qt).default([]),updatedAt:Be}).strict();const en=Kt.omit({id:!0,createdAt:!0,updatedAt:!0}).strict(),tn=en.partial().strict(),nn=Kt,rn=m.z.object({modelSelection:rt,codexModelHash:qe.optional(),claudeModelHash:qe.optional()}).strict();function on(e){const t={app:qt.parse(e.app),endpoint:Kt.shape.endpoint.parse(e.endpoint),key:Kt.shape.key.parse(e.key),model:Kt.shape.model.parse(e.model)};return`mdl_${r.createHash("sha256").update(JSON.stringify(t)).digest("hex")}`}const sn=m.z.enum(["market","custom"]),an=m.z.enum(["active","deprecated","yanked"]),cn=m.z.discriminatedUnion("kind",[m.z.object({kind:m.z.literal("builtin"),key:m.z.string().trim().min(1).max(120)}).strict(),m.z.object({kind:m.z.literal("remote"),url:m.z.string().trim().url().max(2048),mediaType:m.z.enum(["image/png","image/jpeg","image/webp"]).optional(),digest:nt.optional()}).strict()]),dn=m.z.array(m.z.string().trim().min(1).max(80)).default([]),ln=m.z.array(m.z.string().trim().min(1).max(120)).default([]),un=m.z.record(m.z.string().trim().min(2).max(35),m.z.string().trim().min(1).max(4096)),mn=m.z.object({os:m.z.string().trim().min(1).max(40),architecture:m.z.string().trim().min(1).max(40),digest:nt.optional(),downloadSizeBytes:m.z.number().int().positive().optional(),unpackedSizeBytes:m.z.number().int().positive().optional()}).strict(),pn=m.z.object({name:m.z.string().trim().min(1).max(128).regex(We),version:m.z.string().trim().min(1).max(160).optional(),reference:tt,manifestDigest:nt.optional(),publishedAt:Be.optional(),platforms:m.z.array(mn).default([]),status:an.default("active")}).strict(),gn=m.z.object({id:qe,publisher:m.z.string().trim().min(1).max(160),slug:m.z.string().trim().min(1).max(160),name:m.z.string().trim().min(1).max(160),description:m.z.string().trim().min(1).max(4096),localizedDescriptions:un.optional(),cover:cn.optional(),repository:m.z.string().trim().min(1).max(512),defaultTag:m.z.string().trim().min(1).max(128).regex(We),tags:m.z.array(pn).min(1),capabilities:dn,optionalApps:ln,defaultEnv:Ge,labels:Ke,status:an.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."})});m.z.object({protocolVersion:Je,catalogId:qe,revision:m.z.string().trim().min(1).max(240),source:m.z.enum(["embedded","remote","cache"]),generatedAt:Be,expiresAt:Be.optional(),items:m.z.array(gn)}).strict(),m.z.object({source:m.z.enum(["embedded","remote","cache"]),state:m.z.enum(["ready","refreshing","stale","failed"]),revision:m.z.string().trim().min(1).max(240),updatedAt:Be,error:m.z.string().trim().max(4096).optional()}).strict(),m.z.object({id:qe,origin:m.z.literal("custom"),name:m.z.string().trim().min(1).max(160),description:m.z.string().trim().max(4096).optional(),localizedDescriptions:un.optional(),cover:cn.optional(),reference:tt,repository:m.z.string().trim().min(1).max(512),tag:m.z.string().trim().min(1).max(128).regex(We).optional(),pullPolicy:m.z.literal("if-not-present").default("if-not-present"),capabilities:dn,optionalApps:ln,defaultEnv:Ge,labels:Ke,createdAt:Be,updatedAt:Be}).strict();const hn=m.z.object({name:m.z.string().trim().min(1).max(128).regex(We),version:m.z.string().trim().min(1).max(160).optional(),reference:tt,manifestDigest:nt.optional(),status:an}).strict(),fn=m.z.object({id:qe,origin:sn,name:m.z.string().trim().min(1).max(160),description:m.z.string().trim().max(4096).optional(),localizedDescriptions:un.optional(),cover:cn,repository:m.z.string().trim().min(1).max(512),tag:m.z.string().trim().min(1).max(128).regex(We).optional(),availableTags:m.z.array(hn),reference:tt,digest:nt.optional(),downloadSizeBytes:m.z.number().int().positive().optional(),unpackedSizeBytes:m.z.number().int().positive().optional(),capabilities:dn,optionalApps:ln,defaultEnv:Ge,labels:Ke,readOnly:m.z.boolean(),lifecycleStatus:an.optional(),market:m.z.object({catalogId:qe,catalogRevision:m.z.string().trim().min(1).max(240),publisher:m.z.string().trim().min(1).max(160),version:m.z.string().trim().min(1).max(160).optional()}).strict().optional()}).strict(),yn=m.z.object({id:qe,origin:sn,name:m.z.string().trim().min(1).max(160),description:m.z.string().trim().max(4096).optional(),localizedDescriptions:un.optional(),cover:cn.optional(),repository:m.z.string().trim().min(1).max(512),tag:m.z.string().trim().min(1).max(128).regex(We).optional(),requestedReference:tt,resolvedDigest:nt.optional(),resolvedReference:tt.optional(),downloadSizeBytes:m.z.number().int().positive().optional(),pullPolicy:m.z.literal("if-not-present").default("if-not-present"),capabilities:dn,optionalApps:ln,defaultEnv:Ge,labels:Ke,market:m.z.object({catalogId:qe,catalogRevision:m.z.string().trim().min(1).max(240),publisher:m.z.string().trim().min(1).max(160),version:m.z.string().trim().min(1).max(160).optional()}).strict().optional(),createdAt:Be,updatedAt:Be}).strict(),In=m.z.object({phase:m.z.enum(["checking-image","pulling-image","resolving-image","ready","failed"]),requestedReference:tt,generation:m.z.number().int().nonnegative().default(0),error:m.z.string().trim().max(4096).optional(),startedAt:Be,updatedAt:Be}).strict(),An="image.pull.terminal.output",bn="image.pull.terminal.finished",wn=m.z.object({instanceId:qe,generation:m.z.number().int().nonnegative(),requestedReference:tt,sequence:m.z.number().int().nonnegative(),observedAt:Be}).strict(),zn=wn.extend({data:m.z.string().min(1).max(65536),replay:m.z.boolean().optional()}).strict(),Nn=wn.extend({outcome:m.z.enum(["succeeded","failed"])}).strict();wn.extend({status:m.z.enum(["connecting","pulling","extracting","complete","failed"]),layers:m.z.object({total:m.z.number().int().nonnegative(),completed:m.z.number().int().nonnegative(),downloaded:m.z.number().int().nonnegative(),downloading:m.z.number().int().nonnegative(),extracting:m.z.number().int().nonnegative()}).strict(),bytes:m.z.object({current:m.z.number().finite().nonnegative(),total:m.z.number().finite().positive()}).strict().optional(),percent:m.z.number().finite().min(0).max(100).optional(),message:m.z.string().trim().min(1).max(500),terminalTail:m.z.string().max(262144).optional(),terminalTruncated:m.z.boolean().optional()}).strict();const vn=m.z.object({id:qe,name:m.z.string().trim().min(1).max(160),connectionMode:m.z.enum(["local-ipc","local-loopback","direct-http","reverse-wss"]).default("direct-http"),auth:m.z.object({mode:m.z.enum(["local-static-key","paired-hmac"]).default("local-static-key"),keyId:qe.optional(),secret:m.z.string().trim().max(4096).optional(),pairedAt:Be.optional(),pairing:m.z.object({status:m.z.enum(["pending","paired","expired"]).default("pending"),joinToken:m.z.string().trim().max(4096).optional(),expiresAt:Be.optional()}).strict().optional()}).strict().default({mode:"local-static-key"}),endpoint:m.z.string().trim().max(2048).optional(),controlEndpoint:m.z.string().trim().max(2048).optional(),containerEndpoint:m.z.string().trim().max(2048).optional(),publicWebBase:m.z.string().trim().max(2048).optional(),status:m.z.enum(["unknown","online","offline","degraded"]).default("unknown"),health:m.z.enum(["unknown","ok","degraded","failed"]).default("unknown"),capabilities:m.z.record(m.z.string(),m.z.unknown()).default({}),appInventory:lt.optional(),labels:Ke,lastSeenAt:Be.optional(),createdAt:Be,updatedAt:Be}).strict(),En=m.z.object({id:qe,nodeId:qe,name:m.z.string().trim().min(1).max(160),type:m.z.enum(["docker","kubernetes","local"]),status:m.z.enum(["unknown","online","offline","degraded"]).default("unknown"),accessStrategy:m.z.enum(["node-proxy","direct-port","kubernetes-ingress","kubernetes-port-forward"]).default("node-proxy"),capabilities:m.z.record(m.z.string(),m.z.unknown()).default({}),labels:Ke,createdAt:Be,updatedAt:Be}).strict(),Sn=m.z.object({instanceId:qe,runtimeKind:m.z.literal("docker"),state:m.z.enum(["pending","available","stopped","unavailable"]),sampledAt:Be,cpu:m.z.object({usagePercent:m.z.number().nonnegative()}).strict().optional(),memory:m.z.object({usageBytes:m.z.number().nonnegative(),limitBytes:m.z.number().nonnegative().optional(),usagePercent:m.z.number().nonnegative().optional()}).strict().optional(),network:m.z.object({rxBytes:m.z.number().nonnegative(),txBytes:m.z.number().nonnegative()}).strict().optional(),blockIo:m.z.object({readBytes:m.z.number().nonnegative(),writeBytes:m.z.number().nonnegative()}).strict().optional(),pids:m.z.number().int().nonnegative().optional(),error:m.z.string().trim().max(2048).optional()}).strict();m.z.object({ok:m.z.boolean().optional(),role:m.z.string().optional(),nodeId:qe.optional(),platform:ut.optional()}).passthrough();const _n=m.z.object({bindScope:m.z.enum(["loopback","all-ipv4"]),port:m.z.number().int().min(1).max(65535)}).strict(),Tn=_n.extend({host:m.z.enum(["127.0.0.1","0.0.0.0"]),status:m.z.enum(["listening","error"]),source:m.z.enum(["bootstrap","persisted"]),error:m.z.string().trim().max(2048).optional()}).strict(),kn=_n;m.z.object({nodeId:qe,joinToken:m.z.string().trim().min(1),expiresAt:Be}).passthrough(),m.z.object({id:qe,keyId:qe,url:m.z.string().trim().min(1).max(2048).optional(),name:m.z.string().trim().min(1).max(160).optional(),pairedAt:Be,updatedAt:Be.optional(),active:m.z.boolean().optional(),current:m.z.boolean().optional()}).passthrough(),m.z.object({remote:m.z.object({id:qe,url:m.z.string().trim().min(1).max(2048).optional(),keyId:qe,pairedAt:Be,active:m.z.boolean()}).passthrough(),tunnel:m.z.object({status:m.z.enum(["disabled","saved","connecting","connected","failed"]),error:m.z.string().trim().max(2048).optional()}).passthrough()}).passthrough(),m.z.object({deleted:m.z.boolean().optional()}).passthrough();const Cn=m.z.object({repository:m.z.string().trim().optional(),tag:m.z.string().trim().optional(),id:m.z.string().trim(),createdSince:m.z.string().trim().optional(),size:m.z.string().trim().optional(),sizeBytes:m.z.number().int().nonnegative().optional(),reference:m.z.string().trim().min(1),repoDigests:m.z.array(m.z.string().trim().min(1).max(512)).default([])}).passthrough();m.z.object({image:fn,status:m.z.enum(["available","pull-required","unknown"]),localImage:Cn.optional(),localSizeBytes:m.z.number().int().nonnegative().optional(),downloadSizeBytes:m.z.number().int().positive().optional(),unpackedSizeBytes:m.z.number().int().positive().optional(),error:m.z.string().trim().max(2048).optional()}).strict();const xn=m.z.lazy(()=>m.z.object({name:m.z.string().trim().min(1),path:m.z.string().trim().min(1).max(4096),children:m.z.array(xn)}).passthrough());m.z.object({status:m.z.number().int().min(100).max(599).optional(),headers:m.z.record(m.z.string(),m.z.string()).optional(),bodyBase64:m.z.string().optional()}).passthrough();const On=m.z.object({strategy:m.z.enum(["node-proxy","direct-port","kubernetes-ingress","kubernetes-port-forward"]).default("node-proxy"),web:m.z.string().trim().max(2048).optional(),api:m.z.string().trim().max(2048).optional(),vnc:m.z.string().trim().max(2048).optional(),tty:m.z.string().trim().max(2048).optional(),logs:m.z.string().trim().max(2048).optional(),status:m.z.enum(["unknown","reachable","endpoint-unreachable"]).default("unknown")}).strict(),Rn=m.z.object({strategy:m.z.enum(["control-plane-proxy","direct-port","node-proxy","kubernetes-ingress","kubernetes-port-forward"]).default("control-plane-proxy"),web:m.z.string().trim().max(2048).optional(),api:m.z.string().trim().max(2048).optional(),ws:m.z.string().trim().max(2048).optional(),status:m.z.enum(["unknown","reachable","endpoint-unreachable"]).default("unknown")}).strict().default({strategy:"control-plane-proxy",status:"unknown"}),Dn=m.z.object({mode:m.z.enum(["local-bind","git-clone","empty-volume","persistent-volume"]).optional(),status:m.z.enum(["unknown","pending","ready","failed"]).default("unknown"),path:m.z.string().trim().max(4096).optional(),resolvedCommit:m.z.string().trim().max(120).optional(),error:m.z.string().trim().max(2048).optional()}).passthrough(),Mn=m.z.object({id:qe,name:m.z.string().trim().min(1).max(160),projectId:qe.optional(),source:Vt,sourceSnapshot:m.z.record(m.z.string(),m.z.unknown()).default({}),modelSelection:rt,nodeId:qe,runtimeId:qe,imageSelection:it.optional(),imageSnapshot:yn.optional(),imageProvisioning:In.optional(),stateRevision:m.z.number().int().min(0).default(0),processIncarnationId:m.z.string().trim().min(1).max(120).optional(),status:m.z.enum(["created","provisioning","starting","registering","registered","running","stopping","stopped","failed","unhealthy"]).default("created"),health:m.z.enum(["unknown","ok","degraded","failed"]).default("unknown"),connectionStatus:m.z.enum(["unknown","online","offline","endpoint-unreachable"]).default("unknown"),agentStatus:m.z.enum(["unknown","online","offline"]).default("unknown"),targetStatus:m.z.enum(["unknown","reachable","endpoint-unreachable"]).default("unknown"),uiAccessStatus:m.z.enum(["unknown","reachable","endpoint-unreachable"]).default("unknown"),controlMode:m.z.enum(["standalone","controlled"]).default("controlled"),protocolVersion:He.optional(),instanceVersion:m.z.string().trim().max(80).optional(),build:_t.optional(),runtimeVersion:xt.optional(),ready:m.z.boolean().default(!1),capabilities:m.z.record(m.z.string(),m.z.unknown()).default({}),appInventory:lt.optional(),config:m.z.object({autoImportAgentConfigs:m.z.boolean().default(!0),defaultCodexPermissionMode:se.default("ask")}).strict().default({autoImportAgentConfigs:!0,defaultCodexPermissionMode:"ask"}),workspace:Dn.default({status:"unknown"}),target:On.default({strategy:"direct-port",status:"unknown"}),access:Rn,apps:m.z.object({runningCount:m.z.number().int().min(0).default(0),problemCount:m.z.number().int().min(0).default(0),updatedAt:Be.optional(),revision:m.z.number().int().min(0).optional()}).strict().default({runningCount:0,problemCount:0}),aiSessions:ve.default(()=>({runningCount:0,waitingCount:0,staleCount:0,sessions:[],updatedAt:(new Date).toISOString()})),triggers:m.z.object({enabledCount:m.z.number().int().min(0).default(0),runningCount:m.z.number().int().min(0).default(0),errorCount:m.z.number().int().min(0).default(0),configs:m.z.array(m.z.object({configHash:m.z.string().trim().min(1),config:je,deployments:m.z.array($e).default([]),runtime:m.z.array(Fe).default([])}).strict()).default([]),recentRuns:m.z.array(Ue).default([])}).strict().optional(),runtime:m.z.object({kind:m.z.string().trim().max(80).optional(),containerName:m.z.string().trim().max(240).optional(),containerId:m.z.string().trim().max(240).optional(),workspacePath:m.z.string().trim().max(4096).optional(),pid:m.z.number().int().positive().optional(),port:m.z.number().int().positive().max(65535).optional(),labels:m.z.record(m.z.string(),m.z.string()).default({})}).strict().default({labels:{}}),registrationToken:m.z.string().trim().min(1).max(240).optional(),lastHeartbeatAt:Be.optional(),createdAt:Be,updatedAt:Be}).strict(),Pn="instance.lifecycle.snapshot",jn=m.z.object({instanceId:Mn.shape.id,revision:m.z.number().int().min(0),updatedAt:Be,status:Mn.shape.status.unwrap(),health:Mn.shape.health.unwrap(),connectionStatus:Mn.shape.connectionStatus.unwrap(),accessStatus:m.z.enum(["reachable","endpoint-unreachable"]),imageProvisioning:In.optional(),workspace:Dn,runtime:Mn.shape.runtime.unwrap(),runtimeVersion:xt.optional(),ready:m.z.boolean(),lastHeartbeatAt:Be.optional()}).strict();function Ln(e,t){return Mn.safeParse($n(e,t))}function $n(e,t){if(!e||"object"!=typeof e||Array.isArray(e))return e;const n=e,r=new Set(Object.keys(Mn.shape)),i={};for(const[e,o]of Object.entries(n))r.has(e)?i[e]=o:t?.({instanceId:"string"==typeof n.id?n.id:void 0,field:e});if(n.capabilities&&"object"==typeof n.capabilities&&!Array.isArray(n.capabilities)){const e={...n.capabilities};Object.prototype.hasOwnProperty.call(e,"apps")&&(t?.({instanceId:"string"==typeof n.id?n.id:void 0,field:"capabilities.apps"}),delete e.apps),i.capabilities=e}else i.capabilities={};i.appInventory=function(e,t,n){if(!e||"object"!=typeof e||Array.isArray(e))return;const r=e;Object.keys(r).some(e=>!["observedAt","items","issues"].includes(e))&&t?.({instanceId:n,field:"appInventory"});const i={observedAt:r.observedAt,items:Array.isArray(r.items)?r.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 r=Vn(e,["id","name","kind","source","availability","diagnosticCode"]);return!r||"object"!=typeof r||Array.isArray(r)?r:{...r,capabilities:Vn(e.capabilities,["automation","supportsCwdSelection"])}}):r.items,issues:Array.isArray(r.issues)?r.issues.map(e=>Vn(e,["code","message"])):r.issues},o=lt.safeParse(i);return o.success?o.data:void 0}(n.appInventory,t,"string"==typeof n.id?n.id:void 0),i.source=function(e,t,n){if(!e||"object"!=typeof e||Array.isArray(e))return e;const r=e,i=r.type,o=Vt.options.find(e=>e.shape.type.value===i);if(!o)return e;const s="local-folder"===i?["type","localFolderId","path","ownerNodeId"]:"git-template"===i?["type","url","templateId","ref","auth","clone"]:["type","repositoryId","url","provider","ref","auth","clone"],a=Vn(r,s);if("local-folder"!==i){const e=Fn(Lt,Vn(r.ref,["type","name","commit"]),"source.ref",t,n),i=Fn($t,Vn(r.auth,["type","secretId"]),"source.auth",t,n),o=Fn(Ft,Vn(r.clone,["depth","submodules","lfs","subdirectory"]),"source.clone",t,n);e?a.ref=e:delete a.ref,i?a.auth=i:delete a.auth,o?a.clone=o:delete a.clone}const c=Fn(o,a,"source",t,n);return c?(Object.keys(r).some(e=>!s.includes(e))&&t?.({instanceId:n,field:"source"}),c):a}(n.source,t,"string"==typeof n.id?n.id:void 0),i.sourceSnapshot=n.sourceSnapshot&&"object"==typeof n.sourceSnapshot&&!Array.isArray(n.sourceSnapshot)?n.sourceSnapshot:{},i.build=Fn(_t,n.build,"build",t,"string"==typeof n.id?n.id:void 0),i.aiSessions=function(e,t,n){if(!e||"object"!=typeof e||Array.isArray(e))return;const r=e,i=Array.isArray(r.sessions)?r.sessions.flatMap((e,r)=>{const i=Fn(Ne,e,`aiSessions.sessions.${r}`,t,n);return i?[i]:[]}):[],o={runningCount:"number"==typeof r.runningCount&&Number.isInteger(r.runningCount)&&r.runningCount>=0?r.runningCount:0,waitingCount:"number"==typeof r.waitingCount&&Number.isInteger(r.waitingCount)&&r.waitingCount>=0?r.waitingCount:0,staleCount:"number"==typeof r.staleCount&&Number.isInteger(r.staleCount)&&r.staleCount>=0?r.staleCount:0,sessions:i,updatedAt:Be.safeParse(r.updatedAt).success?r.updatedAt:(new Date).toISOString()};return Object.keys(r).some(e=>!["runningCount","waitingCount","staleCount","sessions","updatedAt"].includes(e))&&t?.({instanceId:n,field:"aiSessions"}),ve.parse(o)}(n.aiSessions,t,"string"==typeof n.id?n.id:void 0),i.triggers=function(e,t,n){if(!e||"object"!=typeof e||Array.isArray(e))return;const r=e;Object.keys(r).some(e=>!["enabledCount","runningCount","errorCount","configs","recentRuns"].includes(e))&&t?.({instanceId:n,field:"triggers"});const i=(e,r,i)=>Array.isArray(e)?e.flatMap((e,o)=>{const s=Fn(r,e,`${i}.${o}`,t,n);return s?[s]:[]}):[],o=Array.isArray(r.configs)?r.configs.flatMap((e,r)=>{if(!e||"object"!=typeof e||Array.isArray(e))return[];const o=e;Object.keys(o).some(e=>!["configHash","config","deployments","runtime"].includes(e))&&t?.({instanceId:n,field:`triggers.configs.${r}`});const s=function(e,t,n,r){if(!e||"object"!=typeof e||Array.isArray(e))return;const i=e,o=Vn(i,["configHash","name","description","createdAt","updatedAt"]);if(i.source&&"object"==typeof i.source&&!Array.isArray(i.source)){const e=i.source,t="schedule"===e.type?"interval"===e.scheduleKind?["type","scheduleKind","intervalMs"]:"daily"===e.scheduleKind?["type","scheduleKind","timeOfDay","timezone"]:["type","scheduleKind","weekdays","timeOfDay","timezone"]:"file-change"===e.type?["type","roots","globs","ignore","debounceMs"]:["type","agent","statuses","phases"];o.source=Vn(e,t)}return o.action=Vn(i.action,["promptTemplate"]),o.policy=Vn(i.policy,["cooldownMs","maxConcurrentRuns","whenBusy"]),Fn(je,o,t,n,r)}(o.config,`triggers.configs.${r}.config`,t,n);return"string"==typeof o.configHash&&s?[{configHash:o.configHash,config:s,deployments:i(o.deployments,$e,`triggers.configs.${r}.deployments`),runtime:i(o.runtime,Fe,`triggers.configs.${r}.runtime`)}]:[]}):[];return{enabledCount:"number"==typeof r.enabledCount&&Number.isInteger(r.enabledCount)&&r.enabledCount>=0?r.enabledCount:0,runningCount:"number"==typeof r.runningCount&&Number.isInteger(r.runningCount)&&r.runningCount>=0?r.runningCount:0,errorCount:"number"==typeof r.errorCount&&Number.isInteger(r.errorCount)&&r.errorCount>=0?r.errorCount:0,configs:o,recentRuns:i(r.recentRuns,Ue,"triggers.recentRuns")}}(n.triggers,t,"string"==typeof n.id?n.id:void 0),i.apps=Fn(Mn.shape.apps.unwrap(),Vn(n.apps,["runningCount","problemCount","updatedAt","revision"]),"apps",t,"string"==typeof n.id?n.id:void 0)||{runningCount:0,problemCount:0},i.config=Fn(Mn.shape.config.unwrap(),Vn(n.config,["autoImportAgentConfigs","defaultCodexPermissionMode"]),"config",t,"string"==typeof n.id?n.id:void 0)||{autoImportAgentConfigs:!0,defaultCodexPermissionMode:"ask"},i.modelSelection=Fn(rt.unwrap(),Vn(n.modelSelection,["codexModelHash","claudeModelHash"]),"modelSelection",t,"string"==typeof n.id?n.id:void 0)||{},i.imageSnapshot=function(e,t,n,r){if(!e||"object"!=typeof e||Array.isArray(e))return e;const i=e,o=function(e){if(!e||"object"!=typeof e||Array.isArray(e))return e;const t=e,n=new Set(["id","origin","name","description","localizedDescriptions","cover","reference","repository","tag","image","registry","pullPolicy","capabilities","optionalApps","defaultEnv","labels","createdAt","updatedAt"]);for(const e of Object.keys(t))n.has(e);"string"==typeof t.id&&t.id;const r="string"==typeof t.image?t.image:void 0;Object.prototype.hasOwnProperty.call(t,"registry");let i,o="string"==typeof t.reference?t.reference:r;if(o)try{o=Qe(o)}catch{if(!o.includes("@")&&o.lastIndexOf(":")<=o.lastIndexOf("/"))try{o=Qe(`${o}:latest`)}catch{}}try{i=o?et(o):void 0}catch{}return{id:t.id,origin:"custom",name:t.name,description:t.description,localizedDescriptions:t.localizedDescriptions,cover:Vn(t.cover,["kind","key","url","mediaType","digest"]),reference:i?.reference??o,repository:i?.repository??t.repository,tag:i?.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}}(i),{reference:s,...a}=o,c=i.requestedReference??s;let d;try{d="string"==typeof c?et(c):void 0}catch{}const l={img_default:"market_taskhandoff_browser",img_codex:"market_taskhandoff_codex",img_ai:"market_taskhandoff_ai"},u="string"==typeof i.id?i.id:"string"==typeof t?t:void 0,m="market"===i.origin||u&&l[u]?"market":"custom";return void 0===i.image&&void 0===i.reference||n?.({instanceId:r,field:"imageSnapshot.reference"}),{...a,id:u&&l[u]?l[u]:u,origin:m,repository:d?.repository??i.repository,tag:d?.tag??i.tag,requestedReference:d?.reference??c,resolvedDigest:i.resolvedDigest,resolvedReference:i.resolvedReference,downloadSizeBytes:i.downloadSizeBytes,market:"market"===m?Vn(i.market,["catalogId","catalogRevision","publisher","version"])??{catalogId:"task_handoff_embedded",catalogRevision:"legacy",publisher:"task-handoff"}:void 0}}(n.imageSnapshot,n.imageId,t,"string"==typeof n.id?n.id:void 0);const o="string"==typeof n.imageId?{img_default:"market_taskhandoff_browser",img_codex:"market_taskhandoff_codex",img_ai:"market_taskhandoff_ai"}[n.imageId]||n.imageId:void 0,s=Vn(n.imageSelection,["imageId","tag"]);i.imageSelection=s||(o?{imageId:o,tag:i.imageSnapshot?.tag}:void 0),i.imageProvisioning=Fn(In,Vn(n.imageProvisioning,["phase","requestedReference","generation","error","startedAt","updatedAt"]),"imageProvisioning",t,"string"==typeof n.id?n.id:void 0),i.runtimeVersion=function(e,t,n){if(!e||"object"!=typeof e||Array.isArray(e))return;const r=e,i=e=>{if("string"!=typeof e)return;const t=e.trim();return t&&t.length<=80?t:void 0},o=i(r.desiredVersion);if(!o)return void t?.({instanceId:n,field:"runtimeVersion.desiredVersion"});const s=new Set(xt.shape.phase.options),a="string"==typeof r.phase?r.phase:"pending",c=s.has(a)?a:{idle:"pending",queued:"pending",checking:"pending",downloading:"installing",updating:"installing",completed:"matched",succeeded:"matched",ready:"matched",error:"failed"}[a]||"pending";let d;if(c!==a&&t?.({instanceId:n,field:"runtimeVersion.phase"}),r.error&&"object"==typeof r.error&&!Array.isArray(r.error)){const e=r.error,o="string"==typeof e.message?e.message.trim().slice(0,4096):"";if(o){const r=new Set(Ct.shape.code.options),s="string"==typeof e.code&&r.has(e.code)?e.code:"INSTANCE_RUNTIME_INSTALL_FAILED";s!==e.code&&t?.({instanceId:n,field:"runtimeVersion.error.code"});const a=i(e.expectedVersion),c=i(e.actualVersion);d={code:s,message:o,...a?{expectedVersion:a}:{},...c?{actualVersion:c}:{},retryable:!0===e.retryable}}else t?.({instanceId:n,field:"runtimeVersion.error"})}"string"==typeof r.error&&r.error.trim()&&(d={code:"INSTANCE_RUNTIME_INSTALL_FAILED",message:r.error.trim().slice(0,4096),expectedVersion:o,...i(r.actualVersion)?{actualVersion:i(r.actualVersion)}:{},retryable:!1});const l=i(r.actualVersion),u=Be.safeParse(r.lastAttemptAt),m=Be.safeParse(r.matchedAt);return void 0===r.lastAttemptAt||u.success||t?.({instanceId:n,field:"runtimeVersion.lastAttemptAt"}),void 0===r.matchedAt||m.success||t?.({instanceId:n,field:"runtimeVersion.matchedAt"}),{desiredVersion:o,...l?{actualVersion:l}:{},phase:c,attempt:"number"==typeof r.attempt&&Number.isInteger(r.attempt)&&r.attempt>=0?r.attempt:0,...u.success?{lastAttemptAt:u.data}:{},...m.success?{matchedAt:m.data}:{},...d?{error:d}:{}}}(n.runtimeVersion,t,"string"==typeof n.id?n.id:void 0),i.workspace=Fn(Dn,n.workspace,"workspace",t,"string"==typeof n.id?n.id:void 0)||{status:"unknown"},i.runtime=Fn(Mn.shape.runtime.unwrap(),Vn(n.runtime,["kind","containerName","containerId","workspacePath","pid","port","labels"]),"runtime",t,"string"==typeof n.id?n.id:void 0)||{labels:{}},i.target=Fn(On,Vn(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"},i.access=Fn(Rn,Vn(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,r]of Object.entries(Mn.shape))Object.prototype.hasOwnProperty.call(i,e)&&!r.safeParse(i[e]).success&&r.safeParse(void 0).success&&(delete i[e],t?.({instanceId:"string"==typeof n.id?n.id:void 0,field:e}));return i}function Fn(e,t,n,r,i){if(!t||"object"!=typeof t||Array.isArray(t))return;let o=structuredClone(t),s=!1;for(let t=0;t<20;t+=1){const t=e.safeParse(o);if(t.success)return s&&r?.({instanceId:i,field:n}),t.data;let a=!1;for(const e of t.error.issues){if("unrecognized_keys"!==e.code)continue;const t=Un(o,e.path);if(t&&"object"==typeof t&&!Array.isArray(t))for(const n of e.keys)Object.prototype.hasOwnProperty.call(t,n)&&(delete t[n],a=!0,s=!0)}if(!a){const s=structuredClone(o);let a=!1;for(const e of t.error.issues){if(!e.path.length||"string"!=typeof e.path.at(-1))continue;const t=Un(s,e.path.slice(0,-1)),n=e.path.at(-1);t&&"object"==typeof t&&!Array.isArray(t)&&Object.prototype.hasOwnProperty.call(t,n)&&(delete t[n],a=!0)}if(a){const t=e.safeParse(s);if(t.success)return r?.({instanceId:i,field:n}),t.data}break}}r?.({instanceId:i,field:n})}function Un(e,t){let n=e;for(const e of t){if(!n||"object"!=typeof n)return;n=n[e]}return n}function Vn(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 Hn=m.z.object({instanceId:qe.optional(),projectId:qe.optional(),source:Vt.optional(),nodeId:qe.optional(),runtimeId:qe.optional(),imageSelection:it.optional(),instanceVersion:m.z.string().trim().max(80).optional(),protocolVersion:He,build:_t.optional(),controlMode:m.z.enum(["standalone","controlled"]).default("controlled"),capabilities:m.z.record(m.z.string(),m.z.unknown()).default({}),appInventory:lt.optional(),target:On.default({strategy:"direct-port",status:"unknown"}),workspace:Dn.default({status:"unknown"}),registrationToken:m.z.string().trim().max(240).optional(),processIncarnationId:m.z.string().trim().min(1).max(120).optional()}).strict().superRefine((e,t)=>{e.protocolVersion!==Ve||e.appInventory||t.addIssue({code:"custom",path:["appInventory"],message:"Current protocol register payload requires appInventory."})}),qn=m.z.object({status:Mn.shape.status.optional(),health:Mn.shape.health.optional(),protocolVersion:He,build:_t.optional(),capabilities:Mn.shape.capabilities.optional(),appInventory:lt.optional(),apps:Mn.shape.apps.optional(),aiSessions:Mn.shape.aiSessions.optional(),triggers:Mn.shape.triggers.optional(),workspace:Dn.optional(),target:On.partial().optional(),processIncarnationId:m.z.string().trim().min(1).max(120).optional()}).strict().superRefine((e,t)=>{e.protocolVersion!==Ve||e.appInventory||t.addIssue({code:"custom",path:["appInventory"],message:"Current protocol heartbeat payload requires appInventory."})}),Bn=m.z.enum(["web","telegram","wechat","dingding"]);function Kn(e){return e.readyState===(e.OPEN??1)}function Gn(e,t,n){e.close(function(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}(t),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}(n)||void 0)}function Jn(e,t){e.send(t.data,{binary:t.isBinary})}function Wn(e,t){if(Kn(e))for(const n of t.splice(0))Jn(e,n)}function Xn(e,t,n={}){return new Promise((r,i)=>{const o=a.spawn(e,t,{stdio:["ignore","pipe","pipe"]}),s=[],c=[];let d=!1;const l=n.timeoutMs?setTimeout(()=>{d=!0,o.kill("SIGKILL")},n.timeoutMs):void 0;l?.unref?.(),o.stdout.on("data",e=>s.push(Buffer.from(e))),o.stderr.on("data",e=>c.push(Buffer.from(e))),o.on("error",e=>{l&&clearTimeout(l),i(e)}),o.on("close",t=>{l&&clearTimeout(l);const o={stdout:Buffer.concat(s).toString("utf8").trim(),stderr:Buffer.concat(c).toString("utf8").trim()};if(d){const t=new Error(`${e} timed out after ${n.timeoutMs}ms`);return Object.assign(t,{statusCode:504,code:"RUNTIME_COMMAND_TIMEOUT",details:o}),void i(t)}if(0===t)return void r(o);const a=new Error(o.stderr||`${e} exited with code ${t}`);Object.assign(a,{statusCode:502,code:"RUNTIME_EXECUTOR_FAILED",details:o}),i(a)})})}m.z.object({id:qe,channel:Bn,name:m.z.string().trim().min(1).max(160),enabled:m.z.boolean().default(!1),token:m.z.string().trim().max(4096).optional(),defaultChatId:m.z.string().trim().max(240).optional(),allowedUserIds:m.z.array(m.z.string().trim().min(1).max(240)).default([]),pollIntervalMs:m.z.number().int().positive().max(6e4).default(3e3),settings:m.z.record(m.z.string(),m.z.unknown()).default({}),createdAt:Be,updatedAt:Be}).strict(),m.z.object({id:qe,channel:Bn,bridgeId:qe.optional(),chatSessionId:m.z.string().trim().min(1).max(240),userId:m.z.string().trim().max(240).optional(),activeProjectId:qe.optional(),activeInstanceId:qe.optional(),activeAiSessionId:m.z.string().trim().min(1).max(120).optional(),lastUsedAt:Be,createdAt:Be,updatedAt:Be}).strict(),m.z.object({source:m.z.object({type:m.z.literal("chat-gateway").default("chat-gateway"),channel:Bn,bridgeId:qe.optional(),chatSessionId:m.z.string().trim().min(1).max(240),userId:m.z.string().trim().max(240).optional()}).strict(),message:m.z.object({text:m.z.string().trim().max(2e4).default(""),attachments:m.z.array(ne).max(6).default([])}).strict().superRefine((e,t)=>{e.attachments.reduce((e,t)=>e+("inline"===t.source.type?t.size:0),0)>H&&t.addIssue({code:m.z.ZodIssueCode.custom,path:["attachments"],message:"Inline attachments must be 41943040 bytes or less in total."})}),target:m.z.object({instanceId:qe,aiSessionId:m.z.string().trim().min(1).max(120)}).strict().optional()}).strict(),m.z.object({id:qe,instanceId:qe,projectId:qe.optional(),aiSessionId:m.z.string().trim().min(1).max(120),providerSessionId:m.z.string().trim().max(240).optional(),result:m.z.string().default(""),timeoutMs:m.z.number().positive().optional(),source:m.z.string().trim().max(120).optional(),kind:m.z.enum(["task","approval"]).default("task"),status:m.z.enum(["pending","unreachable"]).default("pending"),error:m.z.string().trim().max(2048).optional(),lastSeenAt:Be}).strict();const Yn=(e,t,n={})=>new Promise((r,i)=>{const o=[];let s,a=!1;try{s=g.spawn(e,t,{name:"xterm-256color",cols:n.cols||120,rows:n.rows||40,cwd:process.cwd(),env:process.env})}catch(e){return void i(e)}const c=n.timeoutMs?setTimeout(()=>{a=!0,s.kill("SIGKILL")},n.timeoutMs):void 0;c?.unref?.(),s.onData(e=>{o.push(e),n.onData?.(e)}),s.onExit(({exitCode:t})=>{c&&clearTimeout(c);const s={stdout:o.join(""),stderr:""};a?i(Object.assign(new Error(`${e} timed out after ${n.timeoutMs}ms`),{statusCode:504,code:"RUNTIME_COMMAND_TIMEOUT",details:s})):0!==t?i(Object.assign(new Error(s.stdout.replace(/\u001b\[[0-?]*[ -/]*[@-~]/g,"").split(/\r?\n/).map(e=>e.trim()).filter(Boolean).at(-1)||`${e} exited with code ${t}`),{statusCode:502,code:"RUNTIME_EXECUTOR_FAILED",details:s})):r(s)})});class Zn{inFlight=new Map;runCommand;runTerminalCommand;constructor(e=Xn,t){this.runCommand=e,this.runTerminalCommand=t||function(e){return e===Xn?Yn:async(t,n,r={})=>{const i=await e(t,n,{timeoutMs:r.timeoutMs});return i.stdout&&r.onData?.(i.stdout),i.stderr&&r.onData?.(i.stderr),i}}(e)}ensure(e,t,n){const r=Qe(e),i=this.inFlight.get(r);if(i)return t&&(i.phaseListeners.add(t),i.phase&&t(i.phase)),n&&(i.terminalListeners.add(n),i.terminalTail&&n({sequence:i.terminalSequence,data:i.terminalTail,replay:!0})),i.promise;const o=new Set,s=new Set;t&&o.add(t),n&&s.add(n);const a={promise:Promise.resolve(void 0),phaseListeners:o,terminalListeners:s,terminalSequence:0,terminalTail:""};return a.promise=this.ensureOnce(r,e=>{a.phase=e,o.forEach(t=>t(e))},e=>{a.terminalSequence+=1,a.terminalTail=`${a.terminalTail}${e}`.slice(-262144);const t={sequence:a.terminalSequence,data:e};s.forEach(e=>e(t))}).finally(()=>this.inFlight.delete(r)),this.inFlight.set(r,a),a.promise}async ensureOnce(e,t,n){t("checking-image");let r=await this.inspect(e).catch(()=>{}),i=!1;r||(t("pulling-image"),await this.runTerminalCommand("docker",["pull",e],{cols:120,rows:40,onData:n}),i=!0,r=await this.inspect(e)),t("resolving-image");const o=(s=r,Array.isArray(s.RepoDigests)?s.RepoDigests.filter(e=>"string"==typeof e):[]).find(e=>/@sha256:[a-fA-F0-9]{64}$/.test(e));var s;const a=o?.split("@").at(-1)?.toLowerCase();return{requestedReference:e,...a?{resolvedDigest:a}:{},resolvedReference:o||e,pulled:i}}async inspect(e){const t=await this.runCommand("docker",["image","inspect",e,"--format","{{json .}}"]);return JSON.parse(t.stdout.trim()||"{}")}}function Qn(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}class er{runCommand;publishHost;images;launcherAssetsDir;portResolutionRetryDelaysMs;constructor(e=Xn,r={}){this.runCommand=e,this.images=r.imageService||new Zn(e),this.publishHost=r.publishHost||"127.0.0.1",this.launcherAssetsDir=r.launcherAssetsDir||function(){const e=("undefined"==typeof document?require("url").pathToFileURL(__filename).href:b&&"SCRIPT"===b.tagName.toUpperCase()&&b.src||new URL("cli.js",document.baseURI).href)?n.dirname(s.fileURLToPath("undefined"==typeof document?require("url").pathToFileURL(__filename).href:b&&"SCRIPT"===b.tagName.toUpperCase()&&b.src||new URL("cli.js",document.baseURI).href)):__dirname,r=[n.resolve(e,"../../../../../docker"),n.resolve(e,"../docker"),n.resolve(e,"../../docker")];return r.find(e=>t.existsSync(n.join(e,"runtime-installer.mjs")))||r[0]}(),this.portResolutionRetryDelaysMs=r.portResolutionRetryDelaysMs?.length?r.portResolutionRetryDelaysMs:[0,100,250,500,1e3]}async start(e){ur(e);const t=e.instance.runtime.containerName||dr(e.instance.id),n=await this.inspectContainerForStart(t);if(n){ar(t,n.id,e.instance.runtime.containerId,"before start","RUNTIME_EXECUTOR_FAILED");const r=n.labels["task-handoff.instance-id"];if(r!==e.instance.id)throw ir("RUNTIME_EXECUTOR_FAILED",`Docker container ${t} belongs to ${r||"an unknown instance"}, not ${e.instance.id}.`);try{await this.runCommand("docker",["start",t])}catch(e){throw ir("RUNTIME_EXECUTOR_FAILED",`Could not start Docker container ${t}.`,e)}return this.runningResult(e,t,n.id)}let r;await this.images.ensure(e.image.resolvedReference||e.image.requestedReference);try{r=await this.runCommand("docker",function(e,t,n={}){const r=n.publishHost||"127.0.0.1",i=e.node?.id||"node_unset",o=e.runtime?.id||"runtime_local_docker",s=["run","-d","--name",t,"--label",`task-handoff.instance-id=${e.instance.id}`,"--label",`task-handoff.project-id=${e.project.id}`,"--label",`task-handoff.node-id=${i}`,"--label",`task-handoff.runtime-id=${o}`,"--label",`task-handoff.image-id=${e.image.id}`,"--shm-size","1gb","--security-opt","seccomp=unconfined","--network","bridge","--add-host","host.docker.internal:host-gateway","--tmpfs","/tmp:rw,mode=1777","-v",`${t}-data:/data`,"-v",`${t}-agent-home:/home/agent`,"-p",`${r}::8080`],a={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_REGISTRATION_TOKEN:e.instance.registrationToken||"",TASK_HANDOFF_PROJECT_ID:e.project.id,TASK_HANDOFF_NODE_ID:i,TASK_HANDOFF_RUNTIME_ID:o,TASK_HANDOFF_IMAGE_ID:e.image.id,...e.image.tag?{TASK_HANDOFF_IMAGE_TAG:e.image.tag}:{},TASK_HANDOFF_CHAT_BRIDGES:"none",TASK_HANDOFF_WORKSPACE:e.project.workspacePolicy.path||"/workspace",TASK_HANDOFF_WORKSPACE_MODE:e.project.workspacePolicy.mode};for(const[e,t]of Object.entries(a))lr(s,e,t);"local-folder"===e.project.source.type?s.push("-v",`${e.project.source.path}:${e.project.workspacePolicy.path||"/workspace"}:${e.project.workspacePolicy.readOnly?"ro":"rw"}`):(lr(s,"TASK_HANDOFF_PROJECT_SOURCE",JSON.stringify(e.project.source)),lr(s,"TASK_HANDOFF_WORKSPACE_POLICY",JSON.stringify(e.project.workspacePolicy)),lr(s,"TASK_HANDOFF_GIT_URL",e.project.source.url),e.project.source.ref?.commit?lr(s,"TASK_HANDOFF_GIT_COMMIT",e.project.source.ref.commit):e.project.source.ref?.name&&lr(s,"TASK_HANDOFF_GIT_REF",e.project.source.ref.name),e.project.source.clone?.depth&&lr(s,"TASK_HANDOFF_GIT_DEPTH",String(e.project.source.clone.depth)),lr(s,"TASK_HANDOFF_GIT_SUBMODULES",e.project.source.clone?.submodules?"true":"false"),lr(s,"TASK_HANDOFF_GIT_LFS",e.project.source.clone?.lfs?"true":"false"),e.project.source.clone?.subdirectory&&lr(s,"TASK_HANDOFF_WORKSPACE_SUBDIRECTORY",e.project.source.clone.subdirectory));for(const[t,n]of Object.entries(e.image.defaultEnv))lr(s,t,n);for(const[t,n]of Object.entries(e.modelEnv||{}))lr(s,t,n);return s.push(e.image.resolvedReference||e.image.requestedReference),s}(e,t,{publishHost:this.publishHost}))}catch(e){throw ir("RUNTIME_EXECUTOR_FAILED",`Could not create Docker container ${t}.`,e)}return this.runningResult(e,t,r.stdout||void 0)}async runningResult(e,t,n){const r=await this.containerPort(t,"8080/tcp"),i=r?`http://127.0.0.1:${r}`:void 0,o=e.node?.id||"node_unset",s=e.runtime?.id||"runtime_local_docker";return{status:"registering",health:"unknown",connectionStatus:i?"online":"unknown",agentStatus:"unknown",targetStatus:"unknown",uiAccessStatus:"unknown",target:{strategy:"direct-port",status:i?"reachable":"unknown",...i?{web:i,api:`${i}/api`}:{}},workspace:{mode:e.project.workspacePolicy.mode,status:"pending",path:e.project.workspacePolicy.path},runtime:{...e.instance.runtime,kind:"docker",containerName:t,...n?{containerId:n}:{},labels:{...e.instance.runtime.labels,"task-handoff.instance-id":e.instance.id,"task-handoff.project-id":e.project.id,"task-handoff.node-id":o,"task-handoff.runtime-id":s,"task-handoff.image-id":e.image.id}}}}async stop(e){const t=e.instance.runtime.containerName||dr(e.instance.id);try{await this.runCommand("docker",["stop",t])}catch(e){if(!sr(e))throw ir("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){ur(e);const n=e.instance.runtime.containerName||dr(e.instance.id),r=await this.inspectContainerId(n);if(!r)throw ir("INSTANCE_RUNTIME_RESTART_FAILED",`Docker container ${n} does not exist.`);ar(n,r,t,"before restart","INSTANCE_RUNTIME_RESTART_FAILED"),await this.runCommand("docker",["restart",n]);const i=await this.inspectContainerId(n);if(!i||i!==r)throw ir("INSTANCE_RUNTIME_RESTART_FAILED",`Docker container identity changed while restarting ${n}.`);return ar(n,i,t,"after restart","INSTANCE_RUNTIME_RESTART_FAILED"),this.runningResult(e,n,i)}async delete(e){const t=e.instance.runtime.containerName||dr(e.instance.id);try{await this.runCommand("docker",["rm","-f",t])}catch(e){if(!sr(e))throw ir("RUNTIME_EXECUTOR_FAILED",`Could not delete Docker container ${t}.`,e)}return{status:"stopped",health:"unknown",connectionStatus:"offline",target:{...e.instance.target,status:"unknown"},runtime:e.instance.runtime}}async installRuntime(e){const t=await this.installRuntimeRelease(e);ar(e.containerName,t,e.expectedContainerId,"before runtime restart","INSTANCE_RUNTIME_RESTART_FAILED");try{await this.runCommand("docker",["restart",e.containerName])}catch(t){throw ir("INSTANCE_RUNTIME_RESTART_FAILED",`Could not restart Docker container ${e.containerName}.`,t)}const n=await this.inspectContainerId(e.containerName);if(!n||n!==t)throw ir("INSTANCE_RUNTIME_RESTART_FAILED",`Docker container identity changed while updating ${e.containerName}.`);return ar(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 ir("INSTANCE_RUNTIME_INSTALL_FAILED",`Docker container ${e.containerName} does not exist.`);ar(e.containerName,t,e.expectedContainerId,"before runtime install","INSTANCE_RUNTIME_INSTALL_FAILED");const n=`/opt/task-handoff/instance-runtime/incoming/task-handoff-runtime-${r=e.identity.version,r.replace(/[^0-9A-Za-z.+_-]/g,"-")}-${e.identity.sha256.slice(0,12)}.tar.gz`;var r;await this.runCommand("docker",["exec","--user","0",e.containerName,"install","-d","-o","root","-g","root","-m","0755","/opt/task-handoff/instance-runtime/incoming"]),await this.runCommand("docker",["cp",e.artifactPath,`${e.containerName}:${n}`]);try{await this.runCommand("docker",["exec","--user","0",e.containerName,"task-handoff-runtime","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 ir("INSTANCE_RUNTIME_INSTALL_FAILED",`Could not install controlled-instance ${e.identity.version} in ${e.containerName}.`,t)}finally{await this.runCommand("docker",["exec","--user","0",e.containerName,"rm","-f",n]).catch(()=>({stdout:"",stderr:""}))}const i=await this.inspectContainerId(e.containerName);if(!i||i!==t)throw ir("INSTANCE_RUNTIME_INSTALL_FAILED",`Docker container identity changed while installing ${e.containerName}.`);return ar(e.containerName,i,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,"task-handoff-runtime","verify-active"]).catch(()=>{});if(!n?.stdout)return{containerId:t};try{const e=kt.safeParse(JSON.parse(n.stdout));return e.success?{containerId:t,...e.data}:{containerId:t}}catch{return{containerId:t}}}async inspectRuntimeTarget(e){let t,n;if(e){const r=await this.runCommand("docker",["inspect","--format","{{json .}}",e]).then(e=>JSON.parse(e.stdout.trim()||"{}")).catch(()=>{});if(t=r?.Platform,"string"==typeof r?.Image&&r.Image){const e=await this.runCommand("docker",["image","inspect","--format","{{json .}}",r.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 ir("INSTANCE_BASE_RUNTIME_INCOMPATIBLE","Could not inspect the Docker runtime target.",e)});t||=e.OSType,n||=e.Architecture}const r="linux"===(i=t)||"darwin"===i?i:"windows"===i||"win32"===i?"win32":void 0;var i;const o=function(e){return"amd64"===e||"x86_64"===e||"x64"===e?"x64":"arm64"===e||"aarch64"===e?"arm64":void 0}(n);if(!r||!o)throw ir("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Docker reported an unsupported runtime target ${String(t||"unknown")}/${String(n||"unknown")}.`);return{platform:r,arch:o,launcherAbi:1}}async installRuntimeLauncher(e){const t=await this.inspectContainerId(e);if(!t)throw ir("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Docker container ${e} does not exist.`);const r=[[n.join(this.launcherAssetsDir,"entrypoint.sh"),"/root/.task-handoff-entrypoint.bootstrap"],[n.join(this.launcherAssetsDir,"instance-launcher.sh"),"/root/.task-handoff-instance-launcher.bootstrap"],[n.join(this.launcherAssetsDir,"runtime-installer.mjs"),"/root/.task-handoff-runtime-installer.bootstrap"]];for(const[t,n]of r)await this.runCommand("docker",["cp",t,`${e}:${n}`]);try{await this.runCommand("docker",["exec","--user","0",e,"bash","-ceu","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; install -m 0755 /root/.task-handoff-entrypoint.bootstrap /usr/local/bin/task-handoff-entrypoint; install -m 0755 /root/.task-handoff-instance-launcher.bootstrap /usr/local/bin/task-handoff-instance-launcher; install -d /usr/local/lib/task-handoff; install -m 0755 /root/.task-handoff-runtime-installer.bootstrap /usr/local/lib/task-handoff/runtime-installer.mjs; ln -sfn /usr/local/lib/task-handoff/runtime-installer.mjs /usr/local/bin/task-handoff-runtime; rm -f /root/.task-handoff-entrypoint.bootstrap /root/.task-handoff-instance-launcher.bootstrap /root/.task-handoff-runtime-installer.bootstrap"])}catch(t){throw ir("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Could not install the runtime launcher in ${e}.`,t)}if(await this.inspectContainerId(e)!==t)throw ir("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Docker container identity changed while installing the runtime launcher in ${e}.`)}async inspectContainerId(e){try{return(await this.runCommand("docker",["inspect","--format","{{.Id}}",e])).stdout.trim()||void 0}catch(t){if(sr(t))return;throw ir("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(sr(t))return;throw ir("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])):{};return{id:e.Id,labels:n}}catch(t){throw ir("RUNTIME_EXECUTOR_FAILED",`Docker returned invalid inspection data for ${e}.`,t)}}async containerPort(e,t){let n,r=!1;for(const i of this.portResolutionRetryDelaysMs){i>0&&await rr(i);try{const n=tr((await this.runCommand("docker",["port",e,t])).stdout);if(n)return n}catch(e){n=e}try{const n=nr((await this.runCommand("docker",["inspect","--format","{{json .NetworkSettings.Ports}}",e])).stdout,t);if(r=!0,n)return n}catch(e){n=e}}if(r)throw ir("RUNTIME_EXECUTOR_FAILED",`Docker container ${e} does not publish ${t}.`);throw ir("RUNTIME_EXECUTOR_FAILED",`Could not resolve the published port for Docker container ${e}.`,n)}}function tr(e){const t=e.split(/\r?\n/).find(Boolean);return t?.match(/:(\d+)$/)?.[1]}function nr(e,t){const n=JSON.parse(e||"null");if(!n||"object"!=typeof n||Array.isArray(n))return;const r=n[t];if(Array.isArray(r))for(const e of r){if(!e||"object"!=typeof e||Array.isArray(e))continue;const t=e.HostPort;if("string"==typeof t&&/^\d+$/.test(t))return t}}function rr(e){return new Promise(t=>setTimeout(t,e))}function ir(e,t,n){const r=or(n),i=new Error(r?`${t} Cause: ${r}`:t,void 0===n?void 0:{cause:n});return Object.assign(i,{statusCode:502,code:e}),i}function or(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 sr(e){const t=or(e)?.toLowerCase()||"";return t.includes("no such container")||t.includes("no such object")}function ar(e,t,n,r,i){if(n&&t!==n)throw ir(i,`Docker container ${e} identity mismatch ${r}: expected ${n}, got ${t}.`)}async function cr(e=Xn){return async function(e=Xn){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>",r=t.Tag||"<none>",i=t.ID||t.IDShort||"",o="<none>"!==n&&"<none>"!==r?`${n}:${r}`:i,s="<none>"!==n&&t.Digest&&"<none>"!==t.Digest?[`${n}@${t.Digest}`]:[];return{repository:n,tag:r,id:i,createdSince:t.CreatedSince,size:t.Size,sizeBytes:Qn(t.Size),reference:o,repoDigests:s}}).filter(e=>Boolean(e.reference))}(e)}function dr(e){return`task-handoff-${e.replace(/[^a-zA-Z0-9_.-]/g,"-")}`}function lr(e,t,n){e.push("-e",`${t}=${n}`)}function ur(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=m.z.enum(["created","starting","running","stopping","stopped","exited","failed","closed","terminated","unknown"]),pr=m.z.object({type:m.z.enum(["app-session","provider-session","adapter-key"]),id:m.z.string().trim().min(1).max(240),agent:m.z.string().trim().min(1).max(80).optional(),adapter:m.z.string().trim().min(1).max(80).optional(),key:m.z.string().trim().min(1).max(240).optional()}).strict(),gr=m.z.record(m.z.string(),m.z.unknown()).and(m.z.object({id:m.z.string().trim().min(1).max(160),appId:m.z.string().trim().min(1).max(160).optional(),title:m.z.string().trim().max(240).optional(),kind:m.z.string().trim().max(80).optional(),status:mr.default("unknown"),bindings:m.z.array(pr).max(40).default([]),workspace:m.z.object({cwd:m.z.string().trim().max(4096).optional()}).strict().optional(),createdAt:m.z.string().datetime().optional(),updatedAt:m.z.string().datetime().optional()})),hr=m.z.object({runningCount:m.z.number().int().min(0).default(0),problemCount:m.z.number().int().min(0).default(0),sessions:m.z.array(gr).default([]),updatedAt:m.z.string().datetime()}).strict();m.z.object({streamId:m.z.string().trim().min(1).max(240),revision:m.z.number().int().min(0),lastEventAt:m.z.string().datetime(),snapshot:hr}).strict(),hr.pick({runningCount:!0,problemCount:!0,updatedAt:!0}).extend({revision:m.z.number().int().min(0).optional()});const fr=m.z.enum(["app-session-created","app-session-updated","app-session-deleted","app-session-recovered","control-action","heartbeat-sync","startup"]),yr=m.z.object({streamId:m.z.string().trim().min(1).max(240),instanceId:m.z.string().trim().min(1).max(160),nodeId:m.z.string().trim().min(1).max(160).optional(),revision:m.z.number().int().min(0),previousRevision:m.z.number().int().min(0).optional(),traceId:m.z.string().trim().min(1).max(160),generatedAt:m.z.string().datetime(),reason:fr}).strict(),Ir=m.z.object({meta:yr,snapshot:hr}).strict(),Ar=m.z.object({meta:yr,session:gr}).strict(),br=m.z.object({meta:yr,sessionId:m.z.string().trim().min(1).max(160),tombstone:gr.optional(),expiresAt:m.z.string().datetime().optional()}).strict();function wr(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"}m.z.object({streamId:m.z.string().trim().min(1).max(240),instanceId:m.z.string().trim().min(1).max(160),sinceRevision:m.z.number().int().min(0),latestRevision:m.z.number().int().min(0),earliestRetainedRevision:m.z.number().int().min(0),syncRequired:m.z.boolean().default(!1),events:m.z.array(m.z.discriminatedUnion("type",[m.z.object({type:m.z.literal("app-session.snapshot"),payload:Ir}).strict(),m.z.object({type:m.z.literal("app-session.patch"),payload:Ar}).strict(),m.z.object({type:m.z.literal("app-session.removed"),payload:br}).strict()])).default([])}).strict();const zr=m.z.enum(["ai.sessions","app.sessions"]),Nr=m.z.object({topic:zr,instanceId:m.z.string().trim().min(1).max(160),streamId:m.z.string().trim().min(1).max(240),latestRevision:m.z.number().int().min(0),earliestRetainedRevision:m.z.number().int().min(0)}).strict(),vr=m.z.object({protocolVersion:m.z.literal(1),streams:m.z.array(Nr)}).strict();class Er{attempt=0;timer;get pending(){return Boolean(this.timer)}get attempts(){return this.attempt}schedule(e,t={}){if(this.timer)return;const n=function(e,t=Math.random){const n=Math.min(3e4,1e3*2**Math.max(0,e));return Math.min(3e4,Math.round(n*(.75+.5*t())))}(this.attempt,t.random);this.attempt+=1;const r=t.setTimeoutFn||setTimeout;return this.timer=r(()=>{this.timer=void 0,e()},n),{attempt:this.attempt,delay:n}}reset(e=clearTimeout){this.timer&&e(this.timer),this.timer=void 0,this.attempt=0}cancel(e=clearTimeout){this.timer&&e(this.timer),this.timer=void 0}}function Sr(e,t=6e4){const n=[];for(let r=0;r<e.length;r+=t)n.push(e.slice(r,r+t));return n}class _r{sockets=new Map;socketUrls=new Map;retries=new Map;outputs=new Set;imagePullTerminalByInstance=new Map;state;token;logger;safetyIntervalMs;lastAiSessionEventByInstance=new Map;lastAppSessionEventByInstance=new Map;timer;reconnectAttempts=0;safetyReconciliations=0;localSequence=0;createSocket;setIntervalFn;clearIntervalFn;constructor(e,t,n={}){var r;this.state=e,this.token=t,this.logger=n.logger,this.safetyIntervalMs=(r=n.safetyIntervalMs,Math.min(6e4,Math.max(3e4,r??45e3))),this.createSocket=n.createSocket||((e,t)=>new u(e,t)),this.setIntervalFn=n.setIntervalFn||setInterval,this.clearIntervalFn=n.clearIntervalFn||clearInterval}start(){this.sync(),this.timer=this.setIntervalFn(()=>{this.safetyReconciliations+=1,this.sync()},this.safetyIntervalMs)}stop(){this.timer&&(this.clearIntervalFn(this.timer),this.timer=void 0);for(const e of this.sockets.values())e.close();this.sockets.clear(),this.socketUrls.clear();for(const e of this.retries.values())e.timer.cancel();this.retries.clear(),this.outputs.clear()}addOutput(e){this.outputs.add(e),e.on("close",()=>this.outputs.delete(e)),e.on("error",()=>this.outputs.delete(e));for(const t of this.state.listInstances()){const n=Tr(t);n?this.sendForwarded(e,this.createEvent(Pn,n,{instanceId:t.id})):this.logger?.warn?.({instanceId:t.id},"instance.lifecycle.snapshot.invalid")}for(const[t,n]of this.imagePullTerminalByInstance)Sr(n.tail).forEach((r,i)=>this.sendForwarded(e,this.createEvent(An,{...n.output,sequence:n.output.sequence+i,data:r,...0===i?{replay:!0}:{}},{instanceId:t}))),n.finished&&this.sendForwarded(e,this.createEvent(bn,n.finished,{instanceId:t}));return this.syncNow(),()=>{this.outputs.delete(e)}}publish(e,t,n={}){this.rememberImagePullTerminal(e,t);const r=this.createEvent(e,t,n);for(const e of this.outputs)this.sendForwarded(e,r)}rememberImagePullTerminal(e,t){if(e===An){const e=zn.safeParse(t);if(!e.success)return;const n=e.data,r=this.imagePullTerminalByInstance.get(n.instanceId);if(r&&n.generation<r.output.generation)return;const i=r?.output.generation===n.generation,o=n.replay||!i?n.data:`${r.tail}${n.data}`.slice(-262144);return void this.imagePullTerminalByInstance.set(n.instanceId,{output:n,tail:o})}if(e===bn){const e=Nn.safeParse(t);if(!e.success)return;const n=e.data,r=this.imagePullTerminalByInstance.get(n.instanceId);r?.output.generation===n.generation&&(r.finished=n)}}publishInstanceLifecycle(e){this.publish(Pn,function(e){return jn.parse(kr(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 r=++this.localSequence;return{v:1,id:`node_evt_${Date.now().toString(36)}_${r.toString(36)}`,seq:r,type:e,topic:wr(e),createdAt:(new Date).toISOString(),payload:t,scope:n}}sendForwarded(e,t){const n=JSON.stringify({type:"node-agent.event.forwarded",event:t});e.readyState===u.OPEN&&e.send(n)}syncNow(){this.sync()}diagnostics(){return{reconnectAttempts:this.reconnectAttempts,safetyReconciliations:this.safetyReconciliations,activeConnections:this.sockets.size,pendingRetries:[...this.retries.values()].filter(e=>e.timer.pending).length,safetyIntervalMs:this.safetyIntervalMs}}sync(){const e=new Set(this.state.listInstances().map(e=>e.id));for(const t of this.imagePullTerminalByInstance.keys())e.has(t)||this.imagePullTerminalByInstance.delete(t);if(!this.outputs.size){for(const e of this.sockets.values())e.close();this.sockets.clear(),this.socketUrls.clear();for(const e of this.retries.values())e.timer.cancel();return void this.retries.clear()}const t=new Set;for(const e of this.state.listInstances()){const n=xr(e);if(!n)continue;t.add(e.id);const r=this.retries.get(e.id);r?.timer.pending&&r.url!==n&&(r.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,r=this.createSocket(t,{headers:n});this.sockets.set(e,r),this.socketUrls.set(e,t),r.on("open",()=>{const n=this.retries.get(e);n?.timer.reset(),this.retries.set(e,{timer:n?.timer||new Er,url:t}),r.readyState===u.OPEN&&(r.send(JSON.stringify({v:1,type:"subscribe",topics:[q,"app.sessions","apps","instances"]})),this.logger?.info?.({instanceId:e,url:t},"ai-session.event.forward.connect"),this.logger?.info?.({instanceId:e,url:t},"app-session.event.forward.connect"))}),r.on("message",t=>{const n=function(e,t){try{const n=JSON.parse(String(e));if(!n||"object"!=typeof n||Array.isArray(n))return;const r=n,i="string"==typeof r.type?r.type:"";if(!i||"events.connected"===i)return;const o=r.scope&&"object"==typeof r.scope&&!Array.isArray(r.scope)?r.scope:{};return{v:1,id:"string"==typeof r.id?r.id:`evt_${Date.now().toString(36)}`,seq:Number(r.seq)||0,type:i,topic:"string"==typeof r.topic?r.topic:wr(i),createdAt:"string"==typeof r.createdAt?r.createdAt:(new Date).toISOString(),payload:"payload"in r?r.payload:{},scope:{...o,instanceId:t}}}catch{return}}(t,e);if(!n)return;if("streams.hello"===n.type){const t=vr.safeParse(n.payload);if(!t.success)return this.logger?.warn?.({instanceId:e,issues:t.error.issues},"session-stream.handshake.invalid"),void r.close(1002,"Incompatible session stream handshake.");const i=JSON.stringify({type:"node-agent.streams.hello",instanceId:e,payload:t.data});for(const e of this.outputs)e.readyState===u.OPEN&&e.send(i);return}this.recordAiSessionEvent(e,n),this.recordAppSessionEvent(e,n);const i=JSON.stringify({type:"node-agent.event.forwarded",event:n});for(const e of this.outputs)e.readyState===u.OPEN&&e.send(i)}),r.on("close",()=>{this.sockets.get(e)===r&&(this.sockets.delete(e),this.socketUrls.delete(e),this.scheduleReconnect(e))}),r.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"),r.close()})}scheduleReconnect(e){const t=this.state.listInstances().find(t=>t.id===e),n=t&&xr(t);if(!n||!this.outputs.size)return;const r=this.retries.get(e)??{timer:new Er};if(r.timer.pending)return;r.url=n;const i=r.timer.schedule(()=>{this.sockets.has(e)||this.connect(e,n)});i&&(this.reconnectAttempts+=1,this.logger?.info?.({instanceId:e,url:n,attempt:i.attempt,delay:i.delay,reconnectAttempts:this.reconnectAttempts},"session-stream.connection.reconnect-scheduled")),this.retries.set(e,r)}recordAiSessionEvent(e,t){if(t.topic!==q)return;if("ai-session.message-delta"===t.type)return;const n=Cr(t.payload),r=this.lastAiSessionEventByInstance.get(e);r?.streamId===n.streamId&&void 0!==r.revision&&void 0!==n.revision&&n.revision>r.revision+1&&this.logger?.warn?.({instanceId:e,traceId:n.traceId,streamId:n.streamId,previousRevision:r.revision,revision:n.revision},"ai-session.event.forward.gap"),this.lastAiSessionEventByInstance.set(e,{streamId:n.streamId??r?.streamId,revision:n.revision??r?.revision}),this.logger?.info?.({instanceId:e,traceId:n.traceId,eventType:t.type,streamId:n.streamId,revision:n.revision},"ai-session.event.forward.message")}recordAppSessionEvent(e,t){if("app.sessions"!==t.topic)return;const n=Cr(t.payload),r=this.lastAppSessionEventByInstance.get(e);r?.streamId===n.streamId&&void 0!==r.revision&&void 0!==n.revision&&n.revision>r.revision+1&&this.logger?.warn?.({instanceId:e,traceId:n.traceId,streamId:n.streamId,previousRevision:r.revision,revision:n.revision},"app-session.event.forward.gap"),this.lastAppSessionEventByInstance.set(e,{streamId:n.streamId??r?.streamId,revision:n.revision??r?.revision}),this.logger?.info?.({instanceId:e,traceId:n.traceId,eventType:t.type,streamId:n.streamId,revision:n.revision},"app-session.event.forward.message")}}function Tr(e){const t=jn.safeParse(kr(e));return t.success?t.data:void 0}function kr(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 Cr(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 xr(e){if(!function(e){return!1!==e.ready&&(!e.runtimeVersion||["matched","failed"].includes(e.runtimeVersion.phase))}(e))return;const t=e.target?.api||e.target?.web;if(t)try{const e=new URL("/api/events",t);return e.protocol="https:"===e.protocol?"wss:":"ws:",e.toString()}catch{return}}const Or=new Set(["provisioning","starting","registering","registered","running","unhealthy"]),Rr=JSON.stringify({id:"{{.ID}}",name:"{{.Name}}",cpu:"{{.CPUPerc}}",memory:"{{.MemUsage}}",memoryPercent:"{{.MemPerc}}",network:"{{.NetIO}}",blockIo:"{{.BlockIO}}",pids:"{{.PIDs}}"});class Dr{snapshots=new Map;runCommand;targets;publish;intervalMs;timer;inFlight;pendingTargets=new Map;collectingTargets=new Map;constructor(e,t,n,r=3e3){this.runCommand=e,this.targets=t,this.publish=n,this.intervalMs=r}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(!Or.has(t.status))return Fr(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=Mr(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,Mr(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=>Or.has(e.status)&&(e.runtime.containerId||e.runtime.containerName));for(const t of e.filter(e=>Or.has(e.status)&&!e.runtime.containerId&&!e.runtime.containerName))this.update(Ur(t.id));for(const t of e.filter(e=>!Or.has(e.status)))this.update(Fr(t.id));if(!t.length)return;const n=t.map(e=>e.runtime.containerId||e.runtime.containerName),r=(new Date).toISOString();try{const e=await this.runCommand("docker",["stats","--no-stream","--format",Rr,...n],{timeoutMs:5e3});this.applyDockerOutput(t,e.stdout,r)}catch(e){if(1===t.length)return void this.update(Vr(t[0].id,r,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",Rr,t],{timeoutMs:5e3});this.applyDockerOutput([e],n.stdout,r)}catch(t){this.update(Vr(e.id,r,t instanceof Error?t.message:String(t)))}}))}}applyDockerOutput(e,t,n){const r=function(e,t=(new Date).toISOString()){const n=new Map;for(const r of e.split(/\r?\n/).filter(Boolean)){let e;try{e=JSON.parse(r)}catch{continue}const i=$r(e.id),o=$r(e.name),s=i||o;if(!s)continue;const a=Pr($r(e.memory)),c=Pr($r(e.network)),d=Pr($r(e.blockIo)),l=Sn.parse({instanceId:s,runtimeKind:"docker",state:"available",sampledAt:t,cpu:jr(e.cpu,"usagePercent"),memory:a?{usageBytes:a[0],...void 0!==a[1]?{limitBytes:a[1]}:{},...jr(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:Lr(e.pids)});i&&n.set(i,l),o&&n.set(o,l)}return n}(t,n);for(const t of e){const e=[t.runtime.containerId,t.runtime.containerName].filter(Boolean),i=[...r.entries()].find(([t])=>e.some(e=>e===t||e.startsWith(t)||t.startsWith(e)))?.[1];this.update(i?{...i,instanceId:t.id}:Vr(t.id,n,"Container metrics were not returned by Docker."))}}update(e){const t=Sn.parse(e);this.snapshots.set(t.instanceId,t),this.publish?.(t)}}function Mr(e){return[e.status,e.runtime.containerId||"",e.runtime.containerName||""].join("\0")}function Pr(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]),r=t[2].toLowerCase(),i=r.includes("i"),o="b"===r[0]?"":r[0],s=o?"kmgtpe".indexOf(o)+1:0;return Math.round(n*(i?1024:1e3)**s)}(e||""));return void 0===t?void 0:[t,n]}function jr(e,t){const n=Number($r(e).replace(/%$/,""));return Number.isFinite(n)&&n>=0?{[t]:n}:void 0}function Lr(e){const t=Number($r(e));return Number.isFinite(t)&&t>=0?t:void 0}function $r(e){return"string"==typeof e||"number"==typeof e?String(e).trim():""}function Fr(e){return{instanceId:e,runtimeKind:"docker",state:"stopped",sampledAt:(new Date).toISOString()}}function Ur(e){return{instanceId:e,runtimeKind:"docker",state:"pending",sampledAt:(new Date).toISOString()}}function Vr(e,t,n){return{instanceId:e,runtimeKind:"docker",state:"unavailable",sampledAt:t,error:n.slice(0,2048)}}function Hr(e){try{return t.statSync(e).isDirectory()}catch{return!1}}function qr(e,r){let i;try{i=t.statSync(e)}catch{return}if(!i.isDirectory())return;const o=n.resolve(e),s=n.basename(o)||o;let a=[];try{a=r>0?t.readdirSync(o,{withFileTypes:!0}):[]}catch{a=[]}const c=r>0?a.filter(e=>e.isDirectory()||e.isSymbolicLink()&&Hr(n.join(o,e.name))).sort((e,t)=>e.name.localeCompare(t.name)).slice(0,80).flatMap(e=>{const t=qr(n.join(o,e.name),r-1);return t?[t]:[]}):[];return{name:s,path:o,children:c}}function Br(e){return(e.path?[e.path]:function(){if("win32"!==process.platform)return[n.parse(n.resolve(process.cwd())).root];const e=n.parse(n.resolve(process.cwd())).root,t=Array.from({length:26},(e,t)=>`${String.fromCharCode(65+t)}:\\`);return[...new Set([e,...t])].filter(Hr)}()).flatMap(t=>{const n=qr(t,e.depth);return n?[n]:[]})}const Kr=m.z.object({path:m.z.string().trim().min(1).max(2048),method:m.z.string().trim().min(1).max(20).default("GET"),headers:m.z.record(m.z.string(),m.z.string()).default({}),body:m.z.string().optional(),bodyBase64:m.z.string().optional()}).strict(),Gr=m.z.object({id:m.z.string().trim().min(1).max(120).optional(),name:m.z.string().trim().min(1).max(160),path:m.z.string().trim().min(1).max(4096),defaultImageSelection:it.optional(),labels:m.z.record(m.z.string(),m.z.string()).default({})}).strict(),Jr=m.z.object({path:m.z.string().trim().min(1).max(4096).optional(),depth:m.z.coerce.number().int().min(0).max(1).default(0)}).strict(),Wr=m.z.object({id:m.z.string().trim().min(1).max(120).optional(),name:m.z.string().trim().min(1).max(160).optional(),runtimeId:m.z.string().trim().min(1).max(120),imageSelection:it.optional(),projectId:m.z.string().trim().min(1).max(120).optional(),image:yn.optional(),source:Vt,sourceSnapshot:m.z.record(m.z.string(),m.z.unknown()).default({}),config:m.z.object({autoImportAgentConfigs:m.z.boolean().optional(),defaultCodexPermissionMode:se.optional()}).strict().optional(),modelSelection:Mn.shape.modelSelection}).strict(),Xr=m.z.object({name:m.z.string().trim().min(1).max(160).optional(),config:m.z.object({autoImportAgentConfigs:m.z.boolean().optional(),defaultCodexPermissionMode:se.optional()}).strict().optional(),modelSelection:Mn.shape.modelSelection.optional()}).strict(),Yr=m.z.object({id:m.z.string().trim().min(1).max(120).optional(),name:m.z.string().trim().min(1).max(160),type:m.z.enum(["docker","kubernetes","local"]),status:m.z.enum(["unknown","online","offline","degraded"]).default("unknown"),accessStrategy:m.z.enum(["node-proxy","direct-port","kubernetes-ingress","kubernetes-port-forward"]).optional(),capabilities:m.z.record(m.z.string(),m.z.unknown()).default({}),labels:m.z.record(m.z.string(),m.z.string()).default({})}).strict(),Zr=Yr.omit({id:!0}).partial().strict();function Qr(){return process.env.TASK_HANDOFF_NODE_AGENT_DATA_DIR||n.join(p.homedir(),".config","task-handoff","node-agent")}function ei(e=Qr()){const t=n.resolve(e);return{dataDir:t,identityPath:n.join(t,"identity.json"),settingsPath:n.join(t,"runtime-settings.json"),localFoldersDir:n.join(t,"local-folders"),nodeRuntimesDir:n.join(t,"node-runtimes"),controlledInstancesDir:n.join(t,"controlled-instances"),nodeModelsDir:n.join(t,"models"),modelAssignmentsDir:n.join(t,"model-assignments"),modelEnvironmentsDir:n.join(t,"model-environments"),updatesDir:n.join(t,"updates"),logsDir:n.join(t,"logs")}}function ti(e){t.mkdirSync(e,{recursive:!0})}function ni(e,t){ti(n.dirname(e)),h.sync(e,`${JSON.stringify(t,null,2)}\n`,{encoding:"utf8"})}function ri(e,t){console.warn(JSON.stringify({message:e,...t}))}function ii(e){return e&&"object"==typeof e&&"issues"in e?{issues:e.issues}:{error:e instanceof Error?e.message:String(e)}}function oi(e,n){const r=n.logger||ri;let i;try{i=JSON.parse(t.readFileSync(e,"utf8"))}catch(t){return void r("stored JSON could not be read",{filePath:e,...ii(t)})}if(!n.schema)return i;const o=n.sanitize?n.sanitize(i):i,s=n.schema.safeParse(o);if(s.success)return s.data;const a="strip"in n.schema&&"function"==typeof n.schema.strip?n.schema.strip().safeParse(o):void 0;if(a?.success)return r("unknown stored fields were ignored",{filePath:e,issues:s.error.issues}),a.data;r("stored record failed validation and was isolated",{filePath:e,issues:s.error.issues})}function si(e){return`${e}_${r.randomUUID().replace(/-/g,"").slice(0,20)}`}function ai(){return r.randomBytes(24).toString("base64url")}class ci{directory;options;constructor(e,t={}){this.directory=e,this.options=t}init(){ti(this.directory)}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=oi(n.join(this.directory,e),this.options);return t?[t]:[]})}get(e){const n=this.filePath(e);return t.existsSync(n)?oi(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 ni(this.filePath(n.id),n),n}patch(e,t){const n=this.get(e);if(!n)return;const r={...n,...t,id:n.id,createdAt:n.createdAt,updatedAt:(new Date).toISOString()};return this.put(r)}delete(e){const n=this.filePath(e);return!!t.existsSync(n)&&(t.unlinkSync(n),!0)}}class di{filePathValue;defaults;options;constructor(e,t,n={}){this.filePathValue=e,this.defaults=t,this.options=n}init(){ti(n.dirname(this.filePathValue)),t.existsSync(this.filePathValue)||this.put(this.defaults())}get(){return this.init(),t.existsSync(this.filePathValue)?oi(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 ni(this.filePathValue,n),n}}function li(e,t=process.platform){const i=n.resolve(e),o=r.createHash("sha256").update(i).digest("hex").slice(0,16);return"win32"===t?`\\\\.\\pipe\\task-handoff-node-agent-${o}`:n.join("/tmp",`task-handoff-node-agent-${process.getuid?.()??"user"}`,`${o}.sock`)}const ui="TASK_HANDOFF_NODE_AGENT_V1";function mi(e=""){return r.createHash("sha256").update(e).digest("hex")}function pi(e,t){return r.createHmac("sha256",e).update(function(e){return[ui,e.keyId,e.method.toUpperCase(),e.pathWithQuery,e.timestamp,e.nonce,e.bodySha256].join("\n")}(t)).digest("hex")}function gi(e){const t=e.timestamp||(new Date).toISOString(),n=e.nonce||r.randomBytes(18).toString("base64url"),i=mi(e.body||""),o=pi(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":o}}const hi=new Set(["DELETE","GET","HEAD","PATCH","POST","PUT","OPTIONS"]);function fi(e){return"string"==typeof e&&hi.has(e.toUpperCase())?e.toUpperCase():"GET"}function yi(){return(new Date).toISOString()}function Ii(e,t){if(!e)return!0;const n=f.valid(e),r=f.valid(t);return n&&r?f.gt(r,n):e!==t}function Ai(){return process.env.TASK_HANDOFF_NPM_COMMAND||"npm"}function bi(e,r){const i=n.join(e,...r.split("/"),"package.json");try{const e=JSON.parse(t.readFileSync(i,"utf8"));if(e.name!==r||"string"!=typeof e.version||!e.version.trim())throw new Error(`Installed package manifest is invalid: ${i}`);return{name:r,version:e.version.trim()}}catch(e){if("ENOENT"===e.code)return;throw e}}async function wi(e){const t=(await e(Ai(),["root","--global"])).stdout.trim();if(!t)throw new Error("npm did not return its global module root.");const n=bi(t,"@task-handoff/server"),r=bi(t,"@task-handoff/node-agent");return n?{packageName:"@task-handoff/server",currentVersion:n.version,relatedCurrentVersions:r?[r.version]:[]}:{packageName:"@task-handoff/node-agent",currentVersion:r?.version,relatedCurrentVersions:[]}}function zi(e){if(!e||"object"!=typeof e||Array.isArray(e))return e;const t=e,n="string"==typeof t.updatedAt?t.updatedAt:yi(),r=t.target&&"object"==typeof t.target&&!Array.isArray(t.target)?t.target:void 0,i="controlled-instance"===r?.component,o={updating:"updating-node",downloading:"updating-node",installing:"updating-node",restarting:"restarting-node",completed:"succeeded",success:"succeeded",error:"failed"},s=new Set(["queued","updating-node","restarting-node","converging-instances","succeeded","degraded","failed"]),a="string"==typeof t.status?t.status:"queued",c=i?"failed":s.has(a)?a:o[a]||"failed",d="string"==typeof t.toVersion&&t.toVersion?t.toVersion:"unknown",l=Ot.strip().safeParse(t.impact).success?Ot.strip().parse(t.impact):{runningInstanceCount:0,stoppedInstanceCount:0,activeInstanceCount:0,restartInstanceCount:0,runningInstanceIds:[],stoppedInstanceIds:[],activeInstanceIds:[]},u=i?{code:"LEGACY_INSTANCE_UPDATE_RETIRED",message:"Independent controlled-instance update jobs were retired in favor of Node reconciliation.",retryable:!1}:"failed"!==c||t.error||s.has(a)||a in o?"string"==typeof t.error?{code:"NODE_UPDATE_FAILED",message:t.error,retryable:!1}:Ct.strip().safeParse(t.error).success?Ct.strip().parse(t.error):t.error&&"object"==typeof t.error?{code:"NODE_UPDATE_FAILED",message:"string"==typeof t.error.message?t.error.message:"Stored update job contained an unknown error.",retryable:!1}:void 0:{code:"NODE_UPDATE_FAILED",message:`Stored update job used an unknown status: ${a}.`,retryable:!1},{target:m,error:p,...g}=t,h={phase:"succeeded"===c?"succeeded":"failed"===c?"failed":c||"queued",desiredVersion:d,expectedInstanceIds:[],expectedInstanceCount:0,matchedInstanceCount:0,pendingInstanceCount:0,failedInstanceCount:i||"failed"===c?1:0,deferredInstanceCount:0},f=Rt.strip().safeParse(t.rollout);return{...g,source:"npm",status:c,impact:l,runtimeArtifacts:Array.isArray(t.runtimeArtifacts)?t.runtimeArtifacts.flatMap(e=>{const t=kt.strip().safeParse(e);return t.success?[t.data]:[]}):[],rollout:f.success?f.data:h,...u?{error:u}:{},...i?{completedAt:t.completedAt||n}:{}}}class Ni{records;constructor(e){this.records=new ci(e.updatesDir,{schema:Pt,sanitize:zi})}init(){this.records.init()}list(){return this.records.list().sort((e,t)=>t.createdAt.localeCompare(e.createdAt))}create(e,t){const n=yi();return this.records.put(Pt.parse({id:si("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(Pt.parse({...n,...t,id:e,createdAt:n.createdAt,updatedAt:yi()}))}reconcileRollouts(e,t,n={}){const r=new Map(e.map(e=>[e.id,e]));for(const e of this.list().filter(e=>["updating-node","restarting-node","converging-instances"].includes(e.status))){if(n.processStarted&&"restarting-node"===e.status&&t!==e.toVersion){this.patch(e.id,{status:"failed",rollout:{...e.rollout,phase:"failed",nodeVersion:t},error:{code:"NODE_UPDATE_FAILED",message:`Node agent restarted with version ${t}, expected ${e.toVersion}.`,retryable:!1},completedAt:yi()});continue}const i="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"!==i.status)continue;const o=i.rollout.expectedInstanceIds,s=o.map(e=>r.get(e)),a=s.filter(e=>e?.ready&&"matched"===e.runtimeVersion?.phase&&e.runtimeVersion.actualVersion===i.toVersion).length,c=s.filter(e=>e&&["created","stopped","failed"].includes(e.status||"")&&"failed"!==e.runtimeVersion?.phase).length,d=s.filter(e=>!e||"failed"===e.runtimeVersion?.phase).length,l=Math.max(0,o.length-a-d-c),u=d>0?"degraded":0===l?"succeeded":"converging-instances";this.patch(i.id,{status:u,rollout:{...i.rollout,phase:u,nodeVersion:t,expectedInstanceCount:o.length,matchedInstanceCount:a,pendingInstanceCount:l,failedInstanceCount:d,deferredInstanceCount:i.impact.stoppedInstanceCount+c},..."succeeded"===u||"degraded"===u?{completedAt:yi()}:{}})}}run(e,t){(async()=>{this.patch(e.id,{status:"updating-node",rollout:{...e.rollout,phase:"updating-node"},startedAt:yi(),error:void 0});try{await t(e),this.patch(e.id,{status:"succeeded",completedAt:yi()})}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:yi()})}})()}}const vi="runtime-manifest.json";class Ei 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 Si(e,t=""){const r=[],i=await y.readdir(n.join(e,t),{withFileTypes:!0});for(const o of i){const i=t?n.posix.join(t,o.name):o.name;if(!t&&i===vi)continue;const s=n.join(e,...i.split("/"));if(o.isDirectory()){r.push(...await Si(e,i));continue}if(o.isSymbolicLink()){const t=await y.readlink(s);if(n.isAbsolute(t))throw new Ei("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload symlink is absolute: ${i}`);const o=n.resolve(n.dirname(s),t),a=n.relative(n.resolve(e),o);if(!a||".."===a||a.startsWith(`..${n.sep}`)||n.isAbsolute(a))throw new Ei("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload symlink escapes the artifact: ${i}`);if(!await y.lstat(o).catch(()=>{}))throw new Ei("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload symlink is broken: ${i}`);r.push({absolutePath:s,relativePath:i,kind:"symlink",target:t,size:Buffer.byteLength(t)});continue}if(!o.isFile())throw new Ei("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload contains unsupported entry: ${i}`);const a=await y.lstat(s);r.push({absolutePath:s,relativePath:i,kind:"file",size:a.size})}return r}async function _i(e){const n=(await Si(e)).sort((e,t)=>function(e,t){return Buffer.compare(Buffer.from(e,"utf8"),Buffer.from(t,"utf8"))}(e.relativePath,t.relativePath)),i=r.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 Ti(e){for(const[t,n]of[["version",e.version],["platform",e.platform],["arch",e.arch]])if(!/^[0-9A-Za-z._-]+$/.test(n))throw new Ei("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Invalid runtime artifact ${t}: ${n}`);return`${e.version}-${e.platform}-${e.arch}`}function ki(e,t){return`${Ti(e)}-${e.sha256}-${t}`}async function Ci(e){const n=r.createHash("sha256");for await(const r of t.createReadStream(e))n.update(r);return n.digest("hex")}class xi{#e;#t;#n=new Map;constructor(e){this.#e=e.cacheDir,this.#t=e.fetchImpl??fetch}resolve(e,t){const n=kt.parse(e);if(!/^[a-f0-9]{64}$/.test(t.archiveSha256))throw new Ei("INSTANCE_RUNTIME_ARTIFACT_INVALID","Runtime archive SHA-256 is invalid.");if((t.archiveUrl?1:0)+(t.archivePath?1:0)!=1)throw new Ei("INSTANCE_RUNTIME_ARTIFACT_INVALID","Runtime artifact source must specify exactly one archive location.");const r=ki(n,t.archiveSha256),i=this.#n.get(r);if(i)return i;const o=this.#r(n,t).finally(()=>this.#n.delete(r));return this.#n.set(r,o),o}async#r(e,i){if(!/^[a-f0-9]{64}$/.test(i.archiveSha256))throw new Ei("INSTANCE_RUNTIME_ARTIFACT_INVALID","Runtime archive SHA-256 is invalid.");const o=ki(e,i.archiveSha256),s=n.join(this.#e,"archives"),a=n.join(s,`${o}.tar.gz`);if(await y.mkdir(s,{recursive:!0}),await this.#i(a,e,i.archiveSha256))return{identity:e,archivePath:a,cacheHit:!0};await y.rm(a,{force:!0});const c=n.join(s,`.${o}.${r.randomUUID()}.part`);try{const n=await y.open(c,"wx");if(i.archivePath)await I.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 Ei("INSTANCE_RUNTIME_ARTIFACT_UNAVAILABLE",`Runtime artifact download failed with HTTP ${e.status}.`,{retryable:e.status>=500});await I.pipeline(e.body,n.createWriteStream())}if(await Ci(c)!==i.archiveSha256)throw new Ei("INSTANCE_RUNTIME_ARTIFACT_INVALID","Downloaded runtime archive SHA-256 does not match release metadata.");return await this.#o(c,e),await y.rename(c,a),{identity:e,archivePath:a,cacheHit:!1}}catch(e){if(e instanceof Ei)throw e;throw new Ei("INSTANCE_RUNTIME_ARTIFACT_UNAVAILABLE","Could not download runtime artifact.",{cause:e,retryable:!0})}finally{await y.rm(c,{force:!0})}}async#i(e,t,n){try{return await Ci(e)===n&&(await this.#o(e,t),!0)}catch{return!1}}async#o(e,t){const i=n.join(this.#e,"validation",`${Ti(t)}-${r.randomUUID()}`);try{await async function(e,t){await y.mkdir(t,{recursive:!0});try{await A.extract({file:e,cwd:t,strict:!0,preservePaths:!1,filter:(e,t)=>{const r=n.posix.normalize(e.replace(/^\.\//,""));if(!r||".."===r||r.startsWith("../")||n.posix.isAbsolute(r))throw new Ei("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime archive entry escapes the artifact root: ${e}`);const i=t.type;if("File"!==i&&"OldFile"!==i&&"Directory"!==i&&"SymbolicLink"!==i)throw new Ei("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime archive contains unsupported entry type ${i??"unknown"}: ${e}`);return!0}})}catch(e){throw new Ei("INSTANCE_RUNTIME_ARTIFACT_INVALID","Could not extract runtime artifact safely.",{cause:e})}}(e,i),await async function(e,t,r){const i=await async function(e){let t;try{t=JSON.parse(await y.readFile(n.join(e,vi),"utf8"))}catch(e){throw new Ei("INSTANCE_RUNTIME_ARTIFACT_INVALID","Runtime artifact manifest is missing or invalid JSON.",{cause:e})}const r=kt.safeParse(t);if(!r.success)throw new Ei("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime artifact manifest is invalid: ${r.error.message}`);return r.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 Ei("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime artifact ${"sha256"===n?"SHA-256":n} mismatch: expected ${t[n]}, got ${e[n]}.`)}(i,t),1!==i.formatVersion)throw new Ei("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Unsupported runtime artifact format ${i.formatVersion}.`);if(r?.platform&&"universal"!==i.platform&&i.platform!==r.platform)throw new Ei("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime artifact platform ${i.platform} does not match ${r.platform}.`);if(r?.arch&&"universal"!==i.arch&&i.arch!==r.arch)throw new Ei("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime artifact architecture ${i.arch} does not match ${r.arch}.`);if(void 0!==r?.launcherAbi&&i.launcherAbi>r.launcherAbi)throw new Ei("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Runtime requires launcher ABI ${i.launcherAbi}, but the base runtime provides ${r.launcherAbi}.`);const o=function(e,t){if(!e||e.includes("\\")||n.posix.isAbsolute(e))throw new Ei("INSTANCE_RUNTIME_ARTIFACT_INVALID",`${t} must be a non-empty POSIX relative path.`);const r=n.posix.normalize(e);if("."===r||".."===r||r.startsWith("../"))throw new Ei("INSTANCE_RUNTIME_ARTIFACT_INVALID",`${t} escapes the runtime root.`);return r}(i.entrypoint,"Runtime entrypoint"),s=await y.lstat(n.join(e,...o.split("/"))).catch(()=>{});if(!s?.isFile())throw new Ei("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime entrypoint is missing: ${o}`);const a=await _i(e);if(a!==i.sha256)throw new Ei("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload SHA-256 mismatch: expected ${i.sha256}, got ${a}.`);return i}(i,t,{platform:t.platform,arch:t.arch})}finally{await y.rm(i,{recursive:!0,force:!0})}}}async function Oi(e,t,r,i=fetch){if("linux"!==t||!["x64","arm64"].includes(r))throw new Ei("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Managed controlled-instance updates require a Linux x64 or arm64 target, received ${t}/${r}.`);const o=await async function(e){const t=`controlled-instance-runtime-${e}-linux-universal`,r=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[i,o]=await Promise.all([y.readFile(n.join(r,`${t}.manifest.json`),"utf8"),y.readFile(n.join(r,`${t}.tar.gz.sha256`),"utf8")]),s=kt.safeParse(JSON.parse(i));if(!s.success||s.data.version!==e||"linux"!==s.data.platform||"universal"!==s.data.arch)throw new Ei("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Bundled controlled-instance ${e} has an invalid Linux manifest.`);const a=o.trim().split(/\s+/)[0]?.toLowerCase();if(!a||!/^[a-f0-9]{64}$/.test(a))throw new Ei("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Bundled controlled-instance ${e} has an invalid archive checksum.`);return{identity:s.data,source:{archivePath:n.join(r,`${t}.tar.gz`),archiveSha256:a}}}catch(t){if("ENOENT"===t.code)return;if(t instanceof Ei)throw t;throw new Ei("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Could not read bundled controlled-instance ${e}.`,{cause:t})}}(e);if(o)return o;const s=`controlled-instance-runtime-${e}-linux-universal`,a=function(e){const t=process.env.TASK_HANDOFF_RUNTIME_RELEASE_BASE_URL?.trim();return t?t.replaceAll("{version}",e).replace(/\/$/,""):`https://github.com/edgestorage/task-handoff/releases/download/v${e}`}(e),c=`${a}/${s}.manifest.json`,d=`${a}/${s}.tar.gz`,l=`${a}/${s}.tar.gz.sha256`,[u,m]=await Promise.all([i(c),i(l)]).catch(t=>{throw new Ei("INSTANCE_RUNTIME_ARTIFACT_UNAVAILABLE",`Could not read release metadata for controlled-instance ${e}.`,{cause:t,retryable:!0})});if(!u.ok||!m.ok)throw new Ei("INSTANCE_RUNTIME_ARTIFACT_UNAVAILABLE",`Release metadata for controlled-instance ${e} is unavailable (manifest HTTP ${u.status}, checksum HTTP ${m.status}).`,{retryable:u.status>=500||m.status>=500});let p;try{p=await u.json()}catch(t){throw new Ei("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Release manifest for controlled-instance ${e} is not valid JSON.`,{cause:t})}const g=kt.safeParse(p);if(!g.success)throw new Ei("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Release manifest for controlled-instance ${e} is invalid: ${g.error.message}`);if(g.data.version!==e||"linux"!==g.data.platform||"universal"!==g.data.arch)throw new Ei("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Release identity mismatch: requested ${e}-linux-universal, received ${g.data.version}-${g.data.platform}-${g.data.arch}.`);const h=(await m.text()).trim().split(/\s+/)[0]?.toLowerCase();if(!h||!/^[a-f0-9]{64}$/.test(h))throw new Ei("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Release checksum for controlled-instance ${e} is invalid.`);return{identity:g.data,source:{archiveUrl:d,archiveSha256:h}}}class Ri{store;desiredVersion;hooks;inFlight=new Map;requests=new Map;cancelled=new Set;now;delay;drainTimeoutMs;verificationTimeoutMs;pollIntervalMs;maxAttempts;retryBaseDelayMs;retryMaxDelayMs;constructor(e,t,n,r={}){this.store=e,this.desiredVersion=t,this.hooks=n,this.now=r.now||(()=>new Date),this.delay=r.delay||(e=>new Promise(t=>setTimeout(t,e))),this.drainTimeoutMs=r.drainTimeoutMs??3e5,this.verificationTimeoutMs=r.verificationTimeoutMs??6e4,this.pollIntervalMs=r.pollIntervalMs??250,this.maxAttempts=function(e){if(!Number.isInteger(e)||e<=0)throw new TypeError("maxAttempts must be a positive integer.");return e}(r.maxAttempts??3),this.retryBaseDelayMs=Ui(r.retryBaseDelayMs??1e3,"retryBaseDelayMs"),this.retryMaxDelayMs=Ui(r.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 r=this.inFlight.get(e);if(r)return r;const i=Promise.resolve().then(()=>this.reconcile(e,n)).finally(()=>{this.inFlight.delete(e),this.requests.delete(e)});return this.inFlight.set(e,i),i}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 r=this.desiredVersion();if(this.cancelled.has(e)&&!t.resumeCancelled)return this.storePhase(n,"pending");const i=Di(n),o=i===r&&(await(this.hooks.isInstalled?.(n,r))??!0);if(this.cancelled.has(e))return this.storePhase(this.requireInstance(e),"pending");if(i===r&&o)return this.storeState(n,{desiredVersion:r,actualVersion:i,phase:"matched",attempt:n.runtimeVersion?.attempt||0,matchedAt:this.timestamp()},!Pi(n)&&"failed"!==n.health);const s=n.runtimeVersion?.desiredVersion===r;if(s&&"failed"===n.runtimeVersion?.phase)return n;if(s&&(n.runtimeVersion?.attempt||0)>=this.maxAttempts)return"failed"===n.runtimeVersion?.phase&&n.runtimeVersion.error?n:this.storeBatchFailure(n,r,Fi(r,i,this.maxAttempts,n.runtimeVersion?.error));if(n=this.storeState(n,function(e,t,n,r=!1){const i=e.runtimeVersion,o=i?.desiredVersion===t&&"matched"!==i.phase;return{desiredVersion:t,...n?{actualVersion:n}:{},phase:"pending",attempt:o?i.attempt:0,error:(o?i.error:void 0)||(n!==t||r?ji(t,n):Li("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,r,i,o)),Pi(n)&&!t.startRequested)return n;let a=!1;try{for(;(n.runtimeVersion?.attempt||0)<this.maxAttempts;){if(this.cancelled.has(e))return this.storePhase(this.requireInstance(e),"pending");let i;try{if(n=this.storePhase(n,"draining"),await(this.hooks.beginDrain?.(n)),a=!0,n=this.requireInstance(e),Mi(n)){const t=await this.waitUntil(e,this.drainTimeoutMs,e=>!Mi(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),await this.hooks.install(n,r),this.cancelled.has(e)||Pi(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 i=await this.waitUntil(e,this.verificationTimeoutMs,e=>Di(e)===r);if(this.cancelled.has(e))return this.storePhase(this.requireInstance(e),"pending");if(!i)throw Li("INSTANCE_RUNTIME_VERIFICATION_FAILED",`Instance ${e} did not register controlled-instance ${r} after restart.`,r,Di(this.requireInstance(e)),!0);const o=this.requireInstance(e);if(this.hooks.isInstalled&&!await this.hooks.isInstalled(o,r))throw Li("INSTANCE_RUNTIME_VERIFICATION_FAILED",`Instance ${e} reported controlled-instance ${r}, but its active runtime release is missing.`,r,Di(o),!0);return this.storeState(o,{desiredVersion:r,actualVersion:r,phase:"matched",attempt:o.runtimeVersion?.attempt||1,matchedAt:this.timestamp()},!Pi(o)&&"failed"!==o.health)}catch(t){if(this.cancelled.has(e))return this.storePhase(this.requireInstance(e),"pending");i=$i(t,r,Di(this.store.get(e)))}n=this.requireInstance(e);const o=n.runtimeVersion?.attempt||1;if(!i.retryable||o>=this.maxAttempts)return this.storeBatchFailure(n,r,o>=this.maxAttempts&&i.retryable?Fi(r,Di(n),this.maxAttempts,i):i);n=this.storeState(n,{desiredVersion:r,...Di(n)?{actualVersion:Di(n)}:{},phase:"pending",attempt:o,lastAttemptAt:this.timestamp(),error:i}),await this.delay(this.retryDelayMs(o))}return this.storeBatchFailure(n,r,Fi(r,Di(n),this.maxAttempts,n.runtimeVersion?.error))}finally{a&&await(this.hooks.endDrain?.(this.requireInstance(e)))}}storeBatchFailure(e,t,n){const r=Di(e);return this.storeState(e,{desiredVersion:t,...r?{actualVersion:r}:{},phase:"failed",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))}storePhase(e,t,n=!1){const r=this.desiredVersion(),i=Di(e),o=e.runtimeVersion?.desiredVersion===r?e.runtimeVersion.error:void 0;return this.storeState(e,{desiredVersion:r,...i?{actualVersion:i}:{},phase:t,attempt:(e.runtimeVersion?.attempt||0)+(n?1:0),lastAttemptAt:this.timestamp(),...o?{error:o}:"pending"===t?{error:ji(r,i)}:{}},"restarting"!==t&&void 0)}storeState(e,t,n){const r=this.store.get(e.id)||e;return this.store.put(Mn.parse({...r,runtimeVersion:t,...void 0===n?{}:{ready:n},updatedAt:this.timestamp()}))}async waitUntil(e,t,n){const r=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()>=r)return!1;await this.delay(Math.min(this.pollIntervalMs,Math.max(0,r-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 Di(e){return e?.build?.packageVersion||e?.instanceVersion}function Mi(e){return e.apps.runningCount>0||e.aiSessions.runningCount>0}function Pi(e){return["created","stopped","failed"].includes(e.status)}function ji(e,t){return Li("INSTANCE_RUNTIME_VERSION_MISMATCH",`Expected controlled-instance ${e}, received ${t||"an unknown version"}.`,e,t,!0)}function Li(e,t,n,r,i){return{code:e,message:t,expectedVersion:n,...r?{actualVersion:r}:{},retryable:i}}function $i(e,t,n){if(e&&"object"==typeof e&&"code"in e&&"message"in e){const r=e,i=Ct.shape.code.safeParse(r.code);if(i.success&&"string"==typeof r.message)return Li(i.data,r.message,t,n,"boolean"!=typeof r.retryable||r.retryable)}return Li("INSTANCE_RUNTIME_INSTALL_FAILED",e instanceof Error?e.message:String(e),t,n,!0)}function Fi(e,t,n,r){const i=r?.message?` Last error: ${r.message}`:"";return Li(r?.code||"INSTANCE_RUNTIME_INSTALL_FAILED",`Runtime convergence stopped after ${n} attempts for this instance run.${i}`,e,t,!0)}function Ui(e,t){if(!Number.isFinite(e)||e<0)throw new TypeError(`${t} must be a nonnegative finite number.`);return e}const Vi=m.z.record(m.z.string(),m.z.string()),Hi=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 qi{directory;constructor(e){this.directory=e}get(e){try{return Vi.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 r=Vi.parse(n);t.mkdirSync(this.directory,{recursive:!0,mode:448});const i=this.filePath(e);return h.sync(i,`${JSON.stringify(r,null,2)}\n`,{encoding:"utf8",mode:384}),t.chmodSync(i,384),r}delete(e){t.rmSync(this.filePath(e),{force:!0})}filePath(e){return n.join(this.directory,`${e}.json`)}}class Bi{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=Gt.parse(e);this.init();const r=this.filePath(n.id);return h.sync(r,`${JSON.stringify(n,null,2)}\n`,{encoding:"utf8",mode:384}),t.chmodSync(r,384),n}delete(e){const n=this.filePath(e);return!!t.existsSync(n)&&(t.unlinkSync(n),!0)}read(e){try{const r=JSON.parse(t.readFileSync(e,"utf8")),i=n.basename(e,".json"),o=Gt.safeParse(r);if(o.success&&o.data.id===i&&on(o.data)===o.data.id)return o.data;const s=Gt.strip().safeParse(r);return s.success&&s.data.id===i&&on(s.data)===s.data.id?(console.warn(JSON.stringify({message:"unknown stored node model fields were ignored",nodeId:this.nodeId,filePath:e})),s.data):void console.warn(JSON.stringify({message:"stored node model failed validation and was isolated",nodeId:this.nodeId,filePath:e}))}catch(t){return void console.warn(JSON.stringify({message:"stored node model could not be read",nodeId:this.nodeId,filePath:e,error:t instanceof Error?t.message:String(t)}))}}filePath(e){return n.join(this.directory,`${e}.json`)}}class Ki{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 r=JSON.parse(t.readFileSync(n,"utf8")),i=Xt.safeParse(r);if(i.success)return i.data;const o=Xt.strip().safeParse(r);if(o.success)return console.warn(JSON.stringify({message:"unknown stored model assignment fields were ignored",instanceId:e,filePath:n})),o.data;throw i.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=Xt.parse(e);this.init();const r=this.filePath(n.instanceId);return h.sync(r,`${JSON.stringify(n,null,2)}\n`,{encoding:"utf8",mode:384}),t.chmodSync(r,384),n}delete(e){t.rmSync(this.filePath(e),{force:!0})}filePath(e){return n.join(this.directory,`${e}.json`)}}class Gi{usedNonces=new Map;identity;nodeId;overrideSecret;overrideKeyId;nowMs;constructor(e,t,n,r,i=Date.now){this.identity=e,this.nodeId=t,this.overrideSecret=n,this.overrideKeyId=r,this.nowMs=i}hasRemoteSecrets(){return this.identity.remoteSecrets(this.overrideSecret,this.overrideKeyId).length>0}verify(e){const t=function(e){const t=new Map;for(const[n,r]of Object.entries(e)){const e=Array.isArray(r)?r.join(","):"string"==typeof r?r:void 0===r?"":String(r);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=this.identity.remoteSecrets(this.overrideSecret,this.overrideKeyId);if(!n.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 i=n.filter(e=>t.keyId===e.keyId);if(!i.length)throw Object.assign(new Error("Invalid node agent HMAC key id."),{statusCode:401,code:"NODE_AGENT_HMAC_KEY_INVALID"});const o=Date.parse(t.timestamp);if(!Number.isFinite(o)||Math.abs(this.nowMs()-o)>6e4)throw Object.assign(new Error("Node agent HMAC timestamp is outside the allowed window."),{statusCode:401,code:"NODE_AGENT_HMAC_TIMESTAMP_INVALID"});if(!t.nonce)throw Object.assign(new Error("Node agent HMAC nonce is missing."),{statusCode:401,code:"NODE_AGENT_HMAC_NONCE_MISSING"});this.pruneNonces();const s=`${t.nodeId}:${t.keyId}:${t.nonce}`;if(this.usedNonces.has(s))throw Object.assign(new Error("Node agent HMAC nonce was already used."),{statusCode:401,code:"NODE_AGENT_HMAC_NONCE_REPLAY"});const a=mi(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(!i.some(n=>function(e,t){const n=Buffer.from(e,"hex"),i=Buffer.from(t,"hex");return n.length===i.length&&r.timingSafeEqual(n,i)}(t.signature,pi(n.secret,{keyId:t.keyId,method:e.method,pathWithQuery:e.url,timestamp:t.timestamp,nonce:t.nonce,bodySha256:a}))))throw Object.assign(new Error("Invalid node agent HMAC signature."),{statusCode:401,code:"NODE_AGENT_HMAC_SIGNATURE_INVALID"});return this.usedNonces.set(s,o+6e4+1),t.keyId}pruneNonces(){const e=this.nowMs();for(const[t,n]of this.usedNonces)n<=e&&this.usedNonces.delete(t)}}const Ji=m.z.string().trim().min(1).max(160),Wi=m.z.string().datetime(),Xi=m.z.string().min(1).max(4096),Yi=m.z.string().trim().url().max(2048),Zi=m.z.object({tokenHash:m.z.string().trim().min(1).max(256),expiresAt:Wi,createdAt:Wi,controlPlaneName:m.z.string().trim().min(1).max(160).optional(),controlPlaneUrl:Yi.optional()}).strip(),Qi=m.z.object({id:Ji,keyId:Ji,name:m.z.string().trim().min(1).max(160).optional(),url:Yi.optional(),secret:Xi,pairedAt:Wi,updatedAt:Wi,active:m.z.boolean().default(!0)}).strip(),eo=m.z.object({controlPlaneName:m.z.string().trim().min(1).max(160).optional(),controlPlaneUrl:m.z.string().trim().max(2048).optional(),expiresInMs:m.z.number().int().positive().max(36e5).optional()}).strict(),to=m.z.object({joinToken:m.z.string().trim().min(1).max(4096),controlPlaneId:m.z.string().trim().min(1).max(160).optional(),controlPlaneName:m.z.string().trim().min(1).max(160).optional(),controlPlaneUrl:m.z.string().trim().max(2048).optional()}).strict(),no=m.z.object({controlPlaneUrl:m.z.string().trim().url().max(2048),joinToken:m.z.string().trim().min(1).max(4096),controlPlaneName:m.z.string().trim().min(1).max(160).optional(),activate:m.z.boolean().optional()}).strict();function ro(){return(new Date).toISOString()}const io=new Set(["nodeId","createdAt","updatedAt","pairingInvites","remoteControlPlanes"]),oo=new Set(["tokenHash","expiresAt","createdAt","controlPlaneName","controlPlaneUrl"]),so=new Set(["id","keyId","name","url","secret","pairedAt","updatedAt","active"]);function ao(e,t){console.warn(JSON.stringify({message:e,...t}))}function co(e,t){return Object.assign(new Error(e,void 0===t?void 0:{cause:t}),{code:"NODE_AGENT_IDENTITY_INVALID"})}function lo(e,t){return Object.keys(e).filter(e=>!t.has(e))}function uo(e,t,n){const r=Wi.safeParse(e);return r.success?r.data:(n("invalid node agent identity timestamp was replaced",{field:t}),ro())}function mo(e,t){if(!e||"object"!=typeof e||Array.isArray(e))throw co("Node agent identity must be a JSON object.");const n=e,r=Ji.safeParse(n.nodeId);if(!r.success)throw co("Node agent identity has an invalid nodeId.",r.error);const i=r.data,o=lo(n,io);return o.length&&t("unknown node agent identity fields were ignored",{fields:o}),{nodeId:i,createdAt:uo(n.createdAt,"createdAt",t),updatedAt:uo(n.updatedAt,"updatedAt",t),pairingInvites:Array.isArray(n.pairingInvites)?n.pairingInvites.flatMap(e=>{if(!e||"object"!=typeof e||Array.isArray(e))return t("invalid node agent pairing invite was ignored",{}),[];const n=lo(e,oo);n.length&&t("unknown node agent pairing invite fields were ignored",{fields:n});const r=Zi.safeParse(e);return r.success?[r.data]:(t("invalid node agent pairing invite was ignored",{issues:r.error.issues}),[])}):[],remoteControlPlanes:Array.isArray(n.remoteControlPlanes)?n.remoteControlPlanes.flatMap(e=>{if(!e||"object"!=typeof e||Array.isArray(e))return t("invalid node agent remote control-plane was ignored",{}),[];const n=lo(e,so);n.length&&t("unknown node agent remote control-plane fields were ignored",{fields:n});const r=Qi.safeParse(e);return r.success?[r.data]:(t("invalid node agent remote control-plane was ignored",{issues:r.error.issues}),[])}):[]}}class po{paths;logger;constructor(e,t={}){this.paths=e,this.logger=t.logger||ao}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 co(`Node agent identity contains invalid JSON: ${this.paths.identityPath}`,e)}return mo(n,this.logger)}write(e){t.mkdirSync(n.dirname(this.paths.identityPath),{recursive:!0});const r=mo({...e,updatedAt:ro()},this.logger);h.sync(this.paths.identityPath,`${JSON.stringify(r,null,2)}\n`,{encoding:"utf8",mode:384})}}function go(){return(new Date).toISOString()}class ho{store;constructor(e){this.store=new po(e)}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=si("node");return this.writeNodeId(n),n}createPairingInvite(e){const t=this.prunePairingInvites(this.store.read()||this.newIdentity()),n=go(),r=new Date(Date.now()+(e.expiresInMs||6e5)).toISOString(),i=ai(),o={tokenHash:mi(i),createdAt:n,expiresAt:r,...e.controlPlaneName?{controlPlaneName:e.controlPlaneName}:{},...e.controlPlaneUrl?{controlPlaneUrl:e.controlPlaneUrl}:{}};return this.store.write({...t,pairingInvites:[...t.pairingInvites||[],o]}),{...o,token:i}}completePairingInvite(e){const t=this.prunePairingInvites(this.store.read()||this.newIdentity()),n=mi(e.joinToken),r=(t.pairingInvites||[]).find(e=>e.tokenHash===n);if(!r){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 i=go(),o={id:e.controlPlaneId||si("cp"),keyId:si("key"),...e.controlPlaneName||r.controlPlaneName?{name:e.controlPlaneName||r.controlPlaneName}:{},...e.controlPlaneUrl||r.controlPlaneUrl?{url:e.controlPlaneUrl||r.controlPlaneUrl}:{},secret:ai(),pairedAt:i,updatedAt:i,active:!0};return this.store.write({...t,pairingInvites:(t.pairingInvites||[]).filter(e=>e.tokenHash!==n),remoteControlPlanes:[...(t.remoteControlPlanes||[]).filter(e=>e.id!==o.id),o]}),o}upsertRemoteControlPlane(e){const t=this.store.read()||this.newIdentity(),n=e.url?.replace(/\/$/,"");return this.store.write({...t,remoteControlPlanes:[...(t.remoteControlPlanes||[]).filter(t=>t.id!==e.id&&(!n||t.url?.replace(/\/$/,"")!==n)),e]}),e}createRemoteControlPlane(e){const t=go();return{id:si("cp"),keyId:si("key"),...e.name?{name:e.name}:{},url:e.url,secret:ai(),pairedAt:t,updatedAt:t,active:!1!==e.active}}configuredRemoteControlPlanes(){return this.store.read()?.remoteControlPlanes||[]}listRemoteControlPlanes(e=""){return(this.store.read()?.remoteControlPlanes||[]).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))}deleteRemoteControlPlane(e,t=""){if(t&&e===t){const e=new Error("Cannot delete the key currently used by this control-plane connection.");throw Object.assign(e,{statusCode:409,code:"NODE_AGENT_REMOTE_KEY_IN_USE"}),e}const n=this.store.read();if(!n)return!1;const r=(n.remoteControlPlanes||[]).filter(t=>t.keyId!==e);return r.length!==(n.remoteControlPlanes||[]).length&&(this.store.write({...n,remoteControlPlanes:r}),!0)}remoteSecrets(e,t){return[...(this.store.read()?.remoteControlPlanes||[]).map(e=>({keyId:e.keyId,secret:e.secret})),...e&&t?[{keyId:t,secret:e}]:[]]}reverseTunnelSecret(e,t,n){if(t&&n)return{keyId:n,secret:t};const r=this.store.read()?.remoteControlPlanes||[];if(!r.length)return;if(e){const t=e.replace(/\/$/,""),n=r.find(e=>e.url?.replace(/\/$/,"")===t);if(n)return{keyId:n.keyId,secret:n.secret}}const i=[...r].sort((e,t)=>t.updatedAt.localeCompare(e.updatedAt))[0];return i?{keyId:i.keyId,secret:i.secret}:void 0}newIdentity(){return{nodeId:this.resolveNodeId(),createdAt:go(),updatedAt:go(),pairingInvites:[],remoteControlPlanes:[]}}writeNodeId(e){const t=this.store.read();this.store.write({...t||{createdAt:go()},nodeId:e,updatedAt:go(),pairingInvites:t?.pairingInvites||[],remoteControlPlanes:t?.remoteControlPlanes||[]})}prunePairingInvites(e){const t=Date.now();return{...e,pairingInvites:(e.pairingInvites||[]).filter(e=>Date.parse(e.expiresAt)>t)}}}const fo=new Set(["content-encoding","content-length","transfer-encoding"]),yo=["codex","claude"],Io=5e3,Ao="runtime_local_host",bo="task-handoff.node-agent.builtin",wo=new Set(["linux","darwin","win32","freebsd","openbsd","aix","sunos"]);function zo(e){return wo.has(e)?e:"unknown"}function No(e){const t={...e};return delete t[bo],t}const vo=m.z.object({version:m.z.literal(1),externalListener:_n}).strict(),Eo=m.z.object({}).strict().default({}),So=jt.strict();function _o(e){const t=process.env[e]?.trim();return t||void 0}const To=function(e,t=process.env,n=e){let r;return()=>{const i=t.TASK_HANDOFF_VERSION?.trim();return i||(r||=N(e,t,n),r)}}("@task-handoff/node-agent",process.env,"@task-handoff/control-plane");function ko(e){const t=To();return e===t?{desiredVersion:t,actualVersion:e,phase:"matched",attempt:0,matchedAt:Lo()}:{desiredVersion:t,...e?{actualVersion:e}:{},phase:"pending",attempt:0,error:{code:"INSTANCE_RUNTIME_VERSION_MISMATCH",message:`Expected controlled-instance ${t}, received ${e||"an unknown version"}.`,expectedVersion:t,...e?{actualVersion:e}:{},retryable:!0}}}function Co(e,t,n=!0){if(!n)return ko(t);const r=To(),i=e.runtimeVersion;if(!i||i.desiredVersion!==r)return ko(t);const o=()=>({code:"INSTANCE_RUNTIME_VERSION_MISMATCH",message:`Expected controlled-instance ${r}, received ${t||"an unknown version"}.`,expectedVersion:r,...t?{actualVersion:t}:{},retryable:!0}),s="INSTANCE_RUNTIME_VERSION_MISMATCH"!==i.error?.code?i.error:t===r?void 0:o();return xt.parse({...i,desiredVersion:r,...t?{actualVersion:t}:{actualVersion:void 0},..."pending"===i.phase?{error:s||(t!==r?o():void 0)}:{}})}function xo(e){return Object.fromEntries([...e.entries()].filter(([e])=>!fo.has(e.toLowerCase())))}function Oo(e){return e.bodyBase64?Buffer.from(e.bodyBase64,"base64"):e.body}const Ro=67108864;function Do(){const e=Number(process.env.TASK_HANDOFF_INSTANCE_PROXY_MAX_RESPONSE_BYTES);return Number.isSafeInteger(e)&&e>0?e:67108864}function Mo(e){const t=e.authorization;return"string"==typeof t&&t.startsWith("Bearer ")?t.slice(7).trim():void 0}function Po(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 jo(e){return!e.ip&&!e.socket.remoteAddress&&!e.socket.remoteFamily}function Lo(){return(new Date).toISOString()}function $o(e){return"all-ipv4"===e?"0.0.0.0":"127.0.0.1"}function Fo(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:{},r=Object.keys(t).filter(e=>"version"!==e&&"externalListener"!==e),i=Object.keys(n).filter(e=>"bindScope"!==e&&"port"!==e);return(r.length||i.length)&&console.warn(JSON.stringify({message:"unknown stored node agent runtime setting fields were ignored",filePath:"runtime-settings.json",fields:[...r,...i.map(e=>`externalListener.${e}`)]})),{version:t.version,externalListener:{bindScope:n.bindScope,port:n.port}}}function Uo(e){return"local-folder"===e.type?Ht.parse({mode:"local-bind",path:"/workspace",readOnly:!1}):Ht.parse({mode:"git-clone",path:"/workspace",readOnly:!1})}function Vo(e){const t=Vt.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 Bt.parse({id:n,name:"string"==typeof e.sourceSnapshot.name?e.sourceSnapshot.name:e.name,source:t,defaultImageSelection:e.imageSelection,defaultNodeId:e.nodeId,defaultRuntimeId:e.runtimeId,workspacePolicy:Uo(t),labels:{},createdAt:e.createdAt,updatedAt:e.updatedAt})}async function Ho(e,t){if(!t.target.web)return"unknown";const n=new AbortController,r=setTimeout(()=>n.abort(),2e3);try{return(await e(`${Go(t)}/api/health`,{signal:n.signal})).ok?"reachable":"endpoint-unreachable"}catch{return"endpoint-unreachable"}finally{clearTimeout(r)}}async function qo(e,t,n,r){const i=new AbortController,o=setTimeout(()=>i.abort(),r);try{return await e(t,{...n,signal:i.signal})}finally{clearTimeout(o)}}async function Bo(e,t,n,r){if(!t.config.autoImportAgentConfigs)return void r.diagnostic({instanceId:t.id,action:n},"node instance config auto-import skipped");if("reachable"!==t.targetStatus)return;const i=Go(t),o=Number(process.env.TASK_HANDOFF_CONFIG_AUTO_IMPORT_TIMEOUT_MS||Io);for(const s of yo)try{const a=await qo(e,`${i}/api/config-sync/import/${encodeURIComponent(s)}`,{method:"POST"},Number.isFinite(o)&&o>0?o:Io);if(!a.ok){r.warn({instanceId:t.id,action:n,preset:s,statusCode:a.status},"node instance config auto-import failed");continue}r.diagnostic({instanceId:t.id,action:n,preset:s},"node instance config auto-import completed")}catch(e){r.warn({instanceId:t.id,action:n,preset:s,error:e instanceof Error?e.message:String(e)},"node instance config auto-import failed")}}async function Ko(e,t,n){const r=t.requireInstance(n);if("reachable"!==r.targetStatus||!r.target.web)return!1;const i=await qo(e,`${Go(r)}/api/internal/model-environment`,{method:"PUT",headers:{"content-type":"application/json",authorization:`Bearer ${r.registrationToken}`},body:JSON.stringify(t.resolvedAssignedModelEnvironment(n))},Io);if(!i.ok)throw Object.assign(new Error(`Instance ${n} rejected its managed model environment with HTTP ${i.status}.`),{statusCode:502,code:"INSTANCE_MODEL_ENVIRONMENT_APPLY_FAILED"});return!0}function Go(e){const t=e.target.web;if(!t){const t=new Error(`Instance ${e.id} does not have a web endpoint.`);throw Object.assign(t,{statusCode:409,code:"NODE_INSTANCE_WEB_ENDPOINT_MISSING"}),t}if("direct-port"!==e.target.strategy)return t.replace(/\/$/,"");try{const e=new URL(t);return e.port?(e.hostname=process.env.TASK_HANDOFF_NODE_AGENT_PROXY_HOST||"127.0.0.1",e.toString().replace(/\/$/,"")):t.replace(/\/$/,"")}catch{return t.replace(/\/$/,"")}}function Jo(e,t){const n=new Error(t);throw Object.assign(n,{statusCode:403,code:e}),n}function Wo(e,t){e!==Ve&&console.warn(JSON.stringify({message:"protocol version mismatch",peer:t,expectedProtocolVersion:Ve,actualProtocolVersion:e||"missing",errorCode:"PROTOCOL_VERSION_MISMATCH"}))}function Xo(e){return"none"!==e.capabilities.artifactKind}function Yo(e={}){return{...e,requiresImage:!1,supportsControlledInstanceApi:!0,supportsContainerLifecycle:!1,supportsAppSessions:!0,supportsHostSessions:!0,artifactKind:"none",isolation:"none"}}function Zo(e){return new Promise(t=>{const n=o.createServer();n.once("error",()=>t(!1)),n.listen({host:"127.0.0.1",port:e},()=>{n.close(()=>t(!0))})})}function Qo(e,t=3e3){return null!==e.exitCode||null!==e.signalCode?Promise.resolve():new Promise(n=>{const r=setTimeout(()=>{null===e.exitCode&&null===e.signalCode&&e.kill("SIGKILL"),n()},t);r.unref(),e.once("exit",()=>{clearTimeout(r),n()})})}const es="task-handoff.local-process-nonce",ts=1e3;function ns(e){return e.runtime.port?`http://127.0.0.1:${e.runtime.port}`:e.target.web}async function rs(e,t){try{const n=await fetch(`${e}/api/internal/node-agent/process-identity`,{headers:{authorization:`Bearer ${t}`},signal:AbortSignal.timeout(ts)});if(!n.ok)return;const r=(await n.json()).data;if("string"!=typeof r?.instanceId||"number"!=typeof r.pid||"string"!=typeof r.processNonce)return;return{instanceId:r.instanceId,pid:r.pid,processNonce:r.processNonce,startIdentity:"string"==typeof r.startIdentity?r.startIdentity:void 0}}catch{return}}async function is(e,t){if(k(e)!==t)return!1;try{process.kill(e,"SIGTERM")}catch{return!0}const n=Date.now()+3e3;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 r=Date.now()+1e3;for(;Date.now()<r;){try{process.kill(e,0)}catch{return!0}await new Promise(e=>setTimeout(e,50))}return!1}function os(e,t){return Object.assign(new Error(t),{statusCode:503,code:"LOCAL_INSTANCE_STOP_UNCONFIRMED",instanceId:e.id})}async function ss(e,t,r){const i=t.get(e.id);if(i&&!i.killed)return i.kill("SIGTERM"),t.delete(e.id),void await Qo(i);const o=await async function(e){const t=ns(e),n=e.runtime.labels?.[es];if(!t||!n||!e.registrationToken)return;const r=await rs(t,e.registrationToken);if(r&&r.instanceId===e.id&&r.processNonce===n)try{return(await fetch(`${t}/api/internal/node-agent/shutdown`,{method:"POST",headers:{authorization:`Bearer ${e.registrationToken}`},signal:AbortSignal.timeout(ts)})).ok?r:void 0}catch{return}}(e);if(o){const t=ns(e),n=Date.now()+3e3;for(;t&&Date.now()<n;){if(!await rs(t,e.registrationToken))return;await new Promise(e=>setTimeout(e,50))}const r=t?await rs(t,e.registrationToken):void 0;if(r&&r.instanceId===o.instanceId&&r.pid===o.pid&&r.processNonce===o.processNonce&&r.startIdentity===o.startIdentity&&r.startIdentity&&await is(r.pid,r.startIdentity))return;throw os(e,`Controlled instance ${e.id} accepted shutdown but its exit could not be confirmed.`)}const s=function(e=function(){const e="win32"===process.platform?p.tmpdir():"/tmp";return n.join(e,`task-handoff-local-controlled-instance-${function(){const e=process.getuid?.();return void 0!==e?String(e):p.userInfo().username.replace(/[^a-zA-Z0-9_.-]/g,"_")}()}.lock`)}()){return C(e)}(r),a=await async function(e){const t=ns(e);if(t)try{const[n,r]=await Promise.all([fetch(`${t}/api/instance/status`,{signal:AbortSignal.timeout(ts)}),fetch(`${t}/api/diagnostics`,{signal:AbortSignal.timeout(ts)})]);if(!n.ok||!r.ok)return;const i=await n.json(),o=await r.json(),s=o.data?.runtime?.pid;if(i.data?.id!==e.id||"controlled"!==i.data.controlMode||"number"!=typeof s||!Number.isInteger(s)||s<=0)return;const a=k(s);return a?{pid:s,startIdentity:a}:void 0}catch{return}}(e);if(a){if(await is(a.pid,a.startIdentity))return;throw os(e,`Legacy controlled instance ${e.id} did not exit after termination.`)}if(s?.instanceId===e.id&&R(s))throw os(e,`Local controlled instance ${e.id} is still owned by pid ${s.pid}, but its process identity could not be verified.`)}const as=new Set(["provisioning","starting","registering","registered","running"]);async function cs(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}}}function ds(e){return!0===e.managedArtifacts}class ls{managedArtifacts=!0;executor;platform;arch;runCommand;constructor(e,t,n,r){this.executor=e,this.runCommand=t,this.platform=n,this.arch=r}artifactTarget(e){return this.executor.inspectRuntimeTarget(e?.instance.runtime.containerName)}async installRuntime(e,t){const n=e.instance.runtime.containerName;if(!n)throw Object.assign(new Error(`Instance ${e.instance.id} does not have a Docker container.`),{code:"INSTANCE_RUNTIME_INSTALL_FAILED"});await this.executor.installRuntimeLauncher(n),await this.executor.installRuntimeRelease({containerName:n,expectedContainerId:e.instance.runtime.containerId,artifactPath:t.archivePath,identity:t.identity})}async inspectRuntime(e,t){const n=e.instance.runtime.containerName;return!!n&&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)}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){return this.executor.delete(e)}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:zo(this.platform),...t?{serverVersion:t}:{}}}}}catch(t){return{status:"offline",capabilities:{...e.capabilities,daemon:{status:"offline",hostPlatform:zo(this.platform),error:t instanceof Error?t.message:String(t)}}}}}}class us{runCommand;paths;nodeAgentUrl;processByInstanceId=new Map;commandOverride;lockPath;constructor(e,t,n,r,i){this.runCommand=e,this.paths=t,this.nodeAgentUrl=n,this.commandOverride=r,this.lockPath=i}async start(e){await ss(e.instance,this.processByInstanceId,this.lockPath);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),o=e.instance.runtime.port||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 Zo(e))return e;const n=new Error(`No free localhost port found in range ${t}-${Math.min(t+999,65535)}.`);throw Object.assign(n,{statusCode:503,code:"LOCAL_INSTANCE_PORT_UNAVAILABLE"}),n}(),s=n.join(this.paths.dataDir,"local-instances",e.instance.id),c=n.join(s,"logs");t.mkdirSync(c,{recursive:!0});const[d,...l]=function(e){if(e)return e;const r=n.resolve(process.cwd(),"bin","task-handoff.js");if(t.existsSync(r))return[process.execPath,r,"web"];throw Object.assign(new Error("The bundled controlled-instance command is unavailable."),{statusCode:500,code:"LOCAL_CONTROLLED_COMMAND_MISSING"})}(this.commandOverride),u=[...l,"--host","127.0.0.1","--port",String(o)],m=r.randomUUID(),p=t.openSync(n.join(c,"controlled-instance.out.log"),"a"),g=t.openSync(n.join(c,"controlled-instance.err.log"),"a"),h=a.spawn(d,u,{cwd:i,detached:!1,stdio:["ignore",p,g],env:{...process.env,TASK_HANDOFF_CONTROL_MODE:"controlled",TASK_HANDOFF_RUNTIME_KIND:"local",TASK_HANDOFF_CONTROLLED_INSTANCE_VERSION:To(),...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:m,TASK_HANDOFF_WORKSPACE:i,TASK_HANDOFF_WORKSPACE_MODE:"local-bind",TASK_HANDOFF_DATA_DIR:s,TASK_HANDOFF_LOG_DIR:c,TASK_HANDOFF_APP_SESSION_PERSIST:"1",TASK_HANDOFF_CODEX_APP_SERVER:process.env.TASK_HANDOFF_CODEX_APP_SERVER||"1",TASK_HANDOFF_WEB_PORT:String(o),TASK_HANDOFF_WEB_HOST:"127.0.0.1",...e.modelEnv||{}}});t.closeSync(p),t.closeSync(g);try{await function(e){return new Promise((t,n)=>{const r=()=>{e.off("error",i),t()},i=t=>{e.off("spawn",r),n(t)};e.once("spawn",r),e.once("error",i)})}(h)}catch(e){const r=e instanceof Error?e.message:String(e);try{t.appendFileSync(n.join(c,"controlled-instance.lifecycle.log"),`[${(new Date).toISOString()}] spawn failed command=${d} cwd=${i} error=${r}\n`)}catch{}throw Object.assign(new Error(`Controlled instance process could not start with command ${d} in ${i}: ${r}`),{statusCode:500,code:"LOCAL_INSTANCE_PROCESS_SPAWN_FAILED"})}this.processByInstanceId.set(e.instance.id,h),h.on("error",e=>{try{t.appendFileSync(n.join(c,"controlled-instance.lifecycle.log"),`[${(new Date).toISOString()}] process error pid=${h.pid??""} error=${e.message}\n`)}catch{}}),h.once("exit",(r,i)=>{this.processByInstanceId.delete(e.instance.id);try{t.appendFileSync(n.join(c,"controlled-instance.lifecycle.log"),`[${(new Date).toISOString()}] exited pid=${h.pid??""} code=${r??""} signal=${i??""}\n`)}catch{}});const f=`http://127.0.0.1:${o}`,y=h.pid?k(h.pid):void 0,I=!(!h.pid||!e.instance.registrationToken)&&await async function(e,t,n,r,i=3e3){const o=Date.now()+i;for(;Date.now()<o;){if(null!==n.exitCode||null!==n.signalCode)return!1;const i=await rs(e,r);if(i&&i.instanceId===t.instanceId&&i.pid===t.pid&&i.processNonce===t.processNonce&&i.startIdentity===t.startIdentity)return!0;await new Promise(e=>setTimeout(e,100))}return!1}(f,{instanceId:e.instance.id,pid:h.pid,processNonce:m,startIdentity:y},h,e.instance.registrationToken);if(!I)throw this.processByInstanceId.get(e.instance.id)===h&&this.processByInstanceId.delete(e.instance.id),null===h.exitCode&&null===h.signalCode&&h.kill("SIGTERM"),await Qo(h),Object.assign(new Error(`Controlled instance process did not become ready for instance ${e.instance.id} on ${f}.`),{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:f,api:`${f}/api`},workspace:{mode:"local-bind",status:"pending",path:i},runtime:{kind:"local",workspacePath:i,pid:h.pid,port:o,labels:{...e.instance.runtime.labels,"task-handoff.runtime-kind":"local",[es]:m}}}}async stop(e){return await ss(e.instance,this.processByInstanceId,this.lockPath),{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 await ss(e.instance,this.processByInstanceId,this.lockPath),this.start(e)}async delete(e){return this.stop(e)}async check(e){const[t,n]=await Promise.all([cs(this.runCommand,"codex"),cs(this.runCommand,"claude")]);return{status:"online",capabilities:Yo({...e.capabilities,apps:{terminal:!0,codex:t,claude:n}})}}async stopAll(){const e=Array.from(this.processByInstanceId.values());for(const e of this.processByInstanceId.values())e.killed||e.kill("SIGTERM");this.processByInstanceId.clear(),await Promise.all(e.map(e=>Qo(e)))}}class ms{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;const t=new Error(`Runtime type ${e.type} is not supported by this node agent.`);throw Object.assign(t,{statusCode:400,code:"NODE_RUNTIME_TYPE_UNSUPPORTED"}),t}managedAdapters(){return[this.docker,this.local].filter(ds)}async stopAll(){this.local instanceof us&&await this.local.stopAll()}}class ps extends ci{onStored;setOnStored(e){this.onStored=e}put(e){const t=super.get(e.id)?.stateRevision||0,n=super.put(Mn.parse({...e,stateRevision:Math.max(e.stateRevision||0,t)+1}));return this.onStored?.(n),n}}class gs{nodeId;paths;localFolders;nodeRuntimes;controlledInstances;models;modelAssignments;modelEnvironments;updateJobs;node;listenerPort;containerUrlOverride;platform;constructor(e,t,n,r,i,o){this.paths=e,this.nodeId=t,this.localFolders=new ci(e.localFoldersDir,{schema:Ut,sanitize:at}),this.nodeRuntimes=new ci(e.nodeRuntimesDir,{schema:En}),this.controlledInstances=new ps(e.controlledInstancesDir,{schema:Mn,sanitize:e=>$n(e,e=>{console.warn(JSON.stringify({message:"legacy controlled instance field was ignored",...e}))})}),this.models=new Bi(e.nodeModelsDir,t),this.modelAssignments=new Ki(e.modelAssignmentsDir),this.modelEnvironments=new qi(e.modelEnvironmentsDir),this.updateJobs=new Ni(e),this.listenerPort=i,this.platform=o,this.containerUrlOverride=r;const s=Lo();this.node=vn.parse({id:t,name:t,connectionMode:"direct-http",endpoint:n,controlEndpoint:n,containerEndpoint:this.containerUrl,publicWebBase:n?n.replace(/:\d+$/,""):void 0,status:"online",health:"ok",capabilities:{},labels:{},createdAt:s,updatedAt:s})}init(){this.localFolders.init();for(const e of this.localFolders.list())this.localFolders.put(e);if(this.nodeRuntimes.init(),this.controlledInstances.init(),this.models.init(),this.modelAssignments.init(),this.migrateLegacyModelEnvironments(),this.updateJobs.init(),this.updateJobs.reconcileRollouts(this.controlledInstances.list(),To(),{processStarted:!0}),!this.nodeRuntimes.get("runtime_local_docker")){const e=Lo();this.nodeRuntimes.put(En.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(Ao),t=Lo();this.nodeRuntimes.put(En.parse({id:Ao,nodeId:this.nodeId,name:"Local Runtime",type:"local",status:e?.status||"unknown",accessStrategy:"node-proxy",capabilities:Yo(e?.capabilities),labels:{...e?.labels,[bo]:"true"},createdAt:e?.createdAt||t,updatedAt:e?.updatedAt||t}))}for(const e of this.nodeRuntimes.list())e.nodeId!==this.nodeId&&this.nodeRuntimes.put(En.parse({...e,nodeId:this.nodeId,updatedAt:Lo()}));for(const e of this.localFolders.list())e.nodeId!==this.nodeId&&this.localFolders.put(Ut.parse({...e,nodeId:this.nodeId,updatedAt:Lo()}));this.normalizeInstanceRuntimeVersions()}normalizeInstanceRuntimeVersions(){for(const e of this.controlledInstances.list()){const t=ko(e.build?.packageVersion||e.instanceVersion),n=Xo(this.requireRuntime(e.runtimeId)),r=["created","stopped","failed"].includes(e.status),i=n&&e.runtimeVersion?.desiredVersion===t.desiredVersion?e.runtimeVersion:void 0,o=n?"matched"===t.phase?r?t:{...t,phase:"verifying",matchedAt:void 0}:"failed"===i?.phase?{...t,phase:"failed",attempt:i.attempt,lastAttemptAt:i.lastAttemptAt,error:i.error}:{...t,attempt:i?.attempt||0,lastAttemptAt:i?.lastAttemptAt}:t;this.controlledInstances.put(Mn.parse({...e,ready:!1,runtimeVersion:o,updatedAt:Lo()}))}}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=Lo()}runningInstanceCount(){const e=new Set(["created","stopped","failed"]);return this.listInstances().filter(t=>!e.has(t.status)).length}createLocalFolder(e){const t=Lo(),n=Ut.parse({...e,id:e.id||si("folder"),nodeId:this.nodeId,labels:e.labels||{},createdAt:t,updatedAt:t});return this.localFolders.put(n)}createRuntime(e){if("local"===e.type){const e="win32"===this.platform,t=new Error(e?"Local Runtime is not supported on Windows.":"Local Runtime is built in and cannot be added manually.");throw Object.assign(t,{statusCode:e?400:409,code:e?"LOCAL_RUNTIME_UNSUPPORTED":"LOCAL_RUNTIME_BUILTIN"}),t}const t=Lo(),n=En.parse({...e,id:e.id||si("runtime"),nodeId:this.nodeId,accessStrategy:e.accessStrategy||(r=e.type,"docker"===r?"direct-port":"node-proxy"),capabilities:e.capabilities||{},labels:No(e.labels),createdAt:t,updatedAt:t});var r;return this.nodeRuntimes.put(n)}updateRuntime(e,t){const n=this.requireRuntime(e);if("true"===n.labels[bo]){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 r=En.parse({...n,...t,id:n.id,nodeId:this.nodeId,accessStrategy:t.accessStrategy||n.accessStrategy,capabilities:t.capabilities||n.capabilities,labels:t.labels?No(t.labels):n.labels,createdAt:n.createdAt,updatedAt:Lo()});return this.nodeRuntimes.put(r)}deleteRuntime(e){if("true"===this.requireRuntime(e).labels[bo]){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=En.parse({...n,...e,id:n.id,nodeId:this.nodeId,createdAt:n.createdAt,updatedAt:Lo()});return this.nodeRuntimes.put(t)}):this.nodeRuntimes.put(En.parse({...n,status:"unknown",updatedAt:Lo()}))}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=Ln(t);if(!n.success)throw function(e,t){const n=t.map(e=>`${e.path.join(".")||"body"}: ${e.message}`).join("; "),r=new Error(`Stored instance ${e} is not compatible with protocol ${Ve}: ${n}`);return Object.assign(r,{statusCode:409,code:"NODE_INSTANCE_PAYLOAD_INVALID"}),r}(e,n.error.issues);return n.data}listInstances(){return this.controlledInstances.list().flatMap(e=>{const t=Ln(e);return t.success?[t.data]:[]})}listModels(){const e=new Map;for(const t of this.listInstances()){const n=this.modelAssignments.get(t.id);for(const t of[n?.codexModelHash,n?.claudeModelHash])t&&e.set(t,(e.get(t)||0)+1)}return this.models.list().map(t=>this.publicModel(t,e.get(t.id)||0))}createModel(e){const t=Lo(),n=on(e),r=this.models.get(n),i=Gt.parse({...e,id:n,enabled:e.enabled??!0,order:e.order??this.nextModelOrder(),labels:e.labels||{},createdAt:r?.createdAt||t,updatedAt:t});return this.publicModel(this.models.put(i),this.modelReferenceIds(n).length)}deployModel(e){const t=on(e);if(e.id!==t)throw Object.assign(new Error(`Model content hash ${t} does not match ${e.id}.`),{statusCode:400,code:"NODE_MODEL_HASH_MISMATCH"});const n=this.models.get(e.id)||this.models.put(Gt.parse(e));return this.publicModel(n,this.modelReferenceIds(n.id).length)}updateModel(e,t){const n=this.requireModel(e),r=Gt.parse({...n,...t,key:t.key?.trim()?t.key:n.key,createdAt:n.createdAt,updatedAt:Lo()}),i=on(r),o=this.models.put(Gt.parse({...r,id:i}));return this.publicModel(o,this.modelReferenceIds(i).length)}deleteModel(e){this.requireModel(e);const t=this.modelReferenceIds(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)}assignModels(e,t){const n=this.requireInstance(e);if(this.validateAssignmentRef("codex",t.codexModelHash),this.validateAssignmentRef("claude",t.claudeModelHash),void 0!==t.modelSelection.codexModelHash&&(t.modelSelection.codexModelHash??void 0)!==t.codexModelHash)throw Object.assign(new Error("Codex model selection does not match its node assignment."),{statusCode:400,code:"NODE_MODEL_SELECTION_MISMATCH"});if(void 0!==t.modelSelection.claudeModelHash&&(t.modelSelection.claudeModelHash??void 0)!==t.claudeModelHash)throw Object.assign(new Error("Claude model selection does not match its node assignment."),{statusCode:400,code:"NODE_MODEL_SELECTION_MISMATCH"});const r=this.modelAssignments.get(e),i=Xt.parse({instanceId:e,codexModelHash:t.codexModelHash,claudeModelHash:t.claudeModelHash,updatedAt:Lo()});this.modelAssignments.put(i);try{return{assignment:i,instance:this.controlledInstances.put(Mn.parse({...n,modelSelection:t.modelSelection,updatedAt:Lo()}))}}catch(t){throw r?this.modelAssignments.put(r):this.modelAssignments.delete(e),t}}resolvedAssignedModelEnvironment(e){const t=this.modelAssignments.get(e);if(!t){if(this.modelEnvironments.has(e))throw Object.assign(new Error(`Legacy model environment for instance ${e} requires manual migration.`),{statusCode:409,code:"NODE_MODEL_MIGRATION_REQUIRED"});return{}}return{...this.modelEnvironmentForRef("codex",t.codexModelHash),...this.modelEnvironmentForRef("claude",t.claudeModelHash)}}validateAssignmentRef(e,t){if(!t)return;const n=this.requireModel(t);if(n.app!==e)throw Object.assign(new Error(`Model ${n.id} belongs to ${n.app}, not ${e}.`),{statusCode:400,code:"NODE_MODEL_APP_MISMATCH"});if(!n.enabled)throw Object.assign(new Error(`Model ${n.id} is disabled.`),{statusCode:409,code:"NODE_MODEL_DISABLED"})}modelEnvironmentForRef(e,t){if(!t)return{};this.validateAssignmentRef(e,t);const n=this.requireModel(t);return"codex"===e?{OPENAI_API_KEY:n.key,OPENAI_BASE_URL:n.endpoint,TASK_HANDOFF_CODEX_BASE_URL:n.endpoint,TASK_HANDOFF_CODEX_MODEL:n.model}:{ANTHROPIC_API_KEY:n.key,ANTHROPIC_BASE_URL:n.endpoint,TASK_HANDOFF_CLAUDE_MODEL:n.model}}requireModel(e){const t=this.models.get(e);if(!t)throw Object.assign(new Error(`Model ${e} was not found on node ${this.nodeId}.`),{statusCode:404,code:"NODE_MODEL_NOT_FOUND"});if(on(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}modelReferenceIds(e){return this.listInstances().filter(t=>{const n=this.modelAssignments.get(t.id);return n?.codexModelHash===e||n?.claudeModelHash===e}).map(e=>e.id)}publicModel(e,t){const{key:n,...r}=e;return Wt.parse({...r,keyPreview:n.length<=8?"set":`${n.slice(0,4)}...${n.slice(-4)}`,keySet:!0,referenceCount:t})}nextModelOrder(){return this.models.list().reduce((e,t)=>Math.max(e,t.order),0)+100}migrateLegacyModelEnvironments(){for(const e of this.modelEnvironments.listInstanceIds()){if(!this.controlledInstances.get(e)){this.warnLegacyModelMigration(e,"instance-not-found");continue}if(this.modelAssignments.get(e)){try{this.resolvedAssignedModelEnvironment(e),this.modelEnvironments.delete(e)}catch{this.warnLegacyModelMigration(e,"existing-assignment-invalid")}continue}let t;try{t=this.modelEnvironments.get(e)}catch{this.warnLegacyModelMigration(e,"sidecar-invalid");continue}if(!Object.keys(t).length){this.modelEnvironments.delete(e);continue}if(Object.keys(t).some(e=>!Hi.has(e))){this.warnLegacyModelMigration(e,"unknown-fields");continue}const n=[];try{const r=this.migrateLegacyModelForApp(t,"codex",n),i=this.migrateLegacyModelForApp(t,"claude",n);if(!r&&!i)throw new Error("no complete model configuration");const o={...r?{codexModelHash:r}:{},...i?{claudeModelHash:i}:{}};this.assignModels(e,{modelSelection:o,codexModelHash:r,claudeModelHash:i}),this.resolvedAssignedModelEnvironment(e),this.modelEnvironments.delete(e)}catch{this.modelAssignments.delete(e);for(const e of n)this.models.delete(e);this.warnLegacyModelMigration(e,"mapping-failed")}}}migrateLegacyModelForApp(e,t,n){const r=e["codex"===t?"OPENAI_API_KEY":"ANTHROPIC_API_KEY"],i="codex"===t?e.TASK_HANDOFF_CODEX_BASE_URL||e.OPENAI_BASE_URL:e.ANTHROPIC_BASE_URL,o="codex"===t?e.TASK_HANDOFF_CODEX_MODEL||e.CODEX_MODEL:e.TASK_HANDOFF_CLAUDE_MODEL||e.CLAUDE_MODEL;if(!Boolean(r||i||o))return;if(!r||!i||!o)throw new Error("model configuration incomplete");const s=on({app:t,endpoint:i,key:r,model:o}),a=this.models.get(s);if(a){if(a.app!==t||a.key!==r||a.endpoint!==i||a.model!==o||!a.enabled)throw new Error("existing model conflicts with legacy environment");return s}const c=Lo();return this.models.put(Gt.parse({id:s,name:`Migrated ${"codex"===t?"Codex":"Claude"} model`,endpoint:i,key:r,model:o,app:t,enabled:!0,order:this.nextModelOrder(),labels:{migratedFrom:"instance-model-environment"},createdAt:c,updatedAt:c})),n.push(s),s}warnLegacyModelMigration(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}))}createInstance(e){const t=this.requireRuntime(e.runtimeId),r=Lo(),i=e.id||si("inst"),o=Vt.parse(e.source);if(function(e){return"boolean"==typeof e.capabilities.requiresImage?e.capabilities.requiresImage:"local"!==e.type}(t)&&(!e.imageSelection||!e.image)){const e=new Error(`Runtime ${t.name} requires an image.`);throw Object.assign(e,{statusCode:400,code:"NODE_RUNTIME_IMAGE_REQUIRED"}),e}if("local"===t.type&&"local-folder"!==o.type){const e=new Error("Localhost runtime currently supports local folder sources only.");throw Object.assign(e,{statusCode:400,code:"LOCAL_RUNTIME_REQUIRES_LOCAL_FOLDER"}),e}if("local"===t.type&&this.listInstances().some(e=>"local"===this.requireRuntime(e.runtimeId).type)){const e=new Error("A localhost instance already exists on this node.");throw Object.assign(e,{statusCode:409,code:"LOCAL_RUNTIME_INSTANCE_EXISTS"}),e}const s=e.image?yn.parse(e.image):void 0,a="local"===t.type&&"local-folder"===o.type?n.resolve(o.path):void 0,c=Mn.parse({id:i,name:e.name||`instance-${i.replace(/^inst_?/,"").slice(0,6)}`,source:o,sourceSnapshot:e.sourceSnapshot||{},modelSelection:e.modelSelection,projectId:e.projectId,nodeId:this.nodeId,runtimeId:t.id,imageSelection:e.imageSelection,imageSnapshot:s,imageProvisioning:s&&"docker"===t.type?{phase:"checking-image",requestedReference:s.requestedReference,generation:0,startedAt:r,updatedAt:r}:void 0,status:s&&"docker"===t.type?"provisioning":"created",health:"unknown",connectionStatus:"unknown",agentStatus:"unknown",targetStatus:"unknown",uiAccessStatus:"unknown",controlMode:"controlled",ready:!1,runtimeVersion:ko(),capabilities:{},config:{autoImportAgentConfigs:e.config?.autoImportAgentConfigs??!0,defaultCodexPermissionMode:e.config?.defaultCodexPermissionMode??("docker"===t.type?"full-access":"ask")},workspace:"local"===t.type?{mode:"local-bind",status:"unknown",path:a}:{status:"unknown"},target:{strategy:"node-proxy",status:"unknown"},runtime:"local"===t.type?{kind:"local",workspacePath:a,labels:{"task-handoff.runtime-kind":"local"}}:{labels:{}},registrationToken:ai(),createdAt:r,updatedAt:r});return this.controlledInstances.put(c)}registerInstance(e,t,n){const r=Hn.parse(t),i=Lo(),o=this.controlledInstances.get(e);if(!o){const t=new Error(`Instance ${e} was not found on node ${this.nodeId}.`);throw Object.assign(t,{statusCode:404,code:"NODE_INSTANCE_NOT_FOUND"}),t}if(this.validateInstanceReport(o,r,n),r.processIncarnationId&&r.processIncarnationId===o.processIncarnationId)return o;Wo(r.protocolVersion,`Instance ${e}`);const s=r.build?.packageVersion||r.instanceVersion,a=Xo(this.requireRuntime(o.runtimeId)),c=Co(o,s,a),d=Mn.parse({...o,status:"registered",health:s===To()?"ok":"degraded",ready:!a&&s===To(),connectionStatus:"online",agentStatus:"online",targetStatus:"endpoint-unreachable"===r.target.status?"endpoint-unreachable":"reachable"===r.target.status?"reachable":o.targetStatus,uiAccessStatus:"endpoint-unreachable"===r.target.status?"endpoint-unreachable":o.uiAccessStatus,controlMode:r.controlMode,protocolVersion:r.protocolVersion,instanceVersion:r.instanceVersion,build:r.build,runtimeVersion:c,processIncarnationId:r.processIncarnationId||o.processIncarnationId,capabilities:r.capabilities,appInventory:r.appInventory,workspace:r.workspace,target:{...o.target,...r.target},registrationToken:o.registrationToken||r.registrationToken,lastHeartbeatAt:i,updatedAt:i});return this.controlledInstances.put(d)}heartbeatInstance(e,t,n){const r=this.requireInstance(e);this.validateInstanceToken(r,n);const i=qn.parse(t);r.processIncarnationId&&i.processIncarnationId&&i.processIncarnationId!==r.processIncarnationId&&function(e,t){const n=new Error(t);throw Object.assign(n,{statusCode:409,code:"INSTANCE_PROCESS_INCARNATION_MISMATCH"}),n}(0,`Instance ${e} report belongs to an obsolete controlled-instance process.`),Wo(i.protocolVersion,`Instance ${e}`);const o=Lo(),s=i.target?{...r.target,...i.target}:r.target,a={...s,status:"unknown"===s.status&&(s.web||s.api)?"reachable":s.status},c="endpoint-unreachable"===a.status?"endpoint-unreachable":"reachable"===a.status?"reachable":r.targetStatus,d=Co(r,i.build?.packageVersion||r.build?.packageVersion||r.instanceVersion,Xo(this.requireRuntime(r.runtimeId))),l=i.health||r.health,u="running"===(i.status||r.status)&&"failed"!==l,m=Mn.parse({...r,...i,target:a,ready:u,health:l,runtimeVersion:d,processIncarnationId:i.processIncarnationId||r.processIncarnationId,agentStatus:"online",targetStatus:c,uiAccessStatus:c,connectionStatus:"online",build:i.build||r.build,lastHeartbeatAt:o,updatedAt:o});return this.controlledInstances.put(m)}validateInstanceReport(e,t,n){this.validateInstanceToken(e,n||t.registrationToken),t.instanceId&&t.instanceId!==e.id&&Jo("INSTANCE_ID_MISMATCH",`Instance ${t.instanceId} cannot register as ${e.id}.`),t.nodeId&&t.nodeId!==this.nodeId&&Jo("INSTANCE_NODE_MISMATCH",`Instance ${e.id} belongs to node ${this.nodeId}.`),t.runtimeId&&t.runtimeId!==e.runtimeId&&Jo("INSTANCE_RUNTIME_MISMATCH",`Instance ${e.id} belongs to runtime ${e.runtimeId}.`),t.imageSelection&&t.imageSelection.imageId!==e.imageSelection?.imageId&&Jo("INSTANCE_IMAGE_MISMATCH",`Instance ${e.id} belongs to image ${e.imageSelection?.imageId}.`)}validateInstanceToken(e,t){e.registrationToken&&t===e.registrationToken||Jo("INSTANCE_REGISTRATION_TOKEN_INVALID",`Invalid registration token for instance ${e.id}.`)}context(e,t=this.resolvedAssignedModelEnvironment(e.id)){const n=e.imageSnapshot||yn.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});return{project:Vo(e),image:n,node:this.node,runtime:this.requireRuntime(e.runtimeId),instance:e,nodeAgentUrl:this.containerUrl,modelEnv:t}}}class hs{app;state;settings;sockets=new Set;config;source;status="error";error;constructor(e){this.app=e.app,this.state=e.state,this.settings=e.settings,this.config=e.config,this.source=e.source,this.app.server.on("connection",e=>{this.sockets.add(e),e.once("close",()=>this.sockets.delete(e))})}current(){return Tn.parse({...this.config,host:$o(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){this.status="error",this.error=e instanceof Error?e.message:String(e),this.app.log.error({host:$o(this.config.bindScope),port:this.config.port,error:this.error},"node agent TCP listener failed to start; Unix IPC remains available")}return this.current()}async update(e){const t=kn.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){const t=new Error(`Cannot change the node agent port while ${e} controlled instance(s) are running.`);throw Object.assign(t,{statusCode:409,code:"NODE_AGENT_LISTENER_PORT_IN_USE_BY_INSTANCES",blockingInstanceCount:e}),t}}const n={config:this.config,source:this.source,status:this.status,error:this.error};await this.stop();try{await this.listen(t)}catch(e){await this.restore(n);const r=new Error(`Failed to bind node agent TCP listener at ${$o(t.bindScope)}:${t.port}: ${e instanceof Error?e.message:String(e)}`);throw Object.assign(r,{statusCode:409,code:"NODE_AGENT_LISTENER_BIND_FAILED"}),r}try{this.settings.put({version:1,externalListener:t})}catch(e){await this.stop(),await this.restore(n);const t=new Error(`Failed to persist node agent TCP listener: ${e instanceof Error?e.message:String(e)}`);throw Object.assign(t,{statusCode:500,code:"NODE_AGENT_LISTENER_PERSIST_FAILED"}),t}return this.config=t,this.source="persisted",this.status="listening",this.error=void 0,this.state.setListenerPort(t.port),this.current()}async shutdown(){await this.stop()}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)}async listen(e){await new Promise((t,n)=>{const r=e=>{this.app.server.off("listening",i),n(e)},i=()=>{this.app.server.off("error",r),t()};this.app.server.once("error",r),this.app.server.once("listening",i),this.app.server.listen({host:$o(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()})}}async function fs(e,t,n,r,i,o="request"){const s=e.requireInstance(r);if(s.imageProvisioning&&"ready"!==s.imageProvisioning.phase&&"docker"===e.requireRuntime(s.runtimeId).type)return i.diagnostic({instanceId:r,action:"start",reason:o,runtimeId:s.runtimeId,imageId:s.imageSelection?.imageId,imagePhase:s.imageProvisioning.phase},"node instance start queued until image provisioning completes"),e.controlledInstances.put(Mn.parse({...s,status:"starting",updatedAt:Lo()}));i.diagnostic({instanceId:r,action:"start",reason:o,runtimeId:s.runtimeId,imageId:s.imageSelection?.imageId},"node instance start requested");const a=e.controlledInstances.put(Mn.parse({...s,status:"starting",ready:!1,updatedAt:Lo()})),c=t.forRuntime(e.requireRuntime(a.runtimeId)),d=await c.start(e.context(a)),l=await Ho(n,Mn.parse({...a,...d,target:d.target?{...a.target,...d.target}:a.target,workspace:d.workspace?{...a.workspace,error:void 0,...d.workspace}:a.workspace,runtime:d.runtime?{...a.runtime,...d.runtime}:a.runtime,updatedAt:Lo()})),u=ys(a,e.requireInstance(r),{...d,target:d.target?{...d.target,status:l}:void 0,workspace:d.workspace?{error:void 0,...d.workspace}:void 0,targetStatus:l,uiAccessStatus:l}),m=e.controlledInstances.put(u);return i.diagnostic({instanceId:r,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}function ys(e,t,n){const r=t.stateRevision>e.stateRevision&&t.lastHeartbeatAt!==e.lastHeartbeatAt&&"online"===t.agentStatus;return Mn.parse({...t,...n,...r?{status:t.status,health:t.health,connectionStatus:t.connectionStatus,agentStatus:t.agentStatus,targetStatus:t.targetStatus,uiAccessStatus:t.uiAccessStatus}:{},ready:!!r&&t.ready,target:n.target?r?{...n.target,...t.target}:{...t.target,...n.target}:t.target,workspace:n.workspace?r?{...n.workspace,...t.workspace}:{...t.workspace,...n.workspace}:t.workspace,runtime:n.runtime?{...t.runtime,...n.runtime}:t.runtime,updatedAt:Lo()})}function Is(e,t){const n=t instanceof Error?t.message:String(t);return Mn.parse({...e,status:"failed",ready:!1,health:"failed",connectionStatus:"offline",agentStatus:"offline",targetStatus:"unknown",uiAccessStatus:"unknown",workspace:{...e.workspace,error:n},updatedAt:Lo()})}function As(e){return Mn.parse({...e,health:"unknown",connectionStatus:"offline",agentStatus:"offline",targetStatus:"unknown",uiAccessStatus:"unknown",target:{...e.target,status:"unknown"},updatedAt:Lo()})}async function bs(e={}){const r=e.token||process.env.TASK_HANDOFF_NODE_AGENT_TOKEN,i=Number(e.port||process.env.TASK_HANDOFF_NODE_AGENT_PORT||"8091"),o=`http://127.0.0.1:${i}`,a=e.containerUrl||process.env.TASK_HANDOFF_NODE_AGENT_CONTAINER_URL,p=ei(e.dataDir),g=e.remoteSecret||process.env.TASK_HANDOFF_NODE_AGENT_REMOTE_SECRET,h=e.remoteKeyId||process.env.TASK_HANDOFF_NODE_AGENT_REMOTE_KEY_ID,f=new ho(p),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||li(p.dataDir),w="local-ipc"===I?`ipc://${encodeURIComponent(A)}`:o,z=e.platform||process.platform,N=e.arch||process.arch,v=new gs(p,y,o,a,i,z);v.node.connectionMode=I,v.node.controlEndpoint=w,v.node.endpoint=w,v.init();const E=e.dockerCommandRunner||Xn,S=new Zn(E,e.dockerTerminalCommandRunner),_=new er(E,{publishHost:"127.0.0.1",imageService:S}),T=new ms(new ls(_,E,z,N),new us(e.dockerCommandRunner||Xn,p,()=>v.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)),k=e.updateCommandRunner||e.dockerCommandRunner||Xn,C=e.fetchImpl||fetch,x=new xi({cacheDir:n.join(p.dataDir,"runtime-artifacts"),fetchImpl:C}),O=e.resolveRuntimeArtifactRelease||((e,t,n)=>Oi(e,t,n,C)),R=async(t,n,r)=>{const i=await n.artifactTarget(r);if(e.resolveRuntimeArtifact)return e.resolveRuntimeArtifact(t,i.platform,i.arch);const o=await O(t,i.platform,i.arch);if(o.identity.launcherAbi>i.launcherAbi)throw Object.assign(new Error(`Runtime requires launcher ABI ${o.identity.launcherAbi}, but ${i.platform}-${i.arch} provides ABI ${i.launcherAbi}.`),{code:"INSTANCE_BASE_RUNTIME_INCOMPATIBLE",retryable:!1});return x.resolve(o.identity,o.source)},D=e=>T.forRuntime(v.requireRuntime(e.runtimeId)),M=e=>{const t=D(e);return ds(t)?t:void 0},P=e=>{const t=M(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})},j=e=>Boolean(M(e)),L=(e,t)=>{const n=v.context(e);return R(t,P(e),n)},$=d({logger:e.logger??!0}),F={requests:0,active:0,completed:0,aborted:0,limitRejected:0,responseBytes:0,totalDurationMs:0,maxResponseBytes:Do()};$.decorate("nodeAgentState",v),await $.register(l);const U=new _r(v,r,{logger:$.log,safetyIntervalMs:Number(process.env.TASK_HANDOFF_EVENT_CONNECTION_SAFETY_INTERVAL_MS)||void 0}),V=new Ri(v.controlledInstances,To,{isInstalled:async(e,t)=>{const n=await L(e,t);return P(e).inspectRuntime(v.context(e),n.identity)},beginDrain:async e=>{try{const t=await async function(e,t){const n=Go(t);if(t.registrationToken&&(await qo(e,`${n}/api/internal/node-agent/drain`,{method:"POST",headers:{authorization:`Bearer ${t.registrationToken}`}},1e4)).ok)return{requested:t.apps.runningCount,failures:[]};const r=await qo(e,`${n}/api/apps/sessions`,{method:"GET",headers:{"cache-control":"no-cache"}},5e3);if(!r.ok)throw new Error(`Could not list app sessions for runtime drain (HTTP ${r.status}).`);const i=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,r=(n&&"object"==typeof n&&!Array.isArray(n)?n:t).sessions;return Array.isArray(r)?r:[]}(await r.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(i.map(async t=>{try{const r=await qo(e,`${n}/api/apps/sessions/${encodeURIComponent(t)}/stop`,{method:"POST"},5e3);return r.ok?void 0:{sessionId:t,error:`HTTP ${r.status}`}}catch(e){return{sessionId:t,error:e instanceof Error?e.message:String(e)}}}));return{requested:i.length,failures:o.filter(e=>Boolean(e))}}(C,e);t.failures.length?$.log.warn({instanceId:e.id,requested:t.requested,failures:t.failures},"runtime convergence could not stop every app session"):$.log.info({instanceId:e.id,requested:t.requested},"runtime convergence requested app session drain")}catch(t){$.log.warn({instanceId:e.id,error:t instanceof Error?t.message:String(t)},"runtime convergence could not request app session drain")}},endDrain:async e=>{try{await async function(e,t){return!!t.registrationToken&&(await qo(e,`${Go(t)}/api/internal/node-agent/resume`,{method:"POST",headers:{authorization:`Bearer ${t.registrationToken}`}},5e3)).ok}(C,e)&&$.log.info({instanceId:e.id},"runtime convergence released app session drain")}catch(t){$.log.warn({instanceId:e.id,error:t instanceof Error?t.message:String(t)},"runtime convergence could not release app session drain")}},install:async(e,t)=>{const n=P(e);await n.installRuntime(v.context(e),await L(e,t))},restart:async e=>{const t=D(e),n=v.requireInstance(e.id),r=v.controlledInstances.put(Mn.parse({...n,build:void 0,instanceVersion:void 0,ready:!1,updatedAt:Lo()})),i=await t.restart(v.context(r)),o=v.requireInstance(e.id);v.controlledInstances.put(ys(r,o,i))},onForcedDrain:e=>$.log.warn({instanceId:e.id},"runtime convergence drain deadline reached; restarting instance")},{drainTimeoutMs:Number(process.env.TASK_HANDOFF_RUNTIME_DRAIN_TIMEOUT_MS)||void 0,verificationTimeoutMs:Number(process.env.TASK_HANDOFF_RUNTIME_VERIFY_TIMEOUT_MS)||void 0,maxAttempts:Number(process.env.TASK_HANDOFF_RUNTIME_MAX_ATTEMPTS)||void 0});v.controlledInstances.setOnStored(e=>{U.publishInstanceLifecycle(e),v.updateJobs.reconcileRollouts(v.listInstances(),To())}),U.start(),$.decorate("nodeAgentEventForwarder",U);const H=new Dr(E,()=>v.listInstances().filter(e=>"docker"===v.requireRuntime(e.runtimeId).type),e=>U.publish("instance.metrics.snapshot",e,{instanceId:e.instanceId}));H.start(),$.decorate("nodeAgentRuntimeMetrics",H);const q=(re=process.env.TASK_HANDOFF_DIAGNOSTIC_LOGS,["1","true","yes","on"].includes(String(re||"").trim().toLowerCase())),B=new Gi(f,y,g,h),K=(e,t)=>{q&&$.log.info(e,t)},G={diagnostic:K,warn:(e,t)=>$.log.warn(e,t)},J=new Set,W=new Map,X=(e,t,n)=>{const r=n&&"object"==typeof n&&!Array.isArray(n)?n.protocolVersion:void 0;if("string"!=typeof r||r===Ve)return n;const i=({field:n,action:i})=>$.log.warn({instanceId:e,report:t,protocolVersion:r,expectedProtocolVersion:Ve,field:n,action:i},"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,r=["instanceId","projectId","source","nodeId","runtimeId","imageSelection","instanceVersion","protocolVersion","build","controlMode","capabilities","appInventory","target","workspace","registrationToken","processIncarnationId"],i=new Set([...r,"imageId"]);for(const e of Object.keys(n))i.has(e)||t?.({field:e,action:"ignored"});return Object.prototype.hasOwnProperty.call(n,"imageId")&&t?.({field:"imageId",action:"migrated"}),{...Vn(n,r),imageSelection:st(n.imageSelection,n.imageId)}}(n,i):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"],r=new Set(n);for(const n of Object.keys(e))r.has(n)||t?.({field:n,action:"ignored"});return Vn(e,n)}(n,i)},Y=async(e,t)=>{try{let n=v.requireInstance(e);"failed"===n.runtimeVersion?.phase&&j(n)&&(n=v.controlledInstances.put(Mn.parse({...n,ready:!1,runtimeVersion:ko(Di(n)),updatedAt:Lo()})));const r=v.requireRuntime(n.runtimeId);await fs(v,T,C,e,G);const i=v.requireInstance(e);if("docker"===r.type&&"ready"!==i.imageProvisioning?.phase)return U.syncNow(),i;J.add(e),W.delete(e);let o=v.requireInstance(e);if(j(o)){try{o=await V.schedule(e,{startRequested:!0})}catch(n){o=v.requireInstance(e),G.warn({instanceId:e,action:"runtime.converge",reason:t,error:n instanceof Error?n.message:String(n)},"node instance runtime convergence failed after start")}"failed"===o.runtimeVersion?.phase&&G.warn({instanceId:e,action:"runtime.converge",reason:t,error:o.runtimeVersion.error},"node instance started with failed runtime convergence")}return await Bo(C,o,"start",G),U.syncNow(),o}catch(n){const r=Is(v.requireInstance(e),n);throw v.controlledInstances.put(r),U.syncNow(),G.warn({instanceId:e,action:"start",reason:t,error:n instanceof Error?n.message:String(n)},"node instance start failed"),n}},Z=e=>{e.imageProvisioning&&async function(t,n,r,i,o,s,a){const c=e=>{const n=t.controlledInstances.get(r);n&&n.imageProvisioning?.generation===i&&n.imageSnapshot&&(t.controlledInstances.put(Mn.parse({...n,status:"starting"===n.status?"starting":"provisioning",imageProvisioning:{...n.imageProvisioning,phase:e,error:void 0,updatedAt:Lo()},updatedAt:Lo()})),o())},d=t.controlledInstances.get(r);if(!d?.imageSnapshot||d.imageProvisioning?.generation!==i)return;let l=0,u=!1;try{const m=await n.ensure(d.imageSnapshot.requestedReference,c,e=>{u=!0,l=e.sequence,a?.(e)});u&&a?.({sequence:l+1,outcome:"succeeded"});const p=t.controlledInstances.get(r);if(!p?.imageSnapshot||p.imageProvisioning?.generation!==i)return;t.controlledInstances.put(Mn.parse({...p,status:"starting"===p.status?"starting":"created",health:"unknown",imageSnapshot:{...p.imageSnapshot,requestedReference:m.requestedReference,resolvedDigest:m.resolvedDigest,resolvedReference:m.resolvedReference},imageProvisioning:{...p.imageProvisioning,phase:"ready",error:void 0,updatedAt:Lo()},updatedAt:Lo()})),o(),s.diagnostic({instanceId:r,action:"image.provision",reference:m.requestedReference,digest:m.resolvedDigest,pulled:m.pulled},"node instance image provisioning completed"),"starting"===p.status&&await((async e=>{await Y(e,"image-ready").catch(()=>{})})(e.id))}catch(e){u&&a?.({sequence:l+1,outcome:"failed"});const n=t.controlledInstances.get(r);if(!n?.imageProvisioning||n.imageProvisioning.generation!==i)return;const c=e instanceof Error?e.message:String(e);t.controlledInstances.put(Mn.parse({...n,status:"failed",health:"failed",imageProvisioning:{...n.imageProvisioning,phase:"failed",error:c,updatedAt:Lo()},updatedAt:Lo()})),o(),s.warn({instanceId:r,action:"image.provision",reference:n.imageProvisioning.requestedReference,error:c},"node instance image provisioning failed")}}(v,S,e.id,e.imageProvisioning.generation,()=>U.syncNow(),G,t=>{const n={instanceId:e.id,generation:e.imageProvisioning.generation,requestedReference:e.imageProvisioning.requestedReference,observedAt:Lo()};if("outcome"in t)U.publish(bn,{...n,sequence:1e3*t.sequence,outcome:t.outcome},{instanceId:e.id});else for(const[r,i]of function(e,t=6e4){const n=[];for(let r=0;r<e.length;r+=t)n.push(e.slice(r,r+t));return n}(t.data).entries())U.publish(An,{...n,sequence:1e3*t.sequence+r,data:i,...t.replay?{replay:!0}:{}},{instanceId:e.id})})},Q=async e=>{const t=new Map;for(const e of T.managedAdapters()){const n=await e.artifactTarget();t.set(`${n.platform}-${n.arch}`,{adapter:e})}for(const e of v.listInstances()){const n=M(e);if(!n)continue;const r=v.context(e),i=await n.artifactTarget(r);t.set(`${i.platform}-${i.arch}`,{adapter:n,context:r})}return(await Promise.all([...t.values()].map(({adapter:t,context:n})=>R(e,t,n)))).sort((e,t)=>`${e.identity.platform}/${e.identity.arch}`.localeCompare(`${t.identity.platform}/${t.identity.arch}`))},ee=async e=>{const t=te(),n=await wi(k),r="@task-handoff/server"===n.packageName?[...new Set([...n.relatedCurrentVersions,To()])]:n.relatedCurrentVersions,i=await async function(e){const t=e.packageName||"@task-handoff/node-agent",n=await async function(e,t,n){const r=function(e){return"stable"===e?"latest":e}(n),i=await e(Ai(),["view",`${t}@${r}`,"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(!i)return;const o=JSON.parse(i.stdout);if("string"!=typeof o)throw new Error(`npm did not resolve ${t}@${r} to one version.`);return o}(e.runCommand,t,e.channel);if(!n)return function(e){return Mt.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:yi()})}({channel:e.channel,currentVersion:e.currentVersion,impact:e.impact});const r=Ii(e.currentVersion,n)||(e.relatedCurrentVersions||[]).some(e=>Ii(e,n)),i=r?await async function(e,t,n){const r=await e(Ai(),["view",`${t}@${n}`,"dist.integrity","--json"]),i=JSON.parse(r.stdout);if("string"!=typeof i||!/^sha(?:256|384|512)-[A-Za-z0-9+/=]+$/.test(i))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 i}(e.runCommand,t,n):void 0;return Mt.parse({source:"npm",channel:e.channel,currentVersion:e.currentVersion,availableVersion:n,...i?{artifactRef:`npm:${t}@${n}#${i}`}:{},runtimeArtifacts:e.runtimeArtifacts||[],impact:e.impact||{runningInstanceCount:0,stoppedInstanceCount:0,activeInstanceCount:0,restartInstanceCount:0,runningInstanceIds:[],stoppedInstanceIds:[],activeInstanceIds:[]},updateAvailable:r,checkedAt:yi()})}({channel:e.channel,currentVersion:n.currentVersion||To(),runCommand:k,packageName:n.packageName,relatedCurrentVersions:r,impact:t});if(!i.updateAvailable)return i;const o=await Q(i.availableVersion),s={...i,runtimeArtifacts:o.map(e=>e.identity),preflightToken:ai()};return ne.set(s.preflightToken,{result:s,expiresAt:Date.now()+6e5}),s},te=()=>{const e=v.listInstances(),t=e.filter(e=>!["created","stopped","failed"].includes(e.status)),n=t.filter(e=>e.apps.runningCount>0||e.aiSessions.runningCount>0);return{runningInstanceCount:t.length,stoppedInstanceCount:e.length-t.length,activeInstanceCount:n.length,restartInstanceCount:t.length,runningInstanceIds:t.map(e=>e.id).sort(),stoppedInstanceIds:e.filter(e=>!t.includes(e)).map(e=>e.id).sort(),activeInstanceIds:n.map(e=>e.id).sort()}},ne=new Map;var re;let ie;$.setErrorHandler((e,t,n)=>{const r=function(e){if(e instanceof m.z.ZodError)return{statusCode:400,code:"VALIDATION_ERROR",message:e.issues.map(e=>`${e.path.join(".")||"body"}: ${e.message}`).join("; ")};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)}}(e);(q||r.statusCode>=500)&&(r.statusCode>=500?$.log.error.bind($.log):$.log.warn.bind($.log))({method:t.method,url:t.url,statusCode:r.statusCode,errorCode:r.code,error:r.message},"node agent request failed"),n.code(r.statusCode).send({error:{code:r.code,message:r.message,...e&&"object"==typeof e&&"string"==typeof e.expectedVersion?{expectedVersion:e.expectedVersion}:{},...e&&"object"==typeof e&&"string"==typeof e.actualVersion?{actualVersion:e.actualVersion}:{},...e&&"object"==typeof e&&"string"==typeof e.phase?{phase:e.phase}:{},...e&&"object"==typeof e&&"boolean"==typeof e.retryable?{retryable:e.retryable}:{},...e&&"object"==typeof e&&"number"==typeof e.blockingInstanceCount?{blockingInstanceCount:e.blockingInstanceCount}:{}}})}),$.addHook("preHandler",async e=>{const t=B.verify(e);if(t)e.nodeAgentAuthKeyId=t;else if(jo(e)){if(r&&Mo(e.headers)!==r){const e=new Error("Invalid node agent token.");throw Object.assign(e,{statusCode:401,code:"NODE_AGENT_UNAUTHORIZED"}),e}}else if("/api/node-agent/pairing/complete"!==e.url.split("?")[0]&&!function(e){const t=e.split("?")[0];return/^\/api\/node-agent\/instances\/[^/]+\/(register|heartbeat)$/.test(t)}(e.url)){if(B.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 Po(e.ip)||Po(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(r&&Mo(e.headers)!==r){const e=new Error("Invalid node agent token.");throw Object.assign(e,{statusCode:401,code:"NODE_AGENT_UNAUTHORIZED"}),e}}});let oe=!1,se=!1;$.addHook("onClose",async()=>{se=!0,ie&&clearTimeout(ie),H.stop(),U.stop();for(const e of v.listInstances())V.cancel(e.id);await async function(e,t){await t.stopAll();for(const t of e.listInstances())"local"===e.requireRuntime(t.runtimeId).type&&e.controlledInstances.put(As(t))}(v,T)});const ae=async()=>{for(const e of v.listInstances().filter(e=>["provisioning","starting"].includes(e.status)&&"ready"!==e.imageProvisioning?.phase&&"docker"===v.requireRuntime(e.runtimeId).type))Z(e);const e=v.listInstances().filter(e=>{if(J.has(e.id))return!1;const t=v.requireRuntime(e.runtimeId);return"local"===t.type?as.has(e.status):"docker"===t.type&&(as.has(e.status)||"provisioning"===e.status&&"ready"===e.imageProvisioning?.phase)});for(const t of e)try{await fs(v,T,C,t.id,G,"restore"),await Bo(C,v.requireInstance(t.id),"start",G),J.add(t.id),W.delete(t.id)}catch(e){"local"===v.requireRuntime(t.runtimeId).type&&v.controlledInstances.put(Is(v.requireInstance(t.id),e));const n=e instanceof Error?e.message:String(e);W.get(t.id)!==n&&(W.set(t.id,n),G.warn({instanceId:t.id,action:"restore",runtimeId:t.runtimeId,error:n},"node instance restore failed; recovery will retry"))}},ce=async()=>{const e=v.listInstances().filter(e=>j(e)&&!V.isRunning(e.id)&&(J.has(e.id)||"unknown"!==e.target.status)&&(!e.ready||"matched"!==e.runtimeVersion?.phase)&&!["created","stopped","failed","provisioning","stopping"].includes(e.status));await Promise.all(e.map(async e=>{try{await V.schedule(e.id)}catch(t){$.log.error({instanceId:e.id,error:t},"runtime convergence recovery failed")}}))};$.decorate("nodeAgentRestoreManagedInstances",ae),$.decorate("nodeAgentRecoverManagedInstances",ce),$.decorate("nodeAgentStartRecoverySupervisor",()=>{if(oe)return;oe=!0;const e=()=>{(async()=>{await ae(),await ce()})().catch(e=>$.log.error({error:e},"node agent startup recovery cycle failed")).finally(t)},t=()=>{se||(ie=setTimeout(()=>{ie=void 0,e()},1e4),ie.unref?.())};e()}),$.get("/api/node-agent/health",async()=>{return{data:{ok:!0,role:"node-agent",nodeId:y,platform:zo(z),arch:process.arch,protocolVersion:Ve,build:(e="node-agent",{component:e,packageName:"@task-handoff/node-agent",packageVersion:To(),protocolVersion:Ve,buildId:_o("TASK_HANDOFF_BUILD_ID"),builtAt:_o("TASK_HANDOFF_BUILT_AT"),gitCommit:_o("TASK_HANDOFF_GIT_COMMIT"),imageRef:_o("TASK_HANDOFF_IMAGE_REF"),imageDigest:_o("TASK_HANDOFF_IMAGE_DIGEST")}),instanceProxy:{...F},serverTime:(new Date).toISOString()}};var e});const de=e=>{if(!jo(e)){const e=new Error("Node agent TCP listener settings are available only over local Unix IPC.");throw Object.assign(e,{statusCode:403,code:"NODE_AGENT_LISTENER_LOCAL_IPC_ONLY"}),e}if(!$.nodeAgentListenerManager){const e=new Error("Node agent TCP listener manager is not initialized.");throw Object.assign(e,{statusCode:503,code:"NODE_AGENT_LISTENER_UNAVAILABLE"}),e}return $.nodeAgentListenerManager};return $.get("/api/node-agent/settings/external-listener",async e=>({data:de(e).current()})),$.patch("/api/node-agent/settings/external-listener",async e=>({data:await de(e).update(e.body)})),$.get("/api/node-agent/updates/jobs",async()=>({data:v.updateJobs.list()})),$.post("/api/node-agent/updates/check",async e=>({data:await ee(Dt.parse(e.body))})),$.post("/api/node-agent/updates/apply",async(e,r)=>{const i=So.parse(e.body),o=await(async e=>{const t=ne.get(e.preflightToken);if(ne.delete(e.preflightToken),!t||t.expiresAt<=Date.now()){const e=new Error("The update preflight is missing or expired. Check for updates again.");throw Object.assign(e,{statusCode:409,code:"UPDATE_PREFLIGHT_EXPIRED"}),e}const n=t.result,r=await wi(k);if(n.channel!==e.channel||n.availableVersion!==e.targetVersion||n.currentVersion!==(r.currentVersion||To())||!0!==n.artifactRef?.startsWith(`npm:${r.packageName}@`)||JSON.stringify(n.impact)!==JSON.stringify(te())){const e=new Error("The update target or affected instances changed after preflight. Check for updates again.");throw Object.assign(e,{statusCode:409,code:"UPDATE_PREFLIGHT_STALE"}),e}const i=await Q(n.availableVersion);if(JSON.stringify(n.runtimeArtifacts)!==JSON.stringify(i.map(e=>e.identity))){const e=new Error("The runtime artifacts changed after preflight. Check for updates again.");throw Object.assign(e,{statusCode:409,code:"UPDATE_PREFLIGHT_STALE"}),e}return n})(i);if(!o.supported){const e=new Error(o.reason||"The requested update is not supported.");throw Object.assign(e,{statusCode:400,code:"UPDATE_UNSUPPORTED"}),e}if(!o.updateAvailable){const e=new Error(o.reason||"No update is available for the selected channel.");throw Object.assign(e,{statusCode:409,code:"UPDATE_NOT_AVAILABLE"}),e}const a=v.updateJobs.create(y,o),c=("undefined"==typeof document?require("url").pathToFileURL(__filename).href:b&&"SCRIPT"===b.tagName.toUpperCase()&&b.src||new URL("cli.js",document.baseURI).href)?n.dirname(s.fileURLToPath("undefined"==typeof document?require("url").pathToFileURL(__filename).href:b&&"SCRIPT"===b.tagName.toUpperCase()&&b.src||new URL("cli.js",document.baseURI).href)):__dirname,{worker:d,packaged:l,expectedWorker:u}=function(e,r=t.existsSync){const i=[n.resolve(e,"..","bin","task-handoff-node-update-worker"),n.resolve(e,"..","..","bin","task-handoff-node-update-worker")],o=i.find(r),s=n.resolve(e,"..","..","..","..","scripts","node-update-worker.cjs");return o?{worker:o,packaged:!0,expectedWorker:i[0]}:r(s)?{worker:s,packaged:!1,expectedWorker:i[0]}:{worker:void 0,packaged:!1,expectedWorker:i[0]}}(c);if(!d){v.updateJobs.patch(a.id,{status:"failed",rollout:{...a.rollout,phase:"failed"},error:{code:"NODE_UPDATE_FAILED",message:`Update worker was not found: ${u}`,retryable:!1},completedAt:Lo()});const e=new Error(`Node agent update worker was not found: ${u}`);throw Object.assign(e,{statusCode:500,code:"UPDATE_WORKER_NOT_FOUND"}),e}return await k("systemd-run",["--unit",`task-handoff-update-${a.id}`,"--collect","--property=Type=exec",...l?[d]:[process.execPath,d],"--job-file",v.updateJobs.records.filePath(a.id),"--target-version",a.toVersion,"--npm-command",Ai(),..._o("TASK_HANDOFF_CONTROL_PLANE_HEALTH_URL")?["--control-plane-health-url",_o("TASK_HANDOFF_CONTROL_PLANE_HEALTH_URL")]:[]]),r.code(202).send({data:a})}),$.post("/api/node-agent/pairing/invites",async(e,t)=>{const n=f.createPairingInvite(eo.parse(e.body||{}));return t.code(201).send({data:{nodeId:y,joinToken:n.token,expiresAt:n.expiresAt}})}),$.post("/api/node-agent/pairing/complete",async(e,t)=>{const n=f.completePairingInvite(to.parse(e.body));return t.code(201).send({data:{nodeId:y,keyId:n.keyId,secret:n.secret,pairedAt:n.pairedAt}})}),$.get("/api/node-agent/remotes",async e=>({data:f.listRemoteControlPlanes(e.nodeAgentAuthKeyId)})),$.delete("/api/node-agent/remotes/:keyId",async e=>{const t=m.z.string().trim().min(1).max(160).parse(e.params.keyId),n=f.deleteRemoteControlPlane(t,e.nodeAgentAuthKeyId);return n&&$.nodeAgentReverseTunnels?.connectConfigured(),{data:{deleted:n}}}),$.post("/api/node-agent/remotes/connect",async(e,t)=>{const n=no.parse(e.body),r=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(/\/$/,"")}(n.controlPlaneUrl),i=f.createRemoteControlPlane({url:r,...n.controlPlaneName?{name:n.controlPlaneName}:{},active:!1!==n.activate}),o=await async function(e,t,n){const r=await e(new URL("/api/node-join/complete",t).toString(),{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(n)}),i=await r.json().catch(()=>({}));if(!r.ok){const e=new Error(i.error?.message||`Control-plane node join failed with HTTP ${r.status}.`);throw Object.assign(e,{statusCode:r.status,code:i.error?.code||"NODE_AGENT_REMOTE_JOIN_FAILED"}),e}return i.data||{}}(C,r,{joinToken:n.joinToken,nodeId:y,nodeName:v.node.name,keyId:i.keyId,secret:i.secret,pairedAt:i.pairedAt}),s=f.upsertRemoteControlPlane({...i,..."string"==typeof o.name&&o.name?{name:n.controlPlaneName||o.name}:{}});let a,c=!1!==s.active?"saved":"disabled";if(!1!==s.active&&$.nodeAgentReverseTunnels)try{$.nodeAgentReverseTunnels.connect({url:r,keyId:s.keyId,secret:s.secret}),c="connecting"}catch(e){c="failed",a=e instanceof Error?e.message:String(e)}return t.code(201).send({data:{remote:{id:s.id,url:s.url,keyId:s.keyId,pairedAt:s.pairedAt,active:!1!==s.active},tunnel:{status:c,...a?{error:a}:{}}}})}),$.get("/api/node-agent/runtimes",async()=>({data:v.nodeRuntimes.list()})),$.post("/api/node-agent/runtimes",async(e,t)=>t.code(201).send({data:v.createRuntime(Yr.parse(e.body))})),$.patch("/api/node-agent/runtimes/:id",async e=>({data:v.updateRuntime(e.params.id,Zr.parse(e.body))})),$.delete("/api/node-agent/runtimes/:id",async e=>({data:{deleted:v.deleteRuntime(e.params.id)}})),$.post("/api/node-agent/runtimes/:id/check",async e=>{const t=v.requireRuntime(e.params.id);return{data:await v.checkRuntime(t.id,T.forRuntime(t))}}),$.get("/api/node-agent/local-folders",async()=>({data:v.localFolders.list()})),$.get("/api/node-agent/folders/tree",async e=>({data:Br(Jr.parse(e.query))})),$.post("/api/node-agent/local-folders",async(e,t)=>t.code(201).send({data:v.createLocalFolder(Gr.parse(e.body))})),$.delete("/api/node-agent/local-folders/:id",async e=>({data:{deleted:v.localFolders.delete(e.params.id)}})),$.get("/api/node-agent/models",async()=>({data:v.listModels()})),$.post("/api/node-agent/models",async(e,t)=>t.code(201).send({data:v.createModel(en.parse(e.body))})),$.put("/api/node-agent/models/:id/deploy",async e=>{const t=e.params.id,n=nn.parse(e.body);if(n.id!==t)throw Object.assign(new Error(`Model payload id ${n.id} does not match route id ${t}.`),{statusCode:400,code:"NODE_MODEL_ID_MISMATCH"});return{data:v.deployModel(n)}}),$.patch("/api/node-agent/models/:id",async e=>({data:v.updateModel(e.params.id,tn.parse(e.body))})),$.delete("/api/node-agent/models/:id",async e=>({data:{deleted:v.deleteModel(e.params.id)}})),$.get("/api/node-agent/instances",async()=>({data:v.listInstances()})),$.post("/api/node-agent/instances",async(e,t)=>{const n=v.createInstance(Wr.parse(e.body));return U.syncNow(),n.imageProvisioning&&Z(n),t.code(201).send({data:n})}),$.post("/api/node-agent/instances/:id/image-provisioning/retry",async e=>{const t=function(e,t){const n=e.requireInstance(t);if("docker"!==e.requireRuntime(n.runtimeId).type||!n.imageSnapshot){const e=new Error(`Instance ${t} does not use a Docker image.`);throw Object.assign(e,{statusCode:400,code:"INSTANCE_IMAGE_PROVISIONING_UNSUPPORTED"}),e}if("failed"!==n.status||"failed"!==n.imageProvisioning?.phase){const e=new Error(`Instance ${t} does not have failed image provisioning to retry.`);throw Object.assign(e,{statusCode:409,code:"INSTANCE_IMAGE_PROVISIONING_NOT_FAILED"}),e}const r=Lo();return e.controlledInstances.put(Mn.parse({...n,status:"provisioning",health:"unknown",imageProvisioning:{phase:"checking-image",requestedReference:n.imageSnapshot.requestedReference,generation:(n.imageProvisioning?.generation||0)+1,startedAt:r,updatedAt:r},updatedAt:r}))}(v,e.params.id);return U.syncNow(),Z(t),{data:t}}),$.patch("/api/node-agent/instances/:id",async e=>{const t=e.params.id,n=v.requireInstance(t),r=Xr.parse(e.body),i=Mn.parse({...n,...r,...r.config?{config:{...n.config,...r.config}}:{},updatedAt:Lo()}),o=v.controlledInstances.put(i);return U.syncNow(),{data:o}}),$.put("/api/node-agent/instances/:id/model-assignment",async e=>{const t=e.params.id,n=v.assignModels(t,rn.parse(e.body));return await Ko(C,v,t),{data:n}}),$.post("/api/node-agent/instances/:id/register",async(e,t)=>{const n=e.params.id,r=X(n,"register",e.body),i=v.registerInstance(n,Hn.parse(r),Mo(e.headers));return U.syncNow(),K({instanceId:n,action:"register",protocolVersion:i.protocolVersion,build:i.build,targetStatus:i.targetStatus,targetStrategy:i.target.strategy},"node instance registered"),!j(i)||i.ready&&"matched"===i.runtimeVersion?.phase||V.schedule(n).catch(e=>$.log.error({instanceId:n,error:e},"runtime convergence after registration failed")),t.code(201).send({data:i})}),$.post("/api/node-agent/instances/:id/heartbeat",async e=>{const t=e.params.id,n=X(t,"heartbeat",e.body),r=v.heartbeatInstance(t,qn.parse(n),Mo(e.headers));return U.syncNow(),K({instanceId:t,action:"heartbeat",status:r.status,health:r.health,protocolVersion:r.protocolVersion,build:r.build,targetStatus:r.targetStatus,apps:r.apps.runningCount},"node instance heartbeat accepted"),!j(r)||r.ready&&"matched"===r.runtimeVersion?.phase||V.schedule(t).catch(e=>$.log.error({instanceId:t,error:e},"runtime convergence after heartbeat failed")),{data:r}}),$.get("/api/node-agent/events",{websocket:!0},e=>{const t=e;t.send(JSON.stringify({type:"node-agent.events.connected",nodeId:y,serverTime:(new Date).toISOString()}));const n=U.addOutput(t);t.on("close",n),t.on("error",n)}),$.get("/api/node-agent/docker/images",async()=>({data:await cr(e.dockerCommandRunner)})),$.get("/api/node-agent/instances/:id/metrics",async e=>{const t=e.params.id,n=v.requireInstance(t);if("docker"!==v.requireRuntime(n.runtimeId).type){const e=new Error(`Runtime type ${v.requireRuntime(n.runtimeId).type} does not provide resource metrics.`);throw Object.assign(e,{statusCode:409,code:"INSTANCE_METRICS_UNSUPPORTED"}),e}return{data:await H.snapshot(t)}}),$.post("/api/node-agent/instances/:id/start",async e=>{const t=e.params.id;return Eo.parse(e.body),{data:await Y(t,"request")}}),$.post("/api/node-agent/instances/:id/runtime/reconcile",async e=>{const t=e.params.id;Eo.parse(e.body);const n=v.requireInstance(t);v.controlledInstances.put(Mn.parse({...n,ready:!1,runtimeVersion:ko(Di(n)),updatedAt:Lo()}));const r=await V.schedule(t,{startRequested:!["created","stopped"].includes(n.status),resumeCancelled:!0});return U.syncNow(),{data:r}}),$.post("/api/node-agent/instances/:id/stop",async e=>{const t=e.params.id;await V.cancel(t);const n=v.requireInstance(t);K({instanceId:n.id,action:"stop",runtimeId:n.runtimeId,containerName:n.runtime.containerName},"node instance stop requested");const r=T.forRuntime(v.requireRuntime(n.runtimeId)),i=await r.stop(v.context(n)),o=Mn.parse({...n,...i,ready:!1,agentStatus:"offline",targetStatus:"unknown",uiAccessStatus:"unknown",updatedAt:Lo()}),s=v.controlledInstances.put(o);return U.syncNow(),K({instanceId:n.id,action:"stop",status:s.status,connectionStatus:s.connectionStatus,containerName:s.runtime.containerName},"node instance stop completed"),{data:s}}),$.post("/api/node-agent/instances/:id/restart",async e=>{const t=e.params.id;let n=v.requireInstance(t);if(Eo.parse(e.body),j(n)&&(!n.ready||"matched"!==n.runtimeVersion?.phase)){"failed"===n.runtimeVersion?.phase&&(n=v.controlledInstances.put(Mn.parse({...n,runtimeVersion:ko(Di(n)),updatedAt:Lo()})));const e=await V.schedule(t,{startRequested:!0});return U.syncNow(),{data:e}}K({instanceId:t,action:"restart",runtimeId:n.runtimeId,imageId:n.imageSelection?.imageId,containerName:n.runtime.containerName},"node instance restart requested");const r=T.forRuntime(v.requireRuntime(n.runtimeId)),i=await r.restart(v.context(n)),o=Mn.parse({...n,...i,target:i.target?{...n.target,...i.target}:n.target,updatedAt:Lo()}),s=await Ho(C,o),a=ys(n,v.requireInstance(t),{...i,target:i.target?{...i.target,status:s}:void 0,targetStatus:s,uiAccessStatus:s}),c=v.controlledInstances.put(a);return J.add(t),W.delete(t),await Bo(C,c,"restart",G),U.syncNow(),K({instanceId:t,action:"restart",status:c.status,connectionStatus:c.connectionStatus,targetStatus:c.targetStatus,targetWeb:c.target.web,containerName:c.runtime.containerName},"node instance restart completed"),{data:c}}),$.post("/api/node-agent/instances/:id/delete",async e=>{const t=e.params.id,n=v.requireInstance(t);await V.cancel(t),K({instanceId:t,action:"delete",runtimeId:n.runtimeId,containerName:n.runtime.containerName},"node instance delete requested");const r=T.forRuntime(v.requireRuntime(n.runtimeId));await r.delete(v.context(n,{})),K({instanceId:t,action:"delete"},"node instance delete completed");const i=v.controlledInstances.delete(t);return v.modelAssignments.delete(t),v.modelEnvironments.delete(t),U.syncNow(),{data:{deleted:i}}}),$.post("/api/node-agent/instances/:id/proxy",async(e,t)=>{const n=e.params.id,r=Kr.parse(e.body),i=Go(v.requireInstance(n)),o=r.path.startsWith("/")?r.path:`/${r.path}`;"POST"===r.method&&"/api/apps/sessions"===o&&await Ko(C,v,n),K({instanceId:n,action:"proxy",method:r.method,path:o,instanceBase:i},"node instance proxy requested");const s=await C(`${i}${o}`,{method:r.method,headers:{...r.headers},body:Oo(r)}),a=s.headers.get("content-type")||"application/octet-stream",c=await s.text();K({instanceId:n,action:"proxy",method:r.method,path:o,statusCode:s.status,contentType:a},"node instance proxy completed"),t.code(s.status).type(a).send(c)}),$.post("/api/node-agent/instances/:id/proxy/stream",{bodyLimit:Ro},async(e,t)=>{const n=Date.now();F.requests+=1,F.active+=1;const r=new AbortController;let i=0,o=!1,s=!1;const a=e=>{s||(s=!0,F.active-=1,F.totalDurationMs+=Date.now()-n,F.responseBytes+=i,F[e]+=1)},d=()=>{r.abort(),o&&a("aborted")};e.raw.once("aborted",d),t.raw.once("close",d);try{const n=e.params.id,s=Kr.parse(e.body),d=Go(v.requireInstance(n)),l=s.path.startsWith("/")?s.path:`/${s.path}`;K({instanceId:n,action:"proxy.stream",method:s.method,path:l,instanceBase:d},"node instance streaming proxy requested");const u=await C(`${d}${l}`,{method:s.method,headers:{...s.headers},body:Oo(s),signal:r.signal}),m=Number(u.headers.get("content-length"));if(Number.isFinite(m)&&m>F.maxResponseBytes)return F.limitRejected+=1,r.abort(),t.code(502).send({error:{code:"INSTANCE_PROXY_RESPONSE_TOO_LARGE",message:`Instance response exceeds ${F.maxResponseBytes} bytes.`}});t.code(u.status);for(const[e,n]of Object.entries(xo(u.headers)))t.header(e,n);if(!u.body||"HEAD"===s.method)return a("completed"),t.send();const p=new c.Transform({transform(e,t,n){if(i+=e.length,i>F.maxResponseBytes)return F.limitRejected+=1,r.abort(),void n(Object.assign(new Error("Instance proxy response limit exceeded."),{code:"INSTANCE_PROXY_RESPONSE_TOO_LARGE"}));n(null,e)}});return o=!0,p.once("end",()=>a("completed")),p.once("error",()=>a("aborted")),t.send(c.Readable.fromWeb(u.body).pipe(p))}catch(e){throw a("aborted"),e}finally{e.raw.off("aborted",d),o||a("completed")}}),$.post("/api/node-agent/instances/:id/proxy/raw",{bodyLimit:Ro},async(e,t)=>{const n=e.params.id,r=Kr.parse(e.body),i=Go(v.requireInstance(n)),o=r.path.startsWith("/")?r.path:`/${r.path}`;K({instanceId:n,action:"proxy.raw",method:r.method,path:o,instanceBase:i},"node instance raw proxy requested");const s=await C(`${i}${o}`,{method:r.method,headers:{...r.headers},body:Oo(r)}),a=Number(s.headers.get("content-length"));if(Number.isFinite(a)&&a>F.maxResponseBytes)return F.limitRejected+=1,t.code(502).send({error:{code:"INSTANCE_PROXY_RESPONSE_TOO_LARGE",message:`Instance response exceeds ${F.maxResponseBytes} bytes.`}});let c;try{c=await async function(e,t){if(!e.body)return Buffer.alloc(0);const n=[];let r=0;const i=e.body.getReader();for(;;){const{done:e,value:o}=await i.read();if(e)break;if(r+=o.byteLength,r>t)throw await i.cancel("Instance proxy response limit exceeded.").catch(()=>{}),Object.assign(new Error("Instance proxy response limit exceeded."),{code:"INSTANCE_PROXY_RESPONSE_TOO_LARGE"});n.push(Buffer.from(o))}return Buffer.concat(n,r)}(s,F.maxResponseBytes)}catch(e){if(!(e instanceof Error)||"INSTANCE_PROXY_RESPONSE_TOO_LARGE"!==e.code)throw e;return F.limitRejected+=1,t.code(502).send({error:{code:"INSTANCE_PROXY_RESPONSE_TOO_LARGE",message:`Instance response exceeds ${F.maxResponseBytes} bytes.`}})}return K({instanceId:n,action:"proxy.raw",method:r.method,path:o,statusCode:s.status,byteLength:c.length},"node instance raw proxy completed"),{data:{status:s.status,headers:xo(s.headers),bodyBase64:c.toString("base64")}}}),$.get("/api/node-agent/instances/:id/proxy/ws/*",{websocket:!0},(e,t)=>{const n=t.params.id,r=t.params["*"]||"",i=t.url.indexOf("?"),o=i>=0?t.url.slice(i):"";let s;try{const i=Go(v.requireInstance(n)),a=new URL(`/${r}${o}`,`${i}/`);a.protocol="https:"===a.protocol?"wss:":"ws:";const c=function(e){const t=e["sec-websocket-protocol"],n=(Array.isArray(t)?t.join(","):"string"==typeof t?t:"").split(",").map(e=>e.trim()).filter(Boolean);return n.length?n:void 0}(t.headers);K({instanceId:n,action:"proxy.ws",path:`/${r}${o}`,upstreamUrl:a.toString(),protocols:c||[]},"node instance websocket proxy opening"),s=c?new u(a,c):new u(a),s.on("open",()=>{K({instanceId:n,action:"proxy.ws",path:`/${r}${o}`},"node instance websocket proxy opened"),e.on("message",(e,t)=>s?.readyState===u.OPEN&&s.send(function(e,t){return t?e:e.toString()}(e,t))),e.on("close",()=>s?.close()),e.on("error",()=>s?.close())}),s.on("message",(t,n)=>{e.readyState===u.OPEN&&e.send(n?t:t.toString())}),s.on("close",()=>{K({instanceId:n,action:"proxy.ws",path:`/${r}${o}`},"node instance websocket proxy closed"),e.close()}),s.on("error",t=>{K({instanceId:n,action:"proxy.ws",path:`/${r}${o}`,error:t instanceof Error?t.message:String(t)},"node instance websocket proxy failed"),e.close(1011,"Instance websocket proxy failed.")})}catch(t){K({instanceId:n,action:"proxy.ws",path:`/${r}${o}`,error:t instanceof Error?t.message:String(t)},"node instance websocket endpoint unavailable"),s?.close(),e.close(1011,"Instance websocket endpoint is not reachable.")}}),$}function ws(e){const t=new URL("/api/node-agent/tunnel",e);return t.protocol="https:"===t.protocol?"wss:":"ws:",t.toString()}function zs(e,t,n,r){const i=t.token||process.env.TASK_HANDOFF_NODE_AGENT_TOKEN,o=new ho(n),s=new Map;let a=!1;const c=(t,n)=>{const o=function(e,t){const n=new URL(t.tunnelUrl);n.searchParams.set("nodeId",t.nodeId);const r=t.secret?gi({nodeId:t.nodeId,keyId:t.keyId,secret:t.secret,method:"GET",pathWithQuery:`${n.pathname}${n.search}`}):{},i=new u(n,{headers:r}),o=new Map,s=new Map;let a;i.on("error",r=>{e.log.warn({nodeId:t.nodeId,tunnelUrl:`${n.origin}${n.pathname}`,error:r instanceof Error?r.message:String(r)},"node agent reverse tunnel connection failed")});const c=e=>{const n=e.startsWith("/")?e:`/${e}`,r="function"==typeof t.port?t.port():t.port,i=new URL(`/api/node-agent${n}`,`http://127.0.0.1:${r}`);return i.protocol="ws:",i},d=e=>t.secret?gi({nodeId:t.nodeId,keyId:t.keyId,secret:t.secret,method:"GET",pathWithQuery:`${e.pathname}${e.search}`}):{},l=(e,t=1e3,n="")=>{const r=o.get(e);o.delete(e),r?.upstream?.close(t,n),r?.tunnel?.close(t,n)},m=(e,t,n=!1)=>new Promise((r,i)=>{e.send(t,{binary:n},e=>e?i(e):r())});return i.on("open",()=>{i.send(JSON.stringify({type:"node-agent.identify",nodeId:t.nodeId,serverTime:(new Date).toISOString()})),a=e.nodeAgentEventForwarder?.addOutput(i)}),i.on("close",()=>{for(const e of o.keys())l(e,1001,"Reverse tunnel disconnected.");for(const[e,t]of s)s.delete(e),t.controller.abort(),t.tunnel.close(1001,"Reverse tunnel disconnected.");a?.(),a=void 0}),i.on("message",async r=>{let a;try{a=JSON.parse(String(r))}catch{return void i.send(JSON.stringify({type:"node-agent.error",code:"INVALID_JSON"}))}const p=a&&"object"==typeof a?a:{};if("control-plane.http.open"===p.type){const e="string"==typeof p.streamId?p.streamId:"",r="string"==typeof p.route&&p.route.startsWith("/")?p.route:"/health",i=p.init&&"object"==typeof p.init?p.init:{},o=i.headers&&"object"==typeof i.headers?i.headers:{},a=new AbortController,c=(e=>{const t=new URL(n);return t.pathname=`${t.pathname.replace(/\/$/,"")}/http-streams/${encodeURIComponent(e)}`,t})(e),l=new u(c,{headers:d(c)});return s.set(e,{tunnel:l,controller:a}),l.on("open",async()=>{try{const n=await fetch((e=>{const n=e.startsWith("/")?e:`/${e}`,r="function"==typeof t.port?t.port():t.port;return new URL(`/api/node-agent${n}`,`http://127.0.0.1:${r}`)})(r),{method:fi(i.method),headers:{...o,...t.token?{authorization:`Bearer ${t.token}`}:{}},body:"string"==typeof i.body?i.body:void 0,signal:a.signal});if(await m(l,JSON.stringify({type:"node-agent.http.head",streamId:e,status:n.status,headers:Object.fromEntries(n.headers.entries())})),n.body){const e=n.body.getReader();for(;;){const{done:t,value:n}=await e.read();if(t)break;await m(l,Buffer.from(n),!0)}}await m(l,JSON.stringify({type:"node-agent.http.end",streamId:e})),l.close(1e3,"HTTP stream completed.")}catch(t){l.readyState===u.OPEN&&(await m(l,JSON.stringify({type:"node-agent.http.error",streamId:e,message:t instanceof Error?t.message:String(t)})).catch(()=>{}),l.close(1011,"HTTP stream failed."))}finally{s.delete(e)}}),l.on("close",()=>{a.abort(),s.delete(e)}),void l.on("error",()=>a.abort())}if("control-plane.websocket.open"===p.type){const e="string"==typeof p.streamId?p.streamId:"",r="string"==typeof p.route?p.route:"",s=Array.isArray(p.protocols)?p.protocols.filter(e=>"string"==typeof e):void 0;try{const a=t.token?{authorization:`Bearer ${t.token}`}:void 0,l=s?.length?new u(c(r),s,{headers:a}):new u(c(r),{headers:a}),m=(e=>{const t=new URL(n);return t.pathname=`${t.pathname.replace(/\/$/,"")}/streams/${encodeURIComponent(e)}`,t})(e),p=new u(m,{headers:d(m)});o.set(e,{upstream:l,tunnel:p,close:(e=1e3,t="")=>{l.close(e,t),p.close(e,t)}}),l.on("open",()=>{i.send(JSON.stringify({type:"node-agent.websocket.open",streamId:e,protocol:l.protocol}))}),function(e,t,n={}){const r=n.pendingFrameLimit??256;let i=!1,o=Kn(t);const s=[],a=[];let c;const d=()=>{c&&(clearTimeout(c),c=void 0)},l=(n,i)=>{if(n.length>=r)return Gn(e,1011,"WebSocket bridge pending frame limit exceeded."),void Gn(t,1011,"WebSocket bridge pending frame limit exceeded.");n.push(i)};n.upstreamOpenTimeoutMs&&!o&&(c=setTimeout(()=>{o||i||(Gn(e,1011,"Upstream websocket did not open."),Gn(t))},n.upstreamOpenTimeoutMs)),e.on("open",()=>Wn(e,a)),t.on("open",()=>{d(),o=!0,n.onUpstreamOpen?.(),Wn(t,s)}),e.on("message",(e,n=!1)=>{const r={data:e,isBinary:Boolean(n)};Kn(t)?Jn(t,r):l(s,r)}),t.on("message",(t,n=!1)=>{const r={data:t,isBinary:Boolean(n)};Kn(e)?Jn(e,r):l(a,r)}),t.on("close",(t,r)=>{d(),n.onUpstreamClose?.(t,r),(o||i||!n.onUpstreamCloseBeforeOpen?.())&&Gn(e,t,r)}),t.on("error",t=>{n.onUpstreamError?.(t),(o||i||!n.onUpstreamErrorBeforeOpen?.(t))&&Gn(e)}),e.on("close",(e,r)=>{d(),i=!0,n.onClientClose?.(e,r),Gn(t,e,r)}),e.on("error",e=>{d(),i=!0,n.onClientError?.(e),Gn(t,1011,"WebSocket bridge client failed.")})}(p,l,{pendingFrameLimit:256,upstreamOpenTimeoutMs:1e4,onClientClose:()=>{o.delete(e)},onClientError:t=>{o.delete(e),i.send(JSON.stringify({type:"node-agent.websocket.error",streamId:e,message:t instanceof Error?t.message:String(t)}))},onUpstreamClose:(t,n)=>{o.delete(e),i.send(JSON.stringify({type:"node-agent.websocket.close",streamId:e,code:"number"==typeof t?t:1e3,reason:Buffer.isBuffer(n)?n.toString("utf8"):String(n||"")}))},onUpstreamError:t=>{o.delete(e),i.send(JSON.stringify({type:"node-agent.websocket.error",streamId:e,message:t instanceof Error?t.message:String(t)}))}})}catch(t){i.send(JSON.stringify({type:"node-agent.websocket.error",streamId:e,message:t instanceof Error?t.message:String(t)}))}return}if("control-plane.websocket.close"===p.type){const e="string"==typeof p.streamId?p.streamId:"";return void l(e,"number"==typeof p.code?p.code:1e3,"string"==typeof p.reason?p.reason:"")}if("control-plane.request"===p.type){const n="string"==typeof p.requestId?p.requestId:"",r=p.init&&"object"==typeof p.init?p.init:{},o="string"==typeof p.route&&p.route.startsWith("/")?p.route:"/health",s=r.headers&&"object"==typeof r.headers?r.headers:{};try{const a=await e.inject({method:fi(r.method),url:`/api/node-agent${o}`,headers:{...s,...t.token?{authorization:`Bearer ${t.token}`}:{}},payload:"string"==typeof r.body?r.body:void 0});i.send(JSON.stringify({type:"node-agent.response",requestId:n,status:a.statusCode,headers:a.headers,body:a.body}))}catch(e){i.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)}}))}}}),i}(e,{...n.config,nodeId:r,port:()=>e.nodeAgentState.currentListenerPort,token:i});return n.socket=o,o.on("open",()=>{s.get(t)===n&&n.socket===o&&(n.retry.reset(),e.log.info({nodeId:r,tunnelUrl:new URL(n.config.tunnelUrl).origin},"node agent reverse tunnel connected"))}),o.on("close",(i,d)=>{s.get(t)===n&&n.socket===o&&(n.socket=void 0,a||(e.log.warn({nodeId:r,tunnelUrl:new URL(n.config.tunnelUrl).origin,code:i,reason:Buffer.isBuffer(d)?d.toString("utf8"):String(d||"")},"node agent reverse tunnel disconnected"),((t,n)=>{if(a||n.retry.pending||s.get(t)!==n)return;const i=n.retry.schedule(()=>{a||s.get(t)!==n||n.socket||c(t,n)});i&&e.log.info({nodeId:r,tunnelUrl:new URL(n.config.tunnelUrl).origin,attempt:i.attempt,delay:i.delay},"node agent reverse tunnel reconnect scheduled")})(t,n)))}),o},d=(e,t)=>{const n=s.get(e);n?.retry.cancel();const r={config:t,retry:new Er};return s.set(e,r),n?.socket?.close(1e3,"Reverse tunnel reconnecting."),c(e,r)},l=(e,t)=>e.tunnelUrl===t.tunnelUrl&&e.keyId===t.keyId&&e.secret===t.secret;return{connect:e=>{const t=e.url.replace(/\/$/,"");return d(t,{tunnelUrl:ws(e.url),keyId:e.keyId,secret:e.secret})},connectConfigured:()=>{a=!1;const e=new Map,n=function(e){const t=e.controlPlaneTunnelUrl||process.env.TASK_HANDOFF_CONTROL_PLANE_TUNNEL_URL;if(t)return t;const n=process.env.TASK_HANDOFF_CONTROL_PLANE_URL;if(!n)return;const r=new URL("/api/node-agent/tunnel",n);return r.protocol="https:"===r.protocol?"wss:":"ws:",r.toString()}(t);if(n){const r=o.reverseTunnelSecret(process.env.TASK_HANDOFF_CONTROL_PLANE_URL,t.remoteSecret||process.env.TASK_HANDOFF_NODE_AGENT_REMOTE_SECRET,t.remoteKeyId||process.env.TASK_HANDOFF_NODE_AGENT_REMOTE_KEY_ID),i=(process.env.TASK_HANDOFF_CONTROL_PLANE_URL||n).replace(/\/$/,"");e.set(i,{tunnelUrl:n,keyId:r?.keyId,secret:r?.secret})}for(const t of o.configuredRemoteControlPlanes())t.url&&!1!==t.active&&e.set(t.url.replace(/\/$/,""),{tunnelUrl:ws(t.url),keyId:t.keyId,secret:t.secret});(e=>{for(const[t,n]of s)e.has(t)||(n.retry.cancel(),s.delete(t),n.socket?.close(1e3,"Reverse tunnel configuration removed."));for(const[t,n]of e){const e=s.get(t);e&&l(e.config,n)||d(t,n)}})(e)},closeAll:()=>{a=!0;for(const e of s.values())e.retry.cancel(),e.socket?.close(1001,"Node agent shutting down.");s.clear()}}}async function Ns(e){const o=ei(e.dataDir),s=(a=e.host,c=e.port,_n.parse({bindScope:"0.0.0.0"===a.trim()?"all-ipv4":"loopback",port:c}));var a,c;const d=t.existsSync(o.settingsPath),l=function(e,t){return new di(e.settingsPath,()=>({version:1,externalListener:t}),{schema:vo,sanitize:Fo})}(o,s),u=l.get().externalListener,m=function(e,i={}){return function(e,i={}){t.mkdirSync(n.dirname(e),{recursive:!0});const o={pid:process.pid,hostname:p.hostname(),component:i.component,command:process.argv.join(" "),acquiredAt:(new Date).toISOString(),token:r.randomUUID(),startIdentity:k(process.pid),dataDir:i.dataDir,host:i.host,port:i.port,instanceId:i.instanceId};for(let n=0;n<5;n+=1)try{return t.mkdirSync(e),t.writeFileSync(S(e),`${JSON.stringify({token:o.token,pid:o.pid,startIdentity:o.startIdentity,startedAt:(new Date).toISOString()})}\n`,{encoding:"utf8",mode:384,flag:"wx"}),D(e,o),{lockPath:e,owner:o,release(){const n=x(e);n?.token===o.token&&t.rmSync(e,{recursive:!0,force:!0})}}}catch(o){if("EEXIST"!==o.code)throw o;const s=x(e);if(R(s))throw new v(e,s,i.error);if(!s&&(P(e)||$(e)<(i.incompleteLockStaleMs??2e3))){if(n+1<5){L();continue}throw new v(e,void 0,i.error)}const a=r.randomUUID();if(!F(e,a)){if(n+1<5){L();continue}throw new v(e,x(e),i.error)}const c=x(e);if(R(c))throw j(_(e)),new v(e,c,i.error);if(s?.token&&c?.token!==s.token){j(_(e));continue}if(!V(e,a))continue;t.rmSync(e,{recursive:!0,force:!0})}const s=x(e);throw new v(e,s,i.error)}(e,{...i,component:"node-agent",error:{label:"Node agent",code:"NODE_AGENT_ALREADY_RUNNING"}})}(n.join(p.tmpdir(),`task-handoff-node-agent-${process.getuid?.()??"user"}.lock`),{dataDir:o.dataDir,host:$o(u.bindScope),port:u.port});try{const r={...e,port:u.port},s=await bs(r),a=zs(s,r,o,new ho(o).resolveNodeId(e.nodeId||process.env.TASK_HANDOFF_NODE_ID));s.decorate("nodeAgentReverseTunnels",a);const c=new hs({app:s,state:s.nodeAgentState,settings:l,config:u,source:d?"persisted":"bootstrap"});let p;s.decorate("nodeAgentListenerManager",c),function(e){let t=!1;const n=async n=>{if(!t){t=!0,a.closeAll(),p?.close();try{await e.close()}finally{process.exitCode=n?0:process.exitCode}}},r=()=>{n("SIGINT")},i=()=>{n("SIGTERM")};process.once("SIGINT",r),process.once("SIGTERM",i),e.addHook("onClose",async()=>{process.off("SIGINT",r),process.off("SIGTERM",i)})}(s),s.addHook("onClose",async()=>{p?.close(),m.release()});try{await s.ready();const r=e.ipcPath||process.env.TASK_HANDOFF_NODE_AGENT_IPC_PATH||li(o.dataDir);p=await async function(e,r){!function(e,r=process.platform){if("win32"!==r){t.mkdirSync(n.dirname(e),{recursive:!0,mode:448});try{t.chmodSync(n.dirname(e),448)}catch{}try{t.unlinkSync(e)}catch(e){if("ENOENT"!==e.code)throw e}}}(r);const o=i.createServer((t,n)=>{e.server.emit("request",t,n)});return o.on("upgrade",(t,n,r)=>{e.server.emit("upgrade",t,n,r)}),await new Promise((e,t)=>{o.once("error",t),o.listen(r,()=>{o.off("error",t),e()})}),o}(s,r),await c.start(),a.connectConfigured(),s.nodeAgentStartRecoverySupervisor?.()}catch(e){throw await s.close(),e}}catch(e){throw m.release(),e}}function vs(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 Es(e){if("local-ipc"!==e&&"local-loopback"!==e)throw new Error("Connection mode must be local-ipc or local-loopback.");return e}function Ss(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(N("@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",vs,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",Es).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 Ns({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",Ss).option("--json","Print raw JSON output").action(async e=>{const n=t.opts(),r=e.ipcPath||n.ipcPath||process.env.TASK_HANDOFF_NODE_AGENT_IPC_PATH,o=e.dataDir||n.dataDir||process.env.TASK_HANDOFF_NODE_AGENT_DATA_DIR,s=e.endpoint?void 0:r||li(o||Qr()),a=await async function(e){const t={"content-type":"application/json",...e.token?{authorization:`Bearer ${e.token}`}:{}},n=JSON.stringify({...e.expiresInMs?{expiresInMs:e.expiresInMs}:{}}),r=e.endpoint?await fetch(`${e.endpoint.replace(/\/$/,"")}/api/node-agent/pairing/invites`,{method:"POST",headers:t,body:n}):await async function(e,t,n={}){const r=n.method||"GET",o="string"==typeof n.body||n.body instanceof Buffer?n.body:void 0===n.body||null===n.body?void 0:String(n.body),s=new Headers(n.headers||{});return void 0===o||s.has("content-length")||s.set("content-length",String(Buffer.byteLength(o))),new Promise((a,d)=>{const l=i.request({socketPath:e,method:r,path:`/api/node-agent${t}`,headers:Object.fromEntries(s.entries())},e=>{const t=e.statusCode||500;a(new Response("HEAD"!==r&&204!==t&&205!==t&&304!==t?c.Readable.toWeb(e):null,{status:t,headers:e.headers}))});l.on("error",d);const u=()=>l.destroy(new DOMException("The operation was aborted.","AbortError"));n.signal?.aborted?u():n.signal?.addEventListener("abort",u,{once:!0}),l.once("close",()=>n.signal?.removeEventListener("abort",u)),void 0!==o&&l.write(o),l.end()})}(e.ipcPath,"/pairing/invites",{method:"POST",headers:t,body:n}),o=await r.json().catch(()=>({}));if(!r.ok)throw new Error(o.error?.message||`Node agent pairing invite failed with HTTP ${r.status}`);const s="string"==typeof o.data?.joinToken?o.data.joinToken:"";if(!s)throw new Error("Node agent pairing invite response did not include a join token.");return{nodeId:"string"==typeof o.data?.nodeId?o.data.nodeId:"",joinToken:s,expiresAt:"string"==typeof o.data?.expiresAt?o.data.expiresAt:""}}({endpoint:e.endpoint,ipcPath:s,token:e.token,expiresInMs:e.expiresInMs});e.json?console.log(JSON.stringify(a,null,2)):(a.nodeId&&console.log(`Node: ${a.nodeId}`),console.log(`Join token: ${a.joinToken}`),a.expiresAt&&console.log(`Expires: ${a.expiresAt}`))}),await t.parseAsync(process.argv)})().catch(e=>{console.error(e instanceof Error?e.message:String(e)),process.exitCode=1});
1
+ "use strict";var e=require("commander"),t=require("node:fs"),n=require("node:path"),r=require("node:crypto"),i=require("node:http"),o=require("node:net"),s=require("node:url"),a=require("node:child_process"),c=require("node:stream"),d=require("fastify"),l=require("@fastify/websocket"),u=require("ws"),m=require("zod"),p=require("node:os"),g=require("node-pty"),h=require("write-file-atomic"),f=require("semver"),y=require("node:fs/promises"),I=require("node:stream/promises"),A=require("tar"),b="undefined"!=typeof document?document.currentScript:null;function w(e,n){try{const r=JSON.parse(t.readFileSync(e,"utf8"));if(n&&r.name!==n)return;return"string"==typeof r.version&&r.version.trim()?r.version.trim():void 0}catch{return}}function N(e){if(e)try{return n.dirname(t.realpathSync(e))}catch{return}}function z(e,t=process.env,r=e){const i=t.TASK_HANDOFF_VERSION?.trim();if(i)return i;const o=r.split("/").at(-1),s=process.argv[1]?n.resolve(process.argv[1]):void 0,a=s?n.dirname(s):void 0,c=[N(s),a,process.cwd()].filter(e=>Boolean(e));for(const t of new Set(c)){let r=t;for(;;){const t=w(n.join(r,"package.json"),e);if(t)return t;const i=n.dirname(r);if(i===r)break;r=i}}let d;for(const e of new Set(c)){let t=e;for(;;){if(o){const e=w(n.join(t,"packages",o,"package.json"),r);if(e)return e}d||=w(n.join(t,"package.json"));const e=n.dirname(t);if(e===t)break;t=e}}return d||"unknown"}class v extends Error{code;lockPath;owner;constructor(e,t,n={}){const r=t?.pid?` pid ${t.pid}`:"";super(`${n.label||"Process"} is already running${r}. Lock: ${e}`),this.name="ProcessSingletonError",this.code=n.code||"PROCESS_ALREADY_RUNNING",this.lockPath=e,this.owner=t}}function E(e){return n.join(e,"owner.json")}function S(e){return n.join(e,"initializing.json")}function _(e){return n.join(e,"recovering.json")}function T(e){return Number.isInteger(e)&&Number(e)>0}function k(e,n=process.platform){if(T(e)){if("linux"===n)try{const n=t.readFileSync(`/proc/${e}/stat`,"utf8"),r=n.lastIndexOf(")");if(r<0)return;const i=n.slice(r+2).trim().split(/\s+/)[19];return i?`linux:${i}`:void 0}catch{return}if(["darwin","freebsd","openbsd","aix","sunos"].includes(n)){const t=a.spawnSync("ps",["-o","lstart=","-p",String(e)],{encoding:"utf8",timeout:1e3}),r=0===t.status?t.stdout.trim().replace(/\s+/g," "):"";return r?`${n}:${r}`:void 0}if("win32"===n){const t=`(Get-Process -Id ${e} -ErrorAction Stop).StartTime.ToUniversalTime().Ticks`,n=a.spawnSync("powershell.exe",["-NoProfile","-NonInteractive","-Command",t],{encoding:"utf8",timeout:2e3}),r=0===n.status?n.stdout.trim():"";return/^\d+$/.test(r)?`win32:${r}`:void 0}}}function C(e){try{const n=JSON.parse(t.readFileSync(E(e),"utf8"));if(T(n.pid)&&"string"==typeof n.startTime){const e=n;return{pid:e.pid,hostname:"string"==typeof e.hostname&&e.hostname?e.hostname:p.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(!(T(n.pid)&&"string"==typeof n.hostname&&n.hostname&&"string"==typeof n.command&&"string"==typeof n.acquiredAt&&Number.isFinite(Date.parse(n.acquiredAt))&&"string"==typeof n.token&&n.token))return;return n}catch{return}}const O=C;function x(e){if(!T(e))return!1;try{return process.kill(Number(e),0),!0}catch(e){return"EPERM"===e.code}}function R(e){if(!e||!x(e.pid))return!1;if(!e.startIdentity)return!0;const t=k(e.pid);return void 0===t||t===e.startIdentity}function D(e,r){const i=n.join(e,`.owner-${r.token}.tmp`);t.writeFileSync(i,`${JSON.stringify(r,null,2)}\n`,{encoding:"utf8",mode:384,flag:"wx"});const o=P(e);if(o?.token!==r.token)throw M(i),new Error(`Process lock initialization was superseded: ${e}`);t.renameSync(i,E(e)),M(S(e))}function P(e){try{return JSON.parse(t.readFileSync(S(e),"utf8"))}catch{return}}function j(e){const t=P(e);return T(t?.pid)&&R({pid:t.pid,startIdentity:t.startIdentity})}function M(e){try{t.unlinkSync(e)}catch(e){if("ENOENT"!==e.code)throw e}}function L(){Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,20)}function $(e){try{const n=P(e),r=Date.parse(n?.startedAt||"");return Number.isFinite(r)?Math.max(0,Date.now()-r):Math.max(0,Date.now()-t.statSync(e).mtimeMs)}catch{return 0}}function F(e,i){try{return t.writeFileSync(_(e),`${JSON.stringify({token:i,pid:process.pid,startedAt:(new Date).toISOString()})}\n`,{encoding:"utf8",mode:384,flag:"wx"}),!0}catch(o){if("EEXIST"===o.code)return!!function(e){const i=_(e),o=U(i),s=Date.parse(o?.startedAt||"");if(x(o?.pid)||Number.isFinite(s)&&Date.now()-s<2e3)return!1;const a=n.join(e,`.recovering-${r.randomUUID()}.stale`);try{t.renameSync(i,a)}catch(e){if(["ENOENT","EEXIST"].includes(e.code||""))return!1;throw e}const c=U(a);if(c?.token===o?.token)return M(a),!0;try{t.linkSync(a,i)}catch(e){if("EEXIST"!==e.code)throw e}finally{M(a)}return!1}(e)&&F(e,i);if("ENOENT"===o.code)return!1;throw o}}function U(e){try{return JSON.parse(t.readFileSync(e,"utf8"))}catch{return}}function V(e,t){return U(_(e))?.token===t}const H=41943040,q="ai.sessions",B=m.z.string().trim().min(1).max(80),K=m.z.enum(["running","waiting","idle","failed"]);m.z.object({instanceId:m.z.string().trim().min(1).max(160),sessionId:m.z.string().trim().min(1).max(120),unread:m.z.boolean(),sessionUpdatedAt:m.z.string().datetime(),updatedAt:m.z.string().datetime()}).strict();const G=m.z.enum(["thinking","tool","editing","approval","responding","unknown"]),J=m.z.object({id:m.z.string().trim().min(1).max(240).optional(),kind:m.z.string().trim().min(1).max(80).optional(),name:m.z.string().trim().min(1).max(120),inputPreview:m.z.string().trim().max(500).optional(),startedAt:m.z.string().datetime().optional()}).strict(),W=m.z.enum(["pending-init","running","interrupted","completed","errored","shutdown","not-found"]),Y=m.z.enum(["started","interacted","interrupted"]),X=m.z.object({threadId:m.z.string().trim().min(1).max(240),path:m.z.string().trim().max(4096).optional(),status:W,activity:Y.optional(),message:m.z.string().trim().max(1e3).optional(),updatedAt:m.z.string().datetime()}).strict(),Q=m.z.object({toolCalls:m.z.number().int().min(0).default(0),edits:m.z.number().int().min(0).default(0),approvals:m.z.number().int().min(0).default(0)}).strict().default({toolCalls:0,edits:0,approvals:0}),Z=m.z.object({send:m.z.boolean().optional(),interrupt:m.z.boolean().optional(),approval:m.z.boolean().optional()}).strict(),ee=m.z.enum(["image","file"]),te=m.z.object({id:m.z.string().trim().min(1).max(120),kind:ee,name:m.z.string().trim().min(1).max(240),mime:m.z.string().trim().min(1).max(120),size:m.z.number().int().min(0).max(Number.MAX_SAFE_INTEGER)}),ne=m.z.union([te.extend({source:m.z.object({type:m.z.literal("inline"),encoding:m.z.literal("base64"),data:m.z.string().min(1).max(31457280)}).strict()}).strict().superRefine((e,t)=>{const n="image"===e.kind?20971520:512e3;(e.size<=0||("file"===e.kind?e.size>=n:e.size>n))&&t.addIssue({code:m.z.ZodIssueCode.custom,path:["size"],message:`Inline ${e.kind} must be between 1 byte and ${n} bytes.`})}),te.extend({source:m.z.object({type:m.z.literal("runtime-path"),path:m.z.string().trim().min(1).max(4096)}).strict()}).strict()]),re=te.extend({sourceType:m.z.enum(["inline","runtime-path"])}).strict(),ie=m.z.union([m.z.object({id:m.z.string().trim().min(1).max(120),kind:ee.optional(),source:m.z.object({type:m.z.literal("upload-ref")}).strict().default({type:"upload-ref"})}).strict(),m.z.object({id:m.z.string().trim().min(1).max(120),kind:ee,name:m.z.string().trim().min(1).max(240),mime:m.z.string().trim().min(1).max(120),size:m.z.number().int().min(0).max(Number.MAX_SAFE_INTEGER),source:m.z.object({type:m.z.literal("runtime-path"),path:m.z.string().trim().min(1).max(4096)}).strict()}).strict()]),oe=m.z.enum(["auto","queue","steer","immediate"]),se=m.z.enum(["ask","auto-review","full-access"]),ae=m.z.enum(["review","rename","goal","compact"]);m.z.object({command:ae,argument:m.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.`})}),m.z.object({command:ae,value:m.z.string().max(4e3).optional(),turnId:m.z.string().trim().min(1).max(240).optional()}).strict(),m.z.enum(["skill","app","plugin"]);const ce=m.z.object({name:m.z.string().trim().min(1).max(240),path:m.z.string().trim().min(1).max(4096)}),de=m.z.discriminatedUnion("kind",[ce.extend({kind:m.z.literal("skill"),path:m.z.string().trim().min(1).max(4096).refine(e=>e.startsWith("/"),"Skill paths must be absolute.")}).strict(),ce.extend({kind:m.z.literal("app"),path:m.z.string().trim().min(7).max(4096).regex(/^app:\/\/[^\s/]+$/,"App paths must use app://<id>.")}).strict(),ce.extend({kind:m.z.literal("plugin"),path:m.z.string().trim().min(10).max(4096).regex(/^plugin:\/\/[^\s/]+$/,"Plugin paths must use plugin://<id>.")}).strict()]),le=m.z.array(de).max(20).default([]),ue=m.z.enum(["plugin","skill","file","directory","app"]),me=m.z.object({kind:ue,name:m.z.string().trim().min(1).max(240),description:m.z.string().trim().max(1e3).optional(),path:m.z.string().trim().min(1).max(4096),icon:m.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."})}),pe=m.z.object({category:m.z.enum(["skills","plugins","apps","files"]),code:m.z.string().trim().min(1).max(160),message:m.z.string().trim().min(1).max(2e3)}).strict();m.z.object({sessionId:m.z.string().trim().min(1).max(120),providerSessionId:m.z.string().trim().min(1).max(240),cwd:m.z.string().trim().min(1).max(4096),candidates:m.z.array(me).max(1e3).default([]),diagnostics:m.z.array(pe).max(20).default([])}).strict(),m.z.object({query:m.z.string().trim().max(240).default("")}).strict(),m.z.object({sessionId:m.z.string().trim().min(1).max(120),cwd:m.z.string().trim().min(1).max(4096),query:m.z.string().trim().max(240),requestId:m.z.string().trim().min(1).max(160),candidates:m.z.array(me.refine(e=>"file"===e.kind||"directory"===e.kind,"File search only returns files and directories.")).max(200).default([]),complete:m.z.boolean().default(!1)}).strict();const ge=m.z.object({message:m.z.string().trim().min(1).max(2e4),mode:oe.optional(),permissionMode:se.optional()});ge.extend({attachments:m.z.array(ne).max(6).default([]),references:le}).strict().superRefine((e,t)=>{e.attachments.reduce((e,t)=>e+("inline"===t.source.type?t.size:0),0)>H&&t.addIssue({code:m.z.ZodIssueCode.custom,path:["attachments"],message:"Inline attachments must be 41943040 bytes or less in total."})}),ge.extend({attachments:m.z.array(ie).max(6).default([]),references:le}).strict(),m.z.object({decision:m.z.enum(["allow","deny","skip"])}).strict(),m.z.object({queueIds:m.z.array(m.z.string().trim().min(1).max(120)).max(100)}).strict(),m.z.object({code:m.z.string().trim().min(1).max(160),message:m.z.string(),instanceId:m.z.string().trim().min(1).max(160).optional(),nodeId:m.z.string().trim().min(1).max(160).optional(),route:m.z.string().trim().min(1).max(4096).optional()}).strict();const he=m.z.object({id:m.z.string().trim().min(1).max(120),message:m.z.string().trim().min(1).max(2e4),attachments:m.z.array(re).max(6).default([]),references:le,permissionMode:se.optional(),status:m.z.enum(["queued","sending","failed"]).default("queued"),createdAt:m.z.string().datetime(),updatedAt:m.z.string().datetime(),error:m.z.string().trim().max(4e3).optional()}).strict(),fe=m.z.object({pendingCount:m.z.number().int().min(0).default(0),items:m.z.array(he).max(100).default([])}).strict().default({pendingCount:0,items:[]}),ye=m.z.enum(["control","realtime","adapter-snapshot","transcript-tail","transcript-scan","process-scan","app-session"]),Ie=m.z.object({id:m.z.string().trim().min(1).max(240),status:m.z.enum(["running","completed"]),startedAt:m.z.string().datetime().optional(),completedAt:m.z.string().datetime().optional()}).strict(),Ae=m.z.object({id:m.z.string().trim().min(1).max(240),providerTurnId:m.z.string().trim().max(240).optional(),source:ye.optional(),userPrompt:m.z.string().trim().optional(),status:m.z.enum(["queued","running","waiting","completed","failed"]).default("running"),phase:G.optional(),summary:m.z.string().trim().max(1e3).optional(),lastMessage:m.z.string().trim().optional(),lastMessageItemId:m.z.string().trim().max(240).optional(),contextCompactions:m.z.array(Ie).max(20).optional(),revision:m.z.number().int().min(0).default(0),sourcePriority:m.z.number().int().min(0).max(100).optional(),snapshotVersion:m.z.number().int().min(0).optional(),observedAt:m.z.string().datetime().optional(),startedAt:m.z.string().datetime().optional(),updatedAt:m.z.string().datetime().optional(),completedAt:m.z.string().datetime().optional()}).strict(),be=Ae.pick({id:!0,providerTurnId:!0,userPrompt:!0,status:!0,phase:!0,summary:!0,lastMessage:!0,contextCompactions:!0,startedAt:!0,updatedAt:!0,completedAt:!0}).strict(),we=m.z.object({id:m.z.string().trim().min(1).max(120),agent:B,appSessionId:m.z.string().trim().max(120).optional(),appId:m.z.string().trim().max(120).optional(),providerSessionId:m.z.string().trim().max(240).optional(),providerMeta:m.z.record(m.z.string(),m.z.unknown()).optional(),appBindingKeys:m.z.array(m.z.string().trim().min(1).max(240)).max(20).optional(),actions:Z.optional(),activeTurnId:m.z.string().trim().max(240).optional(),title:m.z.string().trim().max(240).optional(),cwd:m.z.string().trim().max(4096).optional(),userPrompt:m.z.string().trim().optional(),turns:m.z.array(Ae).max(50).optional(),status:K.default("running"),phase:G.default("unknown"),summary:m.z.string().trim().max(1e3).optional(),lastMessage:m.z.string().trim().optional(),lastMessageItemId:m.z.string().trim().max(240).optional(),currentTool:J.optional(),toolCallsSinceLastMessage:m.z.number().int().min(0).default(0),subAgents:m.z.array(X).max(50).default([]),transcriptPath:m.z.string().trim().max(4096).optional(),transcriptSize:m.z.number().int().min(0).optional(),startedAt:m.z.string().datetime(),updatedAt:m.z.string().datetime(),completedAt:m.z.string().datetime().optional(),error:m.z.string().trim().max(4e3).optional(),counters:Q,queue:fe}).strict();m.z.object({session:we,provider:m.z.string().trim().min(1).max(80),action:m.z.enum(["send","queue","steer","interrupt","approval"]),decision:m.z.enum(["allow","deny","skip"]).optional(),turnId:m.z.string().trim().min(1).max(240).optional(),providerTurnId:m.z.string().trim().min(1).max(240).optional(),queueId:m.z.string().trim().min(1).max(120).optional()}).strict();const Ne=m.z.object({id:m.z.string().trim().min(1).max(120),agent:m.z.enum(["codex","claude"]),providerSessionId:m.z.string().trim().min(1).max(240),title:m.z.string().trim().max(240).optional(),userPrompt:m.z.string().trim().optional(),lastMessage:m.z.string().trim().optional(),cwd:m.z.string().trim().min(1).max(4096),lastActiveAt:m.z.string().datetime(),archivedAt:m.z.string().datetime()}).strict();m.z.object({schemaVersion:m.z.literal(1).default(1),items:m.z.array(Ne).max(50).default([])}).strict(),m.z.object({items:m.z.array(Ne).max(50).default([])}).strict(),m.z.object({item:Ne,turns:m.z.array(be).max(50).default([])}).strict(),m.z.object({disposition:m.z.enum(["resumed","already-open"]),aiSessionId:m.z.string().trim().min(1).max(120),providerSessionId:m.z.string().trim().min(1).max(240),appSessionId:m.z.string().trim().min(1).max(120)}).strict();const ze=we.pick({id:!0,agent:!0,appSessionId:!0,appId:!0,providerSessionId:!0,providerMeta:!0,appBindingKeys:!0,actions:!0,activeTurnId:!0,title:!0,cwd:!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}),ve=m.z.object({runningCount:m.z.number().int().min(0).default(0),waitingCount:m.z.number().int().min(0).default(0),staleCount:m.z.number().int().min(0).default(0),sessions:m.z.array(ze).default([]),updatedAt:m.z.string().datetime()}).strict();m.z.object({streamId:m.z.string().trim().min(1).max(240),revision:m.z.number().int().min(0),lastEventAt:m.z.string().datetime(),snapshot:ve}).strict(),ve.pick({runningCount:!0,waitingCount:!0,staleCount:!0,updatedAt:!0}).extend({idleCount:m.z.number().int().min(0).default(0),problemCount:m.z.number().int().min(0).default(0),revision:m.z.number().int().min(0).optional()});const Ee=m.z.enum(["provider-event","app-session-created","app-session-updated","app-session-deleted","discovery-scan","control-action","heartbeat-sync","startup"]),Se=m.z.object({streamId:m.z.string().trim().min(1).max(240),instanceId:m.z.string().trim().min(1).max(160),nodeId:m.z.string().trim().min(1).max(160).optional(),revision:m.z.number().int().min(0),previousRevision:m.z.number().int().min(0).optional(),traceId:m.z.string().trim().min(1).max(160),generatedAt:m.z.string().datetime(),reason:Ee}).strict(),_e=m.z.object({meta:Se,snapshot:ve}).strict(),Te=m.z.object({meta:Se,upserted:m.z.array(ze).default([]),removed:m.z.array(m.z.string().trim().min(1).max(120)).default([])}).strict(),ke=m.z.object({meta:Se,sessionIds:m.z.array(m.z.string().trim().min(1).max(120)).default([]),expiresAt:m.z.string().datetime()}).strict();m.z.object({instanceId:m.z.string().trim().min(1).max(160),nodeId:m.z.string().trim().min(1).max(160).optional(),sessionId:m.z.string().trim().min(1).max(120),providerSessionId:m.z.string().trim().min(1).max(240),turnId:m.z.string().trim().min(1).max(240),itemId:m.z.string().trim().min(1).max(240),delta:m.z.string().min(1),generatedAt:m.z.string().datetime()}).strict(),m.z.object({streamId:m.z.string().trim().min(1).max(240),instanceId:m.z.string().trim().min(1).max(160),sinceRevision:m.z.number().int().min(0),latestRevision:m.z.number().int().min(0),earliestRetainedRevision:m.z.number().int().min(0),syncRequired:m.z.boolean().default(!1),events:m.z.array(m.z.discriminatedUnion("type",[m.z.object({type:m.z.literal("ai-session.snapshot"),payload:_e}).strict(),m.z.object({type:m.z.literal("ai-session.patch"),payload:Te}).strict(),m.z.object({type:m.z.literal("ai-session.removed"),payload:ke}).strict()])).default([])}).strict();const Ce=m.z.object({source:ye,sourcePriority:m.z.number().int().min(0).max(100).optional(),observedAt:m.z.string().datetime().optional(),snapshotVersion:m.z.number().int().min(0).optional()}).strict(),Oe=Ce.extend({type:m.z.literal("snapshot"),agent:m.z.string().trim().min(1).max(80),appSessionId:m.z.string().trim().max(120).optional(),appId:m.z.string().trim().max(120).optional(),providerSessionId:m.z.string().trim().max(240).optional(),providerMeta:m.z.record(m.z.string(),m.z.unknown()).optional(),appBindingKeys:m.z.array(m.z.string().trim().min(1).max(240)).max(20).optional(),actions:Z.optional(),title:m.z.string().trim().max(240).optional(),cwd:m.z.string().trim().max(4096).optional(),activeTurnId:m.z.string().trim().max(240).optional(),userPrompt:m.z.string().trim().optional(),turns:m.z.array(Ae).max(50).optional(),status:K.optional(),phase:G.optional(),summary:m.z.string().trim().max(1e3).optional(),lastMessage:m.z.string().trim().optional(),lastMessageItemId:m.z.string().trim().max(240).optional(),currentTool:J.optional(),toolCallsSinceLastMessage:m.z.number().int().min(0).optional(),subAgents:m.z.array(X).max(50).optional(),transcriptPath:m.z.string().trim().max(4096).optional(),transcriptSize:m.z.number().int().min(0).optional(),replaceActivity:m.z.boolean().optional()}).strict(),xe=Ce.extend({type:m.z.literal("event"),sessionId:m.z.string().trim().min(1).max(120),kind:m.z.enum(["lifecycle","send-ack","turn-started","user-message","assistant-message","approval-requested","turn-completed","tool-activity","sub-agent-activity","context-compaction"]),activeTurnId:m.z.string().trim().max(240).optional(),providerTurnId:m.z.string().trim().max(240).optional(),userPrompt:m.z.string().trim().optional(),text:m.z.string().optional(),itemId:m.z.string().trim().max(240).optional(),status:K.optional(),phase:G.optional(),summary:m.z.string().trim().max(1e3).optional(),error:m.z.string().trim().max(4e3).optional(),currentTool:J.nullable().optional(),toolCallsSinceLastMessage:m.z.number().int().min(0).optional(),subAgents:m.z.array(X).max(50).optional(),contextCompaction:Ie.optional(),counters:m.z.object({toolCalls:m.z.number().int().min(0).optional(),edits:m.z.number().int().min(0).optional(),approvals:m.z.number().int().min(0).optional()}).strict().optional()}).strict().superRefine((e,t)=>{if("context-compaction"===e.kind?e.contextCompaction||t.addIssue({code:"custom",path:["contextCompaction"],message:"context-compaction events require contextCompaction"}):void 0!==e.contextCompaction&&t.addIssue({code:"custom",path:["contextCompaction"],message:"contextCompaction is only valid for context-compaction events"}),"sub-agent-activity"===e.kind?e.subAgents||t.addIssue({code:"custom",path:["subAgents"],message:"sub-agent-activity events require subAgents"}):void 0!==e.subAgents&&t.addIssue({code:"custom",path:["subAgents"],message:"subAgents is only valid for sub-agent-activity events"}),"tool-activity"!==e.kind)return void 0!==e.currentTool&&t.addIssue({code:"custom",path:["currentTool"],message:"currentTool is only valid for tool-activity events"}),void(void 0!==e.toolCallsSinceLastMessage&&t.addIssue({code:"custom",path:["toolCallsSinceLastMessage"],message:"toolCallsSinceLastMessage is only valid for tool-activity events"}));"currentTool"in e||t.addIssue({code:"custom",path:["currentTool"],message:"tool-activity events require currentTool"}),void 0===e.toolCallsSinceLastMessage&&t.addIssue({code:"custom",path:["toolCallsSinceLastMessage"],message:"tool-activity events require toolCallsSinceLastMessage"})});m.z.discriminatedUnion("type",[Oe,xe]);const Re=m.z.union([m.z.object({type:m.z.literal("schedule"),scheduleKind:m.z.literal("interval").default("interval"),intervalMs:m.z.number().int().min(1e3)}).strict(),m.z.object({type:m.z.literal("schedule"),scheduleKind:m.z.literal("daily"),timeOfDay:m.z.string().regex(/^([01]\d|2[0-3]):[0-5]\d$/),timezone:m.z.string().trim().min(1).max(120)}).strict(),m.z.object({type:m.z.literal("schedule"),scheduleKind:m.z.literal("weekly"),weekdays:m.z.array(m.z.number().int().min(0).max(6)).min(1).max(7),timeOfDay:m.z.string().regex(/^([01]\d|2[0-3]):[0-5]\d$/),timezone:m.z.string().trim().min(1).max(120)}).strict()]),De=m.z.union([Re,m.z.object({type:m.z.literal("file-change"),roots:m.z.array(m.z.string().trim().min(1).max(4096)).min(1).max(50),globs:m.z.array(m.z.string().trim().min(1).max(500)).min(1).max(100),ignore:m.z.array(m.z.string().trim().min(1).max(500)).max(100).optional(),debounceMs:m.z.number().int().min(100).max(6e4).default(1500)}).strict(),m.z.object({type:m.z.literal("ai-session"),agent:m.z.string().trim().min(1).max(80).optional(),statuses:m.z.array(m.z.enum(["running","waiting","idle","failed"])).max(20).optional(),phases:m.z.array(m.z.enum(["thinking","tool","editing","approval","responding","unknown"])).max(20).optional()}).strict()]),Pe=m.z.object({promptTemplate:m.z.string().trim().min(1).max(2e4)}).strict(),je=m.z.object({cooldownMs:m.z.number().int().min(0).max(864e5).optional(),maxConcurrentRuns:m.z.number().int().min(1).max(20).default(1),whenBusy:m.z.enum(["skip","queue"]).default("skip")}).strict(),Me=m.z.object({configHash:m.z.string().trim().min(8).max(80),name:m.z.string().trim().min(1).max(160),description:m.z.string().trim().max(1e3).optional(),source:De,action:Pe,policy:je.default({maxConcurrentRuns:1,whenBusy:"skip"}),createdAt:m.z.string().datetime(),updatedAt:m.z.string().datetime()}).strict(),Le=m.z.object({type:m.z.literal("ai-session"),aiSessionId:m.z.string().trim().min(1).max(160)}).strict(),$e=m.z.object({configHash:m.z.string().trim().min(8).max(80),deploymentId:m.z.string().trim().min(1).max(240).optional(),instanceId:m.z.string().trim().min(1).max(160),origin:m.z.enum(["control-plane","controlled-instance"]).default("controlled-instance"),enabled:m.z.boolean().default(!0),target:Le,localName:m.z.string().trim().min(1).max(160).optional(),createdAt:m.z.string().datetime(),updatedAt:m.z.string().datetime()}).strict(),Fe=m.z.object({configHash:m.z.string().trim().min(8).max(80),deploymentId:m.z.string().trim().min(1).max(240).optional(),instanceId:m.z.string().trim().min(1).max(160),status:m.z.enum(["idle","running","disabled","error"]).default("idle"),lastTriggeredAt:m.z.string().datetime().optional(),lastCompletedAt:m.z.string().datetime().optional(),lastSkippedAt:m.z.string().datetime().optional(),lastError:m.z.string().trim().max(4e3).optional(),runCount:m.z.number().int().min(0).default(0),skippedCount:m.z.number().int().min(0).default(0)}).strict(),Ue=m.z.object({id:m.z.string().trim().min(1).max(160),configHash:m.z.string().trim().min(8).max(80),deploymentId:m.z.string().trim().min(1).max(240).optional(),instanceId:m.z.string().trim().min(1).max(160),eventType:m.z.enum(["manual","schedule","file-change","ai-session"]),status:m.z.enum(["started","completed","failed","skipped"]),target:Le,promptPreview:m.z.string().trim().max(500),eventSummary:m.z.string().trim().max(1e3).optional(),error:m.z.string().trim().max(4e3).optional(),startedAt:m.z.string().datetime(),completedAt:m.z.string().datetime().optional()}).strict();m.z.object({schemaVersion:m.z.literal(1).default(1),configs:m.z.array(Me).default([]),deployments:m.z.array($e).default([]),runtime:m.z.array(Fe).default([]),recentRuns:m.z.array(Ue).default([])}).strict();const Ve=m.z.string().regex(/^\d{4}-\d{2}-\d{2}$/,"Proxy protocol version must use YYYY-MM-DD format."),He=m.z.string().trim().min(1).max(160).regex(/^[a-zA-Z0-9][a-zA-Z0-9_.:-]*$/),qe=m.z.string().datetime(),Be=m.z.string().trim().min(32).max(4096),Ke=m.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)}),m.z.NEVER}});m.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 r,i;try{r=n.split("/").map(e=>decodeURIComponent(e))}catch{throw new Error("Proxy route contains invalid percent encoding.")}if(r.some(e=>".."===e||"."===e))throw new Error("Proxy route cannot traverse outside the node-agent API.");try{i=new URL(t,"https://node-agent.invalid")}catch{throw new Error("Proxy route is invalid.")}if("https://node-agent.invalid"!==i.origin||i.username||i.password)throw new Error("Proxy route cannot select an absolute upstream URL.");return`${i.pathname}${i.search}`}(e)}catch(e){return t.addIssue({code:"custom",message:e instanceof Error?e.message:String(e)}),m.z.NEVER}});const Ge=m.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"})),Je=m.z.object({code:Ge,message:m.z.string().trim().min(1).max(2048),retryable:m.z.boolean(),details:m.z.record(m.z.string(),m.z.unknown()).optional()}).strict(),We=m.z.enum(["active","consumed","revoked","expired"]),Ye=m.z.object({id:He,targetNodeId:He,tokenHash:m.z.string().trim().min(32).max(256),status:We,createdBy:He,expiresAt:qe,consumedByClaimId:He.optional(),consumedAt:qe.optional(),revokedAt:qe.optional(),createdAt:qe,updatedAt:qe}).strict().omit({tokenHash:!0});m.z.object({targetNodeId:He,expiresInSeconds:m.z.number().int().min(60).max(3600).default(600)}).strict(),m.z.object({invite:Ye,token:m.z.string().trim().min(24).max(512),proxyOrigin:Ke,protocolVersion:Ve}).strict();const Xe=m.z.enum(["active","revoked"]),Qe=m.z.object({id:He,claimId:He,sourceControlPlaneId:He,targetNodeId:He,bindingKeyId:He,credentialHash:m.z.string().trim().min(32).max(256),status:Xe,revision:m.z.number().int().positive(),lastError:Je.optional(),revokedAt:qe.optional(),createdAt:qe,updatedAt:qe}).strict().omit({credentialHash:!0});m.z.object({protocolVersion:Ve,inviteToken:m.z.string().trim().min(24).max(512).optional(),claimId:He,sourceControlPlaneId:He,targetNodeId:He.optional(),bindingKeyId:He,credential:Be}).strict(),m.z.object({sourceControlPlaneId:He,bindingKeyId:He,credential:Be}).strict();const Ze=m.z.object({id:He,name:m.z.string().trim().min(1).max(160),status:m.z.enum(["unknown","online","offline","degraded"]),health:m.z.enum(["unknown","ok","degraded","failed"]),lastSeenAt:qe.optional(),capabilities:m.z.record(m.z.string(),m.z.unknown()).default({})}).strict(),et=m.z.object({protocolVersion:Ve,binding:Qe,streamId:He,revision:m.z.number().int().nonnegative(),observedAt:qe,target:Ze}).strict(),tt=m.z.object({type:m.z.literal("control-plane-proxy.event"),protocolVersion:Ve,streamId:He,bindingId:He,sourceControlPlaneId:He,targetNodeId:He,revision:m.z.number().int().positive(),source:m.z.object({id:m.z.string().trim().min(1).max(512),seq:m.z.number().int().nonnegative()}).strict(),target:Ze,event:m.z.object({type:m.z.string().trim().min(1).max(240),topic:m.z.string().trim().min(1).max(240),createdAt:qe}).strict()}).strict(),nt=m.z.object({type:m.z.literal("control-plane-proxy.events.ready"),protocolVersion:Ve,streamId:He,bindingId:He,sourceControlPlaneId:He,targetNodeId:He,latestRevision:m.z.number().int().nonnegative(),earliestRetainedRevision:m.z.number().int().nonnegative()}).strict(),rt=m.z.object({type:m.z.literal("control-plane-proxy.snapshot-required"),protocolVersion:Ve,streamId:He,bindingId:He,sourceControlPlaneId:He,targetNodeId:He,sinceRevision:m.z.number().int().nonnegative(),latestRevision:m.z.number().int().nonnegative(),earliestRetainedRevision:m.z.number().int().nonnegative(),error:Je}).strict();m.z.discriminatedUnion("type",[tt,nt,rt]),m.z.object({protocolVersion:Ve,binding:Qe,target:et.shape.target}).strict(),m.z.object({id:He,claimId:He,proxyOrigin:Ke,requestedName:m.z.string().trim().min(1).max(160).optional(),sourceControlPlaneId:He,targetNodeId:He.optional(),bindingKeyId:He,credential:Be,status:m.z.enum(["pending","compensation-required"]),createdAt:qe,updatedAt:qe,expiresAt:qe}).strict().omit({credential:!0}),m.z.object({id:He,nodeId:He,proxyOrigin:Ke,proxyBindingId:He,targetNodeId:He,sourceControlPlaneId:He,bindingKeyId:He,credential:Be,createdAt:qe,updatedAt:qe}).strict();const it="2026-08-01",ot=m.z.string(),st=m.z.string().trim().min(1).max(120).regex(/^[a-zA-Z0-9][a-zA-Z0-9_.:-]*$/),at=m.z.string().datetime(),ct=m.z.record(m.z.string(),m.z.string()).default({}),dt=m.z.record(m.z.string(),m.z.string()).default({}),lt=m.z.string().regex(/^\d{4}-\d{2}-\d{2}$/,"Protocol version must use YYYY-MM-DD format."),ut=m.z.object({encoding:m.z.enum(["utf8","base64"]),data:m.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 mt(e){if(null==e)return;const t=ut.parse(e);return"utf8"===t.encoding?t.data:Buffer.from(t.data,"base64")}const pt=/^[A-Za-z0-9_][A-Za-z0-9_.-]{0,127}$/,gt=/^sha256:([a-fA-F0-9]{64})$/,ht=/^(?:localhost|[a-z0-9](?:[a-z0-9.-]*[a-z0-9])?)(?::[1-9][0-9]{0,4})?$/,ft=/^[a-z0-9]+(?:(?:[._]|__|-+)[a-z0-9]+)*$/;function yt(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 r=-1===n?void 0:t.slice(n+1),i=-1===n?t:t.slice(0,n),o=r?gt.exec(r):void 0;if(r&&!o)throw new Error("Docker image digest must use sha256 followed by 64 hexadecimal characters.");const s=i.lastIndexOf("/"),a=i.lastIndexOf(":"),c=a>s,d=c?i.slice(a+1):void 0,l=c?i.slice(0,a):i;if(d&&!pt.test(d))throw new Error("Docker image tag is invalid.");if(!d&&!o)throw new Error("Docker image reference must include an explicit tag or sha256 digest.");const u=l.split("/");if(!u.length||u.some(e=>!e))throw new Error("Docker image repository path is invalid.");const m=u.length>1&&(u[0].includes(".")||u[0].includes(":")||"localhost"===u[0]),p=m?u.slice(1):u;if(m&&!ht.test(u[0].toLowerCase()))throw new Error("Docker image registry host or port is invalid.");if(!p.length||p.some(e=>!ft.test(e)))throw new Error("Docker image repository names must be lowercase and use valid separators.");const g=u.map((e,t)=>m&&0===t?e.toLowerCase():e).join("/"),h=o?`sha256:${o[1].toLowerCase()}`:void 0;return`${g}${d?`:${d}`:""}${h?`@${h}`:""}`}function It(e){const t=yt(e),n=t.indexOf("@"),r=-1===n?void 0:t.slice(n+1),i=-1===n?t:t.slice(0,n),o=i.lastIndexOf("/"),s=i.lastIndexOf(":"),a=s>o;return{reference:t,repository:a?i.slice(0,s):i,tag:a?i.slice(s+1):void 0,digest:r}}const At=m.z.string().trim().min(1).max(512).transform((e,t)=>{try{return yt(e)}catch(e){return t.addIssue({code:"custom",message:e instanceof Error?e.message:String(e)}),m.z.NEVER}}),bt=m.z.string().trim().transform((e,t)=>{const n=gt.exec(e);return n?`sha256:${n[1].toLowerCase()}`:(t.addIssue({code:"custom",message:"Docker image digest must use sha256 followed by 64 hexadecimal characters."}),m.z.NEVER)}),wt=m.z.object({codexModelHash:st.nullable().optional(),claudeModelHash:st.nullable().optional()}).strict().default({}),Nt=m.z.object({imageId:st,tag:m.z.string().trim().min(1).max(128).regex(pt).optional()}).strict(),zt={img_default:"market_taskhandoff_browser",img_codex:"market_taskhandoff_codex",img_ai:"market_taskhandoff_ai"};function vt(e,t){if(e&&"object"==typeof e&&!Array.isArray(e)){const t=e;return{imageId:"string"==typeof t.imageId&&zt[t.imageId]||t.imageId,..."string"==typeof t.tag?{tag:t.tag}:{}}}if("string"==typeof t)return{imageId:zt[t]||t}}function Et(e){if(!e||"object"!=typeof e||Array.isArray(e))return e;const t=e,{defaultImageId:n,...r}=t;return{...r,defaultImageSelection:vt(t.defaultImageSelection,n)}}const St=m.z.object({id:st,name:m.z.string().trim().min(1).max(120),kind:m.z.enum(["tty","gui","web"]),source:m.z.enum(["builtin","custom"]),availability:m.z.enum(["available","missing-dependency"]),capabilities:m.z.object({automation:m.z.enum(["cdp"]).optional(),supportsCwdSelection:m.z.boolean().default(!1)}).strict().default({supportsCwdSelection:!1}),diagnosticCode:m.z.enum(["APP_EXECUTABLE_NOT_FOUND"]).optional()}).strict(),_t=m.z.object({code:m.z.enum(["APP_CATALOG_INVALID"]),message:m.z.string().trim().min(1).max(500)}).strict(),Tt=m.z.object({items:m.z.array(St).max(256),observedAt:at,issues:m.z.array(_t).max(32).default([])}).strict(),kt=m.z.enum(["linux","darwin","win32","freebsd","openbsd","aix","sunos","unknown"]),Ct=m.z.enum(["x64","arm64","arm","ia32","ppc64","s390x","riscv64","unknown"]),Ot=m.z.enum(["apt","dnf","brew","npm"]),xt=m.z.enum(["user","passwordless-sudo","root"]),Rt=m.z.object({platform:kt,arch:Ct,installers:m.z.array(Ot).max(8),privilege:xt,installerAccess:m.z.object({npmGlobalWritable:m.z.boolean().optional()}).strict().optional()}).strict(),Dt=m.z.enum(["installed","not-installed","broken","unsupported"]),Pt=m.z.enum(["recipe","bundled","external","none"]),jt=m.z.object({code:m.z.enum(["BUNDLED","EXTERNALLY_MANAGED","ALREADY_INSTALLED","NOT_INSTALLED","UNSUPPORTED_PLATFORM","INSTALLER_UNAVAILABLE","INSTALLER_NOT_WRITABLE","INSUFFICIENT_PRIVILEGE","OPERATION_IN_PROGRESS"]),message:m.z.string().trim().min(1).max(500)}).strict(),Mt=m.z.object({id:st,name:m.z.string().trim().min(1).max(120),kind:m.z.enum(["tty","gui","web"]),description:m.z.string().trim().max(500).optional(),state:Dt,managementSource:Pt,version:m.z.string().trim().max(120).optional(),canInstall:m.z.boolean(),canUninstall:m.z.boolean(),installReason:jt.optional(),uninstallReason:jt.optional(),activeJobId:st.optional()}).strict(),Lt=m.z.enum(["install","uninstall"]),$t=m.z.enum(["queued","running","succeeded","failed","cancelled","interrupted"]),Ft=m.z.object({current:m.z.number().finite().nonnegative().optional(),total:m.z.number().finite().positive().optional(),unit:m.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"]}),Ut=m.z.object({executable:m.z.string().trim().min(1).max(4096),args:m.z.array(m.z.string().max(4096)).max(128)}).strict(),Vt=m.z.object({code:m.z.string().trim().min(1).max(120).regex(/^[a-z0-9][a-z0-9._-]*$/),message:m.z.string().trim().min(1).max(4096),retryable:m.z.boolean(),sessionIds:m.z.array(st).max(64).optional()}).strict(),Ht=m.z.object({id:st,requestId:st.optional(),appId:st,operation:Lt,state:$t,phase:m.z.string().trim().min(1).max(120).optional(),progress:Ft.optional(),command:Ut.optional(),logTail:m.z.string().max(32768).optional(),logTruncated:m.z.boolean().optional(),error:Vt.optional(),requestedAt:at,startedAt:at.optional(),finishedAt:at.optional(),updatedAt:at}).strict(),qt=m.z.object({streamId:st,sequence:m.z.number().int().nonnegative(),capabilities:Rt,apps:m.z.array(Mt).max(256),activeJobs:m.z.array(Ht).max(256),recentJobs:m.z.array(Ht).max(256),observedAt:at}).strict();m.z.object({requestId:st.optional()}).strict(),m.z.object({job:Ht}).strict(),m.z.object({type:m.z.literal("app-management"),streamId:st,sequence:m.z.number().int().nonnegative(),observedAt:at,job:Ht.optional(),snapshot:qt.optional()}).strict().refine(e=>void 0!==e.job||void 0!==e.snapshot,{message:"An app management event requires a job or snapshot."});const Bt=m.z.object({component:m.z.enum(["control-plane","node-agent","controlled-instance"]),packageName:m.z.string().trim().max(160).optional(),packageVersion:m.z.string().trim().max(80).optional(),protocolVersion:ot.optional(),buildId:m.z.string().trim().max(160).optional(),builtAt:m.z.string().trim().max(120).optional(),gitCommit:m.z.string().trim().max(120).optional(),imageRef:m.z.string().trim().max(512).optional(),imageDigest:m.z.string().trim().max(240).optional()}).strict(),Kt=m.z.enum(["stable","beta","alpha"]),Gt=m.z.object({packageName:m.z.literal("@task-handoff/controlled-instance"),version:m.z.string().trim().min(1).max(80),platform:m.z.string().trim().min(1).max(40),arch:m.z.string().trim().min(1).max(40),formatVersion:m.z.number().int().positive(),launcherAbi:m.z.number().int().positive(),entrypoint:m.z.string().trim().min(1).max(512),sha256:m.z.string().regex(/^[a-f0-9]{64}$/)}).strict(),Jt=m.z.object({code:m.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:m.z.string().trim().min(1).max(4096),expectedVersion:m.z.string().trim().min(1).max(80).optional(),actualVersion:m.z.string().trim().min(1).max(80).optional(),retryable:m.z.boolean().default(!1)}).strict(),Wt=m.z.object({desiredVersion:m.z.string().trim().min(1).max(80),actualVersion:m.z.string().trim().min(1).max(80).optional(),phase:m.z.enum(["pending","draining","installing","restarting","verifying","matched","failed"]),attempt:m.z.number().int().nonnegative().default(0),lastAttemptAt:at.optional(),matchedAt:at.optional(),error:Jt.optional()}).strict(),Yt=m.z.object({runningInstanceCount:m.z.number().int().nonnegative(),stoppedInstanceCount:m.z.number().int().nonnegative(),activeInstanceCount:m.z.number().int().nonnegative(),restartInstanceCount:m.z.number().int().nonnegative(),runningInstanceIds:m.z.array(st).max(1024).default([]),stoppedInstanceIds:m.z.array(st).max(1024).default([]),activeInstanceIds:m.z.array(st).max(1024).default([])}).strict(),Xt=m.z.object({phase:m.z.enum(["queued","updating-node","restarting-node","converging-instances","succeeded","degraded","failed"]),desiredVersion:m.z.string().trim().min(1).max(80),nodeVersion:m.z.string().trim().min(1).max(80).optional(),expectedInstanceIds:m.z.array(st).max(1024).default([]),expectedInstanceCount:m.z.number().int().nonnegative(),matchedInstanceCount:m.z.number().int().nonnegative(),pendingInstanceCount:m.z.number().int().nonnegative(),failedInstanceCount:m.z.number().int().nonnegative(),deferredInstanceCount:m.z.number().int().nonnegative().default(0)}).strict(),Qt=m.z.object({channel:Kt.default("stable")}).strict(),Zt=m.z.object({source:m.z.literal("npm"),channel:Kt,currentVersion:m.z.string().trim().max(240).optional(),availableVersion:m.z.string().trim().min(1).max(240),artifactRef:m.z.string().trim().min(1).max(512).optional(),runtimeArtifacts:m.z.array(Gt).default([]),impact:Yt,updateAvailable:m.z.boolean(),supported:m.z.boolean().default(!0),reason:m.z.string().trim().max(2048).optional(),checkedAt:at,preflightToken:m.z.string().trim().min(16).max(240).optional()}).strict(),en=m.z.object({id:st,nodeId:st,source:m.z.literal("npm"),channel:Kt,fromVersion:m.z.string().trim().max(240).optional(),toVersion:m.z.string().trim().min(1).max(240),artifactRef:m.z.string().trim().min(1).max(512).optional(),runtimeArtifacts:m.z.array(Gt).default([]),impact:Yt,rollout:Xt,status:m.z.enum(["queued","updating-node","restarting-node","converging-instances","succeeded","degraded","failed"]),error:Jt.optional(),startedAt:at.optional(),completedAt:at.optional(),createdAt:at,updatedAt:at}).strict(),tn=m.z.object({channel:Kt,targetVersion:m.z.string().trim().min(1).max(240),preflightToken:m.z.string().trim().min(16).max(240)}).strict(),nn=m.z.object({type:m.z.enum(["branch","tag","commit"]),name:m.z.string().trim().min(1).max(240).optional(),commit:m.z.string().trim().max(80).optional()}).strict(),rn=m.z.object({type:m.z.enum(["none","ssh-key","https-token"]).default("none"),secretId:m.z.string().trim().min(1).max(120).optional()}).strict(),on=m.z.object({depth:m.z.number().int().positive().max(1e5).optional(),submodules:m.z.boolean().default(!1),lfs:m.z.boolean().default(!1),subdirectory:m.z.string().trim().max(240).default("")}).strict();m.z.object({id:st,name:m.z.string().trim().min(1).max(160),url:m.z.string().trim().min(1).max(2048),provider:m.z.string().trim().max(80).optional(),ref:nn.default({type:"branch",name:"main"}),auth:rn.default({type:"none"}),clone:on.default({submodules:!1,lfs:!1,subdirectory:""}),defaultImageSelection:Nt.optional(),labels:ct,createdAt:at,updatedAt:at}).strict();const sn=m.z.object({id:st,nodeId:st,name:m.z.string().trim().min(1).max(160),path:m.z.string().trim().min(1).max(4096),defaultImageSelection:Nt.optional(),labels:ct,createdAt:at,updatedAt:at}).strict(),an=m.z.discriminatedUnion("type",[m.z.object({type:m.z.literal("git-repository"),repositoryId:st.optional(),url:m.z.string().trim().min(1).max(2048),provider:m.z.string().trim().max(80).optional(),ref:nn.default({type:"branch",name:"main"}),auth:rn.default({type:"none"}),clone:on.default({submodules:!1,lfs:!1,subdirectory:""})}).strict(),m.z.object({type:m.z.literal("git-template"),url:m.z.string().trim().min(1).max(2048),templateId:m.z.string().trim().min(1).max(120).optional(),ref:nn.default({type:"branch",name:"main"}),auth:rn.default({type:"none"}),clone:on.default({submodules:!1,lfs:!1,subdirectory:""})}).strict(),m.z.object({type:m.z.literal("local-folder"),localFolderId:st.optional(),path:m.z.string().trim().min(1).max(4096),ownerNodeId:st.optional()}).strict()]),cn=m.z.object({mode:m.z.enum(["local-bind","git-clone","empty-volume","persistent-volume"]),path:m.z.string().trim().min(1).max(4096).default("/workspace"),volumeName:m.z.string().trim().max(240).optional(),readOnly:m.z.boolean().default(!1)}).strict(),dn=m.z.enum(["codex","claude"]),ln=m.z.object({id:st,name:m.z.string().trim().min(1).max(160),source:an,defaultImageSelection:Nt.optional(),defaultNodeId:st.optional(),defaultRuntimeId:st.optional(),workspacePolicy:cn,labels:ct,createdAt:at,updatedAt:at}).strict(),un=m.z.object({id:st,name:m.z.string().trim().min(1).max(160),endpoint:m.z.string().trim().min(1).max(2048),key:m.z.string().trim().min(1).max(4096),model:m.z.string().trim().min(1).max(240),app:dn,enabled:m.z.boolean().default(!0),order:m.z.number().int().min(0).max(1e6).default(0),labels:ct,createdAt:at,updatedAt:at}).strict(),mn=un,pn=un.omit({key:!0}).extend({keyPreview:m.z.string().trim().min(1).max(160),keySet:m.z.boolean()}).strict(),gn=pn.extend({referenceCount:m.z.number().int().min(0)}).strict(),hn=m.z.object({instanceId:st,codexModelHash:st.optional(),claudeModelHash:st.optional(),updatedAt:at}).strict(),fn=m.z.discriminatedUnion("type",[m.z.object({type:m.z.literal("control-plane"),name:un.shape.name,enabled:un.shape.enabled,order:un.shape.order}).strict(),m.z.object({type:m.z.literal("node"),nodeId:st,name:un.shape.name,enabled:un.shape.enabled,order:un.shape.order,referenceCount:m.z.number().int().min(0)}).strict()]),yn=m.z.object({id:st,model:pn,locations:m.z.array(fn).min(1),referenceCount:m.z.number().int().min(0).default(0)}).strict(),In=m.z.object({nodeId:st,code:m.z.string().trim().min(1).max(120),message:m.z.string().trim().min(1).max(2e3)}).strict();m.z.object({models:m.z.array(yn),nodeDiagnostics:m.z.array(In).default([]),updatedAt:at}).strict();const An=un.omit({id:!0,createdAt:!0,updatedAt:!0}).strict(),bn=An.partial().strict(),wn=un,Nn=m.z.object({modelSelection:wt,codexModelHash:st.optional(),claudeModelHash:st.optional()}).strict();function zn(e){const t={app:dn.parse(e.app),endpoint:un.shape.endpoint.parse(e.endpoint),key:un.shape.key.parse(e.key),model:un.shape.model.parse(e.model)};return`mdl_${r.createHash("sha256").update(JSON.stringify(t)).digest("hex")}`}const vn=m.z.enum(["market","custom"]),En=m.z.enum(["active","deprecated","yanked"]),Sn=m.z.discriminatedUnion("kind",[m.z.object({kind:m.z.literal("builtin"),key:m.z.string().trim().min(1).max(120)}).strict(),m.z.object({kind:m.z.literal("remote"),url:m.z.string().trim().url().max(2048),mediaType:m.z.enum(["image/png","image/jpeg","image/webp"]).optional(),digest:bt.optional()}).strict()]),_n=m.z.array(m.z.string().trim().min(1).max(80)).default([]),Tn=m.z.array(m.z.string().trim().min(1).max(120)).default([]),kn=m.z.record(m.z.string().trim().min(2).max(35),m.z.string().trim().min(1).max(4096)),Cn=m.z.object({os:m.z.string().trim().min(1).max(40),architecture:m.z.string().trim().min(1).max(40),digest:bt.optional(),downloadSizeBytes:m.z.number().int().positive().optional(),unpackedSizeBytes:m.z.number().int().positive().optional()}).strict(),On=m.z.object({name:m.z.string().trim().min(1).max(128).regex(pt),version:m.z.string().trim().min(1).max(160).optional(),reference:At,manifestDigest:bt.optional(),publishedAt:at.optional(),platforms:m.z.array(Cn).default([]),status:En.default("active")}).strict(),xn=m.z.object({id:st,publisher:m.z.string().trim().min(1).max(160),slug:m.z.string().trim().min(1).max(160),name:m.z.string().trim().min(1).max(160),description:m.z.string().trim().min(1).max(4096),localizedDescriptions:kn.optional(),cover:Sn.optional(),repository:m.z.string().trim().min(1).max(512),defaultTag:m.z.string().trim().min(1).max(128).regex(pt),tags:m.z.array(On).min(1),capabilities:_n,optionalApps:Tn,defaultEnv:dt,labels:ct,status:En.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."})});m.z.object({protocolVersion:lt,catalogId:st,revision:m.z.string().trim().min(1).max(240),source:m.z.enum(["embedded","remote","cache"]),generatedAt:at,expiresAt:at.optional(),items:m.z.array(xn)}).strict(),m.z.object({source:m.z.enum(["embedded","remote","cache"]),state:m.z.enum(["ready","refreshing","stale","failed"]),revision:m.z.string().trim().min(1).max(240),updatedAt:at,error:m.z.string().trim().max(4096).optional()}).strict(),m.z.object({id:st,origin:m.z.literal("custom"),name:m.z.string().trim().min(1).max(160),description:m.z.string().trim().max(4096).optional(),localizedDescriptions:kn.optional(),cover:Sn.optional(),reference:At,repository:m.z.string().trim().min(1).max(512),tag:m.z.string().trim().min(1).max(128).regex(pt).optional(),pullPolicy:m.z.literal("if-not-present").default("if-not-present"),capabilities:_n,optionalApps:Tn,defaultEnv:dt,labels:ct,createdAt:at,updatedAt:at}).strict();const Rn=m.z.object({name:m.z.string().trim().min(1).max(128).regex(pt),version:m.z.string().trim().min(1).max(160).optional(),reference:At,manifestDigest:bt.optional(),status:En}).strict(),Dn=m.z.object({id:st,origin:vn,name:m.z.string().trim().min(1).max(160),description:m.z.string().trim().max(4096).optional(),localizedDescriptions:kn.optional(),cover:Sn,repository:m.z.string().trim().min(1).max(512),tag:m.z.string().trim().min(1).max(128).regex(pt).optional(),availableTags:m.z.array(Rn),reference:At,digest:bt.optional(),downloadSizeBytes:m.z.number().int().positive().optional(),unpackedSizeBytes:m.z.number().int().positive().optional(),capabilities:_n,optionalApps:Tn,defaultEnv:dt,labels:ct,readOnly:m.z.boolean(),lifecycleStatus:En.optional(),market:m.z.object({catalogId:st,catalogRevision:m.z.string().trim().min(1).max(240),publisher:m.z.string().trim().min(1).max(160),version:m.z.string().trim().min(1).max(160).optional()}).strict().optional()}).strict(),Pn=m.z.object({id:st,origin:vn,name:m.z.string().trim().min(1).max(160),description:m.z.string().trim().max(4096).optional(),localizedDescriptions:kn.optional(),cover:Sn.optional(),repository:m.z.string().trim().min(1).max(512),tag:m.z.string().trim().min(1).max(128).regex(pt).optional(),requestedReference:At,resolvedDigest:bt.optional(),resolvedReference:At.optional(),downloadSizeBytes:m.z.number().int().positive().optional(),pullPolicy:m.z.literal("if-not-present").default("if-not-present"),capabilities:_n,optionalApps:Tn,defaultEnv:dt,labels:ct,market:m.z.object({catalogId:st,catalogRevision:m.z.string().trim().min(1).max(240),publisher:m.z.string().trim().min(1).max(160),version:m.z.string().trim().min(1).max(160).optional()}).strict().optional(),createdAt:at,updatedAt:at}).strict(),jn=m.z.object({phase:m.z.enum(["checking-image","pulling-image","resolving-image","ready","failed"]),requestedReference:At,generation:m.z.number().int().nonnegative().default(0),error:m.z.string().trim().max(4096).optional(),startedAt:at,updatedAt:at}).strict(),Mn="image.pull.terminal.output",Ln="image.pull.terminal.finished",$n=m.z.object({instanceId:st,generation:m.z.number().int().nonnegative(),requestedReference:At,sequence:m.z.number().int().nonnegative(),observedAt:at}).strict(),Fn=$n.extend({data:m.z.string().min(1).max(65536),replay:m.z.boolean().optional()}).strict(),Un=$n.extend({outcome:m.z.enum(["succeeded","failed"])}).strict();$n.extend({status:m.z.enum(["connecting","pulling","extracting","complete","failed"]),layers:m.z.object({total:m.z.number().int().nonnegative(),completed:m.z.number().int().nonnegative(),downloaded:m.z.number().int().nonnegative(),downloading:m.z.number().int().nonnegative(),extracting:m.z.number().int().nonnegative()}).strict(),bytes:m.z.object({current:m.z.number().finite().nonnegative(),total:m.z.number().finite().positive()}).strict().optional(),percent:m.z.number().finite().min(0).max(100).optional(),message:m.z.string().trim().min(1).max(500),terminalTail:m.z.string().max(262144).optional(),terminalTruncated:m.z.boolean().optional()}).strict();const Vn=m.z.discriminatedUnion("kind",[m.z.object({kind:m.z.literal("direct")}).strict(),m.z.object({kind:m.z.literal("control-plane-proxy"),proxyId:st,proxyBindingId:st,targetNodeId:st}).strict()]),Hn=m.z.object({reachability:m.z.enum(["unknown","reachable","unreachable"]),bindingStatus:m.z.enum(["unknown","active","revoked"]),bindingRevision:m.z.number().int().positive().optional(),streamId:m.z.string().trim().min(1).max(160).optional(),revision:m.z.number().int().nonnegative().optional(),observedAt:at.optional(),target:Ze.optional(),lastError:Je.optional(),updatedAt:at}).strict(),qn=m.z.object({id:st,name:m.z.string().trim().min(1).max(160),connectionMode:m.z.enum(["local-ipc","local-loopback","direct-http","reverse-wss","control-plane-proxy"]).default("direct-http"),connectionPath:Vn.default({kind:"direct"}),connectionEnabled:m.z.boolean().default(!0),auth:m.z.object({mode:m.z.enum(["local-static-key","paired-hmac","proxy-binding"]).default("local-static-key"),keyId:st.optional(),secret:m.z.string().trim().max(4096).optional(),pairedAt:at.optional(),pairing:m.z.object({status:m.z.enum(["pending","paired","expired"]).default("pending"),joinToken:m.z.string().trim().max(4096).optional(),expiresAt:at.optional()}).strict().optional()}).strict().default({mode:"local-static-key"}),endpoint:m.z.string().trim().max(2048).optional(),controlEndpoint:m.z.string().trim().max(2048).optional(),containerEndpoint:m.z.string().trim().max(2048).optional(),publicWebBase:m.z.string().trim().max(2048).optional(),status:m.z.enum(["unknown","online","offline","degraded"]).default("unknown"),health:m.z.enum(["unknown","ok","degraded","failed"]).default("unknown"),capabilities:m.z.record(m.z.string(),m.z.unknown()).default({}),proxyState:Hn.optional(),appInventory:Tt.optional(),labels:ct,lastSeenAt:at.optional(),createdAt:at,updatedAt:at}).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."})}),Bn=m.z.object({id:st,nodeId:st,name:m.z.string().trim().min(1).max(160),type:m.z.enum(["docker","kubernetes","local"]),status:m.z.enum(["unknown","online","offline","degraded"]).default("unknown"),accessStrategy:m.z.enum(["node-proxy","direct-port","kubernetes-ingress","kubernetes-port-forward"]).default("node-proxy"),capabilities:m.z.record(m.z.string(),m.z.unknown()).default({}),labels:ct,createdAt:at,updatedAt:at}).strict(),Kn=m.z.object({instanceId:st,runtimeKind:m.z.literal("docker"),state:m.z.enum(["pending","available","stopped","unavailable"]),sampledAt:at,cpu:m.z.object({usagePercent:m.z.number().nonnegative()}).strict().optional(),memory:m.z.object({usageBytes:m.z.number().nonnegative(),limitBytes:m.z.number().nonnegative().optional(),usagePercent:m.z.number().nonnegative().optional()}).strict().optional(),network:m.z.object({rxBytes:m.z.number().nonnegative(),txBytes:m.z.number().nonnegative()}).strict().optional(),blockIo:m.z.object({readBytes:m.z.number().nonnegative(),writeBytes:m.z.number().nonnegative()}).strict().optional(),pids:m.z.number().int().nonnegative().optional(),error:m.z.string().trim().max(2048).optional()}).strict();m.z.object({ok:m.z.boolean().optional(),role:m.z.string().optional(),nodeId:st.optional(),platform:kt.optional()}).passthrough();const Gn=m.z.object({bindScope:m.z.enum(["loopback","all-ipv4"]),port:m.z.number().int().min(1).max(65535)}).strict(),Jn=Gn.extend({host:m.z.enum(["127.0.0.1","0.0.0.0"]),status:m.z.enum(["listening","error"]),source:m.z.enum(["bootstrap","persisted"]),error:m.z.string().trim().max(2048).optional()}).strict(),Wn=Gn;m.z.object({nodeId:st,joinToken:m.z.string().trim().min(1),expiresAt:at}).passthrough();const Yn=m.z.object({id:st,keyId:st,name:m.z.string().trim().min(1).max(160).optional(),pairedAt:at,updatedAt:at,current:m.z.boolean()}).passthrough();m.z.object({id:st,pairingKeyId:st,url:m.z.string().trim().min(1).max(2048),name:m.z.string().trim().min(1).max(160).optional(),enabled:m.z.boolean(),createdAt:at,updatedAt:at,status:m.z.enum(["disabled","connecting","connected","reconnecting","failed"]),lastConnectedAt:at.optional(),lastDisconnectedAt:at.optional(),error:m.z.string().optional()}).passthrough(),m.z.object({pairing:Yn,connection:m.z.object({id:st,pairingKeyId:st,url:m.z.string().trim().min(1).max(2048),name:m.z.string().trim().min(1).max(160).optional(),enabled:m.z.boolean(),createdAt:at,updatedAt:at}).passthrough(),tunnel:m.z.object({status:m.z.enum(["disabled","saved","connecting","connected","failed"]),error:m.z.string().trim().max(2048).optional()}).passthrough()}).passthrough(),m.z.object({deleted:m.z.boolean().optional()}).passthrough();const Xn=m.z.object({repository:m.z.string().trim().optional(),tag:m.z.string().trim().optional(),id:m.z.string().trim(),createdSince:m.z.string().trim().optional(),size:m.z.string().trim().optional(),sizeBytes:m.z.number().int().nonnegative().optional(),reference:m.z.string().trim().min(1),repoDigests:m.z.array(m.z.string().trim().min(1).max(512)).default([])}).passthrough();m.z.object({image:Dn,status:m.z.enum(["available","pull-required","unknown"]),localImage:Xn.optional(),localSizeBytes:m.z.number().int().nonnegative().optional(),downloadSizeBytes:m.z.number().int().positive().optional(),unpackedSizeBytes:m.z.number().int().positive().optional(),error:m.z.string().trim().max(2048).optional()}).strict();const Qn=m.z.lazy(()=>m.z.object({name:m.z.string().trim().min(1),path:m.z.string().trim().min(1).max(4096),children:m.z.array(Qn)}).passthrough());m.z.object({status:m.z.number().int().min(100).max(599).optional(),headers:m.z.record(m.z.string(),m.z.string()).optional(),bodyBase64:m.z.string().optional()}).passthrough();const Zn=m.z.object({strategy:m.z.enum(["node-proxy","direct-port","kubernetes-ingress","kubernetes-port-forward"]).default("node-proxy"),web:m.z.string().trim().max(2048).optional(),api:m.z.string().trim().max(2048).optional(),vnc:m.z.string().trim().max(2048).optional(),tty:m.z.string().trim().max(2048).optional(),logs:m.z.string().trim().max(2048).optional(),status:m.z.enum(["unknown","reachable","endpoint-unreachable"]).default("unknown")}).strict(),er=m.z.object({strategy:m.z.enum(["control-plane-proxy","direct-port","node-proxy","kubernetes-ingress","kubernetes-port-forward"]).default("control-plane-proxy"),web:m.z.string().trim().max(2048).optional(),api:m.z.string().trim().max(2048).optional(),ws:m.z.string().trim().max(2048).optional(),status:m.z.enum(["unknown","reachable","endpoint-unreachable"]).default("unknown")}).strict().default({strategy:"control-plane-proxy",status:"unknown"}),tr=m.z.object({mode:m.z.enum(["local-bind","git-clone","empty-volume","persistent-volume"]).optional(),status:m.z.enum(["unknown","pending","ready","failed"]).default("unknown"),path:m.z.string().trim().max(4096).optional(),resolvedCommit:m.z.string().trim().max(120).optional(),error:m.z.string().trim().max(2048).optional()}).passthrough(),nr=m.z.object({id:st,name:m.z.string().trim().min(1).max(160),projectId:st.optional(),source:an,sourceSnapshot:m.z.record(m.z.string(),m.z.unknown()).default({}),modelSelection:wt,nodeId:st,runtimeId:st,imageSelection:Nt.optional(),imageSnapshot:Pn.optional(),imageProvisioning:jn.optional(),stateRevision:m.z.number().int().min(0).default(0),processIncarnationId:m.z.string().trim().min(1).max(120).optional(),status:m.z.enum(["created","provisioning","starting","registering","registered","running","stopping","stopped","failed","unhealthy"]).default("created"),health:m.z.enum(["unknown","ok","degraded","failed"]).default("unknown"),connectionStatus:m.z.enum(["unknown","online","offline","endpoint-unreachable"]).default("unknown"),agentStatus:m.z.enum(["unknown","online","offline"]).default("unknown"),targetStatus:m.z.enum(["unknown","reachable","endpoint-unreachable"]).default("unknown"),uiAccessStatus:m.z.enum(["unknown","reachable","endpoint-unreachable"]).default("unknown"),controlMode:m.z.enum(["standalone","controlled"]).default("controlled"),protocolVersion:ot.optional(),instanceVersion:m.z.string().trim().max(80).optional(),build:Bt.optional(),runtimeVersion:Wt.optional(),ready:m.z.boolean().default(!1),capabilities:m.z.record(m.z.string(),m.z.unknown()).default({}),appInventory:Tt.optional(),config:m.z.object({autoImportAgentConfigs:m.z.boolean().default(!0),defaultCodexPermissionMode:se.default("ask")}).strict().default({autoImportAgentConfigs:!0,defaultCodexPermissionMode:"ask"}),workspace:tr.default({status:"unknown"}),target:Zn.default({strategy:"direct-port",status:"unknown"}),access:er,apps:m.z.object({runningCount:m.z.number().int().min(0).default(0),problemCount:m.z.number().int().min(0).default(0),updatedAt:at.optional(),revision:m.z.number().int().min(0).optional()}).strict().default({runningCount:0,problemCount:0}),aiSessions:ve.default(()=>({runningCount:0,waitingCount:0,staleCount:0,sessions:[],updatedAt:(new Date).toISOString()})),triggers:m.z.object({enabledCount:m.z.number().int().min(0).default(0),runningCount:m.z.number().int().min(0).default(0),errorCount:m.z.number().int().min(0).default(0),configs:m.z.array(m.z.object({configHash:m.z.string().trim().min(1),config:Me,deployments:m.z.array($e).default([]),runtime:m.z.array(Fe).default([])}).strict()).default([]),recentRuns:m.z.array(Ue).default([])}).strict().optional(),runtime:m.z.object({kind:m.z.string().trim().max(80).optional(),containerName:m.z.string().trim().max(240).optional(),containerId:m.z.string().trim().max(240).optional(),workspacePath:m.z.string().trim().max(4096).optional(),pid:m.z.number().int().positive().optional(),port:m.z.number().int().positive().max(65535).optional(),labels:m.z.record(m.z.string(),m.z.string()).default({})}).strict().default({labels:{}}),registrationToken:m.z.string().trim().min(1).max(240).optional(),lastHeartbeatAt:at.optional(),createdAt:at,updatedAt:at}).strict(),rr="instance.lifecycle.snapshot",ir=m.z.object({instanceId:nr.shape.id,revision:m.z.number().int().min(0),updatedAt:at,status:nr.shape.status.unwrap(),health:nr.shape.health.unwrap(),connectionStatus:nr.shape.connectionStatus.unwrap(),accessStatus:m.z.enum(["reachable","endpoint-unreachable"]),imageProvisioning:jn.optional(),workspace:tr,runtime:nr.shape.runtime.unwrap(),runtimeVersion:Wt.optional(),ready:m.z.boolean(),lastHeartbeatAt:at.optional()}).strict();function or(e,t){return nr.safeParse(sr(e,t))}function sr(e,t){if(!e||"object"!=typeof e||Array.isArray(e))return e;const n=e,r=new Set(Object.keys(nr.shape)),i={};for(const[e,o]of Object.entries(n))r.has(e)?i[e]=o:t?.({instanceId:"string"==typeof n.id?n.id:void 0,field:e});if(n.capabilities&&"object"==typeof n.capabilities&&!Array.isArray(n.capabilities)){const e={...n.capabilities};Object.prototype.hasOwnProperty.call(e,"apps")&&(t?.({instanceId:"string"==typeof n.id?n.id:void 0,field:"capabilities.apps"}),delete e.apps),i.capabilities=e}else i.capabilities={};i.appInventory=function(e,t,n){if(!e||"object"!=typeof e||Array.isArray(e))return;const r=e;Object.keys(r).some(e=>!["observedAt","items","issues"].includes(e))&&t?.({instanceId:n,field:"appInventory"});const i={observedAt:r.observedAt,items:Array.isArray(r.items)?r.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 r=dr(e,["id","name","kind","source","availability","diagnosticCode"]);return!r||"object"!=typeof r||Array.isArray(r)?r:{...r,capabilities:dr(e.capabilities,["automation","supportsCwdSelection"])}}):r.items,issues:Array.isArray(r.issues)?r.issues.map(e=>dr(e,["code","message"])):r.issues},o=Tt.safeParse(i);return o.success?o.data:void 0}(n.appInventory,t,"string"==typeof n.id?n.id:void 0),i.source=function(e,t,n){if(!e||"object"!=typeof e||Array.isArray(e))return e;const r=e,i=r.type,o=an.options.find(e=>e.shape.type.value===i);if(!o)return e;const s="local-folder"===i?["type","localFolderId","path","ownerNodeId"]:"git-template"===i?["type","url","templateId","ref","auth","clone"]:["type","repositoryId","url","provider","ref","auth","clone"],a=dr(r,s);if("local-folder"!==i){const e=ar(nn,dr(r.ref,["type","name","commit"]),"source.ref",t,n),i=ar(rn,dr(r.auth,["type","secretId"]),"source.auth",t,n),o=ar(on,dr(r.clone,["depth","submodules","lfs","subdirectory"]),"source.clone",t,n);e?a.ref=e:delete a.ref,i?a.auth=i:delete a.auth,o?a.clone=o:delete a.clone}const c=ar(o,a,"source",t,n);return c?(Object.keys(r).some(e=>!s.includes(e))&&t?.({instanceId:n,field:"source"}),c):a}(n.source,t,"string"==typeof n.id?n.id:void 0),i.sourceSnapshot=n.sourceSnapshot&&"object"==typeof n.sourceSnapshot&&!Array.isArray(n.sourceSnapshot)?n.sourceSnapshot:{},i.build=ar(Bt,n.build,"build",t,"string"==typeof n.id?n.id:void 0),i.aiSessions=function(e,t,n){if(!e||"object"!=typeof e||Array.isArray(e))return;const r=e,i=Array.isArray(r.sessions)?r.sessions.flatMap((e,r)=>{const i=ar(ze,e,`aiSessions.sessions.${r}`,t,n);return i?[i]:[]}):[],o={runningCount:"number"==typeof r.runningCount&&Number.isInteger(r.runningCount)&&r.runningCount>=0?r.runningCount:0,waitingCount:"number"==typeof r.waitingCount&&Number.isInteger(r.waitingCount)&&r.waitingCount>=0?r.waitingCount:0,staleCount:"number"==typeof r.staleCount&&Number.isInteger(r.staleCount)&&r.staleCount>=0?r.staleCount:0,sessions:i,updatedAt:at.safeParse(r.updatedAt).success?r.updatedAt:(new Date).toISOString()};return Object.keys(r).some(e=>!["runningCount","waitingCount","staleCount","sessions","updatedAt"].includes(e))&&t?.({instanceId:n,field:"aiSessions"}),ve.parse(o)}(n.aiSessions,t,"string"==typeof n.id?n.id:void 0),i.triggers=function(e,t,n){if(!e||"object"!=typeof e||Array.isArray(e))return;const r=e;Object.keys(r).some(e=>!["enabledCount","runningCount","errorCount","configs","recentRuns"].includes(e))&&t?.({instanceId:n,field:"triggers"});const i=(e,r,i)=>Array.isArray(e)?e.flatMap((e,o)=>{const s=ar(r,e,`${i}.${o}`,t,n);return s?[s]:[]}):[],o=Array.isArray(r.configs)?r.configs.flatMap((e,r)=>{if(!e||"object"!=typeof e||Array.isArray(e))return[];const o=e;Object.keys(o).some(e=>!["configHash","config","deployments","runtime"].includes(e))&&t?.({instanceId:n,field:`triggers.configs.${r}`});const s=function(e,t,n,r){if(!e||"object"!=typeof e||Array.isArray(e))return;const i=e,o=dr(i,["configHash","name","description","createdAt","updatedAt"]);if(i.source&&"object"==typeof i.source&&!Array.isArray(i.source)){const e=i.source,t="schedule"===e.type?"interval"===e.scheduleKind?["type","scheduleKind","intervalMs"]:"daily"===e.scheduleKind?["type","scheduleKind","timeOfDay","timezone"]:["type","scheduleKind","weekdays","timeOfDay","timezone"]:"file-change"===e.type?["type","roots","globs","ignore","debounceMs"]:["type","agent","statuses","phases"];o.source=dr(e,t)}return o.action=dr(i.action,["promptTemplate"]),o.policy=dr(i.policy,["cooldownMs","maxConcurrentRuns","whenBusy"]),ar(Me,o,t,n,r)}(o.config,`triggers.configs.${r}.config`,t,n);return"string"==typeof o.configHash&&s?[{configHash:o.configHash,config:s,deployments:i(o.deployments,$e,`triggers.configs.${r}.deployments`),runtime:i(o.runtime,Fe,`triggers.configs.${r}.runtime`)}]:[]}):[];return{enabledCount:"number"==typeof r.enabledCount&&Number.isInteger(r.enabledCount)&&r.enabledCount>=0?r.enabledCount:0,runningCount:"number"==typeof r.runningCount&&Number.isInteger(r.runningCount)&&r.runningCount>=0?r.runningCount:0,errorCount:"number"==typeof r.errorCount&&Number.isInteger(r.errorCount)&&r.errorCount>=0?r.errorCount:0,configs:o,recentRuns:i(r.recentRuns,Ue,"triggers.recentRuns")}}(n.triggers,t,"string"==typeof n.id?n.id:void 0),i.apps=ar(nr.shape.apps.unwrap(),dr(n.apps,["runningCount","problemCount","updatedAt","revision"]),"apps",t,"string"==typeof n.id?n.id:void 0)||{runningCount:0,problemCount:0},i.config=ar(nr.shape.config.unwrap(),dr(n.config,["autoImportAgentConfigs","defaultCodexPermissionMode"]),"config",t,"string"==typeof n.id?n.id:void 0)||{autoImportAgentConfigs:!0,defaultCodexPermissionMode:"ask"},i.modelSelection=ar(wt.unwrap(),dr(n.modelSelection,["codexModelHash","claudeModelHash"]),"modelSelection",t,"string"==typeof n.id?n.id:void 0)||{},i.imageSnapshot=function(e,t,n,r){if(!e||"object"!=typeof e||Array.isArray(e))return e;const i=e,o=function(e){if(!e||"object"!=typeof e||Array.isArray(e))return e;const t=e,n=new Set(["id","origin","name","description","localizedDescriptions","cover","reference","repository","tag","image","registry","pullPolicy","capabilities","optionalApps","defaultEnv","labels","createdAt","updatedAt"]);for(const e of Object.keys(t))n.has(e);"string"==typeof t.id&&t.id;const r="string"==typeof t.image?t.image:void 0;Object.prototype.hasOwnProperty.call(t,"registry");let i,o="string"==typeof t.reference?t.reference:r;if(o)try{o=yt(o)}catch{if(!o.includes("@")&&o.lastIndexOf(":")<=o.lastIndexOf("/"))try{o=yt(`${o}:latest`)}catch{}}try{i=o?It(o):void 0}catch{}return{id:t.id,origin:"custom",name:t.name,description:t.description,localizedDescriptions:t.localizedDescriptions,cover:dr(t.cover,["kind","key","url","mediaType","digest"]),reference:i?.reference??o,repository:i?.repository??t.repository,tag:i?.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}}(i),{reference:s,...a}=o,c=i.requestedReference??s;let d;try{d="string"==typeof c?It(c):void 0}catch{}const l={img_default:"market_taskhandoff_browser",img_codex:"market_taskhandoff_codex",img_ai:"market_taskhandoff_ai"},u="string"==typeof i.id?i.id:"string"==typeof t?t:void 0,m="market"===i.origin||u&&l[u]?"market":"custom";return void 0===i.image&&void 0===i.reference||n?.({instanceId:r,field:"imageSnapshot.reference"}),{...a,id:u&&l[u]?l[u]:u,origin:m,repository:d?.repository??i.repository,tag:d?.tag??i.tag,requestedReference:d?.reference??c,resolvedDigest:i.resolvedDigest,resolvedReference:i.resolvedReference,downloadSizeBytes:i.downloadSizeBytes,market:"market"===m?dr(i.market,["catalogId","catalogRevision","publisher","version"])??{catalogId:"task_handoff_embedded",catalogRevision:"legacy",publisher:"task-handoff"}:void 0}}(n.imageSnapshot,n.imageId,t,"string"==typeof n.id?n.id:void 0);const o="string"==typeof n.imageId?{img_default:"market_taskhandoff_browser",img_codex:"market_taskhandoff_codex",img_ai:"market_taskhandoff_ai"}[n.imageId]||n.imageId:void 0,s=dr(n.imageSelection,["imageId","tag"]);i.imageSelection=s||(o?{imageId:o,tag:i.imageSnapshot?.tag}:void 0),i.imageProvisioning=ar(jn,dr(n.imageProvisioning,["phase","requestedReference","generation","error","startedAt","updatedAt"]),"imageProvisioning",t,"string"==typeof n.id?n.id:void 0),i.runtimeVersion=function(e,t,n){if(!e||"object"!=typeof e||Array.isArray(e))return;const r=e,i=e=>{if("string"!=typeof e)return;const t=e.trim();return t&&t.length<=80?t:void 0},o=i(r.desiredVersion);if(!o)return void t?.({instanceId:n,field:"runtimeVersion.desiredVersion"});const s=new Set(Wt.shape.phase.options),a="string"==typeof r.phase?r.phase:"pending",c=s.has(a)?a:{idle:"pending",queued:"pending",checking:"pending",downloading:"installing",updating:"installing",completed:"matched",succeeded:"matched",ready:"matched",error:"failed"}[a]||"pending";let d;if(c!==a&&t?.({instanceId:n,field:"runtimeVersion.phase"}),r.error&&"object"==typeof r.error&&!Array.isArray(r.error)){const e=r.error,o="string"==typeof e.message?e.message.trim().slice(0,4096):"";if(o){const r=new Set(Jt.shape.code.options),s="string"==typeof e.code&&r.has(e.code)?e.code:"INSTANCE_RUNTIME_INSTALL_FAILED";s!==e.code&&t?.({instanceId:n,field:"runtimeVersion.error.code"});const a=i(e.expectedVersion),c=i(e.actualVersion);d={code:s,message:o,...a?{expectedVersion:a}:{},...c?{actualVersion:c}:{},retryable:!0===e.retryable}}else t?.({instanceId:n,field:"runtimeVersion.error"})}"string"==typeof r.error&&r.error.trim()&&(d={code:"INSTANCE_RUNTIME_INSTALL_FAILED",message:r.error.trim().slice(0,4096),expectedVersion:o,...i(r.actualVersion)?{actualVersion:i(r.actualVersion)}:{},retryable:!1});const l=i(r.actualVersion),u=at.safeParse(r.lastAttemptAt),m=at.safeParse(r.matchedAt);return void 0===r.lastAttemptAt||u.success||t?.({instanceId:n,field:"runtimeVersion.lastAttemptAt"}),void 0===r.matchedAt||m.success||t?.({instanceId:n,field:"runtimeVersion.matchedAt"}),{desiredVersion:o,...l?{actualVersion:l}:{},phase:c,attempt:"number"==typeof r.attempt&&Number.isInteger(r.attempt)&&r.attempt>=0?r.attempt:0,...u.success?{lastAttemptAt:u.data}:{},...m.success?{matchedAt:m.data}:{},...d?{error:d}:{}}}(n.runtimeVersion,t,"string"==typeof n.id?n.id:void 0),i.workspace=ar(tr,n.workspace,"workspace",t,"string"==typeof n.id?n.id:void 0)||{status:"unknown"},i.runtime=ar(nr.shape.runtime.unwrap(),dr(n.runtime,["kind","containerName","containerId","workspacePath","pid","port","labels"]),"runtime",t,"string"==typeof n.id?n.id:void 0)||{labels:{}},i.target=ar(Zn,dr(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"},i.access=ar(er,dr(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,r]of Object.entries(nr.shape))Object.prototype.hasOwnProperty.call(i,e)&&!r.safeParse(i[e]).success&&r.safeParse(void 0).success&&(delete i[e],t?.({instanceId:"string"==typeof n.id?n.id:void 0,field:e}));return i}function ar(e,t,n,r,i){if(!t||"object"!=typeof t||Array.isArray(t))return;let o=structuredClone(t),s=!1;for(let t=0;t<20;t+=1){const t=e.safeParse(o);if(t.success)return s&&r?.({instanceId:i,field:n}),t.data;let a=!1;for(const e of t.error.issues){if("unrecognized_keys"!==e.code)continue;const t=cr(o,e.path);if(t&&"object"==typeof t&&!Array.isArray(t))for(const n of e.keys)Object.prototype.hasOwnProperty.call(t,n)&&(delete t[n],a=!0,s=!0)}if(!a){const s=structuredClone(o);let a=!1;for(const e of t.error.issues){if(!e.path.length||"string"!=typeof e.path.at(-1))continue;const t=cr(s,e.path.slice(0,-1)),n=e.path.at(-1);t&&"object"==typeof t&&!Array.isArray(t)&&Object.prototype.hasOwnProperty.call(t,n)&&(delete t[n],a=!0)}if(a){const t=e.safeParse(s);if(t.success)return r?.({instanceId:i,field:n}),t.data}break}}r?.({instanceId:i,field:n})}function cr(e,t){let n=e;for(const e of t){if(!n||"object"!=typeof n)return;n=n[e]}return n}function dr(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 lr=m.z.object({instanceId:st.optional(),projectId:st.optional(),source:an.optional(),nodeId:st.optional(),runtimeId:st.optional(),imageSelection:Nt.optional(),instanceVersion:m.z.string().trim().max(80).optional(),protocolVersion:ot,build:Bt.optional(),controlMode:m.z.enum(["standalone","controlled"]).default("controlled"),capabilities:m.z.record(m.z.string(),m.z.unknown()).default({}),appInventory:Tt.optional(),target:Zn.default({strategy:"direct-port",status:"unknown"}),workspace:tr.default({status:"unknown"}),registrationToken:m.z.string().trim().max(240).optional(),processIncarnationId:m.z.string().trim().min(1).max(120).optional()}).strict().superRefine((e,t)=>{e.protocolVersion!==it||e.appInventory||t.addIssue({code:"custom",path:["appInventory"],message:"Current protocol register payload requires appInventory."})}),ur=m.z.object({status:nr.shape.status.optional(),health:nr.shape.health.optional(),protocolVersion:ot,build:Bt.optional(),capabilities:nr.shape.capabilities.optional(),appInventory:Tt.optional(),apps:nr.shape.apps.optional(),aiSessions:nr.shape.aiSessions.optional(),triggers:nr.shape.triggers.optional(),workspace:tr.optional(),target:Zn.partial().optional(),processIncarnationId:m.z.string().trim().min(1).max(120).optional()}).strict().superRefine((e,t)=>{e.protocolVersion!==it||e.appInventory||t.addIssue({code:"custom",path:["appInventory"],message:"Current protocol heartbeat payload requires appInventory."})}),mr=m.z.enum(["web","telegram","wechat","dingding"]);function pr(e,t,n={}){return new Promise((r,i)=>{const o=a.spawn(e,t,{stdio:["ignore","pipe","pipe"]}),s=[],c=[];let d=!1;const l=n.timeoutMs?setTimeout(()=>{d=!0,o.kill("SIGKILL")},n.timeoutMs):void 0;l?.unref?.(),o.stdout.on("data",e=>s.push(Buffer.from(e))),o.stderr.on("data",e=>c.push(Buffer.from(e))),o.on("error",e=>{l&&clearTimeout(l),i(e)}),o.on("close",t=>{l&&clearTimeout(l);const o={stdout:Buffer.concat(s).toString("utf8").trim(),stderr:Buffer.concat(c).toString("utf8").trim()};if(d){const t=new Error(`${e} timed out after ${n.timeoutMs}ms`);return Object.assign(t,{statusCode:504,code:"RUNTIME_COMMAND_TIMEOUT",details:o}),void i(t)}if(0===t)return void r(o);const a=new Error(o.stderr||`${e} exited with code ${t}`);Object.assign(a,{statusCode:502,code:"RUNTIME_EXECUTOR_FAILED",details:o}),i(a)})})}m.z.object({id:st,channel:mr,name:m.z.string().trim().min(1).max(160),enabled:m.z.boolean().default(!1),token:m.z.string().trim().max(4096).optional(),defaultChatId:m.z.string().trim().max(240).optional(),allowedUserIds:m.z.array(m.z.string().trim().min(1).max(240)).default([]),pollIntervalMs:m.z.number().int().positive().max(6e4).default(3e3),settings:m.z.record(m.z.string(),m.z.unknown()).default({}),createdAt:at,updatedAt:at}).strict(),m.z.object({id:st,channel:mr,bridgeId:st.optional(),chatSessionId:m.z.string().trim().min(1).max(240),userId:m.z.string().trim().max(240).optional(),activeProjectId:st.optional(),activeInstanceId:st.optional(),activeAiSessionId:m.z.string().trim().min(1).max(120).optional(),lastUsedAt:at,createdAt:at,updatedAt:at}).strict(),m.z.object({source:m.z.object({type:m.z.literal("chat-gateway").default("chat-gateway"),channel:mr,bridgeId:st.optional(),chatSessionId:m.z.string().trim().min(1).max(240),userId:m.z.string().trim().max(240).optional()}).strict(),message:m.z.object({text:m.z.string().trim().max(2e4).default(""),attachments:m.z.array(ne).max(6).default([])}).strict().superRefine((e,t)=>{e.attachments.reduce((e,t)=>e+("inline"===t.source.type?t.size:0),0)>H&&t.addIssue({code:m.z.ZodIssueCode.custom,path:["attachments"],message:"Inline attachments must be 41943040 bytes or less in total."})}),target:m.z.object({instanceId:st,aiSessionId:m.z.string().trim().min(1).max(120)}).strict().optional()}).strict(),m.z.object({id:st,instanceId:st,projectId:st.optional(),aiSessionId:m.z.string().trim().min(1).max(120),providerSessionId:m.z.string().trim().max(240).optional(),result:m.z.string().default(""),timeoutMs:m.z.number().positive().optional(),source:m.z.string().trim().max(120).optional(),kind:m.z.enum(["task","approval"]).default("task"),status:m.z.enum(["pending","unreachable"]).default("pending"),error:m.z.string().trim().max(2048).optional(),lastSeenAt:at}).strict();const gr=(e,t,n={})=>new Promise((r,i)=>{const o=[];let s,a=!1;try{s=g.spawn(e,t,{name:"xterm-256color",cols:n.cols||120,rows:n.rows||40,cwd:process.cwd(),env:process.env})}catch(e){return void i(e)}const c=n.timeoutMs?setTimeout(()=>{a=!0,s.kill("SIGKILL")},n.timeoutMs):void 0;c?.unref?.(),s.onData(e=>{o.push(e),n.onData?.(e)}),s.onExit(({exitCode:t})=>{c&&clearTimeout(c);const s={stdout:o.join(""),stderr:""};a?i(Object.assign(new Error(`${e} timed out after ${n.timeoutMs}ms`),{statusCode:504,code:"RUNTIME_COMMAND_TIMEOUT",details:s})):0!==t?i(Object.assign(new Error(s.stdout.replace(/\u001b\[[0-?]*[ -/]*[@-~]/g,"").split(/\r?\n/).map(e=>e.trim()).filter(Boolean).at(-1)||`${e} exited with code ${t}`),{statusCode:502,code:"RUNTIME_EXECUTOR_FAILED",details:s})):r(s)})});class hr{inFlight=new Map;runCommand;runTerminalCommand;constructor(e=pr,t){this.runCommand=e,this.runTerminalCommand=t||function(e){return e===pr?gr:async(t,n,r={})=>{const i=await e(t,n,{timeoutMs:r.timeoutMs});return i.stdout&&r.onData?.(i.stdout),i.stderr&&r.onData?.(i.stderr),i}}(e)}ensure(e,t,n){const r=yt(e),i=this.inFlight.get(r);if(i)return t&&(i.phaseListeners.add(t),i.phase&&t(i.phase)),n&&(i.terminalListeners.add(n),i.terminalTail&&n({sequence:i.terminalSequence,data:i.terminalTail,replay:!0})),i.promise;const o=new Set,s=new Set;t&&o.add(t),n&&s.add(n);const a={promise:Promise.resolve(void 0),phaseListeners:o,terminalListeners:s,terminalSequence:0,terminalTail:""};return a.promise=this.ensureOnce(r,e=>{a.phase=e,o.forEach(t=>t(e))},e=>{a.terminalSequence+=1,a.terminalTail=`${a.terminalTail}${e}`.slice(-262144);const t={sequence:a.terminalSequence,data:e};s.forEach(e=>e(t))}).finally(()=>this.inFlight.delete(r)),this.inFlight.set(r,a),a.promise}async ensureOnce(e,t,n){t("checking-image");let r=await this.inspect(e).catch(()=>{}),i=!1;r||(t("pulling-image"),await this.runTerminalCommand("docker",["pull",e],{cols:120,rows:40,onData:n}),i=!0,r=await this.inspect(e)),t("resolving-image");const o=(s=r,Array.isArray(s.RepoDigests)?s.RepoDigests.filter(e=>"string"==typeof e):[]).find(e=>/@sha256:[a-fA-F0-9]{64}$/.test(e));var s;const a=o?.split("@").at(-1)?.toLowerCase();return{requestedReference:e,...a?{resolvedDigest:a}:{},resolvedReference:o||e,pulled:i}}async inspect(e){const t=await this.runCommand("docker",["image","inspect",e,"--format","{{json .}}"]);return JSON.parse(t.stdout.trim()||"{}")}}function fr(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}class yr{runCommand;publishHost;images;launcherAssetsDir;portResolutionRetryDelaysMs;constructor(e=pr,r={}){this.runCommand=e,this.images=r.imageService||new hr(e),this.publishHost=r.publishHost||"127.0.0.1",this.launcherAssetsDir=r.launcherAssetsDir||function(){const e=("undefined"==typeof document?require("url").pathToFileURL(__filename).href:b&&"SCRIPT"===b.tagName.toUpperCase()&&b.src||new URL("cli.js",document.baseURI).href)?n.dirname(s.fileURLToPath("undefined"==typeof document?require("url").pathToFileURL(__filename).href:b&&"SCRIPT"===b.tagName.toUpperCase()&&b.src||new URL("cli.js",document.baseURI).href)):__dirname,r=[n.resolve(e,"../../../../../docker"),n.resolve(e,"../docker"),n.resolve(e,"../../docker")];return r.find(e=>t.existsSync(n.join(e,"runtime-installer.mjs")))||r[0]}(),this.portResolutionRetryDelaysMs=r.portResolutionRetryDelaysMs?.length?r.portResolutionRetryDelaysMs:[0,100,250,500,1e3]}async start(e){Tr(e);const t=e.instance.runtime.containerName||Sr(e.instance.id),n=await this.inspectContainerForStart(t);if(n){vr(t,n.id,e.instance.runtime.containerId,"before start","RUNTIME_EXECUTOR_FAILED");const r=n.labels["task-handoff.instance-id"];if(r!==e.instance.id)throw wr("RUNTIME_EXECUTOR_FAILED",`Docker container ${t} belongs to ${r||"an unknown instance"}, not ${e.instance.id}.`);try{await this.runCommand("docker",["start",t])}catch(e){throw wr("RUNTIME_EXECUTOR_FAILED",`Could not start Docker container ${t}.`,e)}return this.runningResult(e,t,n.id)}let r;await this.images.ensure(e.image.resolvedReference||e.image.requestedReference);try{r=await this.runCommand("docker",function(e,t,n={}){const r=n.publishHost||"127.0.0.1",i=e.node?.id||"node_unset",o=e.runtime?.id||"runtime_local_docker",s=["run","-d","--name",t,"--label",`task-handoff.instance-id=${e.instance.id}`,"--label",`task-handoff.project-id=${e.project.id}`,"--label",`task-handoff.node-id=${i}`,"--label",`task-handoff.runtime-id=${o}`,"--label",`task-handoff.image-id=${e.image.id}`,"--shm-size","1gb","--security-opt","seccomp=unconfined","--network","bridge","--add-host","host.docker.internal:host-gateway","--tmpfs","/tmp:rw,mode=1777","-v",`${t}-data:/data`,"-v",`${t}-agent-home:/home/agent`,"-p",`${r}::8080`],a={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_REGISTRATION_TOKEN:e.instance.registrationToken||"",TASK_HANDOFF_PROJECT_ID:e.project.id,TASK_HANDOFF_NODE_ID:i,TASK_HANDOFF_RUNTIME_ID:o,TASK_HANDOFF_IMAGE_ID:e.image.id,...e.image.tag?{TASK_HANDOFF_IMAGE_TAG:e.image.tag}:{},TASK_HANDOFF_CHAT_BRIDGES:"none",TASK_HANDOFF_WORKSPACE:e.project.workspacePolicy.path||"/workspace",TASK_HANDOFF_WORKSPACE_MODE:e.project.workspacePolicy.mode};for(const[e,t]of Object.entries(a))_r(s,e,t);"local-folder"===e.project.source.type?s.push("-v",`${e.project.source.path}:${e.project.workspacePolicy.path||"/workspace"}:${e.project.workspacePolicy.readOnly?"ro":"rw"}`):(_r(s,"TASK_HANDOFF_PROJECT_SOURCE",JSON.stringify(e.project.source)),_r(s,"TASK_HANDOFF_WORKSPACE_POLICY",JSON.stringify(e.project.workspacePolicy)),_r(s,"TASK_HANDOFF_GIT_URL",e.project.source.url),e.project.source.ref?.commit?_r(s,"TASK_HANDOFF_GIT_COMMIT",e.project.source.ref.commit):e.project.source.ref?.name&&_r(s,"TASK_HANDOFF_GIT_REF",e.project.source.ref.name),e.project.source.clone?.depth&&_r(s,"TASK_HANDOFF_GIT_DEPTH",String(e.project.source.clone.depth)),_r(s,"TASK_HANDOFF_GIT_SUBMODULES",e.project.source.clone?.submodules?"true":"false"),_r(s,"TASK_HANDOFF_GIT_LFS",e.project.source.clone?.lfs?"true":"false"),e.project.source.clone?.subdirectory&&_r(s,"TASK_HANDOFF_WORKSPACE_SUBDIRECTORY",e.project.source.clone.subdirectory));for(const[t,n]of Object.entries(e.image.defaultEnv))_r(s,t,n);for(const[t,n]of Object.entries(e.modelEnv||{}))_r(s,t,n);return s.push(e.image.resolvedReference||e.image.requestedReference),s}(e,t,{publishHost:this.publishHost}))}catch(e){throw wr("RUNTIME_EXECUTOR_FAILED",`Could not create Docker container ${t}.`,e)}return this.runningResult(e,t,r.stdout||void 0)}async runningResult(e,t,n){const r=await this.containerPort(t,"8080/tcp"),i=r?`http://127.0.0.1:${r}`:void 0,o=e.node?.id||"node_unset",s=e.runtime?.id||"runtime_local_docker";return{status:"registering",health:"unknown",connectionStatus:i?"online":"unknown",agentStatus:"unknown",targetStatus:"unknown",uiAccessStatus:"unknown",target:{strategy:"direct-port",status:i?"reachable":"unknown",...i?{web:i,api:`${i}/api`}:{}},workspace:{mode:e.project.workspacePolicy.mode,status:"pending",path:e.project.workspacePolicy.path},runtime:{...e.instance.runtime,kind:"docker",containerName:t,...n?{containerId:n}:{},labels:{...e.instance.runtime.labels,"task-handoff.instance-id":e.instance.id,"task-handoff.project-id":e.project.id,"task-handoff.node-id":o,"task-handoff.runtime-id":s,"task-handoff.image-id":e.image.id}}}}async stop(e){const t=e.instance.runtime.containerName||Sr(e.instance.id);try{await this.runCommand("docker",["stop",t])}catch(e){if(!zr(e))throw wr("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){Tr(e);const n=e.instance.runtime.containerName||Sr(e.instance.id),r=await this.inspectContainerId(n);if(!r)throw wr("INSTANCE_RUNTIME_RESTART_FAILED",`Docker container ${n} does not exist.`);vr(n,r,t,"before restart","INSTANCE_RUNTIME_RESTART_FAILED"),await this.runCommand("docker",["restart",n]);const i=await this.inspectContainerId(n);if(!i||i!==r)throw wr("INSTANCE_RUNTIME_RESTART_FAILED",`Docker container identity changed while restarting ${n}.`);return vr(n,i,t,"after restart","INSTANCE_RUNTIME_RESTART_FAILED"),this.runningResult(e,n,i)}async delete(e){const t=e.instance.runtime.containerName||Sr(e.instance.id);try{await this.runCommand("docker",["rm","-f",t])}catch(e){if(!zr(e))throw wr("RUNTIME_EXECUTOR_FAILED",`Could not delete Docker container ${t}.`,e)}return{status:"stopped",health:"unknown",connectionStatus:"offline",target:{...e.instance.target,status:"unknown"},runtime:e.instance.runtime}}async installRuntime(e){const t=await this.installRuntimeRelease(e);vr(e.containerName,t,e.expectedContainerId,"before runtime restart","INSTANCE_RUNTIME_RESTART_FAILED");try{await this.runCommand("docker",["restart",e.containerName])}catch(t){throw wr("INSTANCE_RUNTIME_RESTART_FAILED",`Could not restart Docker container ${e.containerName}.`,t)}const n=await this.inspectContainerId(e.containerName);if(!n||n!==t)throw wr("INSTANCE_RUNTIME_RESTART_FAILED",`Docker container identity changed while updating ${e.containerName}.`);return vr(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 wr("INSTANCE_RUNTIME_INSTALL_FAILED",`Docker container ${e.containerName} does not exist.`);vr(e.containerName,t,e.expectedContainerId,"before runtime install","INSTANCE_RUNTIME_INSTALL_FAILED");const n=`/opt/task-handoff/instance-runtime/incoming/task-handoff-runtime-${r=e.identity.version,r.replace(/[^0-9A-Za-z.+_-]/g,"-")}-${e.identity.sha256.slice(0,12)}.tar.gz`;var r;await this.runCommand("docker",["exec","--user","0",e.containerName,"install","-d","-o","root","-g","root","-m","0755","/opt/task-handoff/instance-runtime/incoming"]),await this.runCommand("docker",["cp",e.artifactPath,`${e.containerName}:${n}`]);try{await this.runCommand("docker",["exec","--user","0",e.containerName,"task-handoff-runtime","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 wr("INSTANCE_RUNTIME_INSTALL_FAILED",`Could not install controlled-instance ${e.identity.version} in ${e.containerName}.`,t)}finally{await this.runCommand("docker",["exec","--user","0",e.containerName,"rm","-f",n]).catch(()=>({stdout:"",stderr:""}))}const i=await this.inspectContainerId(e.containerName);if(!i||i!==t)throw wr("INSTANCE_RUNTIME_INSTALL_FAILED",`Docker container identity changed while installing ${e.containerName}.`);return vr(e.containerName,i,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,"task-handoff-runtime","verify-active"]).catch(()=>{});if(!n?.stdout)return{containerId:t};try{const e=Gt.safeParse(JSON.parse(n.stdout));return e.success?{containerId:t,...e.data}:{containerId:t}}catch{return{containerId:t}}}async inspectRuntimeTarget(e){let t,n;if(e){const r=await this.runCommand("docker",["inspect","--format","{{json .}}",e]).then(e=>JSON.parse(e.stdout.trim()||"{}")).catch(()=>{});if(t=r?.Platform,"string"==typeof r?.Image&&r.Image){const e=await this.runCommand("docker",["image","inspect","--format","{{json .}}",r.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 wr("INSTANCE_BASE_RUNTIME_INCOMPATIBLE","Could not inspect the Docker runtime target.",e)});t||=e.OSType,n||=e.Architecture}const r="linux"===(i=t)||"darwin"===i?i:"windows"===i||"win32"===i?"win32":void 0;var i;const o=function(e){return"amd64"===e||"x86_64"===e||"x64"===e?"x64":"arm64"===e||"aarch64"===e?"arm64":void 0}(n);if(!r||!o)throw wr("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Docker reported an unsupported runtime target ${String(t||"unknown")}/${String(n||"unknown")}.`);return{platform:r,arch:o,launcherAbi:1}}async installRuntimeLauncher(e){const t=await this.inspectContainerId(e);if(!t)throw wr("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Docker container ${e} does not exist.`);const r=[[n.join(this.launcherAssetsDir,"entrypoint.sh"),"/root/.task-handoff-entrypoint.bootstrap"],[n.join(this.launcherAssetsDir,"instance-launcher.sh"),"/root/.task-handoff-instance-launcher.bootstrap"],[n.join(this.launcherAssetsDir,"runtime-installer.mjs"),"/root/.task-handoff-runtime-installer.bootstrap"]];for(const[t,n]of r)await this.runCommand("docker",["cp",t,`${e}:${n}`]);try{await this.runCommand("docker",["exec","--user","0",e,"bash","-ceu","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; install -m 0755 /root/.task-handoff-entrypoint.bootstrap /usr/local/bin/task-handoff-entrypoint; install -m 0755 /root/.task-handoff-instance-launcher.bootstrap /usr/local/bin/task-handoff-instance-launcher; install -d /usr/local/lib/task-handoff; install -m 0755 /root/.task-handoff-runtime-installer.bootstrap /usr/local/lib/task-handoff/runtime-installer.mjs; ln -sfn /usr/local/lib/task-handoff/runtime-installer.mjs /usr/local/bin/task-handoff-runtime; rm -f /root/.task-handoff-entrypoint.bootstrap /root/.task-handoff-instance-launcher.bootstrap /root/.task-handoff-runtime-installer.bootstrap"])}catch(t){throw wr("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Could not install the runtime launcher in ${e}.`,t)}if(await this.inspectContainerId(e)!==t)throw wr("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Docker container identity changed while installing the runtime launcher in ${e}.`)}async inspectContainerId(e){try{return(await this.runCommand("docker",["inspect","--format","{{.Id}}",e])).stdout.trim()||void 0}catch(t){if(zr(t))return;throw wr("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(zr(t))return;throw wr("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])):{};return{id:e.Id,labels:n}}catch(t){throw wr("RUNTIME_EXECUTOR_FAILED",`Docker returned invalid inspection data for ${e}.`,t)}}async containerPort(e,t){let n,r=!1;for(const i of this.portResolutionRetryDelaysMs){i>0&&await br(i);try{const n=Ir((await this.runCommand("docker",["port",e,t])).stdout);if(n)return n}catch(e){n=e}try{const n=Ar((await this.runCommand("docker",["inspect","--format","{{json .NetworkSettings.Ports}}",e])).stdout,t);if(r=!0,n)return n}catch(e){n=e}}if(r)throw wr("RUNTIME_EXECUTOR_FAILED",`Docker container ${e} does not publish ${t}.`);throw wr("RUNTIME_EXECUTOR_FAILED",`Could not resolve the published port for Docker container ${e}.`,n)}}function Ir(e){const t=e.split(/\r?\n/).find(Boolean);return t?.match(/:(\d+)$/)?.[1]}function Ar(e,t){const n=JSON.parse(e||"null");if(!n||"object"!=typeof n||Array.isArray(n))return;const r=n[t];if(Array.isArray(r))for(const e of r){if(!e||"object"!=typeof e||Array.isArray(e))continue;const t=e.HostPort;if("string"==typeof t&&/^\d+$/.test(t))return t}}function br(e){return new Promise(t=>setTimeout(t,e))}function wr(e,t,n){const r=Nr(n),i=new Error(r?`${t} Cause: ${r}`:t,void 0===n?void 0:{cause:n});return Object.assign(i,{statusCode:502,code:e}),i}function Nr(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 zr(e){const t=Nr(e)?.toLowerCase()||"";return t.includes("no such container")||t.includes("no such object")}function vr(e,t,n,r,i){if(n&&t!==n)throw wr(i,`Docker container ${e} identity mismatch ${r}: expected ${n}, got ${t}.`)}async function Er(e=pr){return async function(e=pr){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>",r=t.Tag||"<none>",i=t.ID||t.IDShort||"",o="<none>"!==n&&"<none>"!==r?`${n}:${r}`:i,s="<none>"!==n&&t.Digest&&"<none>"!==t.Digest?[`${n}@${t.Digest}`]:[];return{repository:n,tag:r,id:i,createdSince:t.CreatedSince,size:t.Size,sizeBytes:fr(t.Size),reference:o,repoDigests:s}}).filter(e=>Boolean(e.reference))}(e)}function Sr(e){return`task-handoff-${e.replace(/[^a-zA-Z0-9_.-]/g,"-")}`}function _r(e,t,n){e.push("-e",`${t}=${n}`)}function Tr(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 kr=m.z.enum(["created","starting","running","stopping","stopped","exited","failed","closed","terminated","unknown"]),Cr=m.z.object({type:m.z.enum(["app-session","provider-session","adapter-key"]),id:m.z.string().trim().min(1).max(240),agent:m.z.string().trim().min(1).max(80).optional(),adapter:m.z.string().trim().min(1).max(80).optional(),key:m.z.string().trim().min(1).max(240).optional()}).strict(),Or=m.z.record(m.z.string(),m.z.unknown()).and(m.z.object({id:m.z.string().trim().min(1).max(160),appId:m.z.string().trim().min(1).max(160).optional(),title:m.z.string().trim().max(240).optional(),kind:m.z.string().trim().max(80).optional(),status:kr.default("unknown"),bindings:m.z.array(Cr).max(40).default([]),workspace:m.z.object({cwd:m.z.string().trim().max(4096).optional()}).strict().optional(),createdAt:m.z.string().datetime().optional(),updatedAt:m.z.string().datetime().optional()})),xr=m.z.object({runningCount:m.z.number().int().min(0).default(0),problemCount:m.z.number().int().min(0).default(0),sessions:m.z.array(Or).default([]),updatedAt:m.z.string().datetime()}).strict();m.z.object({streamId:m.z.string().trim().min(1).max(240),revision:m.z.number().int().min(0),lastEventAt:m.z.string().datetime(),snapshot:xr}).strict(),xr.pick({runningCount:!0,problemCount:!0,updatedAt:!0}).extend({revision:m.z.number().int().min(0).optional()});const Rr=m.z.enum(["app-session-created","app-session-updated","app-session-deleted","app-session-recovered","control-action","heartbeat-sync","startup"]),Dr=m.z.object({streamId:m.z.string().trim().min(1).max(240),instanceId:m.z.string().trim().min(1).max(160),nodeId:m.z.string().trim().min(1).max(160).optional(),revision:m.z.number().int().min(0),previousRevision:m.z.number().int().min(0).optional(),traceId:m.z.string().trim().min(1).max(160),generatedAt:m.z.string().datetime(),reason:Rr}).strict(),Pr=m.z.object({meta:Dr,snapshot:xr}).strict(),jr=m.z.object({meta:Dr,session:Or}).strict(),Mr=m.z.object({meta:Dr,sessionId:m.z.string().trim().min(1).max(160),tombstone:Or.optional(),expiresAt:m.z.string().datetime().optional()}).strict();function Lr(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"}m.z.object({streamId:m.z.string().trim().min(1).max(240),instanceId:m.z.string().trim().min(1).max(160),sinceRevision:m.z.number().int().min(0),latestRevision:m.z.number().int().min(0),earliestRetainedRevision:m.z.number().int().min(0),syncRequired:m.z.boolean().default(!1),events:m.z.array(m.z.discriminatedUnion("type",[m.z.object({type:m.z.literal("app-session.snapshot"),payload:Pr}).strict(),m.z.object({type:m.z.literal("app-session.patch"),payload:jr}).strict(),m.z.object({type:m.z.literal("app-session.removed"),payload:Mr}).strict()])).default([])}).strict();const $r=m.z.enum(["ai.sessions","app.sessions"]),Fr=m.z.object({topic:$r,instanceId:m.z.string().trim().min(1).max(160),streamId:m.z.string().trim().min(1).max(240),latestRevision:m.z.number().int().min(0),earliestRetainedRevision:m.z.number().int().min(0)}).strict(),Ur=m.z.object({protocolVersion:m.z.literal(1),streams:m.z.array(Fr)}).strict();class Vr{attempt=0;timer;get pending(){return Boolean(this.timer)}get attempts(){return this.attempt}schedule(e,t={}){if(this.timer)return;const n=function(e,t=Math.random){const n=Math.min(3e4,1e3*2**Math.max(0,e));return Math.min(3e4,Math.round(n*(.75+.5*t())))}(this.attempt,t.random);this.attempt+=1;const r=t.setTimeoutFn||setTimeout;return this.timer=r(()=>{this.timer=void 0,e()},n),{attempt:this.attempt,delay:n}}reset(e=clearTimeout){this.timer&&e(this.timer),this.timer=void 0,this.attempt=0}cancel(e=clearTimeout){this.timer&&e(this.timer),this.timer=void 0}}function Hr(e,t=6e4){const n=[];for(let r=0;r<e.length;r+=t)n.push(e.slice(r,r+t));return n}class qr{sockets=new Map;socketUrls=new Map;retries=new Map;outputs=new Set;imagePullTerminalByInstance=new Map;state;token;logger;safetyIntervalMs;lastAiSessionEventByInstance=new Map;lastAppSessionEventByInstance=new Map;timer;reconnectAttempts=0;safetyReconciliations=0;localSequence=0;createSocket;setIntervalFn;clearIntervalFn;constructor(e,t,n={}){var r;this.state=e,this.token=t,this.logger=n.logger,this.safetyIntervalMs=(r=n.safetyIntervalMs,Math.min(6e4,Math.max(3e4,r??45e3))),this.createSocket=n.createSocket||((e,t)=>new u(e,t)),this.setIntervalFn=n.setIntervalFn||setInterval,this.clearIntervalFn=n.clearIntervalFn||clearInterval}start(){this.sync(),this.timer=this.setIntervalFn(()=>{this.safetyReconciliations+=1,this.sync()},this.safetyIntervalMs)}stop(){this.timer&&(this.clearIntervalFn(this.timer),this.timer=void 0);for(const e of this.sockets.values())e.close();this.sockets.clear(),this.socketUrls.clear();for(const e of this.retries.values())e.timer.cancel();this.retries.clear(),this.outputs.clear()}addOutput(e){this.outputs.add(e),e.on("close",()=>this.outputs.delete(e)),e.on("error",()=>this.outputs.delete(e));for(const t of this.state.listInstances()){const n=Br(t);n?this.sendForwarded(e,this.createEvent(rr,n,{instanceId:t.id})):this.logger?.warn?.({instanceId:t.id},"instance.lifecycle.snapshot.invalid")}for(const[t,n]of this.imagePullTerminalByInstance)Hr(n.tail).forEach((r,i)=>this.sendForwarded(e,this.createEvent(Mn,{...n.output,sequence:n.output.sequence+i,data:r,...0===i?{replay:!0}:{}},{instanceId:t}))),n.finished&&this.sendForwarded(e,this.createEvent(Ln,n.finished,{instanceId:t}));return this.syncNow(),()=>{this.outputs.delete(e)}}publish(e,t,n={}){this.rememberImagePullTerminal(e,t);const r=this.createEvent(e,t,n);for(const e of this.outputs)this.sendForwarded(e,r)}rememberImagePullTerminal(e,t){if(e===Mn){const e=Fn.safeParse(t);if(!e.success)return;const n=e.data,r=this.imagePullTerminalByInstance.get(n.instanceId);if(r&&n.generation<r.output.generation)return;const i=r?.output.generation===n.generation,o=n.replay||!i?n.data:`${r.tail}${n.data}`.slice(-262144);return void this.imagePullTerminalByInstance.set(n.instanceId,{output:n,tail:o})}if(e===Ln){const e=Un.safeParse(t);if(!e.success)return;const n=e.data,r=this.imagePullTerminalByInstance.get(n.instanceId);r?.output.generation===n.generation&&(r.finished=n)}}publishInstanceLifecycle(e){this.publish(rr,function(e){return ir.parse(Kr(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 r=++this.localSequence;return{v:1,id:`node_evt_${Date.now().toString(36)}_${r.toString(36)}`,seq:r,type:e,topic:Lr(e),createdAt:(new Date).toISOString(),payload:t,scope:n}}sendForwarded(e,t){const n=JSON.stringify({type:"node-agent.event.forwarded",event:t});e.readyState===u.OPEN&&e.send(n)}syncNow(){this.sync()}diagnostics(){return{reconnectAttempts:this.reconnectAttempts,safetyReconciliations:this.safetyReconciliations,activeConnections:this.sockets.size,pendingRetries:[...this.retries.values()].filter(e=>e.timer.pending).length,safetyIntervalMs:this.safetyIntervalMs}}sync(){const e=new Set(this.state.listInstances().map(e=>e.id));for(const t of this.imagePullTerminalByInstance.keys())e.has(t)||this.imagePullTerminalByInstance.delete(t);if(!this.outputs.size){for(const e of this.sockets.values())e.close();this.sockets.clear(),this.socketUrls.clear();for(const e of this.retries.values())e.timer.cancel();return void this.retries.clear()}const t=new Set;for(const e of this.state.listInstances()){const n=Jr(e);if(!n)continue;t.add(e.id);const r=this.retries.get(e.id);r?.timer.pending&&r.url!==n&&(r.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,r=this.createSocket(t,{headers:n});this.sockets.set(e,r),this.socketUrls.set(e,t),r.on("open",()=>{const n=this.retries.get(e);n?.timer.reset(),this.retries.set(e,{timer:n?.timer||new Vr,url:t}),r.readyState===u.OPEN&&(r.send(JSON.stringify({v:1,type:"subscribe",topics:[q,"app.sessions","apps","instances"]})),this.logger?.info?.({instanceId:e,url:t},"ai-session.event.forward.connect"),this.logger?.info?.({instanceId:e,url:t},"app-session.event.forward.connect"))}),r.on("message",t=>{const n=function(e,t){try{const n=JSON.parse(String(e));if(!n||"object"!=typeof n||Array.isArray(n))return;const r=n,i="string"==typeof r.type?r.type:"";if(!i||"events.connected"===i)return;const o=r.scope&&"object"==typeof r.scope&&!Array.isArray(r.scope)?r.scope:{};return{v:1,id:"string"==typeof r.id?r.id:`evt_${Date.now().toString(36)}`,seq:Number(r.seq)||0,type:i,topic:"string"==typeof r.topic?r.topic:Lr(i),createdAt:"string"==typeof r.createdAt?r.createdAt:(new Date).toISOString(),payload:"payload"in r?r.payload:{},scope:{...o,instanceId:t}}}catch{return}}(t,e);if(!n)return;if("streams.hello"===n.type){const t=Ur.safeParse(n.payload);if(!t.success)return this.logger?.warn?.({instanceId:e,issues:t.error.issues},"session-stream.handshake.invalid"),void r.close(1002,"Incompatible session stream handshake.");const i=JSON.stringify({type:"node-agent.streams.hello",instanceId:e,payload:t.data});for(const e of this.outputs)e.readyState===u.OPEN&&e.send(i);return}this.recordAiSessionEvent(e,n),this.recordAppSessionEvent(e,n);const i=JSON.stringify({type:"node-agent.event.forwarded",event:n});for(const e of this.outputs)e.readyState===u.OPEN&&e.send(i)}),r.on("close",()=>{this.sockets.get(e)===r&&(this.sockets.delete(e),this.socketUrls.delete(e),this.scheduleReconnect(e))}),r.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"),r.close()})}scheduleReconnect(e){const t=this.state.listInstances().find(t=>t.id===e),n=t&&Jr(t);if(!n||!this.outputs.size)return;const r=this.retries.get(e)??{timer:new Vr};if(r.timer.pending)return;r.url=n;const i=r.timer.schedule(()=>{this.sockets.has(e)||this.connect(e,n)});i&&(this.reconnectAttempts+=1,this.logger?.info?.({instanceId:e,url:n,attempt:i.attempt,delay:i.delay,reconnectAttempts:this.reconnectAttempts},"session-stream.connection.reconnect-scheduled")),this.retries.set(e,r)}recordAiSessionEvent(e,t){if(t.topic!==q)return;if("ai-session.message-delta"===t.type)return;const n=Gr(t.payload),r=this.lastAiSessionEventByInstance.get(e);r?.streamId===n.streamId&&void 0!==r.revision&&void 0!==n.revision&&n.revision>r.revision+1&&this.logger?.warn?.({instanceId:e,traceId:n.traceId,streamId:n.streamId,previousRevision:r.revision,revision:n.revision},"ai-session.event.forward.gap"),this.lastAiSessionEventByInstance.set(e,{streamId:n.streamId??r?.streamId,revision:n.revision??r?.revision}),this.logger?.info?.({instanceId:e,traceId:n.traceId,eventType:t.type,streamId:n.streamId,revision:n.revision},"ai-session.event.forward.message")}recordAppSessionEvent(e,t){if("app.sessions"!==t.topic)return;const n=Gr(t.payload),r=this.lastAppSessionEventByInstance.get(e);r?.streamId===n.streamId&&void 0!==r.revision&&void 0!==n.revision&&n.revision>r.revision+1&&this.logger?.warn?.({instanceId:e,traceId:n.traceId,streamId:n.streamId,previousRevision:r.revision,revision:n.revision},"app-session.event.forward.gap"),this.lastAppSessionEventByInstance.set(e,{streamId:n.streamId??r?.streamId,revision:n.revision??r?.revision}),this.logger?.info?.({instanceId:e,traceId:n.traceId,eventType:t.type,streamId:n.streamId,revision:n.revision},"app-session.event.forward.message")}}function Br(e){const t=ir.safeParse(Kr(e));return t.success?t.data:void 0}function Kr(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 Gr(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 Jr(e){if(!function(e){return!1!==e.ready&&(!e.runtimeVersion||["matched","failed"].includes(e.runtimeVersion.phase))}(e))return;const t=e.target?.api||e.target?.web;if(t)try{const e=new URL("/api/events",t);return e.protocol="https:"===e.protocol?"wss:":"ws:",e.toString()}catch{return}}const Wr=new Set(["provisioning","starting","registering","registered","running","unhealthy"]),Yr=JSON.stringify({id:"{{.ID}}",name:"{{.Name}}",cpu:"{{.CPUPerc}}",memory:"{{.MemUsage}}",memoryPercent:"{{.MemPerc}}",network:"{{.NetIO}}",blockIo:"{{.BlockIO}}",pids:"{{.PIDs}}"});class Xr{snapshots=new Map;runCommand;targets;publish;intervalMs;timer;inFlight;pendingTargets=new Map;collectingTargets=new Map;constructor(e,t,n,r=3e3){this.runCommand=e,this.targets=t,this.publish=n,this.intervalMs=r}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(!Wr.has(t.status))return ri(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=Qr(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,Qr(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=>Wr.has(e.status)&&(e.runtime.containerId||e.runtime.containerName));for(const t of e.filter(e=>Wr.has(e.status)&&!e.runtime.containerId&&!e.runtime.containerName))this.update(ii(t.id));for(const t of e.filter(e=>!Wr.has(e.status)))this.update(ri(t.id));if(!t.length)return;const n=t.map(e=>e.runtime.containerId||e.runtime.containerName),r=(new Date).toISOString();try{const e=await this.runCommand("docker",["stats","--no-stream","--format",Yr,...n],{timeoutMs:5e3});this.applyDockerOutput(t,e.stdout,r)}catch(e){if(1===t.length)return void this.update(oi(t[0].id,r,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",Yr,t],{timeoutMs:5e3});this.applyDockerOutput([e],n.stdout,r)}catch(t){this.update(oi(e.id,r,t instanceof Error?t.message:String(t)))}}))}}applyDockerOutput(e,t,n){const r=function(e,t=(new Date).toISOString()){const n=new Map;for(const r of e.split(/\r?\n/).filter(Boolean)){let e;try{e=JSON.parse(r)}catch{continue}const i=ni(e.id),o=ni(e.name),s=i||o;if(!s)continue;const a=Zr(ni(e.memory)),c=Zr(ni(e.network)),d=Zr(ni(e.blockIo)),l=Kn.parse({instanceId:s,runtimeKind:"docker",state:"available",sampledAt:t,cpu:ei(e.cpu,"usagePercent"),memory:a?{usageBytes:a[0],...void 0!==a[1]?{limitBytes:a[1]}:{},...ei(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:ti(e.pids)});i&&n.set(i,l),o&&n.set(o,l)}return n}(t,n);for(const t of e){const e=[t.runtime.containerId,t.runtime.containerName].filter(Boolean),i=[...r.entries()].find(([t])=>e.some(e=>e===t||e.startsWith(t)||t.startsWith(e)))?.[1];this.update(i?{...i,instanceId:t.id}:oi(t.id,n,"Container metrics were not returned by Docker."))}}update(e){const t=Kn.parse(e);this.snapshots.set(t.instanceId,t),this.publish?.(t)}}function Qr(e){return[e.status,e.runtime.containerId||"",e.runtime.containerName||""].join("\0")}function Zr(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]),r=t[2].toLowerCase(),i=r.includes("i"),o="b"===r[0]?"":r[0],s=o?"kmgtpe".indexOf(o)+1:0;return Math.round(n*(i?1024:1e3)**s)}(e||""));return void 0===t?void 0:[t,n]}function ei(e,t){const n=Number(ni(e).replace(/%$/,""));return Number.isFinite(n)&&n>=0?{[t]:n}:void 0}function ti(e){const t=Number(ni(e));return Number.isFinite(t)&&t>=0?t:void 0}function ni(e){return"string"==typeof e||"number"==typeof e?String(e).trim():""}function ri(e){return{instanceId:e,runtimeKind:"docker",state:"stopped",sampledAt:(new Date).toISOString()}}function ii(e){return{instanceId:e,runtimeKind:"docker",state:"pending",sampledAt:(new Date).toISOString()}}function oi(e,t,n){return{instanceId:e,runtimeKind:"docker",state:"unavailable",sampledAt:t,error:n.slice(0,2048)}}function si(e){try{return t.statSync(e).isDirectory()}catch{return!1}}function ai(e,r){let i;try{i=t.statSync(e)}catch{return}if(!i.isDirectory())return;const o=n.resolve(e),s=n.basename(o)||o;let a=[];try{a=r>0?t.readdirSync(o,{withFileTypes:!0}):[]}catch{a=[]}const c=r>0?a.filter(e=>e.isDirectory()||e.isSymbolicLink()&&si(n.join(o,e.name))).sort((e,t)=>e.name.localeCompare(t.name)).slice(0,80).flatMap(e=>{const t=ai(n.join(o,e.name),r-1);return t?[t]:[]}):[];return{name:s,path:o,children:c}}function ci(e){return(e.path?[e.path]:function(){if("win32"!==process.platform)return[n.parse(n.resolve(process.cwd())).root];const e=n.parse(n.resolve(process.cwd())).root,t=Array.from({length:26},(e,t)=>`${String.fromCharCode(65+t)}:\\`);return[...new Set([e,...t])].filter(si)}()).flatMap(t=>{const n=ai(t,e.depth);return n?[n]:[]})}const di=m.z.object({path:m.z.string().trim().min(1).max(2048),method:m.z.string().trim().min(1).max(20).default("GET"),headers:m.z.record(m.z.string(),m.z.string()).default({}),body:m.z.string().optional(),bodyBase64:m.z.string().optional()}).strict(),li=m.z.object({id:m.z.string().trim().min(1).max(120).optional(),name:m.z.string().trim().min(1).max(160),path:m.z.string().trim().min(1).max(4096),defaultImageSelection:Nt.optional(),labels:m.z.record(m.z.string(),m.z.string()).default({})}).strict(),ui=m.z.object({path:m.z.string().trim().min(1).max(4096).optional(),depth:m.z.coerce.number().int().min(0).max(1).default(0)}).strict(),mi=m.z.object({id:m.z.string().trim().min(1).max(120).optional(),name:m.z.string().trim().min(1).max(160).optional(),runtimeId:m.z.string().trim().min(1).max(120),imageSelection:Nt.optional(),projectId:m.z.string().trim().min(1).max(120).optional(),image:Pn.optional(),source:an,sourceSnapshot:m.z.record(m.z.string(),m.z.unknown()).default({}),config:m.z.object({autoImportAgentConfigs:m.z.boolean().optional(),defaultCodexPermissionMode:se.optional()}).strict().optional(),modelSelection:nr.shape.modelSelection}).strict(),pi=m.z.object({name:m.z.string().trim().min(1).max(160).optional(),config:m.z.object({autoImportAgentConfigs:m.z.boolean().optional(),defaultCodexPermissionMode:se.optional()}).strict().optional(),modelSelection:nr.shape.modelSelection.optional()}).strict(),gi=m.z.object({id:m.z.string().trim().min(1).max(120).optional(),name:m.z.string().trim().min(1).max(160),type:m.z.enum(["docker","kubernetes","local"]),status:m.z.enum(["unknown","online","offline","degraded"]).default("unknown"),accessStrategy:m.z.enum(["node-proxy","direct-port","kubernetes-ingress","kubernetes-port-forward"]).optional(),capabilities:m.z.record(m.z.string(),m.z.unknown()).default({}),labels:m.z.record(m.z.string(),m.z.string()).default({})}).strict(),hi=gi.omit({id:!0}).partial().strict();function fi(){return process.env.TASK_HANDOFF_NODE_AGENT_DATA_DIR||n.join(p.homedir(),".config","task-handoff","node-agent")}function yi(e=fi()){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"),nodeModelsDir:n.join(t,"models"),modelAssignmentsDir:n.join(t,"model-assignments"),modelEnvironmentsDir:n.join(t,"model-environments"),updatesDir:n.join(t,"updates"),logsDir:n.join(t,"logs")}}function Ii(e,n){t.mkdirSync(e,{recursive:!0,...void 0===n?{}:{mode:n}}),void 0!==n&&t.chmodSync(e,n)}function Ai(e,r,i={}){Ii(n.dirname(e),i.directoryMode),h.sync(e,`${JSON.stringify(r,null,2)}\n`,{encoding:"utf8",...void 0===i.fileMode?{}:{mode:i.fileMode}}),void 0!==i.fileMode&&t.chmodSync(e,i.fileMode)}function bi(e,t){console.warn(JSON.stringify({message:e,...t}))}function wi(e){return e&&"object"==typeof e&&"issues"in e?{issues:e.issues}:{error:e instanceof Error?e.message:String(e)}}function Ni(e,n){const r=n.logger||bi;let i;try{i=JSON.parse(t.readFileSync(e,"utf8"))}catch(t){return void r("stored JSON could not be read",{filePath:e,...wi(t)})}if(!n.schema)return i;const o=n.sanitize?n.sanitize(i):i,s=n.schema.safeParse(o);if(s.success)return s.data;const a="strip"in n.schema&&"function"==typeof n.schema.strip?n.schema.strip().safeParse(o):void 0;if(a?.success)return r("unknown stored fields were ignored",{filePath:e,issues:s.error.issues}),a.data;r("stored record failed validation and was isolated",{filePath:e,issues:s.error.issues})}function zi(e){return`${e}_${r.randomUUID().replace(/-/g,"").slice(0,20)}`}function vi(){return r.randomBytes(24).toString("base64url")}class Ei{directory;options;constructor(e,t={}){this.directory=e,this.options=t}init(){if(Ii(this.directory,this.options.directoryMode),void 0!==this.options.fileMode)for(const e of t.readdirSync(this.directory).filter(e=>e.endsWith(".json")))t.chmodSync(n.join(this.directory,e),this.options.fileMode)}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=Ni(n.join(this.directory,e),this.options);return t?[t]:[]})}get(e){this.init();const n=this.filePath(e);return t.existsSync(n)?Ni(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 Ai(this.filePath(n.id),n,this.options),n}patch(e,t){const n=this.get(e);if(!n)return;const r={...n,...t,id:n.id,createdAt:n.createdAt,updatedAt:(new Date).toISOString()};return this.put(r)}delete(e){const n=this.filePath(e);return!!t.existsSync(n)&&(t.unlinkSync(n),!0)}}class Si{filePathValue;defaults;options;constructor(e,t,n={}){this.filePathValue=e,this.defaults=t,this.options=n}init(){Ii(n.dirname(this.filePathValue),this.options.directoryMode),t.existsSync(this.filePathValue)?void 0!==this.options.fileMode&&t.chmodSync(this.filePathValue,this.options.fileMode):this.put(this.defaults())}get(){return this.init(),t.existsSync(this.filePathValue)?Ni(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 Ai(this.filePathValue,n,this.options),n}}function _i(e,t=process.platform){const i=n.resolve(e),o=r.createHash("sha256").update(i).digest("hex").slice(0,16);return"win32"===t?`\\\\.\\pipe\\task-handoff-node-agent-${o}`:n.join("/tmp",`task-handoff-node-agent-${process.getuid?.()??"user"}`,`${o}.sock`)}const Ti=new Set(["DELETE","GET","HEAD","PATCH","POST","PUT","OPTIONS"]);function ki(e){return"string"==typeof e&&Ti.has(e.toUpperCase())?e.toUpperCase():"GET"}function Ci(){return(new Date).toISOString()}function Oi(e,t){if(!e)return!0;const n=f.valid(e),r=f.valid(t);return n&&r?f.gt(r,n):e!==t}function xi(){return process.env.TASK_HANDOFF_NPM_COMMAND||"npm"}function Ri(e,r){const i=n.join(e,...r.split("/"),"package.json");try{const e=JSON.parse(t.readFileSync(i,"utf8"));if(e.name!==r||"string"!=typeof e.version||!e.version.trim())throw new Error(`Installed package manifest is invalid: ${i}`);return{name:r,version:e.version.trim()}}catch(e){if("ENOENT"===e.code)return;throw e}}async function Di(e){const t=(await e(xi(),["root","--global"])).stdout.trim();if(!t)throw new Error("npm did not return its global module root.");const n=Ri(t,"@task-handoff/server"),r=Ri(t,"@task-handoff/node-agent");return n?{packageName:"@task-handoff/server",currentVersion:n.version,relatedCurrentVersions:r?[r.version]:[]}:{packageName:"@task-handoff/node-agent",currentVersion:r?.version,relatedCurrentVersions:[]}}function Pi(e){if(!e||"object"!=typeof e||Array.isArray(e))return e;const t=e,n="string"==typeof t.updatedAt?t.updatedAt:Ci(),r=t.target&&"object"==typeof t.target&&!Array.isArray(t.target)?t.target:void 0,i="controlled-instance"===r?.component,o={updating:"updating-node",downloading:"updating-node",installing:"updating-node",restarting:"restarting-node",completed:"succeeded",success:"succeeded",error:"failed"},s=new Set(["queued","updating-node","restarting-node","converging-instances","succeeded","degraded","failed"]),a="string"==typeof t.status?t.status:"queued",c=i?"failed":s.has(a)?a:o[a]||"failed",d="string"==typeof t.toVersion&&t.toVersion?t.toVersion:"unknown",l=Yt.strip().safeParse(t.impact).success?Yt.strip().parse(t.impact):{runningInstanceCount:0,stoppedInstanceCount:0,activeInstanceCount:0,restartInstanceCount:0,runningInstanceIds:[],stoppedInstanceIds:[],activeInstanceIds:[]},u=i?{code:"LEGACY_INSTANCE_UPDATE_RETIRED",message:"Independent controlled-instance update jobs were retired in favor of Node reconciliation.",retryable:!1}:"failed"!==c||t.error||s.has(a)||a in o?"string"==typeof t.error?{code:"NODE_UPDATE_FAILED",message:t.error,retryable:!1}:Jt.strip().safeParse(t.error).success?Jt.strip().parse(t.error):t.error&&"object"==typeof t.error?{code:"NODE_UPDATE_FAILED",message:"string"==typeof t.error.message?t.error.message:"Stored update job contained an unknown error.",retryable:!1}:void 0:{code:"NODE_UPDATE_FAILED",message:`Stored update job used an unknown status: ${a}.`,retryable:!1},{target:m,error:p,...g}=t,h={phase:"succeeded"===c?"succeeded":"failed"===c?"failed":c||"queued",desiredVersion:d,expectedInstanceIds:[],expectedInstanceCount:0,matchedInstanceCount:0,pendingInstanceCount:0,failedInstanceCount:i||"failed"===c?1:0,deferredInstanceCount:0},f=Xt.strip().safeParse(t.rollout);return{...g,source:"npm",status:c,impact:l,runtimeArtifacts:Array.isArray(t.runtimeArtifacts)?t.runtimeArtifacts.flatMap(e=>{const t=Gt.strip().safeParse(e);return t.success?[t.data]:[]}):[],rollout:f.success?f.data:h,...u?{error:u}:{},...i?{completedAt:t.completedAt||n}:{}}}class ji{records;constructor(e){this.records=new Ei(e.updatesDir,{schema:en,sanitize:Pi})}init(){this.records.init()}list(){return this.records.list().sort((e,t)=>t.createdAt.localeCompare(e.createdAt))}create(e,t){const n=Ci();return this.records.put(en.parse({id:zi("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(en.parse({...n,...t,id:e,createdAt:n.createdAt,updatedAt:Ci()}))}reconcileRollouts(e,t,n={}){const r=new Map(e.map(e=>[e.id,e]));for(const e of this.list().filter(e=>["updating-node","restarting-node","converging-instances"].includes(e.status))){if(n.processStarted&&"restarting-node"===e.status&&t!==e.toVersion){this.patch(e.id,{status:"failed",rollout:{...e.rollout,phase:"failed",nodeVersion:t},error:{code:"NODE_UPDATE_FAILED",message:`Node agent restarted with version ${t}, expected ${e.toVersion}.`,retryable:!1},completedAt:Ci()});continue}const i="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"!==i.status)continue;const o=i.rollout.expectedInstanceIds,s=o.map(e=>r.get(e)),a=s.filter(e=>e?.ready&&"matched"===e.runtimeVersion?.phase&&e.runtimeVersion.actualVersion===i.toVersion).length,c=s.filter(e=>e&&["created","stopped","failed"].includes(e.status||"")&&"failed"!==e.runtimeVersion?.phase).length,d=s.filter(e=>!e||"failed"===e.runtimeVersion?.phase).length,l=Math.max(0,o.length-a-d-c),u=d>0?"degraded":0===l?"succeeded":"converging-instances";this.patch(i.id,{status:u,rollout:{...i.rollout,phase:u,nodeVersion:t,expectedInstanceCount:o.length,matchedInstanceCount:a,pendingInstanceCount:l,failedInstanceCount:d,deferredInstanceCount:i.impact.stoppedInstanceCount+c},..."succeeded"===u||"degraded"===u?{completedAt:Ci()}:{}})}}run(e,t){(async()=>{this.patch(e.id,{status:"updating-node",rollout:{...e.rollout,phase:"updating-node"},startedAt:Ci(),error:void 0});try{await t(e),this.patch(e.id,{status:"succeeded",completedAt:Ci()})}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:Ci()})}})()}}const Mi="runtime-manifest.json";class Li 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 $i(e,t=""){const r=[],i=await y.readdir(n.join(e,t),{withFileTypes:!0});for(const o of i){const i=t?n.posix.join(t,o.name):o.name;if(!t&&i===Mi)continue;const s=n.join(e,...i.split("/"));if(o.isDirectory()){r.push(...await $i(e,i));continue}if(o.isSymbolicLink()){const t=await y.readlink(s);if(n.isAbsolute(t))throw new Li("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload symlink is absolute: ${i}`);const o=n.resolve(n.dirname(s),t),a=n.relative(n.resolve(e),o);if(!a||".."===a||a.startsWith(`..${n.sep}`)||n.isAbsolute(a))throw new Li("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload symlink escapes the artifact: ${i}`);if(!await y.lstat(o).catch(()=>{}))throw new Li("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload symlink is broken: ${i}`);r.push({absolutePath:s,relativePath:i,kind:"symlink",target:t,size:Buffer.byteLength(t)});continue}if(!o.isFile())throw new Li("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload contains unsupported entry: ${i}`);const a=await y.lstat(s);r.push({absolutePath:s,relativePath:i,kind:"file",size:a.size})}return r}async function Fi(e){const n=(await $i(e)).sort((e,t)=>function(e,t){return Buffer.compare(Buffer.from(e,"utf8"),Buffer.from(t,"utf8"))}(e.relativePath,t.relativePath)),i=r.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 Ui(e){for(const[t,n]of[["version",e.version],["platform",e.platform],["arch",e.arch]])if(!/^[0-9A-Za-z._-]+$/.test(n))throw new Li("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Invalid runtime artifact ${t}: ${n}`);return`${e.version}-${e.platform}-${e.arch}`}function Vi(e,t){return`${Ui(e)}-${e.sha256}-${t}`}async function Hi(e){const n=r.createHash("sha256");for await(const r of t.createReadStream(e))n.update(r);return n.digest("hex")}class qi{#e;#t;#n=new Map;constructor(e){this.#e=e.cacheDir,this.#t=e.fetchImpl??fetch}resolve(e,t){const n=Gt.parse(e);if(!/^[a-f0-9]{64}$/.test(t.archiveSha256))throw new Li("INSTANCE_RUNTIME_ARTIFACT_INVALID","Runtime archive SHA-256 is invalid.");if((t.archiveUrl?1:0)+(t.archivePath?1:0)!=1)throw new Li("INSTANCE_RUNTIME_ARTIFACT_INVALID","Runtime artifact source must specify exactly one archive location.");const r=Vi(n,t.archiveSha256),i=this.#n.get(r);if(i)return i;const o=this.#r(n,t).finally(()=>this.#n.delete(r));return this.#n.set(r,o),o}async#r(e,i){if(!/^[a-f0-9]{64}$/.test(i.archiveSha256))throw new Li("INSTANCE_RUNTIME_ARTIFACT_INVALID","Runtime archive SHA-256 is invalid.");const o=Vi(e,i.archiveSha256),s=n.join(this.#e,"archives"),a=n.join(s,`${o}.tar.gz`);if(await y.mkdir(s,{recursive:!0}),await this.#i(a,e,i.archiveSha256))return{identity:e,archivePath:a,cacheHit:!0};await y.rm(a,{force:!0});const c=n.join(s,`.${o}.${r.randomUUID()}.part`);try{const n=await y.open(c,"wx");if(i.archivePath)await I.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 Li("INSTANCE_RUNTIME_ARTIFACT_UNAVAILABLE",`Runtime artifact download failed with HTTP ${e.status}.`,{retryable:e.status>=500});await I.pipeline(e.body,n.createWriteStream())}if(await Hi(c)!==i.archiveSha256)throw new Li("INSTANCE_RUNTIME_ARTIFACT_INVALID","Downloaded runtime archive SHA-256 does not match release metadata.");return await this.#o(c,e),await y.rename(c,a),{identity:e,archivePath:a,cacheHit:!1}}catch(e){if(e instanceof Li)throw e;throw new Li("INSTANCE_RUNTIME_ARTIFACT_UNAVAILABLE","Could not download runtime artifact.",{cause:e,retryable:!0})}finally{await y.rm(c,{force:!0})}}async#i(e,t,n){try{return await Hi(e)===n&&(await this.#o(e,t),!0)}catch{return!1}}async#o(e,t){const i=n.join(this.#e,"validation",`${Ui(t)}-${r.randomUUID()}`);try{await async function(e,t){await y.mkdir(t,{recursive:!0});try{await A.extract({file:e,cwd:t,strict:!0,preservePaths:!1,filter:(e,t)=>{const r=n.posix.normalize(e.replace(/^\.\//,""));if(!r||".."===r||r.startsWith("../")||n.posix.isAbsolute(r))throw new Li("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime archive entry escapes the artifact root: ${e}`);const i=t.type;if("File"!==i&&"OldFile"!==i&&"Directory"!==i&&"SymbolicLink"!==i)throw new Li("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime archive contains unsupported entry type ${i??"unknown"}: ${e}`);return!0}})}catch(e){throw new Li("INSTANCE_RUNTIME_ARTIFACT_INVALID","Could not extract runtime artifact safely.",{cause:e})}}(e,i),await async function(e,t,r){const i=await async function(e){let t;try{t=JSON.parse(await y.readFile(n.join(e,Mi),"utf8"))}catch(e){throw new Li("INSTANCE_RUNTIME_ARTIFACT_INVALID","Runtime artifact manifest is missing or invalid JSON.",{cause:e})}const r=Gt.safeParse(t);if(!r.success)throw new Li("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime artifact manifest is invalid: ${r.error.message}`);return r.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 Li("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime artifact ${"sha256"===n?"SHA-256":n} mismatch: expected ${t[n]}, got ${e[n]}.`)}(i,t),1!==i.formatVersion)throw new Li("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Unsupported runtime artifact format ${i.formatVersion}.`);if(r?.platform&&"universal"!==i.platform&&i.platform!==r.platform)throw new Li("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime artifact platform ${i.platform} does not match ${r.platform}.`);if(r?.arch&&"universal"!==i.arch&&i.arch!==r.arch)throw new Li("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime artifact architecture ${i.arch} does not match ${r.arch}.`);if(void 0!==r?.launcherAbi&&i.launcherAbi>r.launcherAbi)throw new Li("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Runtime requires launcher ABI ${i.launcherAbi}, but the base runtime provides ${r.launcherAbi}.`);const o=function(e,t){if(!e||e.includes("\\")||n.posix.isAbsolute(e))throw new Li("INSTANCE_RUNTIME_ARTIFACT_INVALID",`${t} must be a non-empty POSIX relative path.`);const r=n.posix.normalize(e);if("."===r||".."===r||r.startsWith("../"))throw new Li("INSTANCE_RUNTIME_ARTIFACT_INVALID",`${t} escapes the runtime root.`);return r}(i.entrypoint,"Runtime entrypoint"),s=await y.lstat(n.join(e,...o.split("/"))).catch(()=>{});if(!s?.isFile())throw new Li("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime entrypoint is missing: ${o}`);const a=await Fi(e);if(a!==i.sha256)throw new Li("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload SHA-256 mismatch: expected ${i.sha256}, got ${a}.`);return i}(i,t,{platform:t.platform,arch:t.arch})}finally{await y.rm(i,{recursive:!0,force:!0})}}}async function Bi(e,t,r,i=fetch){if("linux"!==t||!["x64","arm64"].includes(r))throw new Li("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Managed controlled-instance updates require a Linux x64 or arm64 target, received ${t}/${r}.`);const o=await async function(e){const t=`controlled-instance-runtime-${e}-linux-universal`,r=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[i,o]=await Promise.all([y.readFile(n.join(r,`${t}.manifest.json`),"utf8"),y.readFile(n.join(r,`${t}.tar.gz.sha256`),"utf8")]),s=Gt.safeParse(JSON.parse(i));if(!s.success||s.data.version!==e||"linux"!==s.data.platform||"universal"!==s.data.arch)throw new Li("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Bundled controlled-instance ${e} has an invalid Linux manifest.`);const a=o.trim().split(/\s+/)[0]?.toLowerCase();if(!a||!/^[a-f0-9]{64}$/.test(a))throw new Li("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Bundled controlled-instance ${e} has an invalid archive checksum.`);return{identity:s.data,source:{archivePath:n.join(r,`${t}.tar.gz`),archiveSha256:a}}}catch(t){if("ENOENT"===t.code)return;if(t instanceof Li)throw t;throw new Li("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Could not read bundled controlled-instance ${e}.`,{cause:t})}}(e);if(o)return o;const s=`controlled-instance-runtime-${e}-linux-universal`,a=function(e){const t=process.env.TASK_HANDOFF_RUNTIME_RELEASE_BASE_URL?.trim();return t?t.replaceAll("{version}",e).replace(/\/$/,""):`https://github.com/edgestorage/task-handoff/releases/download/v${e}`}(e),c=`${a}/${s}.manifest.json`,d=`${a}/${s}.tar.gz`,l=`${a}/${s}.tar.gz.sha256`,[u,m]=await Promise.all([i(c),i(l)]).catch(t=>{throw new Li("INSTANCE_RUNTIME_ARTIFACT_UNAVAILABLE",`Could not read release metadata for controlled-instance ${e}.`,{cause:t,retryable:!0})});if(!u.ok||!m.ok)throw new Li("INSTANCE_RUNTIME_ARTIFACT_UNAVAILABLE",`Release metadata for controlled-instance ${e} is unavailable (manifest HTTP ${u.status}, checksum HTTP ${m.status}).`,{retryable:u.status>=500||m.status>=500});let p;try{p=await u.json()}catch(t){throw new Li("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Release manifest for controlled-instance ${e} is not valid JSON.`,{cause:t})}const g=Gt.safeParse(p);if(!g.success)throw new Li("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Release manifest for controlled-instance ${e} is invalid: ${g.error.message}`);if(g.data.version!==e||"linux"!==g.data.platform||"universal"!==g.data.arch)throw new Li("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Release identity mismatch: requested ${e}-linux-universal, received ${g.data.version}-${g.data.platform}-${g.data.arch}.`);const h=(await m.text()).trim().split(/\s+/)[0]?.toLowerCase();if(!h||!/^[a-f0-9]{64}$/.test(h))throw new Li("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Release checksum for controlled-instance ${e} is invalid.`);return{identity:g.data,source:{archiveUrl:d,archiveSha256:h}}}class Ki{store;desiredVersion;hooks;inFlight=new Map;requests=new Map;cancelled=new Set;now;delay;drainTimeoutMs;verificationTimeoutMs;pollIntervalMs;maxAttempts;retryBaseDelayMs;retryMaxDelayMs;constructor(e,t,n,r={}){this.store=e,this.desiredVersion=t,this.hooks=n,this.now=r.now||(()=>new Date),this.delay=r.delay||(e=>new Promise(t=>setTimeout(t,e))),this.drainTimeoutMs=r.drainTimeoutMs??3e5,this.verificationTimeoutMs=r.verificationTimeoutMs??6e4,this.pollIntervalMs=r.pollIntervalMs??250,this.maxAttempts=function(e){if(!Number.isInteger(e)||e<=0)throw new TypeError("maxAttempts must be a positive integer.");return e}(r.maxAttempts??3),this.retryBaseDelayMs=eo(r.retryBaseDelayMs??1e3,"retryBaseDelayMs"),this.retryMaxDelayMs=eo(r.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 r=this.inFlight.get(e);if(r)return r;const i=Promise.resolve().then(()=>this.reconcile(e,n)).finally(()=>{this.inFlight.delete(e),this.requests.delete(e)});return this.inFlight.set(e,i),i}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 r=this.desiredVersion();if(this.cancelled.has(e)&&!t.resumeCancelled)return this.storePhase(n,"pending");const i=Gi(n),o=i===r&&(await(this.hooks.isInstalled?.(n,r))??!0);if(this.cancelled.has(e))return this.storePhase(this.requireInstance(e),"pending");if(i===r&&o)return this.storeState(n,{desiredVersion:r,actualVersion:i,phase:"matched",attempt:n.runtimeVersion?.attempt||0,matchedAt:this.timestamp()},!Wi(n)&&"failed"!==n.health);const s=n.runtimeVersion?.desiredVersion===r;if(s&&"failed"===n.runtimeVersion?.phase)return n;if(s&&(n.runtimeVersion?.attempt||0)>=this.maxAttempts)return"failed"===n.runtimeVersion?.phase&&n.runtimeVersion.error?n:this.storeBatchFailure(n,r,Zi(r,i,this.maxAttempts,n.runtimeVersion?.error));if(n=this.storeState(n,function(e,t,n,r=!1){const i=e.runtimeVersion,o=i?.desiredVersion===t&&"matched"!==i.phase;return{desiredVersion:t,...n?{actualVersion:n}:{},phase:"pending",attempt:o?i.attempt:0,error:(o?i.error:void 0)||(n!==t||r?Yi(t,n):Xi("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,r,i,o)),Wi(n)&&!t.startRequested)return n;let a=!1;try{for(;(n.runtimeVersion?.attempt||0)<this.maxAttempts;){if(this.cancelled.has(e))return this.storePhase(this.requireInstance(e),"pending");let i;try{if(n=this.storePhase(n,"draining"),await(this.hooks.beginDrain?.(n)),a=!0,n=this.requireInstance(e),Ji(n)){const t=await this.waitUntil(e,this.drainTimeoutMs,e=>!Ji(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),await this.hooks.install(n,r),this.cancelled.has(e)||Wi(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 i=await this.waitUntil(e,this.verificationTimeoutMs,e=>Gi(e)===r);if(this.cancelled.has(e))return this.storePhase(this.requireInstance(e),"pending");if(!i)throw Xi("INSTANCE_RUNTIME_VERIFICATION_FAILED",`Instance ${e} did not register controlled-instance ${r} after restart.`,r,Gi(this.requireInstance(e)),!0);const o=this.requireInstance(e);if(this.hooks.isInstalled&&!await this.hooks.isInstalled(o,r))throw Xi("INSTANCE_RUNTIME_VERIFICATION_FAILED",`Instance ${e} reported controlled-instance ${r}, but its active runtime release is missing.`,r,Gi(o),!0);return this.storeState(o,{desiredVersion:r,actualVersion:r,phase:"matched",attempt:o.runtimeVersion?.attempt||1,matchedAt:this.timestamp()},!Wi(o)&&"failed"!==o.health)}catch(t){if(this.cancelled.has(e))return this.storePhase(this.requireInstance(e),"pending");i=Qi(t,r,Gi(this.store.get(e)))}n=this.requireInstance(e);const o=n.runtimeVersion?.attempt||1;if(!i.retryable||o>=this.maxAttempts)return this.storeBatchFailure(n,r,o>=this.maxAttempts&&i.retryable?Zi(r,Gi(n),this.maxAttempts,i):i);n=this.storeState(n,{desiredVersion:r,...Gi(n)?{actualVersion:Gi(n)}:{},phase:"pending",attempt:o,lastAttemptAt:this.timestamp(),error:i}),await this.delay(this.retryDelayMs(o))}return this.storeBatchFailure(n,r,Zi(r,Gi(n),this.maxAttempts,n.runtimeVersion?.error))}finally{a&&await(this.hooks.endDrain?.(this.requireInstance(e)))}}storeBatchFailure(e,t,n){const r=Gi(e);return this.storeState(e,{desiredVersion:t,...r?{actualVersion:r}:{},phase:"failed",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))}storePhase(e,t,n=!1){const r=this.desiredVersion(),i=Gi(e),o=e.runtimeVersion?.desiredVersion===r?e.runtimeVersion.error:void 0;return this.storeState(e,{desiredVersion:r,...i?{actualVersion:i}:{},phase:t,attempt:(e.runtimeVersion?.attempt||0)+(n?1:0),lastAttemptAt:this.timestamp(),...o?{error:o}:"pending"===t?{error:Yi(r,i)}:{}},"restarting"!==t&&void 0)}storeState(e,t,n){const r=this.store.get(e.id)||e;return this.store.put(nr.parse({...r,runtimeVersion:t,...void 0===n?{}:{ready:n},updatedAt:this.timestamp()}))}async waitUntil(e,t,n){const r=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()>=r)return!1;await this.delay(Math.min(this.pollIntervalMs,Math.max(0,r-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 Gi(e){return e?.build?.packageVersion||e?.instanceVersion}function Ji(e){return e.apps.runningCount>0||e.aiSessions.runningCount>0}function Wi(e){return["created","stopped","failed"].includes(e.status)}function Yi(e,t){return Xi("INSTANCE_RUNTIME_VERSION_MISMATCH",`Expected controlled-instance ${e}, received ${t||"an unknown version"}.`,e,t,!0)}function Xi(e,t,n,r,i){return{code:e,message:t,expectedVersion:n,...r?{actualVersion:r}:{},retryable:i}}function Qi(e,t,n){if(e&&"object"==typeof e&&"code"in e&&"message"in e){const r=e,i=Jt.shape.code.safeParse(r.code);if(i.success&&"string"==typeof r.message)return Xi(i.data,r.message,t,n,"boolean"!=typeof r.retryable||r.retryable)}return Xi("INSTANCE_RUNTIME_INSTALL_FAILED",e instanceof Error?e.message:String(e),t,n,!0)}function Zi(e,t,n,r){const i=r?.message?` Last error: ${r.message}`:"";return Xi(r?.code||"INSTANCE_RUNTIME_INSTALL_FAILED",`Runtime convergence stopped after ${n} attempts for this instance run.${i}`,e,t,!0)}function eo(e,t){if(!Number.isFinite(e)||e<0)throw new TypeError(`${t} must be a nonnegative finite number.`);return e}const to=m.z.record(m.z.string(),m.z.string()),no=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 ro{directory;constructor(e){this.directory=e}get(e){try{return to.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 r=to.parse(n);t.mkdirSync(this.directory,{recursive:!0,mode:448});const i=this.filePath(e);return h.sync(i,`${JSON.stringify(r,null,2)}\n`,{encoding:"utf8",mode:384}),t.chmodSync(i,384),r}delete(e){t.rmSync(this.filePath(e),{force:!0})}filePath(e){return n.join(this.directory,`${e}.json`)}}class io{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=mn.parse(e);this.init();const r=this.filePath(n.id);return h.sync(r,`${JSON.stringify(n,null,2)}\n`,{encoding:"utf8",mode:384}),t.chmodSync(r,384),n}delete(e){const n=this.filePath(e);return!!t.existsSync(n)&&(t.unlinkSync(n),!0)}read(e){try{const r=JSON.parse(t.readFileSync(e,"utf8")),i=n.basename(e,".json"),o=mn.safeParse(r);if(o.success&&o.data.id===i&&zn(o.data)===o.data.id)return o.data;const s=mn.strip().safeParse(r);return s.success&&s.data.id===i&&zn(s.data)===s.data.id?(console.warn(JSON.stringify({message:"unknown stored node model fields were ignored",nodeId:this.nodeId,filePath:e})),s.data):void console.warn(JSON.stringify({message:"stored node model failed validation and was isolated",nodeId:this.nodeId,filePath:e}))}catch(t){return void console.warn(JSON.stringify({message:"stored node model could not be read",nodeId:this.nodeId,filePath:e,error:t instanceof Error?t.message:String(t)}))}}filePath(e){return n.join(this.directory,`${e}.json`)}}class oo{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 r=JSON.parse(t.readFileSync(n,"utf8")),i=hn.safeParse(r);if(i.success)return i.data;const o=hn.strip().safeParse(r);if(o.success)return console.warn(JSON.stringify({message:"unknown stored model assignment fields were ignored",instanceId:e,filePath:n})),o.data;throw i.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=hn.parse(e);this.init();const r=this.filePath(n.instanceId);return h.sync(r,`${JSON.stringify(n,null,2)}\n`,{encoding:"utf8",mode:384}),t.chmodSync(r,384),n}delete(e){t.rmSync(this.filePath(e),{force:!0})}filePath(e){return n.join(this.directory,`${e}.json`)}}const so="TASK_HANDOFF_NODE_AGENT_V1",ao="/api/node-tunnel";function co(e=""){return r.createHash("sha256").update(e).digest("hex")}function lo(e,t){return r.createHmac("sha256",e).update(function(e){return[so,e.keyId,e.method.toUpperCase(),e.pathWithQuery,e.timestamp,e.nonce,e.bodySha256].join("\n")}(t)).digest("hex")}function uo(e){const t=e.timestamp||(new Date).toISOString(),n=e.nonce||r.randomBytes(18).toString("base64url"),i=co(e.body||""),o=lo(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":o}}class mo{usedNonces=new Map;identity;nodeId;overrideSecret;overrideKeyId;nowMs;constructor(e,t,n,r,i=Date.now){this.identity=e,this.nodeId=t,this.overrideSecret=n,this.overrideKeyId=r,this.nowMs=i}hasRemoteSecrets(){return this.identity.remoteSecrets(this.overrideSecret,this.overrideKeyId).length>0}verify(e){const t=function(e){const t=new Map;for(const[n,r]of Object.entries(e)){const e=Array.isArray(r)?r.join(","):"string"==typeof r?r:void 0===r?"":String(r);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=this.identity.remoteSecrets(this.overrideSecret,this.overrideKeyId);if(!n.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 i=n.filter(e=>t.keyId===e.keyId);if(!i.length)throw Object.assign(new Error("Invalid node agent HMAC key id."),{statusCode:401,code:"NODE_AGENT_HMAC_KEY_INVALID"});const o=Date.parse(t.timestamp);if(!Number.isFinite(o)||Math.abs(this.nowMs()-o)>6e4)throw Object.assign(new Error("Node agent HMAC timestamp is outside the allowed window."),{statusCode:401,code:"NODE_AGENT_HMAC_TIMESTAMP_INVALID"});if(!t.nonce)throw Object.assign(new Error("Node agent HMAC nonce is missing."),{statusCode:401,code:"NODE_AGENT_HMAC_NONCE_MISSING"});this.pruneNonces();const s=`${t.nodeId}:${t.keyId}:${t.nonce}`;if(this.usedNonces.has(s))throw Object.assign(new Error("Node agent HMAC nonce was already used."),{statusCode:401,code:"NODE_AGENT_HMAC_NONCE_REPLAY"});const a=co(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(!i.some(n=>function(e,t){const n=Buffer.from(e,"hex"),i=Buffer.from(t,"hex");return n.length===i.length&&r.timingSafeEqual(n,i)}(t.signature,lo(n.secret,{keyId:t.keyId,method:e.method,pathWithQuery:e.url,timestamp:t.timestamp,nonce:t.nonce,bodySha256:a}))))throw Object.assign(new Error("Invalid node agent HMAC signature."),{statusCode:401,code:"NODE_AGENT_HMAC_SIGNATURE_INVALID"});return this.usedNonces.set(s,o+6e4+1),t.keyId}pruneNonces(){const e=this.nowMs();for(const[t,n]of this.usedNonces)n<=e&&this.usedNonces.delete(t)}}const po=m.z.string().trim().min(1).max(160),go=m.z.string().datetime(),ho=m.z.string().min(1).max(4096),fo=m.z.string().trim().url().max(2048),yo=m.z.object({tokenHash:m.z.string().trim().min(1).max(256),expiresAt:go,createdAt:go,controlPlaneName:m.z.string().trim().min(1).max(160).optional()}).strip(),Io=m.z.object({id:po,keyId:po,name:m.z.string().trim().min(1).max(160).optional(),secret:ho,pairedAt:go,updatedAt:go}).strip(),Ao=m.z.object({id:po,pairingKeyId:po,name:m.z.string().trim().min(1).max(160).optional(),url:fo,enabled:m.z.boolean().default(!0),createdAt:go,updatedAt:go}).strip(),bo=m.z.object({controlPlaneName:m.z.string().trim().min(1).max(160).optional(),controlPlaneUrl:m.z.string().trim().max(2048).optional(),expiresInMs:m.z.number().int().positive().max(36e5).optional()}).strict(),wo=m.z.object({joinToken:m.z.string().trim().min(1).max(4096),controlPlaneId:m.z.string().trim().min(1).max(160).optional(),controlPlaneName:m.z.string().trim().min(1).max(160).optional()}).strict(),No=m.z.object({controlPlaneUrl:m.z.string().trim().url().max(2048),joinToken:m.z.string().trim().min(1).max(4096),controlPlaneName:m.z.string().trim().min(1).max(160).optional(),activate:m.z.boolean().optional()}).strict();function zo(){return(new Date).toISOString()}const vo=new Set(["nodeId","createdAt","updatedAt","pairingInvites","controlPlanePairings","controlPlaneConnections","remoteControlPlanes"]),Eo=new Set(["tokenHash","expiresAt","createdAt","controlPlaneName"]),So=new Set(["id","keyId","name","secret","pairedAt","updatedAt"]),_o=new Set(["id","pairingKeyId","name","url","enabled","createdAt","updatedAt"]),To=new Set(["id","keyId","name","url","secret","pairedAt","updatedAt","active"]);function ko(e,t){console.warn(JSON.stringify({message:e,...t}))}function Co(e,t){return Object.assign(new Error(e,void 0===t?void 0:{cause:t}),{code:"NODE_AGENT_IDENTITY_INVALID"})}function Oo(e,t){return Object.keys(e).filter(e=>!t.has(e))}function xo(e,t,n){const r=go.safeParse(e);return r.success?r.data:(n("invalid node agent identity timestamp was replaced",{field:t}),zo())}function Ro(e,t){if(!e||"object"!=typeof e||Array.isArray(e))throw Co("Node agent identity must be a JSON object.");const n=e,r=po.safeParse(n.nodeId);if(!r.success)throw Co("Node agent identity has an invalid nodeId.",r.error);const i=r.data,o=Oo(n,vo);o.length&&t("unknown node agent identity fields were ignored",{fields:o});const s=Array.isArray(n.remoteControlPlanes)?n.remoteControlPlanes.flatMap(e=>{if(!e||"object"!=typeof e||Array.isArray(e))return[];const n=e,r=Oo(n,To);r.length&&t("unknown legacy node agent remote control-plane fields were ignored",{fields:r});const i=Io.safeParse(n);if(!i.success)return t("invalid legacy node agent control-plane pairing was ignored",{issues:i.error.issues}),[];const o=n.url?Ao.safeParse({id:`connection_${i.data.keyId}`,pairingKeyId:i.data.keyId,name:n.name,url:n.url,enabled:!1!==n.active,createdAt:i.data.pairedAt,updatedAt:i.data.updatedAt}):void 0;return[{pairing:i.data,...o?.success?{connection:o.data}:{}}]}):[],a=(e,n,r,i)=>Array.isArray(e)?e.flatMap(e=>{if(!e||"object"!=typeof e||Array.isArray(e))return t(`invalid node agent ${i} was ignored`,{}),[];const o=Oo(e,n);o.length&&t(`unknown node agent ${i} fields were ignored`,{fields:o});const s=r.safeParse(e);return s.success?[s.data]:(t(`invalid node agent ${i} was ignored`,{issues:s.error.issues}),[])}):[];return{nodeId:i,createdAt:xo(n.createdAt,"createdAt",t),updatedAt:xo(n.updatedAt,"updatedAt",t),pairingInvites:Array.isArray(n.pairingInvites)?n.pairingInvites.flatMap(e=>{if(!e||"object"!=typeof e||Array.isArray(e))return t("invalid node agent pairing invite was ignored",{}),[];const n=Oo(e,Eo);n.length&&t("unknown node agent pairing invite fields were ignored",{fields:n});const r=yo.safeParse(e);return r.success?[r.data]:(t("invalid node agent pairing invite was ignored",{issues:r.error.issues}),[])}):[],controlPlanePairings:n.controlPlanePairings?a(n.controlPlanePairings,So,Io,"control-plane pairing"):s.map(e=>e.pairing),controlPlaneConnections:n.controlPlaneConnections?a(n.controlPlaneConnections,_o,Ao,"control-plane connection"):s.flatMap(e=>e.connection?[e.connection]:[])}}class Do{paths;logger;constructor(e,t={}){this.paths=e,this.logger=t.logger||ko}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 Co(`Node agent identity contains invalid JSON: ${this.paths.identityPath}`,e)}return Ro(n,this.logger)}write(e){t.mkdirSync(n.dirname(this.paths.identityPath),{recursive:!0});const r=Ro({...e,updatedAt:zo()},this.logger);h.sync(this.paths.identityPath,`${JSON.stringify(r,null,2)}\n`,{encoding:"utf8",mode:384})}}function Po(){return(new Date).toISOString()}class jo{store;controlPlaneConnectionOperations=new Map;constructor(e){this.store=new Do(e)}async runControlPlaneConnectionOperation(e,t){const n=e.replace(/\/$/,""),r=this.controlPlaneConnectionOperations.get(n)||Promise.resolve();let i;const o=new Promise(e=>{i=e});this.controlPlaneConnectionOperations.set(n,o),await r;try{return await t()}finally{i(),this.controlPlaneConnectionOperations.get(n)===o&&this.controlPlaneConnectionOperations.delete(n)}}resolveNodeId(e){if(e?.trim())return this.writeNodeId(e.trim()),e.trim();const t=this.store.read();if(t?.nodeId)return t.nodeId;const n=zi("node");return this.writeNodeId(n),n}createPairingInvite(e){const t=this.prunePairingInvites(this.store.read()||this.newIdentity()),n=Po(),r=new Date(Date.now()+(e.expiresInMs||6e5)).toISOString(),i=vi(),o={tokenHash:co(i),createdAt:n,expiresAt:r,...e.controlPlaneName?{controlPlaneName:e.controlPlaneName}:{}};return this.store.write({...t,pairingInvites:[...t.pairingInvites||[],o]}),{...o,token:i}}completePairingInvite(e){const t=this.prunePairingInvites(this.store.read()||this.newIdentity()),n=co(e.joinToken),r=(t.pairingInvites||[]).find(e=>e.tokenHash===n);if(!r){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 i=Po(),o={id:e.controlPlaneId||zi("cp"),keyId:zi("key"),...e.controlPlaneName||r.controlPlaneName?{name:e.controlPlaneName||r.controlPlaneName}:{},secret:vi(),pairedAt:i,updatedAt:i};return this.store.write({...t,pairingInvites:(t.pairingInvites||[]).filter(e=>e.tokenHash!==n),controlPlanePairings:[...(t.controlPlanePairings||[]).filter(e=>e.id!==o.id),o]}),o}stageControlPlaneConnection(e){const{pairing:t,connection:n}=this.createControlPlaneConnection(e),r=this.store.read()||this.newIdentity(),i=n.url.replace(/\/$/,""),o=(r.controlPlaneConnections||[]).filter(e=>e.id===n.id||e.url.replace(/\/$/,"")===i);return this.store.write({...r,controlPlanePairings:[...(r.controlPlanePairings||[]).filter(e=>e.keyId!==t.keyId),t],controlPlaneConnections:[...(r.controlPlaneConnections||[]).filter(e=>e.id!==n.id&&e.url.replace(/\/$/,"")!==i),n]}),{pairing:t,connection:n,replacedConnections:o}}commitControlPlaneConnection(e,t={}){const n=this.store.read()||this.newIdentity(),r={...e.pairing,...t.name?{name:t.name}:{}},i={...e.connection,...t.name?{name:t.name}:{}},o=new Set((n.controlPlaneConnections||[]).map(e=>e.pairingKeyId)),s=new Set(e.replacedConnections.map(e=>e.pairingKeyId));return this.store.write({...n,controlPlanePairings:[...(n.controlPlanePairings||[]).filter(e=>e.keyId!==r.keyId&&(!s.has(e.keyId)||o.has(e.keyId))),r],controlPlaneConnections:[...(n.controlPlaneConnections||[]).filter(e=>e.id!==i.id),i]}),{pairing:r,connection:i}}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=Po(),n={id:zi("cp"),keyId:zi("key"),...e.name?{name:e.name}:{},secret:vi(),pairedAt:t,updatedAt:t};return{pairing:n,connection:{id:zi("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||[]).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||[]).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 r=(n.controlPlanePairings||[]).filter(t=>t.keyId!==e);return r.length!==(n.controlPlanePairings||[]).length&&(this.store.write({...n,controlPlanePairings:r}),!0)}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){return[...(this.store.read()?.controlPlanePairings||[]).map(e=>({keyId:e.keyId,secret:e.secret})),...e&&t?[{keyId:t,secret:e}]:[]]}reverseTunnelSecret(e,t,n){if(t&&n)return{keyId:n,secret:t};const r=this.store.read(),i=r?.controlPlanePairings||[];if(!i.length)return;if(e){const t=e.replace(/\/$/,""),n=(r?.controlPlaneConnections||[]).find(e=>e.url.replace(/\/$/,"")===t),o=n&&i.find(e=>e.keyId===n.pairingKeyId);if(o)return{keyId:o.keyId,secret:o.secret}}const o=[...i].sort((e,t)=>t.updatedAt.localeCompare(e.updatedAt))[0];return o?{keyId:o.keyId,secret:o.secret}:void 0}newIdentity(){return{nodeId:this.resolveNodeId(),createdAt:Po(),updatedAt:Po(),pairingInvites:[],controlPlanePairings:[],controlPlaneConnections:[]}}writeNodeId(e){const t=this.store.read();this.store.write({...t||{createdAt:Po()},nodeId:e,updatedAt:Po(),pairingInvites:t?.pairingInvites||[],controlPlanePairings:t?.controlPlanePairings||[],controlPlaneConnections:t?.controlPlaneConnections||[]})}prunePairingInvites(e){const t=Date.now();return{...e,pairingInvites:(e.pairingInvites||[]).filter(e=>Date.parse(e.expiresAt)>t)}}}function Mo(e){return e.readyState===(e.OPEN??1)}function Lo(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 $o(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 Fo(e,t,n){e.close($o(t),Lo(n)||void 0)}function Uo(e,t,n,r){if(Mo(e))for(const e of t.splice(0))if(r(e),!n(e))return}function Vo(e,t){const n=new URL(t.tunnelUrl);n.searchParams.set("nodeId",t.nodeId);const r=t.secret?uo({nodeId:t.nodeId,keyId:t.keyId,secret:t.secret,method:"GET",pathWithQuery:`${n.pathname}${n.search}`}):{},i=new u(n,{headers:r}),o=new Map,s=new Map,a=new Map;let c;i.on("error",r=>{e.log.warn({nodeId:t.nodeId,tunnelUrl:`${n.origin}${n.pathname}`,error:r instanceof Error?r.message:String(r)},"node agent reverse tunnel connection failed")});const d=e=>{const n=e.startsWith("/")?e:`/${e}`,r="function"==typeof t.port?t.port():t.port,i=new URL(`/api/node-agent${n}`,`http://127.0.0.1:${r}`);return i.protocol="ws:",i},l=(e,n,r,i={})=>{const o=e.startsWith("/")?e:`/${e}`;return{...i,...t.secret&&t.keyId?uo({nodeId:t.nodeId,keyId:t.keyId,secret:t.secret,method:n,pathWithQuery:`/api/node-agent${o}`,body:r}):t.token?{authorization:`Bearer ${t.token}`}:{}}},m=e=>t.secret?uo({nodeId:t.nodeId,keyId:t.keyId,secret:t.secret,method:"GET",pathWithQuery:`${e.pathname}${e.search}`}):{},p=(e,t,n)=>{const r=o.get(e);o.delete(e),r?.upstream&&Fo(r.upstream,t,n),r?.tunnel&&Fo(r.tunnel,t,n)},g=(e,t,n=!1)=>new Promise((r,i)=>{e.send(t,{binary:n},e=>e?i(e):r())});i.on("open",()=>{i.send(JSON.stringify({type:"node-agent.identify",nodeId:t.nodeId,serverTime:(new Date).toISOString()})),c=e.nodeAgentEventForwarder?.addOutput(i)}),i.on("close",()=>{for(const e of o.keys())p(e,1001,"Reverse tunnel disconnected.");for(const[e,t]of s)s.delete(e),t.controller.abort(),Fo(t.tunnel,1001,"Reverse tunnel disconnected.");for(const[e,t]of a)a.delete(e),t.abort();c?.(),c=void 0});return i.on("message",r=>{(async r=>{let c;try{c=JSON.parse(String(r))}catch{return void i.send(JSON.stringify({type:"node-agent.error",code:"INVALID_JSON"}))}const h=c&&"object"==typeof c?c:{};if("control-plane.http.open"===h.type){const r="string"==typeof h.streamId?h.streamId:"",o="string"==typeof h.route&&h.route.startsWith("/")?h.route:"/health",a=h.init&&"object"==typeof h.init?h.init:{},c=a.headers&&"object"==typeof a.headers?a.headers:{},d=ki(a.method);let p;try{p=mt(a.body)}catch(n){return e.log.warn({nodeId:t.nodeId,messageType:h.type,streamId:r,error:n instanceof Error?n.message:String(n)},"node agent reverse tunnel request body rejected"),void i.send(JSON.stringify({type:"node-agent.error",code:"NODE_TUNNEL_REQUEST_BODY_INVALID",streamId:r}))}const f=new AbortController,y=(e=>{const t=new URL(n);return t.pathname=`${t.pathname.replace(/\/$/,"")}/http-streams/${encodeURIComponent(e)}`,t})(r),I=new u(y,{headers:m(y)});return s.set(r,{tunnel:I,controller:f}),I.on("open",async()=>{try{const e=await fetch((e=>{const n=e.startsWith("/")?e:`/${e}`,r="function"==typeof t.port?t.port():t.port;return new URL(`/api/node-agent${n}`,`http://127.0.0.1:${r}`)})(o),{method:d,headers:l(o,d,p,c),body:Buffer.isBuffer(p)?new Uint8Array(p):p,signal:f.signal});if(await g(I,JSON.stringify({type:"node-agent.http.head",streamId:r,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 g(I,Buffer.from(n),!0)}}await g(I,JSON.stringify({type:"node-agent.http.end",streamId:r})),I.close(1e3,"HTTP stream completed.")}catch(e){I.readyState===u.OPEN&&(await g(I,JSON.stringify({type:"node-agent.http.error",streamId:r,message:e instanceof Error?e.message:String(e)})).catch(()=>{}),I.close(1011,"HTTP stream failed."))}finally{s.delete(r)}}),I.on("close",()=>{f.abort(),s.delete(r)}),void I.on("error",()=>f.abort())}if("control-plane.http.cancel"===h.type){const e="string"==typeof h.streamId?h.streamId:"",t=s.get(e);if(!t)return;return s.delete(e),t.controller.abort(),void Fo(t.tunnel,1e3,"string"==typeof h.reason?h.reason:"HTTP stream canceled.")}if("control-plane.websocket.open"===h.type){const e="string"==typeof h.streamId?h.streamId:"",t="string"==typeof h.route?h.route:"",r=Array.isArray(h.protocols)?h.protocols.filter(e=>"string"==typeof e):void 0;try{const s=l(t,"GET",void 0),a=r?.length?new u(d(t),r,{headers:s}):new u(d(t),{headers:s}),c=(e=>{const t=new URL(n);return t.pathname=`${t.pathname.replace(/\/$/,"")}/streams/${encodeURIComponent(e)}`,t})(e),p=new u(c,{headers:m(c)});o.set(e,{upstream:a,tunnel:p,close:(e=1e3,t="")=>{Fo(a,e,t),Fo(p,e,t)}}),a.on("open",()=>{i.send(JSON.stringify({type:"node-agent.websocket.open",streamId:e,protocol:a.protocol}))}),function(e,t,n={}){const r=n.pendingFrameLimit??256,i=n.maxFrameBytes??8388608,o=n.maxTotalBytes??1073741824,s=n.maxBufferedBytes??16777216;let a=!1,c=Mo(t);const d=[],l=[];let u,m=0,p=0,g=0;const h=e=>Buffer.isBuffer(e)||e instanceof ArrayBuffer||ArrayBuffer.isView(e)?e.byteLength:Buffer.byteLength("string"==typeof e?e:String(e),"utf8"),f=(r,s)=>{const a=h(s);return g+=a,n.onFrame?.(r,a),!(a>i||g>o)||(Fo(e,1009,"WebSocket bridge traffic limit exceeded."),Fo(t,1009,"WebSocket bridge traffic limit exceeded."),!1)},y=()=>{u&&(clearTimeout(u),u=void 0)},I=(n,r)=>{const i=r.bytes;if((n.bufferedAmount??0)+i>s)return Fo(e,1013,"WebSocket bridge consumer is too slow."),Fo(t,1013,"WebSocket bridge consumer is too slow."),!1;try{return function(e,t){e.send(t.data,{binary:t.isBinary})}(n,r),!0}catch{return Fo(e,1011,"WebSocket bridge send failed."),Fo(t,1011,"WebSocket bridge send failed."),!1}},A=(n,i,o)=>{if(i.length>=r)return Fo(e,1011,"WebSocket bridge pending frame limit exceeded."),void Fo(t,1011,"WebSocket bridge pending frame limit exceeded.");const a="upstream"===n?m:p;if((("upstream"===n?t:e).bufferedAmount??0)+a+o.bytes>s)return Fo(e,1013,"WebSocket bridge consumer is too slow."),void Fo(t,1013,"WebSocket bridge consumer is too slow.");i.push(o),"upstream"===n?m+=o.bytes:p+=o.bytes};n.upstreamOpenTimeoutMs&&!c&&(u=setTimeout(()=>{c||a||(Fo(e,1011,"Upstream websocket did not open."),Fo(t))},n.upstreamOpenTimeoutMs)),e.on("open",()=>Uo(e,l,t=>I(e,t),e=>{p-=e.bytes})),t.on("open",()=>{y(),c=!0,n.onUpstreamOpen?.(),Uo(t,d,e=>I(t,e),e=>{m-=e.bytes})}),e.on("message",(e,n=!1)=>{if(!f("client-to-upstream",e))return;const r={data:e,isBinary:Boolean(n),bytes:h(e)};Mo(t)?I(t,r):A("upstream",d,r)}),t.on("message",(t,n=!1)=>{if(!f("upstream-to-client",t))return;const r={data:t,isBinary:Boolean(n),bytes:h(t)};Mo(e)?I(e,r):A("client",l,r)}),t.on("close",(t,r)=>{y(),n.onUpstreamClose?.(t,r),(c||a||!n.onUpstreamCloseBeforeOpen?.())&&Fo(e,t,r)}),t.on("error",t=>{n.onUpstreamError?.(t),(c||a||!n.onUpstreamErrorBeforeOpen?.(t))&&Fo(e)}),e.on("close",(e,r)=>{y(),a=!0,n.onClientClose?.(e,r),Fo(t,e,r)}),e.on("error",e=>{y(),a=!0,n.onClientError?.(e),Fo(t,1011,"WebSocket bridge client failed.")})}(p,a,{pendingFrameLimit:256,upstreamOpenTimeoutMs:1e4,onClientClose:()=>{o.delete(e)},onClientError:t=>{o.delete(e),i.send(JSON.stringify({type:"node-agent.websocket.error",streamId:e,message:t instanceof Error?t.message:String(t)}))},onUpstreamClose:(t,n)=>{o.delete(e);const r=$o(t),s=Lo(n);i.send(JSON.stringify({type:"node-agent.websocket.close",streamId:e,...void 0===r?{}:{code:r},...s?{reason:s}:{}}))},onUpstreamError:t=>{o.delete(e),i.send(JSON.stringify({type:"node-agent.websocket.error",streamId:e,message:t instanceof Error?t.message:String(t)}))}})}catch(t){i.send(JSON.stringify({type:"node-agent.websocket.error",streamId:e,message:t instanceof Error?t.message:String(t)}))}return}if("control-plane.websocket.close"===h.type){const e="string"==typeof h.streamId?h.streamId:"";return void p(e,"number"==typeof h.code?h.code:1e3,"string"==typeof h.reason?h.reason:"")}if("control-plane.request.cancel"===h.type){const e="string"==typeof h.requestId?h.requestId:"";return a.get(e)?.abort(),void a.delete(e)}if("control-plane.request"===h.type){const n="string"==typeof h.requestId?h.requestId:"",r=h.init&&"object"==typeof h.init?h.init:{},o="string"==typeof h.route&&h.route.startsWith("/")?h.route:"/health",s=r.headers&&"object"==typeof r.headers?r.headers:{},c=ki(r.method);let d;try{d=mt(r.body)}catch(r){return e.log.warn({nodeId:t.nodeId,messageType:h.type,requestId:n,error:r instanceof Error?r.message:String(r)},"node agent reverse tunnel request body rejected"),void i.send(JSON.stringify({type:"node-agent.response",requestId:n,status:400,error:{code:"NODE_TUNNEL_REQUEST_BODY_INVALID",message:"Reverse tunnel request body does not match the negotiated protocol."}}))}const u=new AbortController;a.set(n,u);try{const t=await e.inject({method:c,url:`/api/node-agent${o}`,headers:l(o,c,d,s),payload:d,signal:u.signal});if(u.signal.aborted)return;i.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;i.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)}}})(r).catch(n=>{e.log.warn({nodeId:t.nodeId,error:n instanceof Error?n.message:String(n)},"node agent reverse tunnel message rejected");try{i.send(JSON.stringify({type:"node-agent.error",code:"INVALID_TUNNEL_MESSAGE"}))}catch{}})}),i}function Ho(e){const t=new URL(ao,e);return t.protocol="https:"===t.protocol?"wss:":"ws:",t.toString()}const qo=new Set(["content-encoding","content-length","transfer-encoding"]),Bo=["codex","claude"],Ko=5e3,Go="runtime_local_host",Jo="task-handoff.node-agent.builtin",Wo=new Set(["linux","darwin","win32","freebsd","openbsd","aix","sunos"]);function Yo(e){return Wo.has(e)?e:"unknown"}function Xo(e){const t={...e};return delete t[Jo],t}const Qo=m.z.object({version:m.z.literal(1),externalListener:Gn}).strict(),Zo=m.z.object({}).strict().default({}),es=tn.strict();function ts(e){const t=process.env[e]?.trim();return t||void 0}const ns=function(e,t=process.env,n=e){let r;return()=>{const i=t.TASK_HANDOFF_VERSION?.trim();return i||(r||=z(e,t,n),r)}}("@task-handoff/node-agent",process.env,"@task-handoff/control-plane");function rs(e){const t=ns();return e===t?{desiredVersion:t,actualVersion:e,phase:"matched",attempt:0,matchedAt:ms()}:{desiredVersion:t,...e?{actualVersion:e}:{},phase:"pending",attempt:0,error:{code:"INSTANCE_RUNTIME_VERSION_MISMATCH",message:`Expected controlled-instance ${t}, received ${e||"an unknown version"}.`,expectedVersion:t,...e?{actualVersion:e}:{},retryable:!0}}}function is(e,t,n=!0){if(!n)return rs(t);const r=ns(),i=e.runtimeVersion;if(!i||i.desiredVersion!==r)return rs(t);const o=()=>({code:"INSTANCE_RUNTIME_VERSION_MISMATCH",message:`Expected controlled-instance ${r}, received ${t||"an unknown version"}.`,expectedVersion:r,...t?{actualVersion:t}:{},retryable:!0}),s="INSTANCE_RUNTIME_VERSION_MISMATCH"!==i.error?.code?i.error:t===r?void 0:o();return Wt.parse({...i,desiredVersion:r,...t?{actualVersion:t}:{actualVersion:void 0},..."pending"===i.phase?{error:s||(t!==r?o():void 0)}:{}})}function os(e){return Object.fromEntries([...e.entries()].filter(([e])=>!qo.has(e.toLowerCase())))}function ss(e){return e.bodyBase64?Buffer.from(e.bodyBase64,"base64"):e.body}const as=67108864;function cs(){const e=Number(process.env.TASK_HANDOFF_INSTANCE_PROXY_MAX_RESPONSE_BYTES);return Number.isSafeInteger(e)&&e>0?e:67108864}function ds(e){const t=e.authorization;return"string"==typeof t&&t.startsWith("Bearer ")?t.slice(7).trim():void 0}function ls(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 us(e){return!e.ip&&!e.socket.remoteAddress&&!e.socket.remoteFamily}function ms(){return(new Date).toISOString()}function ps(e){return"all-ipv4"===e?"0.0.0.0":"127.0.0.1"}function gs(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:{},r=Object.keys(t).filter(e=>"version"!==e&&"externalListener"!==e),i=Object.keys(n).filter(e=>"bindScope"!==e&&"port"!==e);return(r.length||i.length)&&console.warn(JSON.stringify({message:"unknown stored node agent runtime setting fields were ignored",filePath:"runtime-settings.json",fields:[...r,...i.map(e=>`externalListener.${e}`)]})),{version:t.version,externalListener:{bindScope:n.bindScope,port:n.port}}}function hs(e){return"local-folder"===e.type?cn.parse({mode:"local-bind",path:"/workspace",readOnly:!1}):cn.parse({mode:"git-clone",path:"/workspace",readOnly:!1})}function fs(e){const t=an.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 ln.parse({id:n,name:"string"==typeof e.sourceSnapshot.name?e.sourceSnapshot.name:e.name,source:t,defaultImageSelection:e.imageSelection,defaultNodeId:e.nodeId,defaultRuntimeId:e.runtimeId,workspacePolicy:hs(t),labels:{},createdAt:e.createdAt,updatedAt:e.updatedAt})}async function ys(e,t){if(!t.target.web)return"unknown";const n=new AbortController,r=setTimeout(()=>n.abort(),2e3);try{return(await e(`${ws(t)}/api/health`,{signal:n.signal})).ok?"reachable":"endpoint-unreachable"}catch{return"endpoint-unreachable"}finally{clearTimeout(r)}}async function Is(e,t,n,r){const i=new AbortController,o=setTimeout(()=>i.abort(),r);try{return await e(t,{...n,signal:i.signal})}finally{clearTimeout(o)}}async function As(e,t,n,r){if(!t.config.autoImportAgentConfigs)return void r.diagnostic({instanceId:t.id,action:n},"node instance config auto-import skipped");if("reachable"!==t.targetStatus)return;const i=ws(t),o=Number(process.env.TASK_HANDOFF_CONFIG_AUTO_IMPORT_TIMEOUT_MS||Ko);for(const s of Bo)try{const a=await Is(e,`${i}/api/config-sync/import/${encodeURIComponent(s)}`,{method:"POST"},Number.isFinite(o)&&o>0?o:Ko);if(!a.ok){r.warn({instanceId:t.id,action:n,preset:s,statusCode:a.status},"node instance config auto-import failed");continue}r.diagnostic({instanceId:t.id,action:n,preset:s},"node instance config auto-import completed")}catch(e){r.warn({instanceId:t.id,action:n,preset:s,error:e instanceof Error?e.message:String(e)},"node instance config auto-import failed")}}async function bs(e,t,n){const r=t.requireInstance(n);if("reachable"!==r.targetStatus||!r.target.web)return!1;const i=await Is(e,`${ws(r)}/api/internal/model-environment`,{method:"PUT",headers:{"content-type":"application/json",authorization:`Bearer ${r.registrationToken}`},body:JSON.stringify(t.resolvedAssignedModelEnvironment(n))},Ko);if(!i.ok)throw Object.assign(new Error(`Instance ${n} rejected its managed model environment with HTTP ${i.status}.`),{statusCode:502,code:"INSTANCE_MODEL_ENVIRONMENT_APPLY_FAILED"});return!0}function ws(e){const t=e.target.web;if(!t){const t=new Error(`Instance ${e.id} does not have a web endpoint.`);throw Object.assign(t,{statusCode:409,code:"NODE_INSTANCE_WEB_ENDPOINT_MISSING"}),t}if("direct-port"!==e.target.strategy)return t.replace(/\/$/,"");try{const e=new URL(t);return e.port?(e.hostname=process.env.TASK_HANDOFF_NODE_AGENT_PROXY_HOST||"127.0.0.1",e.toString().replace(/\/$/,"")):t.replace(/\/$/,"")}catch{return t.replace(/\/$/,"")}}function Ns(e,t){const n=new Error(t);throw Object.assign(n,{statusCode:403,code:e}),n}function zs(e,t){e!==it&&console.warn(JSON.stringify({message:"protocol version mismatch",peer:t,expectedProtocolVersion:it,actualProtocolVersion:e||"missing",errorCode:"PROTOCOL_VERSION_MISMATCH"}))}function vs(e){return"none"!==e.capabilities.artifactKind}function Es(e={}){return{...e,requiresImage:!1,supportsControlledInstanceApi:!0,supportsContainerLifecycle:!1,supportsAppSessions:!0,supportsHostSessions:!0,artifactKind:"none",isolation:"none"}}function Ss(e){return new Promise(t=>{const n=o.createServer();n.once("error",()=>t(!1)),n.listen({host:"127.0.0.1",port:e},()=>{n.close(()=>t(!0))})})}function _s(e,t=3e3){return null!==e.exitCode||null!==e.signalCode?Promise.resolve():new Promise(n=>{const r=setTimeout(()=>{null===e.exitCode&&null===e.signalCode&&e.kill("SIGKILL"),n()},t);r.unref(),e.once("exit",()=>{clearTimeout(r),n()})})}const Ts="task-handoff.local-process-nonce",ks=1e3;function Cs(e){return e.runtime.port?`http://127.0.0.1:${e.runtime.port}`:e.target.web}async function Os(e,t){try{const n=await fetch(`${e}/api/internal/node-agent/process-identity`,{headers:{authorization:`Bearer ${t}`},signal:AbortSignal.timeout(ks)});if(!n.ok)return;const r=(await n.json()).data;if("string"!=typeof r?.instanceId||"number"!=typeof r.pid||"string"!=typeof r.processNonce)return;return{instanceId:r.instanceId,pid:r.pid,processNonce:r.processNonce,startIdentity:"string"==typeof r.startIdentity?r.startIdentity:void 0}}catch{return}}async function xs(e,t){if(k(e)!==t)return!1;try{process.kill(e,"SIGTERM")}catch{return!0}const n=Date.now()+3e3;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 r=Date.now()+1e3;for(;Date.now()<r;){try{process.kill(e,0)}catch{return!0}await new Promise(e=>setTimeout(e,50))}return!1}function Rs(e,t){return Object.assign(new Error(t),{statusCode:503,code:"LOCAL_INSTANCE_STOP_UNCONFIRMED",instanceId:e.id})}async function Ds(e,t,r){const i=t.get(e.id);if(i&&!i.killed)return i.kill("SIGTERM"),t.delete(e.id),void await _s(i);const o=await async function(e){const t=Cs(e),n=e.runtime.labels?.[Ts];if(!t||!n||!e.registrationToken)return;const r=await Os(t,e.registrationToken);if(r&&r.instanceId===e.id&&r.processNonce===n)try{return(await fetch(`${t}/api/internal/node-agent/shutdown`,{method:"POST",headers:{authorization:`Bearer ${e.registrationToken}`},signal:AbortSignal.timeout(ks)})).ok?r:void 0}catch{return}}(e);if(o){const t=Cs(e),n=Date.now()+3e3;for(;t&&Date.now()<n;){if(!await Os(t,e.registrationToken))return;await new Promise(e=>setTimeout(e,50))}const r=t?await Os(t,e.registrationToken):void 0;if(r&&r.instanceId===o.instanceId&&r.pid===o.pid&&r.processNonce===o.processNonce&&r.startIdentity===o.startIdentity&&r.startIdentity&&await xs(r.pid,r.startIdentity))return;throw Rs(e,`Controlled instance ${e.id} accepted shutdown but its exit could not be confirmed.`)}const s=function(e=function(){const e="win32"===process.platform?p.tmpdir():"/tmp";return n.join(e,`task-handoff-local-controlled-instance-${function(){const e=process.getuid?.();return void 0!==e?String(e):p.userInfo().username.replace(/[^a-zA-Z0-9_.-]/g,"_")}()}.lock`)}()){return C(e)}(r),a=await async function(e){const t=Cs(e);if(t)try{const[n,r]=await Promise.all([fetch(`${t}/api/instance/status`,{signal:AbortSignal.timeout(ks)}),fetch(`${t}/api/diagnostics`,{signal:AbortSignal.timeout(ks)})]);if(!n.ok||!r.ok)return;const i=await n.json(),o=await r.json(),s=o.data?.runtime?.pid;if(i.data?.id!==e.id||"controlled"!==i.data.controlMode||"number"!=typeof s||!Number.isInteger(s)||s<=0)return;const a=k(s);return a?{pid:s,startIdentity:a}:void 0}catch{return}}(e);if(a){if(await xs(a.pid,a.startIdentity))return;throw Rs(e,`Legacy controlled instance ${e.id} did not exit after termination.`)}if(s?.instanceId===e.id&&R(s))throw Rs(e,`Local controlled instance ${e.id} is still owned by pid ${s.pid}, but its process identity could not be verified.`)}const Ps=new Set(["provisioning","starting","registering","registered","running"]);async function js(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}}}function Ms(e){return!0===e.managedArtifacts}class Ls{managedArtifacts=!0;executor;platform;arch;runCommand;constructor(e,t,n,r){this.executor=e,this.runCommand=t,this.platform=n,this.arch=r}artifactTarget(e){return this.executor.inspectRuntimeTarget(e?.instance.runtime.containerName)}async installRuntime(e,t){const n=e.instance.runtime.containerName;if(!n)throw Object.assign(new Error(`Instance ${e.instance.id} does not have a Docker container.`),{code:"INSTANCE_RUNTIME_INSTALL_FAILED"});await this.executor.installRuntimeLauncher(n),await this.executor.installRuntimeRelease({containerName:n,expectedContainerId:e.instance.runtime.containerId,artifactPath:t.archivePath,identity:t.identity})}async inspectRuntime(e,t){const n=e.instance.runtime.containerName;return!!n&&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)}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){return this.executor.delete(e)}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:Yo(this.platform),...t?{serverVersion:t}:{}}}}}catch(t){return{status:"offline",capabilities:{...e.capabilities,daemon:{status:"offline",hostPlatform:Yo(this.platform),error:t instanceof Error?t.message:String(t)}}}}}}class $s{runCommand;paths;nodeAgentUrl;processByInstanceId=new Map;commandOverride;lockPath;constructor(e,t,n,r,i){this.runCommand=e,this.paths=t,this.nodeAgentUrl=n,this.commandOverride=r,this.lockPath=i}async start(e){await Ds(e.instance,this.processByInstanceId,this.lockPath);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),o=e.instance.runtime.port||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 Ss(e))return e;const n=new Error(`No free localhost port found in range ${t}-${Math.min(t+999,65535)}.`);throw Object.assign(n,{statusCode:503,code:"LOCAL_INSTANCE_PORT_UNAVAILABLE"}),n}(),s=n.join(this.paths.dataDir,"local-instances",e.instance.id),c=n.join(s,"logs");t.mkdirSync(c,{recursive:!0});const[d,...l]=function(e){if(e)return e;const r=n.resolve(process.cwd(),"bin","task-handoff.js");if(t.existsSync(r))return[process.execPath,r,"web"];throw Object.assign(new Error("The bundled controlled-instance command is unavailable."),{statusCode:500,code:"LOCAL_CONTROLLED_COMMAND_MISSING"})}(this.commandOverride),u=[...l,"--host","127.0.0.1","--port",String(o)],m=r.randomUUID(),p=t.openSync(n.join(c,"controlled-instance.out.log"),"a"),g=t.openSync(n.join(c,"controlled-instance.err.log"),"a"),h=a.spawn(d,u,{cwd:i,detached:!1,stdio:["ignore",p,g],env:{...process.env,TASK_HANDOFF_CONTROL_MODE:"controlled",TASK_HANDOFF_RUNTIME_KIND:"local",TASK_HANDOFF_CONTROLLED_INSTANCE_VERSION:ns(),...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:m,TASK_HANDOFF_WORKSPACE:i,TASK_HANDOFF_WORKSPACE_MODE:"local-bind",TASK_HANDOFF_DATA_DIR:s,TASK_HANDOFF_LOG_DIR:c,TASK_HANDOFF_APP_SESSION_PERSIST:"1",TASK_HANDOFF_CODEX_APP_SERVER:process.env.TASK_HANDOFF_CODEX_APP_SERVER||"1",TASK_HANDOFF_WEB_PORT:String(o),TASK_HANDOFF_WEB_HOST:"127.0.0.1",...e.modelEnv||{}}});t.closeSync(p),t.closeSync(g);try{await function(e){return new Promise((t,n)=>{const r=()=>{e.off("error",i),t()},i=t=>{e.off("spawn",r),n(t)};e.once("spawn",r),e.once("error",i)})}(h)}catch(e){const r=e instanceof Error?e.message:String(e);try{t.appendFileSync(n.join(c,"controlled-instance.lifecycle.log"),`[${(new Date).toISOString()}] spawn failed command=${d} cwd=${i} error=${r}\n`)}catch{}throw Object.assign(new Error(`Controlled instance process could not start with command ${d} in ${i}: ${r}`),{statusCode:500,code:"LOCAL_INSTANCE_PROCESS_SPAWN_FAILED"})}this.processByInstanceId.set(e.instance.id,h),h.on("error",e=>{try{t.appendFileSync(n.join(c,"controlled-instance.lifecycle.log"),`[${(new Date).toISOString()}] process error pid=${h.pid??""} error=${e.message}\n`)}catch{}}),h.once("exit",(r,i)=>{this.processByInstanceId.delete(e.instance.id);try{t.appendFileSync(n.join(c,"controlled-instance.lifecycle.log"),`[${(new Date).toISOString()}] exited pid=${h.pid??""} code=${r??""} signal=${i??""}\n`)}catch{}});const f=`http://127.0.0.1:${o}`,y=h.pid?k(h.pid):void 0,I=!(!h.pid||!e.instance.registrationToken)&&await async function(e,t,n,r,i=3e3){const o=Date.now()+i;for(;Date.now()<o;){if(null!==n.exitCode||null!==n.signalCode)return!1;const i=await Os(e,r);if(i&&i.instanceId===t.instanceId&&i.pid===t.pid&&i.processNonce===t.processNonce&&i.startIdentity===t.startIdentity)return!0;await new Promise(e=>setTimeout(e,100))}return!1}(f,{instanceId:e.instance.id,pid:h.pid,processNonce:m,startIdentity:y},h,e.instance.registrationToken);if(!I)throw this.processByInstanceId.get(e.instance.id)===h&&this.processByInstanceId.delete(e.instance.id),null===h.exitCode&&null===h.signalCode&&h.kill("SIGTERM"),await _s(h),Object.assign(new Error(`Controlled instance process did not become ready for instance ${e.instance.id} on ${f}.`),{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:f,api:`${f}/api`},workspace:{mode:"local-bind",status:"pending",path:i},runtime:{kind:"local",workspacePath:i,pid:h.pid,port:o,labels:{...e.instance.runtime.labels,"task-handoff.runtime-kind":"local",[Ts]:m}}}}async stop(e){return await Ds(e.instance,this.processByInstanceId,this.lockPath),{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 await Ds(e.instance,this.processByInstanceId,this.lockPath),this.start(e)}async delete(e){return this.stop(e)}async check(e){const[t,n]=await Promise.all([js(this.runCommand,"codex"),js(this.runCommand,"claude")]);return{status:"online",capabilities:Es({...e.capabilities,apps:{terminal:!0,codex:t,claude:n}})}}async stopAll(){const e=Array.from(this.processByInstanceId.values());for(const e of this.processByInstanceId.values())e.killed||e.kill("SIGTERM");this.processByInstanceId.clear(),await Promise.all(e.map(e=>_s(e)))}}class Fs{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;const t=new Error(`Runtime type ${e.type} is not supported by this node agent.`);throw Object.assign(t,{statusCode:400,code:"NODE_RUNTIME_TYPE_UNSUPPORTED"}),t}managedAdapters(){return[this.docker,this.local].filter(Ms)}async stopAll(){this.local instanceof $s&&await this.local.stopAll()}}class Us extends Ei{onStored;setOnStored(e){this.onStored=e}put(e){const t=super.get(e.id)?.stateRevision||0,n=super.put(nr.parse({...e,stateRevision:Math.max(e.stateRevision||0,t)+1}));return this.onStored?.(n),n}}class Vs{nodeId;paths;localFolders;nodeRuntimes;controlledInstances;models;modelAssignments;modelEnvironments;updateJobs;node;listenerPort;containerUrlOverride;platform;constructor(e,t,n,r,i,o){this.paths=e,this.nodeId=t,this.localFolders=new Ei(e.localFoldersDir,{schema:sn,sanitize:Et}),this.nodeRuntimes=new Ei(e.nodeRuntimesDir,{schema:Bn}),this.controlledInstances=new Us(e.controlledInstancesDir,{schema:nr,sanitize:e=>sr(e,e=>{console.warn(JSON.stringify({message:"legacy controlled instance field was ignored",...e}))})}),this.models=new io(e.nodeModelsDir,t),this.modelAssignments=new oo(e.modelAssignmentsDir),this.modelEnvironments=new ro(e.modelEnvironmentsDir),this.updateJobs=new ji(e),this.listenerPort=i,this.platform=o,this.containerUrlOverride=r;const s=ms();this.node=qn.parse({id:t,name:t,connectionMode:"direct-http",endpoint:n,controlEndpoint:n,containerEndpoint:this.containerUrl,publicWebBase:n?n.replace(/:\d+$/,""):void 0,status:"online",health:"ok",capabilities:{},labels:{},createdAt:s,updatedAt:s})}init(){this.localFolders.init();for(const e of this.localFolders.list())this.localFolders.put(e);if(this.nodeRuntimes.init(),this.controlledInstances.init(),this.models.init(),this.modelAssignments.init(),this.migrateLegacyModelEnvironments(),this.updateJobs.init(),this.updateJobs.reconcileRollouts(this.controlledInstances.list(),ns(),{processStarted:!0}),!this.nodeRuntimes.get("runtime_local_docker")){const e=ms();this.nodeRuntimes.put(Bn.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(Go),t=ms();this.nodeRuntimes.put(Bn.parse({id:Go,nodeId:this.nodeId,name:"Local Runtime",type:"local",status:e?.status||"unknown",accessStrategy:"node-proxy",capabilities:Es(e?.capabilities),labels:{...e?.labels,[Jo]:"true"},createdAt:e?.createdAt||t,updatedAt:e?.updatedAt||t}))}for(const e of this.nodeRuntimes.list())e.nodeId!==this.nodeId&&this.nodeRuntimes.put(Bn.parse({...e,nodeId:this.nodeId,updatedAt:ms()}));for(const e of this.localFolders.list())e.nodeId!==this.nodeId&&this.localFolders.put(sn.parse({...e,nodeId:this.nodeId,updatedAt:ms()}));this.normalizeInstanceRuntimeVersions()}normalizeInstanceRuntimeVersions(){for(const e of this.controlledInstances.list()){const t=rs(e.build?.packageVersion||e.instanceVersion),n=vs(this.requireRuntime(e.runtimeId)),r=["created","stopped","failed"].includes(e.status),i=n&&e.runtimeVersion?.desiredVersion===t.desiredVersion?e.runtimeVersion:void 0,o=n?"matched"===t.phase?r?t:{...t,phase:"verifying",matchedAt:void 0}:"failed"===i?.phase?{...t,phase:"failed",attempt:i.attempt,lastAttemptAt:i.lastAttemptAt,error:i.error}:{...t,attempt:i?.attempt||0,lastAttemptAt:i?.lastAttemptAt}:t;this.controlledInstances.put(nr.parse({...e,ready:!1,runtimeVersion:o,updatedAt:ms()}))}}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=ms()}runningInstanceCount(){const e=new Set(["created","stopped","failed"]);return this.listInstances().filter(t=>!e.has(t.status)).length}createLocalFolder(e){const t=ms(),n=sn.parse({...e,id:e.id||zi("folder"),nodeId:this.nodeId,labels:e.labels||{},createdAt:t,updatedAt:t});return this.localFolders.put(n)}createRuntime(e){if("local"===e.type){const e="win32"===this.platform,t=new Error(e?"Local Runtime is not supported on Windows.":"Local Runtime is built in and cannot be added manually.");throw Object.assign(t,{statusCode:e?400:409,code:e?"LOCAL_RUNTIME_UNSUPPORTED":"LOCAL_RUNTIME_BUILTIN"}),t}const t=ms(),n=Bn.parse({...e,id:e.id||zi("runtime"),nodeId:this.nodeId,accessStrategy:e.accessStrategy||(r=e.type,"docker"===r?"direct-port":"node-proxy"),capabilities:e.capabilities||{},labels:Xo(e.labels),createdAt:t,updatedAt:t});var r;return this.nodeRuntimes.put(n)}updateRuntime(e,t){const n=this.requireRuntime(e);if("true"===n.labels[Jo]){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 r=Bn.parse({...n,...t,id:n.id,nodeId:this.nodeId,accessStrategy:t.accessStrategy||n.accessStrategy,capabilities:t.capabilities||n.capabilities,labels:t.labels?Xo(t.labels):n.labels,createdAt:n.createdAt,updatedAt:ms()});return this.nodeRuntimes.put(r)}deleteRuntime(e){if("true"===this.requireRuntime(e).labels[Jo]){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=Bn.parse({...n,...e,id:n.id,nodeId:this.nodeId,createdAt:n.createdAt,updatedAt:ms()});return this.nodeRuntimes.put(t)}):this.nodeRuntimes.put(Bn.parse({...n,status:"unknown",updatedAt:ms()}))}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=or(t);if(!n.success)throw function(e,t){const n=t.map(e=>`${e.path.join(".")||"body"}: ${e.message}`).join("; "),r=new Error(`Stored instance ${e} is not compatible with protocol ${it}: ${n}`);return Object.assign(r,{statusCode:409,code:"NODE_INSTANCE_PAYLOAD_INVALID"}),r}(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 nr.parse({...e,status:"starting",ready:!1,updatedAt:n});case"convergence-restart-requested":return nr.parse({...e,build:void 0,instanceVersion:void 0,ready:!1,updatedAt:n});case"runtime-lifecycle-completed":return function(e,t,n,r){const i=t.stateRevision>e.stateRevision&&t.lastHeartbeatAt!==e.lastHeartbeatAt&&"online"===t.agentStatus;return nr.parse({...t,...n,...i?{status:t.status,health:t.health,connectionStatus:t.connectionStatus,agentStatus:t.agentStatus,targetStatus:t.targetStatus,uiAccessStatus:t.uiAccessStatus}:{},ready:!!i&&t.ready,target:n.target?i?{...n.target,...t.target}:{...t.target,...n.target}:t.target,workspace:n.workspace?i?{...n.workspace,...t.workspace}:{...t.workspace,...n.workspace}:t.workspace,runtime:n.runtime?{...t.runtime,...n.runtime}:t.runtime,updatedAt:r})}(t.baseline,e,t.observation,n);case"stop-completed":return nr.parse({...e,status:"stopped",health:"unknown",connectionStatus:"offline",ready:!1,agentStatus:"offline",targetStatus:"unknown",uiAccessStatus:"unknown",target:{...e.target,status:"unknown"},updatedAt:n});case"start-failed":return nr.parse({...e,status:"failed",ready:!1,health:"failed",connectionStatus:"offline",agentStatus:"offline",targetStatus:"unknown",uiAccessStatus:"unknown",workspace:{...e.workspace,error:(r=t.error,r instanceof Error?r.message:String(r))},updatedAt:n})}var r}(this.requireInstance(e),t))}listInstances(){return this.controlledInstances.list().flatMap(e=>{const t=or(e);return t.success?[t.data]:[]})}listModels(){const e=new Map;for(const t of this.listInstances()){const n=this.modelAssignments.get(t.id);for(const t of[n?.codexModelHash,n?.claudeModelHash])t&&e.set(t,(e.get(t)||0)+1)}return this.models.list().map(t=>this.publicModel(t,e.get(t.id)||0))}createModel(e){const t=ms(),n=zn(e),r=this.models.get(n),i=mn.parse({...e,id:n,enabled:e.enabled??!0,order:e.order??this.nextModelOrder(),labels:e.labels||{},createdAt:r?.createdAt||t,updatedAt:t});return this.publicModel(this.models.put(i),this.modelReferenceIds(n).length)}deployModel(e){const t=zn(e);if(e.id!==t)throw Object.assign(new Error(`Model content hash ${t} does not match ${e.id}.`),{statusCode:400,code:"NODE_MODEL_HASH_MISMATCH"});const n=this.models.get(e.id)||this.models.put(mn.parse(e));return this.publicModel(n,this.modelReferenceIds(n.id).length)}updateModel(e,t){const n=this.requireModel(e),r=mn.parse({...n,...t,key:t.key?.trim()?t.key:n.key,createdAt:n.createdAt,updatedAt:ms()}),i=zn(r),o=this.models.put(mn.parse({...r,id:i}));return this.publicModel(o,this.modelReferenceIds(i).length)}deleteModel(e){this.requireModel(e);const t=this.modelReferenceIds(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)}assignModels(e,t){const n=this.requireInstance(e);if(this.validateAssignmentRef("codex",t.codexModelHash),this.validateAssignmentRef("claude",t.claudeModelHash),void 0!==t.modelSelection.codexModelHash&&(t.modelSelection.codexModelHash??void 0)!==t.codexModelHash)throw Object.assign(new Error("Codex model selection does not match its node assignment."),{statusCode:400,code:"NODE_MODEL_SELECTION_MISMATCH"});if(void 0!==t.modelSelection.claudeModelHash&&(t.modelSelection.claudeModelHash??void 0)!==t.claudeModelHash)throw Object.assign(new Error("Claude model selection does not match its node assignment."),{statusCode:400,code:"NODE_MODEL_SELECTION_MISMATCH"});const r=this.modelAssignments.get(e),i=hn.parse({instanceId:e,codexModelHash:t.codexModelHash,claudeModelHash:t.claudeModelHash,updatedAt:ms()});this.modelAssignments.put(i);try{return{assignment:i,instance:this.controlledInstances.put(nr.parse({...n,modelSelection:t.modelSelection,updatedAt:ms()}))}}catch(t){throw r?this.modelAssignments.put(r):this.modelAssignments.delete(e),t}}resolvedAssignedModelEnvironment(e){const t=this.modelAssignments.get(e);if(!t){if(this.modelEnvironments.has(e))throw Object.assign(new Error(`Legacy model environment for instance ${e} requires manual migration.`),{statusCode:409,code:"NODE_MODEL_MIGRATION_REQUIRED"});return{}}return{...this.modelEnvironmentForRef("codex",t.codexModelHash),...this.modelEnvironmentForRef("claude",t.claudeModelHash)}}validateAssignmentRef(e,t){if(!t)return;const n=this.requireModel(t);if(n.app!==e)throw Object.assign(new Error(`Model ${n.id} belongs to ${n.app}, not ${e}.`),{statusCode:400,code:"NODE_MODEL_APP_MISMATCH"});if(!n.enabled)throw Object.assign(new Error(`Model ${n.id} is disabled.`),{statusCode:409,code:"NODE_MODEL_DISABLED"})}modelEnvironmentForRef(e,t){if(!t)return{};this.validateAssignmentRef(e,t);const n=this.requireModel(t);return"codex"===e?{OPENAI_API_KEY:n.key,OPENAI_BASE_URL:n.endpoint,TASK_HANDOFF_CODEX_BASE_URL:n.endpoint,TASK_HANDOFF_CODEX_MODEL:n.model}:{ANTHROPIC_API_KEY:n.key,ANTHROPIC_BASE_URL:n.endpoint,TASK_HANDOFF_CLAUDE_MODEL:n.model}}requireModel(e){const t=this.models.get(e);if(!t)throw Object.assign(new Error(`Model ${e} was not found on node ${this.nodeId}.`),{statusCode:404,code:"NODE_MODEL_NOT_FOUND"});if(zn(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}modelReferenceIds(e){return this.listInstances().filter(t=>{const n=this.modelAssignments.get(t.id);return n?.codexModelHash===e||n?.claudeModelHash===e}).map(e=>e.id)}publicModel(e,t){const{key:n,...r}=e;return gn.parse({...r,keyPreview:n.length<=8?"set":`${n.slice(0,4)}...${n.slice(-4)}`,keySet:!0,referenceCount:t})}nextModelOrder(){return this.models.list().reduce((e,t)=>Math.max(e,t.order),0)+100}migrateLegacyModelEnvironments(){for(const e of this.modelEnvironments.listInstanceIds()){if(!this.controlledInstances.get(e)){this.warnLegacyModelMigration(e,"instance-not-found");continue}if(this.modelAssignments.get(e)){try{this.resolvedAssignedModelEnvironment(e),this.modelEnvironments.delete(e)}catch{this.warnLegacyModelMigration(e,"existing-assignment-invalid")}continue}let t;try{t=this.modelEnvironments.get(e)}catch{this.warnLegacyModelMigration(e,"sidecar-invalid");continue}if(!Object.keys(t).length){this.modelEnvironments.delete(e);continue}if(Object.keys(t).some(e=>!no.has(e))){this.warnLegacyModelMigration(e,"unknown-fields");continue}const n=[];try{const r=this.migrateLegacyModelForApp(t,"codex",n),i=this.migrateLegacyModelForApp(t,"claude",n);if(!r&&!i)throw new Error("no complete model configuration");const o={...r?{codexModelHash:r}:{},...i?{claudeModelHash:i}:{}};this.assignModels(e,{modelSelection:o,codexModelHash:r,claudeModelHash:i}),this.resolvedAssignedModelEnvironment(e),this.modelEnvironments.delete(e)}catch{this.modelAssignments.delete(e);for(const e of n)this.models.delete(e);this.warnLegacyModelMigration(e,"mapping-failed")}}}migrateLegacyModelForApp(e,t,n){const r=e["codex"===t?"OPENAI_API_KEY":"ANTHROPIC_API_KEY"],i="codex"===t?e.TASK_HANDOFF_CODEX_BASE_URL||e.OPENAI_BASE_URL:e.ANTHROPIC_BASE_URL,o="codex"===t?e.TASK_HANDOFF_CODEX_MODEL||e.CODEX_MODEL:e.TASK_HANDOFF_CLAUDE_MODEL||e.CLAUDE_MODEL;if(!Boolean(r||i||o))return;if(!r||!i||!o)throw new Error("model configuration incomplete");const s=zn({app:t,endpoint:i,key:r,model:o}),a=this.models.get(s);if(a){if(a.app!==t||a.key!==r||a.endpoint!==i||a.model!==o||!a.enabled)throw new Error("existing model conflicts with legacy environment");return s}const c=ms();return this.models.put(mn.parse({id:s,name:`Migrated ${"codex"===t?"Codex":"Claude"} model`,endpoint:i,key:r,model:o,app:t,enabled:!0,order:this.nextModelOrder(),labels:{migratedFrom:"instance-model-environment"},createdAt:c,updatedAt:c})),n.push(s),s}warnLegacyModelMigration(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}))}createInstance(e){const t=this.requireRuntime(e.runtimeId),r=ms(),i=e.id||zi("inst"),o=an.parse(e.source);if(function(e){return"boolean"==typeof e.capabilities.requiresImage?e.capabilities.requiresImage:"local"!==e.type}(t)&&(!e.imageSelection||!e.image)){const e=new Error(`Runtime ${t.name} requires an image.`);throw Object.assign(e,{statusCode:400,code:"NODE_RUNTIME_IMAGE_REQUIRED"}),e}if("local"===t.type&&"local-folder"!==o.type){const e=new Error("Localhost runtime currently supports local folder sources only.");throw Object.assign(e,{statusCode:400,code:"LOCAL_RUNTIME_REQUIRES_LOCAL_FOLDER"}),e}if("local"===t.type&&this.listInstances().some(e=>"local"===this.requireRuntime(e.runtimeId).type)){const e=new Error("A localhost instance already exists on this node.");throw Object.assign(e,{statusCode:409,code:"LOCAL_RUNTIME_INSTANCE_EXISTS"}),e}const s=e.image?Pn.parse(e.image):void 0,a="local"===t.type&&"local-folder"===o.type?n.resolve(o.path):void 0,c=nr.parse({id:i,name:e.name||`instance-${i.replace(/^inst_?/,"").slice(0,6)}`,source:o,sourceSnapshot:e.sourceSnapshot||{},modelSelection:e.modelSelection,projectId:e.projectId,nodeId:this.nodeId,runtimeId:t.id,imageSelection:e.imageSelection,imageSnapshot:s,imageProvisioning:s&&"docker"===t.type?{phase:"checking-image",requestedReference:s.requestedReference,generation:0,startedAt:r,updatedAt:r}:void 0,status:s&&"docker"===t.type?"provisioning":"created",health:"unknown",connectionStatus:"unknown",agentStatus:"unknown",targetStatus:"unknown",uiAccessStatus:"unknown",controlMode:"controlled",ready:!1,runtimeVersion:rs(),capabilities:{},config:{autoImportAgentConfigs:e.config?.autoImportAgentConfigs??!0,defaultCodexPermissionMode:e.config?.defaultCodexPermissionMode??("docker"===t.type?"full-access":"ask")},workspace:"local"===t.type?{mode:"local-bind",status:"unknown",path:a}:{status:"unknown"},target:{strategy:"node-proxy",status:"unknown"},runtime:"local"===t.type?{kind:"local",workspacePath:a,labels:{"task-handoff.runtime-kind":"local"}}:{labels:{}},registrationToken:vi(),createdAt:r,updatedAt:r});return this.controlledInstances.put(c)}registerInstance(e,t,n){const r=lr.parse(t),i=ms(),o=this.controlledInstances.get(e);if(!o){const t=new Error(`Instance ${e} was not found on node ${this.nodeId}.`);throw Object.assign(t,{statusCode:404,code:"NODE_INSTANCE_NOT_FOUND"}),t}if(this.validateInstanceReport(o,r,n),r.processIncarnationId&&r.processIncarnationId===o.processIncarnationId)return o;zs(r.protocolVersion,`Instance ${e}`);const s=r.build?.packageVersion||r.instanceVersion,a=vs(this.requireRuntime(o.runtimeId)),c=is(o,s,a),d=nr.parse({...o,status:"registered",health:s===ns()?"ok":"degraded",ready:!a&&s===ns(),connectionStatus:"online",agentStatus:"online",targetStatus:"endpoint-unreachable"===r.target.status?"endpoint-unreachable":"reachable"===r.target.status?"reachable":o.targetStatus,uiAccessStatus:"endpoint-unreachable"===r.target.status?"endpoint-unreachable":o.uiAccessStatus,controlMode:r.controlMode,protocolVersion:r.protocolVersion,instanceVersion:r.instanceVersion,build:r.build,runtimeVersion:c,processIncarnationId:r.processIncarnationId||o.processIncarnationId,capabilities:r.capabilities,appInventory:r.appInventory,workspace:r.workspace,target:{...o.target,...r.target},registrationToken:o.registrationToken||r.registrationToken,lastHeartbeatAt:i,updatedAt:i});return this.controlledInstances.put(d)}heartbeatInstance(e,t,n){const r=this.requireInstance(e);this.validateInstanceToken(r,n);const i=ur.parse(t);r.processIncarnationId&&i.processIncarnationId&&i.processIncarnationId!==r.processIncarnationId&&function(e,t){const n=new Error(t);throw Object.assign(n,{statusCode:409,code:"INSTANCE_PROCESS_INCARNATION_MISMATCH"}),n}(0,`Instance ${e} report belongs to an obsolete controlled-instance process.`),zs(i.protocolVersion,`Instance ${e}`);const o=ms(),s=i.target?{...r.target,...i.target}:r.target,a={...s,status:"unknown"===s.status&&(s.web||s.api)?"reachable":s.status},c="endpoint-unreachable"===a.status?"endpoint-unreachable":"reachable"===a.status?"reachable":r.targetStatus,d=is(r,i.build?.packageVersion||r.build?.packageVersion||r.instanceVersion,vs(this.requireRuntime(r.runtimeId))),l=i.health||r.health,u="running"===(i.status||r.status)&&"failed"!==l,m=nr.parse({...r,...i,target:a,ready:u,health:l,runtimeVersion:d,processIncarnationId:i.processIncarnationId||r.processIncarnationId,agentStatus:"online",targetStatus:c,uiAccessStatus:c,connectionStatus:"online",build:i.build||r.build,lastHeartbeatAt:o,updatedAt:o});return this.controlledInstances.put(m)}validateInstanceReport(e,t,n){this.validateInstanceToken(e,n||t.registrationToken),t.instanceId&&t.instanceId!==e.id&&Ns("INSTANCE_ID_MISMATCH",`Instance ${t.instanceId} cannot register as ${e.id}.`),t.nodeId&&t.nodeId!==this.nodeId&&Ns("INSTANCE_NODE_MISMATCH",`Instance ${e.id} belongs to node ${this.nodeId}.`),t.runtimeId&&t.runtimeId!==e.runtimeId&&Ns("INSTANCE_RUNTIME_MISMATCH",`Instance ${e.id} belongs to runtime ${e.runtimeId}.`),t.imageSelection&&t.imageSelection.imageId!==e.imageSelection?.imageId&&Ns("INSTANCE_IMAGE_MISMATCH",`Instance ${e.id} belongs to image ${e.imageSelection?.imageId}.`)}validateInstanceToken(e,t){e.registrationToken&&t===e.registrationToken||Ns("INSTANCE_REGISTRATION_TOKEN_INVALID",`Invalid registration token for instance ${e.id}.`)}context(e,t=this.resolvedAssignedModelEnvironment(e.id)){const n=e.imageSnapshot||Pn.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});return{project:fs(e),image:n,node:this.node,runtime:this.requireRuntime(e.runtimeId),instance:e,nodeAgentUrl:this.containerUrl,modelEnv:t}}}class Hs{app;state;settings;sockets=new Set;config;source;status="error";error;constructor(e){this.app=e.app,this.state=e.state,this.settings=e.settings,this.config=e.config,this.source=e.source,this.app.server.on("connection",e=>{this.sockets.add(e),e.once("close",()=>this.sockets.delete(e))})}current(){return Jn.parse({...this.config,host:ps(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){this.status="error",this.error=e instanceof Error?e.message:String(e),this.app.log.error({host:ps(this.config.bindScope),port:this.config.port,error:this.error},"node agent TCP listener failed to start; Unix IPC remains available")}return this.current()}async update(e){const t=Wn.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){const t=new Error(`Cannot change the node agent port while ${e} controlled instance(s) are running.`);throw Object.assign(t,{statusCode:409,code:"NODE_AGENT_LISTENER_PORT_IN_USE_BY_INSTANCES",blockingInstanceCount:e}),t}}const n={config:this.config,source:this.source,status:this.status,error:this.error};await this.stop();try{await this.listen(t)}catch(e){await this.restore(n);const r=new Error(`Failed to bind node agent TCP listener at ${ps(t.bindScope)}:${t.port}: ${e instanceof Error?e.message:String(e)}`);throw Object.assign(r,{statusCode:409,code:"NODE_AGENT_LISTENER_BIND_FAILED"}),r}try{this.settings.put({version:1,externalListener:t})}catch(e){await this.stop(),await this.restore(n);const t=new Error(`Failed to persist node agent TCP listener: ${e instanceof Error?e.message:String(e)}`);throw Object.assign(t,{statusCode:500,code:"NODE_AGENT_LISTENER_PERSIST_FAILED"}),t}return this.config=t,this.source="persisted",this.status="listening",this.error=void 0,this.state.setListenerPort(t.port),this.current()}async shutdown(){await this.stop()}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)}async listen(e){await new Promise((t,n)=>{const r=e=>{this.app.server.off("listening",i),n(e)},i=()=>{this.app.server.off("error",r),t()};this.app.server.once("error",r),this.app.server.once("listening",i),this.app.server.listen({host:ps(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()})}}async function qs(e,t,n,r,i,o="request"){const s=e.requireInstance(r);if(s.imageProvisioning&&"ready"!==s.imageProvisioning.phase&&"docker"===e.requireRuntime(s.runtimeId).type)return i.diagnostic({instanceId:r,action:"start",reason:o,runtimeId:s.runtimeId,imageId:s.imageSelection?.imageId,imagePhase:s.imageProvisioning.phase},"node instance start queued until image provisioning completes"),e.controlledInstances.put(nr.parse({...s,status:"starting",updatedAt:ms()}));i.diagnostic({instanceId:r,action:"start",reason:o,runtimeId:s.runtimeId,imageId:s.imageSelection?.imageId},"node instance start requested");const a=e.applyInstanceLifecycle(r,{type:"start-requested"}),c=t.forRuntime(e.requireRuntime(a.runtimeId)),d=await c.start(e.context(a)),l=await ys(n,nr.parse({...a,...d,target:d.target?{...a.target,...d.target}:a.target,workspace:d.workspace?{...a.workspace,error:void 0,...d.workspace}:a.workspace,runtime:d.runtime?{...a.runtime,...d.runtime}:a.runtime,updatedAt:ms()})),u=e.applyInstanceLifecycle(r,{type:"runtime-lifecycle-completed",baseline:a,observation:{...d,target:d.target?{...d.target,status:l}:void 0,workspace:d.workspace?{error:void 0,...d.workspace}:void 0,targetStatus:l,uiAccessStatus:l}});return i.diagnostic({instanceId:r,action:"start",reason:o,status:u.status,connectionStatus:u.connectionStatus,targetStatus:u.targetStatus,targetWeb:u.target.web,containerName:u.runtime.containerName},"node instance start completed"),u}function Bs(e){return nr.parse({...e,health:"unknown",connectionStatus:"offline",agentStatus:"offline",targetStatus:"unknown",uiAccessStatus:"unknown",target:{...e.target,status:"unknown"},updatedAt:ms()})}async function Ks(e={}){const r=e.token||process.env.TASK_HANDOFF_NODE_AGENT_TOKEN,i=Number(e.port||process.env.TASK_HANDOFF_NODE_AGENT_PORT||"8091"),o=`http://127.0.0.1:${i}`,a=e.containerUrl||process.env.TASK_HANDOFF_NODE_AGENT_CONTAINER_URL,p=yi(e.dataDir),g=e.remoteSecret||process.env.TASK_HANDOFF_NODE_AGENT_REMOTE_SECRET,h=e.remoteKeyId||process.env.TASK_HANDOFF_NODE_AGENT_REMOTE_KEY_ID,f=new jo(p),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||_i(p.dataDir),w="local-ipc"===I?`ipc://${encodeURIComponent(A)}`:o,N=e.platform||process.platform,z=e.arch||process.arch,v=new Vs(p,y,o,a,i,N);v.node.connectionMode=I,v.node.controlEndpoint=w,v.node.endpoint=w,v.init();const E=e.dockerCommandRunner||pr,S=new hr(E,e.dockerTerminalCommandRunner),_=new yr(E,{publishHost:"127.0.0.1",imageService:S}),T=new Fs(new Ls(_,E,N,z),new $s(e.dockerCommandRunner||pr,p,()=>v.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)),k=e.updateCommandRunner||e.dockerCommandRunner||pr,C=e.fetchImpl||fetch,O=new qi({cacheDir:n.join(p.dataDir,"runtime-artifacts"),fetchImpl:C}),x=e.resolveRuntimeArtifactRelease||((e,t,n)=>Bi(e,t,n,C)),R=async(t,n,r)=>{const i=await n.artifactTarget(r);if(e.resolveRuntimeArtifact)return e.resolveRuntimeArtifact(t,i.platform,i.arch);const o=await x(t,i.platform,i.arch);if(o.identity.launcherAbi>i.launcherAbi)throw Object.assign(new Error(`Runtime requires launcher ABI ${o.identity.launcherAbi}, but ${i.platform}-${i.arch} provides ABI ${i.launcherAbi}.`),{code:"INSTANCE_BASE_RUNTIME_INCOMPATIBLE",retryable:!1});return O.resolve(o.identity,o.source)},D=e=>T.forRuntime(v.requireRuntime(e.runtimeId)),P=e=>{const t=D(e);return Ms(t)?t:void 0},j=e=>{const t=P(e);if(t)return t;throw Object.assign(new Error(`Runtime for instance ${e.id} does not use managed artifacts.`),{code:"INSTANCE_RUNTIME_ARTIFACT_UNMANAGED",retryable:!1})},M=e=>Boolean(P(e)),L=(e,t)=>{const n=v.context(e);return R(t,j(e),n)},$=d({logger:e.logger??!0}),F={requests:0,active:0,completed:0,aborted:0,limitRejected:0,responseBytes:0,totalDurationMs:0,maxResponseBytes:cs()};$.decorate("nodeAgentState",v),await $.register(l);const U=new qr(v,r,{logger:$.log,safetyIntervalMs:Number(process.env.TASK_HANDOFF_EVENT_CONNECTION_SAFETY_INTERVAL_MS)||void 0}),V=new Ki(v.controlledInstances,ns,{isInstalled:async(e,t)=>{const n=await L(e,t);return j(e).inspectRuntime(v.context(e),n.identity)},beginDrain:async e=>{try{const t=await async function(e,t){const n=ws(t);if(t.registrationToken&&(await Is(e,`${n}/api/internal/node-agent/drain`,{method:"POST",headers:{authorization:`Bearer ${t.registrationToken}`}},1e4)).ok)return{requested:t.apps.runningCount,failures:[]};const r=await Is(e,`${n}/api/apps/sessions`,{method:"GET",headers:{"cache-control":"no-cache"}},5e3);if(!r.ok)throw new Error(`Could not list app sessions for runtime drain (HTTP ${r.status}).`);const i=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,r=(n&&"object"==typeof n&&!Array.isArray(n)?n:t).sessions;return Array.isArray(r)?r:[]}(await r.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(i.map(async t=>{try{const r=await Is(e,`${n}/api/apps/sessions/${encodeURIComponent(t)}/stop`,{method:"POST"},5e3);return r.ok?void 0:{sessionId:t,error:`HTTP ${r.status}`}}catch(e){return{sessionId:t,error:e instanceof Error?e.message:String(e)}}}));return{requested:i.length,failures:o.filter(e=>Boolean(e))}}(C,e);t.failures.length?$.log.warn({instanceId:e.id,requested:t.requested,failures:t.failures},"runtime convergence could not stop every app session"):$.log.info({instanceId:e.id,requested:t.requested},"runtime convergence requested app session drain")}catch(t){$.log.warn({instanceId:e.id,error:t instanceof Error?t.message:String(t)},"runtime convergence could not request app session drain")}},endDrain:async e=>{try{await async function(e,t){return!!t.registrationToken&&(await Is(e,`${ws(t)}/api/internal/node-agent/resume`,{method:"POST",headers:{authorization:`Bearer ${t.registrationToken}`}},5e3)).ok}(C,e)&&$.log.info({instanceId:e.id},"runtime convergence released app session drain")}catch(t){$.log.warn({instanceId:e.id,error:t instanceof Error?t.message:String(t)},"runtime convergence could not release app session drain")}},install:async(e,t)=>{const n=j(e);await n.installRuntime(v.context(e),await L(e,t))},restart:async e=>{const t=D(e),n=v.applyInstanceLifecycle(e.id,{type:"convergence-restart-requested"}),r=await t.restart(v.context(n));v.applyInstanceLifecycle(e.id,{type:"runtime-lifecycle-completed",baseline:n,observation:r})},onForcedDrain:e=>$.log.warn({instanceId:e.id},"runtime convergence drain deadline reached; restarting instance")},{drainTimeoutMs:Number(process.env.TASK_HANDOFF_RUNTIME_DRAIN_TIMEOUT_MS)||void 0,verificationTimeoutMs:Number(process.env.TASK_HANDOFF_RUNTIME_VERIFY_TIMEOUT_MS)||void 0,maxAttempts:Number(process.env.TASK_HANDOFF_RUNTIME_MAX_ATTEMPTS)||void 0});v.controlledInstances.setOnStored(e=>{U.publishInstanceLifecycle(e),v.updateJobs.reconcileRollouts(v.listInstances(),ns())}),U.start(),$.decorate("nodeAgentEventForwarder",U);const H=new Xr(E,()=>v.listInstances().filter(e=>"docker"===v.requireRuntime(e.runtimeId).type),e=>U.publish("instance.metrics.snapshot",e,{instanceId:e.instanceId}));H.start(),$.decorate("nodeAgentRuntimeMetrics",H);const q=(re=process.env.TASK_HANDOFF_DIAGNOSTIC_LOGS,["1","true","yes","on"].includes(String(re||"").trim().toLowerCase())),B=new mo(f,y,g,h),K=(e,t)=>{q&&$.log.info(e,t)},G={diagnostic:K,warn:(e,t)=>$.log.warn(e,t)},J=new Set,W=new Map,Y=(e,t,n)=>{const r=n&&"object"==typeof n&&!Array.isArray(n)?n.protocolVersion:void 0;if("string"!=typeof r||r===it)return n;const i=({field:n,action:i})=>$.log.warn({instanceId:e,report:t,protocolVersion:r,expectedProtocolVersion:it,field:n,action:i},"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,r=["instanceId","projectId","source","nodeId","runtimeId","imageSelection","instanceVersion","protocolVersion","build","controlMode","capabilities","appInventory","target","workspace","registrationToken","processIncarnationId"],i=new Set([...r,"imageId"]);for(const e of Object.keys(n))i.has(e)||t?.({field:e,action:"ignored"});return Object.prototype.hasOwnProperty.call(n,"imageId")&&t?.({field:"imageId",action:"migrated"}),{...dr(n,r),imageSelection:vt(n.imageSelection,n.imageId)}}(n,i):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"],r=new Set(n);for(const n of Object.keys(e))r.has(n)||t?.({field:n,action:"ignored"});return dr(e,n)}(n,i)},X=async(e,t)=>{try{let n=v.requireInstance(e);"failed"===n.runtimeVersion?.phase&&M(n)&&(n=v.controlledInstances.put(nr.parse({...n,ready:!1,runtimeVersion:rs(Gi(n)),updatedAt:ms()})));const r=v.requireRuntime(n.runtimeId);await qs(v,T,C,e,G);const i=v.requireInstance(e);if("docker"===r.type&&"ready"!==i.imageProvisioning?.phase)return U.syncNow(),i;J.add(e),W.delete(e);let o=v.requireInstance(e);if(M(o)){try{o=await V.schedule(e,{startRequested:!0})}catch(n){o=v.requireInstance(e),G.warn({instanceId:e,action:"runtime.converge",reason:t,error:n instanceof Error?n.message:String(n)},"node instance runtime convergence failed after start")}"failed"===o.runtimeVersion?.phase&&G.warn({instanceId:e,action:"runtime.converge",reason:t,error:o.runtimeVersion.error},"node instance started with failed runtime convergence")}return await As(C,o,"start",G),U.syncNow(),o}catch(n){throw v.applyInstanceLifecycle(e,{type:"start-failed",error:n}),U.syncNow(),G.warn({instanceId:e,action:"start",reason:t,error:n instanceof Error?n.message:String(n)},"node instance start failed"),n}},Q=e=>{e.imageProvisioning&&async function(t,n,r,i,o,s,a){const c=e=>{const n=t.controlledInstances.get(r);n&&n.imageProvisioning?.generation===i&&n.imageSnapshot&&(t.controlledInstances.put(nr.parse({...n,status:"starting"===n.status?"starting":"provisioning",imageProvisioning:{...n.imageProvisioning,phase:e,error:void 0,updatedAt:ms()},updatedAt:ms()})),o())},d=t.controlledInstances.get(r);if(!d?.imageSnapshot||d.imageProvisioning?.generation!==i)return;let l=0,u=!1;try{const m=await n.ensure(d.imageSnapshot.requestedReference,c,e=>{u=!0,l=e.sequence,a?.(e)});u&&a?.({sequence:l+1,outcome:"succeeded"});const p=t.controlledInstances.get(r);if(!p?.imageSnapshot||p.imageProvisioning?.generation!==i)return;t.controlledInstances.put(nr.parse({...p,status:"starting"===p.status?"starting":"created",health:"unknown",imageSnapshot:{...p.imageSnapshot,requestedReference:m.requestedReference,resolvedDigest:m.resolvedDigest,resolvedReference:m.resolvedReference},imageProvisioning:{...p.imageProvisioning,phase:"ready",error:void 0,updatedAt:ms()},updatedAt:ms()})),o(),s.diagnostic({instanceId:r,action:"image.provision",reference:m.requestedReference,digest:m.resolvedDigest,pulled:m.pulled},"node instance image provisioning completed"),"starting"===p.status&&await((async e=>{await X(e,"image-ready").catch(()=>{})})(e.id))}catch(e){u&&a?.({sequence:l+1,outcome:"failed"});const n=t.controlledInstances.get(r);if(!n?.imageProvisioning||n.imageProvisioning.generation!==i)return;const c=e instanceof Error?e.message:String(e);t.controlledInstances.put(nr.parse({...n,status:"failed",health:"failed",imageProvisioning:{...n.imageProvisioning,phase:"failed",error:c,updatedAt:ms()},updatedAt:ms()})),o(),s.warn({instanceId:r,action:"image.provision",reference:n.imageProvisioning.requestedReference,error:c},"node instance image provisioning failed")}}(v,S,e.id,e.imageProvisioning.generation,()=>U.syncNow(),G,t=>{const n={instanceId:e.id,generation:e.imageProvisioning.generation,requestedReference:e.imageProvisioning.requestedReference,observedAt:ms()};if("outcome"in t)U.publish(Ln,{...n,sequence:1e3*t.sequence,outcome:t.outcome},{instanceId:e.id});else for(const[r,i]of function(e,t=6e4){const n=[];for(let r=0;r<e.length;r+=t)n.push(e.slice(r,r+t));return n}(t.data).entries())U.publish(Mn,{...n,sequence:1e3*t.sequence+r,data:i,...t.replay?{replay:!0}:{}},{instanceId:e.id})})},Z=async e=>{const t=new Map;for(const e of T.managedAdapters()){const n=await e.artifactTarget();t.set(`${n.platform}-${n.arch}`,{adapter:e})}for(const e of v.listInstances()){const n=P(e);if(!n)continue;const r=v.context(e),i=await n.artifactTarget(r);t.set(`${i.platform}-${i.arch}`,{adapter:n,context:r})}return(await Promise.all([...t.values()].map(({adapter:t,context:n})=>R(e,t,n)))).sort((e,t)=>`${e.identity.platform}/${e.identity.arch}`.localeCompare(`${t.identity.platform}/${t.identity.arch}`))},ee=async e=>{const t=te(),n=await Di(k),r="@task-handoff/server"===n.packageName?[...new Set([...n.relatedCurrentVersions,ns()])]:n.relatedCurrentVersions,i=await async function(e){const t=e.packageName||"@task-handoff/node-agent",n=await async function(e,t,n){const r=function(e){return"stable"===e?"latest":e}(n),i=await e(xi(),["view",`${t}@${r}`,"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(!i)return;const o=JSON.parse(i.stdout);if("string"!=typeof o)throw new Error(`npm did not resolve ${t}@${r} to one version.`);return o}(e.runCommand,t,e.channel);if(!n)return function(e){return Zt.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:Ci()})}({channel:e.channel,currentVersion:e.currentVersion,impact:e.impact});const r=Oi(e.currentVersion,n)||(e.relatedCurrentVersions||[]).some(e=>Oi(e,n)),i=r?await async function(e,t,n){const r=await e(xi(),["view",`${t}@${n}`,"dist.integrity","--json"]),i=JSON.parse(r.stdout);if("string"!=typeof i||!/^sha(?:256|384|512)-[A-Za-z0-9+/=]+$/.test(i))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 i}(e.runCommand,t,n):void 0;return Zt.parse({source:"npm",channel:e.channel,currentVersion:e.currentVersion,availableVersion:n,...i?{artifactRef:`npm:${t}@${n}#${i}`}:{},runtimeArtifacts:e.runtimeArtifacts||[],impact:e.impact||{runningInstanceCount:0,stoppedInstanceCount:0,activeInstanceCount:0,restartInstanceCount:0,runningInstanceIds:[],stoppedInstanceIds:[],activeInstanceIds:[]},updateAvailable:r,checkedAt:Ci()})}({channel:e.channel,currentVersion:n.currentVersion||ns(),runCommand:k,packageName:n.packageName,relatedCurrentVersions:r,impact:t});if(!i.updateAvailable)return i;const o=await Z(i.availableVersion),s={...i,runtimeArtifacts:o.map(e=>e.identity),preflightToken:vi()};return ne.set(s.preflightToken,{result:s,expiresAt:Date.now()+6e5}),s},te=()=>{const e=v.listInstances(),t=e.filter(e=>!["created","stopped","failed"].includes(e.status)),n=t.filter(e=>e.apps.runningCount>0||e.aiSessions.runningCount>0);return{runningInstanceCount:t.length,stoppedInstanceCount:e.length-t.length,activeInstanceCount:n.length,restartInstanceCount:t.length,runningInstanceIds:t.map(e=>e.id).sort(),stoppedInstanceIds:e.filter(e=>!t.includes(e)).map(e=>e.id).sort(),activeInstanceIds:n.map(e=>e.id).sort()}},ne=new Map;var re;let ie;$.setErrorHandler((e,t,n)=>{const r=function(e){if(e instanceof m.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);(q||r.statusCode>=500)&&(r.statusCode>=500?$.log.error.bind($.log):$.log.warn.bind($.log))({method:t.method,url:t.url,statusCode:r.statusCode,errorCode:r.code,error:r.message},"node agent request failed"),n.code(r.statusCode).send({error:{code:r.code,message:r.message,...e&&"object"==typeof e&&"string"==typeof e.expectedVersion?{expectedVersion:e.expectedVersion}:{},...e&&"object"==typeof e&&"string"==typeof e.actualVersion?{actualVersion:e.actualVersion}:{},...e&&"object"==typeof e&&"string"==typeof e.phase?{phase:e.phase}:{},...e&&"object"==typeof e&&"boolean"==typeof e.retryable?{retryable:e.retryable}:{},...e&&"object"==typeof e&&"number"==typeof e.blockingInstanceCount?{blockingInstanceCount:e.blockingInstanceCount}:{}}})}),$.addHook("preHandler",async e=>{const t=B.verify(e);if(t)e.nodeAgentAuthKeyId=t;else if(us(e)){if(r&&ds(e.headers)!==r){const e=new Error("Invalid node agent token.");throw Object.assign(e,{statusCode:401,code:"NODE_AGENT_UNAUTHORIZED"}),e}}else if("/api/node-agent/pairing/complete"!==e.url.split("?")[0]&&!function(e){const t=e.split("?")[0];return/^\/api\/node-agent\/instances\/[^/]+\/(register|heartbeat)$/.test(t)}(e.url)){if(B.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 ls(e.ip)||ls(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(r&&ds(e.headers)!==r){const e=new Error("Invalid node agent token.");throw Object.assign(e,{statusCode:401,code:"NODE_AGENT_UNAUTHORIZED"}),e}}});let oe=!1,se=!1;$.addHook("onClose",async()=>{se=!0,ie&&clearTimeout(ie),H.stop(),U.stop();for(const e of v.listInstances())V.cancel(e.id);await async function(e,t){await t.stopAll();for(const t of e.listInstances())"local"===e.requireRuntime(t.runtimeId).type&&e.controlledInstances.put(Bs(t))}(v,T)});const ae=async()=>{for(const e of v.listInstances().filter(e=>["provisioning","starting"].includes(e.status)&&"ready"!==e.imageProvisioning?.phase&&"docker"===v.requireRuntime(e.runtimeId).type))Q(e);const e=v.listInstances().filter(e=>{if(J.has(e.id))return!1;const t=v.requireRuntime(e.runtimeId);return"local"===t.type?Ps.has(e.status):"docker"===t.type&&(Ps.has(e.status)||"provisioning"===e.status&&"ready"===e.imageProvisioning?.phase)});for(const t of e)try{await qs(v,T,C,t.id,G,"restore"),await As(C,v.requireInstance(t.id),"start",G),J.add(t.id),W.delete(t.id)}catch(e){"local"===v.requireRuntime(t.runtimeId).type&&v.applyInstanceLifecycle(t.id,{type:"start-failed",error:e});const n=e instanceof Error?e.message:String(e);W.get(t.id)!==n&&(W.set(t.id,n),G.warn({instanceId:t.id,action:"restore",runtimeId:t.runtimeId,error:n},"node instance restore failed; recovery will retry"))}},ce=async()=>{const e=v.listInstances().filter(e=>M(e)&&!V.isRunning(e.id)&&(J.has(e.id)||"unknown"!==e.target.status)&&(!e.ready||"matched"!==e.runtimeVersion?.phase)&&!["created","stopped","failed","provisioning","stopping"].includes(e.status));await Promise.all(e.map(async e=>{try{await V.schedule(e.id)}catch(t){$.log.error({instanceId:e.id,error:t},"runtime convergence recovery failed")}}))};$.decorate("nodeAgentRestoreManagedInstances",ae),$.decorate("nodeAgentRecoverManagedInstances",ce),$.decorate("nodeAgentStartRecoverySupervisor",()=>{if(oe)return;oe=!0;const e=()=>{(async()=>{await ae(),await ce()})().catch(e=>$.log.error({error:e},"node agent startup recovery cycle failed")).finally(t)},t=()=>{se||(ie=setTimeout(()=>{ie=void 0,e()},1e4),ie.unref?.())};e()}),$.get("/api/node-agent/health",async()=>{return{data:{ok:!0,role:"node-agent",nodeId:y,platform:Yo(N),arch:process.arch,protocolVersion:it,build:(e="node-agent",{component:e,packageName:"@task-handoff/node-agent",packageVersion:ns(),protocolVersion:it,buildId:ts("TASK_HANDOFF_BUILD_ID"),builtAt:ts("TASK_HANDOFF_BUILT_AT"),gitCommit:ts("TASK_HANDOFF_GIT_COMMIT"),imageRef:ts("TASK_HANDOFF_IMAGE_REF"),imageDigest:ts("TASK_HANDOFF_IMAGE_DIGEST")}),instanceProxy:{...F},serverTime:(new Date).toISOString()}};var e});const de=e=>{if(!us(e)){const e=new Error("Node agent TCP listener settings are available only over local Unix IPC.");throw Object.assign(e,{statusCode:403,code:"NODE_AGENT_LISTENER_LOCAL_IPC_ONLY"}),e}if(!$.nodeAgentListenerManager){const e=new Error("Node agent TCP listener manager is not initialized.");throw Object.assign(e,{statusCode:503,code:"NODE_AGENT_LISTENER_UNAVAILABLE"}),e}return $.nodeAgentListenerManager};return $.get("/api/node-agent/settings/external-listener",async e=>({data:de(e).current()})),$.patch("/api/node-agent/settings/external-listener",async e=>({data:await de(e).update(e.body)})),$.get("/api/node-agent/updates/jobs",async()=>({data:v.updateJobs.list()})),$.post("/api/node-agent/updates/check",async e=>({data:await ee(Qt.parse(e.body))})),$.post("/api/node-agent/updates/apply",async(e,r)=>{const i=es.parse(e.body),o=await(async e=>{const t=ne.get(e.preflightToken);if(ne.delete(e.preflightToken),!t||t.expiresAt<=Date.now()){const e=new Error("The update preflight is missing or expired. Check for updates again.");throw Object.assign(e,{statusCode:409,code:"UPDATE_PREFLIGHT_EXPIRED"}),e}const n=t.result,r=await Di(k);if(n.channel!==e.channel||n.availableVersion!==e.targetVersion||n.currentVersion!==(r.currentVersion||ns())||!0!==n.artifactRef?.startsWith(`npm:${r.packageName}@`)||JSON.stringify(n.impact)!==JSON.stringify(te())){const e=new Error("The update target or affected instances changed after preflight. Check for updates again.");throw Object.assign(e,{statusCode:409,code:"UPDATE_PREFLIGHT_STALE"}),e}const i=await Z(n.availableVersion);if(JSON.stringify(n.runtimeArtifacts)!==JSON.stringify(i.map(e=>e.identity))){const e=new Error("The runtime artifacts changed after preflight. Check for updates again.");throw Object.assign(e,{statusCode:409,code:"UPDATE_PREFLIGHT_STALE"}),e}return n})(i);if(!o.supported){const e=new Error(o.reason||"The requested update is not supported.");throw Object.assign(e,{statusCode:400,code:"UPDATE_UNSUPPORTED"}),e}if(!o.updateAvailable){const e=new Error(o.reason||"No update is available for the selected channel.");throw Object.assign(e,{statusCode:409,code:"UPDATE_NOT_AVAILABLE"}),e}const a=v.updateJobs.create(y,o),c=("undefined"==typeof document?require("url").pathToFileURL(__filename).href:b&&"SCRIPT"===b.tagName.toUpperCase()&&b.src||new URL("cli.js",document.baseURI).href)?n.dirname(s.fileURLToPath("undefined"==typeof document?require("url").pathToFileURL(__filename).href:b&&"SCRIPT"===b.tagName.toUpperCase()&&b.src||new URL("cli.js",document.baseURI).href)):__dirname,{worker:d,packaged:l,expectedWorker:u}=function(e,r=t.existsSync){const i=[n.resolve(e,"..","bin","task-handoff-node-update-worker"),n.resolve(e,"..","..","bin","task-handoff-node-update-worker")],o=i.find(r),s=n.resolve(e,"..","..","..","..","scripts","node-update-worker.cjs");return o?{worker:o,packaged:!0,expectedWorker:i[0]}:r(s)?{worker:s,packaged:!1,expectedWorker:i[0]}:{worker:void 0,packaged:!1,expectedWorker:i[0]}}(c);if(!d){v.updateJobs.patch(a.id,{status:"failed",rollout:{...a.rollout,phase:"failed"},error:{code:"NODE_UPDATE_FAILED",message:`Update worker was not found: ${u}`,retryable:!1},completedAt:ms()});const e=new Error(`Node agent update worker was not found: ${u}`);throw Object.assign(e,{statusCode:500,code:"UPDATE_WORKER_NOT_FOUND"}),e}return await k("systemd-run",["--unit",`task-handoff-update-${a.id}`,"--collect","--property=Type=exec",...l?[d]:[process.execPath,d],"--job-file",v.updateJobs.records.filePath(a.id),"--target-version",a.toVersion,"--npm-command",xi(),...ts("TASK_HANDOFF_CONTROL_PLANE_HEALTH_URL")?["--control-plane-health-url",ts("TASK_HANDOFF_CONTROL_PLANE_HEALTH_URL")]:[]]),r.code(202).send({data:a})}),$.post("/api/node-agent/pairing/invites",async(e,t)=>{const n=f.createPairingInvite(bo.parse(e.body||{}));return t.code(201).send({data:{nodeId:y,joinToken:n.token,expiresAt:n.expiresAt}})}),$.post("/api/node-agent/pairing/complete",async(e,t)=>{const n=f.completePairingInvite(wo.parse(e.body));return t.code(201).send({data:{nodeId:y,keyId:n.keyId,secret:n.secret,pairedAt:n.pairedAt}})}),$.get("/api/node-agent/control-plane-pairings",async e=>({data:f.listControlPlanePairings(e.nodeAgentAuthKeyId)})),$.delete("/api/node-agent/control-plane-pairings/:keyId",async e=>{const t=m.z.string().trim().min(1).max(160).parse(e.params.keyId);return{data:{deleted:f.deleteControlPlanePairing(t,e.nodeAgentAuthKeyId)}}}),$.get("/api/node-agent/control-plane-connections",async()=>({data:f.listControlPlaneConnections().map(e=>({...e,...$.nodeAgentReverseTunnels?.state(e.id)||{status:e.enabled?"connecting":"disabled"}}))})),$.delete("/api/node-agent/control-plane-connections/:connectionId",async e=>{const t=m.z.string().trim().min(1).max(160).parse(e.params.connectionId),n=f.deleteControlPlaneConnection(t);return n&&$.nodeAgentReverseTunnels?.connectConfigured(),{data:{deleted:n}}}),$.post("/api/node-agent/control-plane-connections",async(e,t)=>{const n=No.parse(e.body),r=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(/\/$/,"")}(n.controlPlaneUrl);return f.runControlPlaneConnectionOperation(r,async()=>{const e=f.stageControlPlaneConnection({url:r,...n.controlPlaneName?{name:n.controlPlaneName}:{},enabled:!1!==n.activate});let i;try{i=await async function(e,t,n){const r=await e(new URL("/api/node-join/complete",t).toString(),{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(n)}),i=await r.json().catch(()=>({}));if(!r.ok){const e=new Error(i.error?.message||`Control-plane node join failed with HTTP ${r.status}.`);throw Object.assign(e,{statusCode:r.status,code:i.error?.code||"NODE_AGENT_REMOTE_JOIN_FAILED"}),e}return i.data||{}}(C,r,{joinToken:n.joinToken,nodeId:y,nodeName:v.node.name,keyId:e.pairing.keyId,secret:e.pairing.secret,pairedAt:e.pairing.pairedAt})}catch(t){throw f.rollbackControlPlaneConnection(e),t}const o=f.commitControlPlaneConnection(e,{name:n.controlPlaneName||("string"==typeof i.name&&i.name?i.name:void 0)});let s,a=o.connection.enabled?"saved":"disabled";if($.nodeAgentReverseTunnels)try{$.nodeAgentReverseTunnels.connectConfigured(),o.connection.enabled&&(a="connecting")}catch(e){a="failed",s=e instanceof Error?e.message:String(e)}return t.code(201).send({data:{pairing:f.listControlPlanePairings().find(e=>e.keyId===o.pairing.keyId),connection:o.connection,tunnel:{status:a,...s?{error:s}:{}}}})})}),$.get("/api/node-agent/runtimes",async()=>({data:v.nodeRuntimes.list()})),$.post("/api/node-agent/runtimes",async(e,t)=>t.code(201).send({data:v.createRuntime(gi.parse(e.body))})),$.patch("/api/node-agent/runtimes/:id",async e=>({data:v.updateRuntime(e.params.id,hi.parse(e.body))})),$.delete("/api/node-agent/runtimes/:id",async e=>({data:{deleted:v.deleteRuntime(e.params.id)}})),$.post("/api/node-agent/runtimes/:id/check",async e=>{const t=v.requireRuntime(e.params.id);return{data:await v.checkRuntime(t.id,T.forRuntime(t))}}),$.get("/api/node-agent/local-folders",async()=>({data:v.localFolders.list()})),$.get("/api/node-agent/folders/tree",async e=>({data:ci(ui.parse(e.query))})),$.post("/api/node-agent/local-folders",async(e,t)=>t.code(201).send({data:v.createLocalFolder(li.parse(e.body))})),$.delete("/api/node-agent/local-folders/:id",async e=>({data:{deleted:v.localFolders.delete(e.params.id)}})),$.get("/api/node-agent/models",async()=>({data:v.listModels()})),$.post("/api/node-agent/models",async(e,t)=>t.code(201).send({data:v.createModel(An.parse(e.body))})),$.put("/api/node-agent/models/:id/deploy",async e=>{const t=e.params.id,n=wn.parse(e.body);if(n.id!==t)throw Object.assign(new Error(`Model payload id ${n.id} does not match route id ${t}.`),{statusCode:400,code:"NODE_MODEL_ID_MISMATCH"});return{data:v.deployModel(n)}}),$.patch("/api/node-agent/models/:id",async e=>({data:v.updateModel(e.params.id,bn.parse(e.body))})),$.delete("/api/node-agent/models/:id",async e=>({data:{deleted:v.deleteModel(e.params.id)}})),$.get("/api/node-agent/instances",async()=>({data:v.listInstances()})),$.post("/api/node-agent/instances",async(e,t)=>{const n=v.createInstance(mi.parse(e.body));return U.syncNow(),n.imageProvisioning&&Q(n),t.code(201).send({data:n})}),$.post("/api/node-agent/instances/:id/image-provisioning/retry",async e=>{const t=function(e,t){const n=e.requireInstance(t);if("docker"!==e.requireRuntime(n.runtimeId).type||!n.imageSnapshot){const e=new Error(`Instance ${t} does not use a Docker image.`);throw Object.assign(e,{statusCode:400,code:"INSTANCE_IMAGE_PROVISIONING_UNSUPPORTED"}),e}if("failed"!==n.status||"failed"!==n.imageProvisioning?.phase){const e=new Error(`Instance ${t} does not have failed image provisioning to retry.`);throw Object.assign(e,{statusCode:409,code:"INSTANCE_IMAGE_PROVISIONING_NOT_FAILED"}),e}const r=ms();return e.controlledInstances.put(nr.parse({...n,status:"provisioning",health:"unknown",imageProvisioning:{phase:"checking-image",requestedReference:n.imageSnapshot.requestedReference,generation:(n.imageProvisioning?.generation||0)+1,startedAt:r,updatedAt:r},updatedAt:r}))}(v,e.params.id);return U.syncNow(),Q(t),{data:t}}),$.patch("/api/node-agent/instances/:id",async e=>{const t=e.params.id,n=v.requireInstance(t),r=pi.parse(e.body),i=nr.parse({...n,...r,...r.config?{config:{...n.config,...r.config}}:{},updatedAt:ms()}),o=v.controlledInstances.put(i);return U.syncNow(),{data:o}}),$.put("/api/node-agent/instances/:id/model-assignment",async e=>{const t=e.params.id,n=v.assignModels(t,Nn.parse(e.body));return await bs(C,v,t),{data:n}}),$.post("/api/node-agent/instances/:id/register",async(e,t)=>{const n=e.params.id,r=Y(n,"register",e.body),i=v.registerInstance(n,lr.parse(r),ds(e.headers));return U.syncNow(),K({instanceId:n,action:"register",protocolVersion:i.protocolVersion,build:i.build,targetStatus:i.targetStatus,targetStrategy:i.target.strategy},"node instance registered"),!M(i)||i.ready&&"matched"===i.runtimeVersion?.phase||V.schedule(n).catch(e=>$.log.error({instanceId:n,error:e},"runtime convergence after registration failed")),t.code(201).send({data:i})}),$.post("/api/node-agent/instances/:id/heartbeat",async e=>{const t=e.params.id,n=Y(t,"heartbeat",e.body),r=v.heartbeatInstance(t,ur.parse(n),ds(e.headers));return U.syncNow(),K({instanceId:t,action:"heartbeat",status:r.status,health:r.health,protocolVersion:r.protocolVersion,build:r.build,targetStatus:r.targetStatus,apps:r.apps.runningCount},"node instance heartbeat accepted"),!M(r)||r.ready&&"matched"===r.runtimeVersion?.phase||V.schedule(t).catch(e=>$.log.error({instanceId:t,error:e},"runtime convergence after heartbeat failed")),{data:r}}),$.get("/api/node-agent/events",{websocket:!0},e=>{const t=e;t.send(JSON.stringify({type:"node-agent.events.connected",nodeId:y,serverTime:(new Date).toISOString()}));const n=U.addOutput(t);t.on("close",n),t.on("error",n)}),$.get("/api/node-agent/docker/images",async()=>({data:await Er(e.dockerCommandRunner)})),$.get("/api/node-agent/instances/:id/metrics",async e=>{const t=e.params.id,n=v.requireInstance(t);if("docker"!==v.requireRuntime(n.runtimeId).type){const e=new Error(`Runtime type ${v.requireRuntime(n.runtimeId).type} does not provide resource metrics.`);throw Object.assign(e,{statusCode:409,code:"INSTANCE_METRICS_UNSUPPORTED"}),e}return{data:await H.snapshot(t)}}),$.post("/api/node-agent/instances/:id/start",async e=>{const t=e.params.id;return Zo.parse(e.body),{data:await X(t,"request")}}),$.post("/api/node-agent/instances/:id/runtime/reconcile",async e=>{const t=e.params.id;Zo.parse(e.body);const n=v.requireInstance(t);v.controlledInstances.put(nr.parse({...n,ready:!1,runtimeVersion:rs(Gi(n)),updatedAt:ms()}));const r=await V.schedule(t,{startRequested:!["created","stopped"].includes(n.status),resumeCancelled:!0});return U.syncNow(),{data:r}}),$.post("/api/node-agent/instances/:id/stop",async e=>{const t=e.params.id;await V.cancel(t);const n=v.requireInstance(t);K({instanceId:n.id,action:"stop",runtimeId:n.runtimeId,containerName:n.runtime.containerName},"node instance stop requested");const r=T.forRuntime(v.requireRuntime(n.runtimeId));await r.stop(v.context(n));const i=v.applyInstanceLifecycle(t,{type:"stop-completed"});return U.syncNow(),K({instanceId:n.id,action:"stop",status:i.status,connectionStatus:i.connectionStatus,containerName:i.runtime.containerName},"node instance stop completed"),{data:i}}),$.post("/api/node-agent/instances/:id/restart",async e=>{const t=e.params.id;let n=v.requireInstance(t);if(Zo.parse(e.body),M(n)&&(!n.ready||"matched"!==n.runtimeVersion?.phase)){"failed"===n.runtimeVersion?.phase&&(n=v.controlledInstances.put(nr.parse({...n,runtimeVersion:rs(Gi(n)),updatedAt:ms()})));const e=await V.schedule(t,{startRequested:!0});return U.syncNow(),{data:e}}K({instanceId:t,action:"restart",runtimeId:n.runtimeId,imageId:n.imageSelection?.imageId,containerName:n.runtime.containerName},"node instance restart requested");const r=T.forRuntime(v.requireRuntime(n.runtimeId)),i=await r.restart(v.context(n)),o=nr.parse({...n,...i,target:i.target?{...n.target,...i.target}:n.target,updatedAt:ms()}),s=await ys(C,o),a=v.applyInstanceLifecycle(t,{type:"runtime-lifecycle-completed",baseline:n,observation:{...i,target:i.target?{...i.target,status:s}:void 0,targetStatus:s,uiAccessStatus:s}});return J.add(t),W.delete(t),await As(C,a,"restart",G),U.syncNow(),K({instanceId:t,action:"restart",status:a.status,connectionStatus:a.connectionStatus,targetStatus:a.targetStatus,targetWeb:a.target.web,containerName:a.runtime.containerName},"node instance restart completed"),{data:a}}),$.post("/api/node-agent/instances/:id/delete",async e=>{const t=e.params.id,n=v.requireInstance(t);await V.cancel(t),K({instanceId:t,action:"delete",runtimeId:n.runtimeId,containerName:n.runtime.containerName},"node instance delete requested");const r=T.forRuntime(v.requireRuntime(n.runtimeId));await r.delete(v.context(n,{})),K({instanceId:t,action:"delete"},"node instance delete completed");const i=v.controlledInstances.delete(t);return v.modelAssignments.delete(t),v.modelEnvironments.delete(t),U.syncNow(),{data:{deleted:i}}}),$.post("/api/node-agent/instances/:id/proxy",async(e,t)=>{const n=e.params.id,r=di.parse(e.body),i=ws(v.requireInstance(n)),o=r.path.startsWith("/")?r.path:`/${r.path}`;"POST"===r.method&&"/api/apps/sessions"===o&&await bs(C,v,n),K({instanceId:n,action:"proxy",method:r.method,path:o,instanceBase:i},"node instance proxy requested");const s=await C(`${i}${o}`,{method:r.method,headers:{...r.headers},body:ss(r)}),a=s.headers.get("content-type")||"application/octet-stream",c=await s.text();K({instanceId:n,action:"proxy",method:r.method,path:o,statusCode:s.status,contentType:a},"node instance proxy completed"),t.code(s.status).type(a).send(c)}),$.post("/api/node-agent/instances/:id/proxy/stream",{bodyLimit:as},async(e,t)=>{const n=Date.now();F.requests+=1,F.active+=1;const r=new AbortController;let i=0,o=!1,s=!1;const a=e=>{s||(s=!0,F.active-=1,F.totalDurationMs+=Date.now()-n,F.responseBytes+=i,F[e]+=1)},d=()=>{r.abort(),o&&a("aborted")};e.raw.once("aborted",d),t.raw.once("close",d);try{const n=e.params.id,s=di.parse(e.body),d=ws(v.requireInstance(n)),l=s.path.startsWith("/")?s.path:`/${s.path}`;K({instanceId:n,action:"proxy.stream",method:s.method,path:l,instanceBase:d},"node instance streaming proxy requested");const u=await C(`${d}${l}`,{method:s.method,headers:{...s.headers},body:ss(s),signal:r.signal}),m=Number(u.headers.get("content-length"));if(Number.isFinite(m)&&m>F.maxResponseBytes)return F.limitRejected+=1,r.abort(),t.code(502).send({error:{code:"INSTANCE_PROXY_RESPONSE_TOO_LARGE",message:`Instance response exceeds ${F.maxResponseBytes} bytes.`}});t.code(u.status);for(const[e,n]of Object.entries(os(u.headers)))t.header(e,n);if(!u.body||"HEAD"===s.method)return a("completed"),t.send();const p=new c.Transform({transform(e,t,n){if(i+=e.length,i>F.maxResponseBytes)return F.limitRejected+=1,r.abort(),void n(Object.assign(new Error("Instance proxy response limit exceeded."),{code:"INSTANCE_PROXY_RESPONSE_TOO_LARGE"}));n(null,e)}});return o=!0,p.once("end",()=>a("completed")),p.once("error",()=>a("aborted")),t.send(c.Readable.fromWeb(u.body).pipe(p))}catch(e){throw a("aborted"),e}finally{e.raw.off("aborted",d),o||a("completed")}}),$.post("/api/node-agent/instances/:id/proxy/raw",{bodyLimit:as},async(e,t)=>{const n=e.params.id,r=di.parse(e.body),i=ws(v.requireInstance(n)),o=r.path.startsWith("/")?r.path:`/${r.path}`;K({instanceId:n,action:"proxy.raw",method:r.method,path:o,instanceBase:i},"node instance raw proxy requested");const s=await C(`${i}${o}`,{method:r.method,headers:{...r.headers},body:ss(r)}),a=Number(s.headers.get("content-length"));if(Number.isFinite(a)&&a>F.maxResponseBytes)return F.limitRejected+=1,t.code(502).send({error:{code:"INSTANCE_PROXY_RESPONSE_TOO_LARGE",message:`Instance response exceeds ${F.maxResponseBytes} bytes.`}});let c;try{c=await async function(e,t){if(!e.body)return Buffer.alloc(0);const n=[];let r=0;const i=e.body.getReader();for(;;){const{done:e,value:o}=await i.read();if(e)break;if(r+=o.byteLength,r>t)throw await i.cancel("Instance proxy response limit exceeded.").catch(()=>{}),Object.assign(new Error("Instance proxy response limit exceeded."),{code:"INSTANCE_PROXY_RESPONSE_TOO_LARGE"});n.push(Buffer.from(o))}return Buffer.concat(n,r)}(s,F.maxResponseBytes)}catch(e){if(!(e instanceof Error)||"INSTANCE_PROXY_RESPONSE_TOO_LARGE"!==e.code)throw e;return F.limitRejected+=1,t.code(502).send({error:{code:"INSTANCE_PROXY_RESPONSE_TOO_LARGE",message:`Instance response exceeds ${F.maxResponseBytes} bytes.`}})}return K({instanceId:n,action:"proxy.raw",method:r.method,path:o,statusCode:s.status,byteLength:c.length},"node instance raw proxy completed"),{data:{status:s.status,headers:os(s.headers),bodyBase64:c.toString("base64")}}}),$.get("/api/node-agent/instances/:id/proxy/ws/*",{websocket:!0},(e,t)=>{const n=t.params.id,r=t.params["*"]||"",i=t.url.indexOf("?"),o=i>=0?t.url.slice(i):"";let s;try{const i=ws(v.requireInstance(n)),a=new URL(`/${r}${o}`,`${i}/`);a.protocol="https:"===a.protocol?"wss:":"ws:";const c=function(e){const t=e["sec-websocket-protocol"],n=(Array.isArray(t)?t.join(","):"string"==typeof t?t:"").split(",").map(e=>e.trim()).filter(Boolean);return n.length?n:void 0}(t.headers);K({instanceId:n,action:"proxy.ws",path:`/${r}${o}`,upstreamUrl:a.toString(),protocols:c||[]},"node instance websocket proxy opening"),s=c?new u(a,c):new u(a),s.on("open",()=>{K({instanceId:n,action:"proxy.ws",path:`/${r}${o}`},"node instance websocket proxy opened"),e.on("message",(e,t)=>s?.readyState===u.OPEN&&s.send(function(e,t){return t?e:e.toString()}(e,t))),e.on("close",()=>s?.close()),e.on("error",()=>s?.close())}),s.on("message",(t,n)=>{e.readyState===u.OPEN&&e.send(n?t:t.toString())}),s.on("close",()=>{K({instanceId:n,action:"proxy.ws",path:`/${r}${o}`},"node instance websocket proxy closed"),e.close()}),s.on("error",t=>{K({instanceId:n,action:"proxy.ws",path:`/${r}${o}`,error:t instanceof Error?t.message:String(t)},"node instance websocket proxy failed"),e.close(1011,"Instance websocket proxy failed.")})}catch(t){K({instanceId:n,action:"proxy.ws",path:`/${r}${o}`,error:t instanceof Error?t.message:String(t)},"node instance websocket endpoint unavailable"),s?.close(),e.close(1011,"Instance websocket endpoint is not reachable.")}}),$}async function Gs(e){const o=yi(e.dataDir),s=(a=e.host,c=e.port,Gn.parse({bindScope:"0.0.0.0"===a.trim()?"all-ipv4":"loopback",port:c}));var a,c;const d=t.existsSync(o.settingsPath),l=function(e,t){return new Si(e.settingsPath,()=>({version:1,externalListener:t}),{schema:Qo,sanitize:gs})}(o,s),u=l.get().externalListener,m=function(e,i={}){return function(e,i={}){t.mkdirSync(n.dirname(e),{recursive:!0});const o={pid:process.pid,hostname:p.hostname(),component:i.component,command:process.argv.join(" "),acquiredAt:(new Date).toISOString(),token:r.randomUUID(),startIdentity:k(process.pid),dataDir:i.dataDir,host:i.host,port:i.port,instanceId:i.instanceId};for(let n=0;n<5;n+=1)try{return t.mkdirSync(e),t.writeFileSync(S(e),`${JSON.stringify({token:o.token,pid:o.pid,startIdentity:o.startIdentity,startedAt:(new Date).toISOString()})}\n`,{encoding:"utf8",mode:384,flag:"wx"}),D(e,o),{lockPath:e,owner:o,release(){const n=O(e);n?.token===o.token&&t.rmSync(e,{recursive:!0,force:!0})}}}catch(o){if("EEXIST"!==o.code)throw o;const s=O(e);if(R(s))throw new v(e,s,i.error);if(!s&&(j(e)||$(e)<(i.incompleteLockStaleMs??2e3))){if(n+1<5){L();continue}throw new v(e,void 0,i.error)}const a=r.randomUUID();if(!F(e,a)){if(n+1<5){L();continue}throw new v(e,O(e),i.error)}const c=O(e);if(R(c))throw M(_(e)),new v(e,c,i.error);if(s?.token&&c?.token!==s.token){M(_(e));continue}if(!V(e,a))continue;t.rmSync(e,{recursive:!0,force:!0})}const s=O(e);throw new v(e,s,i.error)}(e,{...i,component:"node-agent",error:{label:"Node agent",code:"NODE_AGENT_ALREADY_RUNNING"}})}(n.join(p.tmpdir(),`task-handoff-node-agent-${process.getuid?.()??"user"}.lock`),{dataDir:o.dataDir,host:ps(u.bindScope),port:u.port});try{const r={...e,port:u.port},s=await Ks(r),a=s.nodeAgentState;if(!a)throw new Error("Node agent state was not initialized.");const c=new jo(o).resolveNodeId(e.nodeId||process.env.TASK_HANDOFF_NODE_ID),p=function(e,t,n,r){const i=t.token||process.env.TASK_HANDOFF_NODE_AGENT_TOKEN,o=new jo(n),s=new Map;let a=!1;const c=(t,n)=>{n.status=n.lastDisconnectedAt?"reconnecting":"connecting",n.error=void 0;const o=Vo(e,{...n.config,nodeId:r,port:()=>e.nodeAgentState.currentListenerPort,token:i});return n.socket=o,o.on("open",()=>{s.get(t)===n&&n.socket===o&&(n.retry.reset(),n.status="connected",n.lastConnectedAt=(new Date).toISOString(),n.error=void 0,e.log.info({nodeId:r,tunnelUrl:new URL(n.config.tunnelUrl).origin},"node agent reverse tunnel connected"))}),o.on("close",(i,d)=>{s.get(t)===n&&n.socket===o&&(n.socket=void 0,n.lastDisconnectedAt=(new Date).toISOString(),n.error=`WebSocket closed${i?` (${i})`:""}${d?`: ${Buffer.isBuffer(d)?d.toString("utf8"):String(d)}`:""}`,a||(e.log.warn({nodeId:r,tunnelUrl:new URL(n.config.tunnelUrl).origin,code:i,reason:Buffer.isBuffer(d)?d.toString("utf8"):String(d||"")},"node agent reverse tunnel disconnected"),((t,n)=>{if(a||n.retry.pending||s.get(t)!==n)return;const i=n.retry.schedule(()=>{a||s.get(t)!==n||n.socket||c(t,n)});i&&(n.status="reconnecting",e.log.info({nodeId:r,tunnelUrl:new URL(n.config.tunnelUrl).origin,attempt:i.attempt,delay:i.delay},"node agent reverse tunnel reconnect scheduled"))})(t,n)))}),o.on("error",e=>{s.get(t)===n&&n.socket===o&&(n.status="failed",n.error=e instanceof Error?e.message:String(e))}),o},d=(e,t)=>{const n=s.get(e);n?.retry.cancel();const r={config:t,retry:new Vr,status:"connecting"};return s.set(e,r),n?.socket?.close(1e3,"Reverse tunnel reconnecting."),c(e,r)},l=(e,t)=>e.tunnelUrl===t.tunnelUrl&&e.keyId===t.keyId&&e.secret===t.secret;return{connectConfigured:()=>{a=!1;const n=new Map,i=o.resolvedControlPlaneAccess(),c=new Set;for(const{connection:t,pairing:o}of i.connections){if(!t.enabled)continue;if(!o){e.log.warn({nodeId:r,connectionId:t.id,pairingKeyId:t.pairingKeyId},"node agent control-plane connection has no pairing");continue}const i=Ho(t.url);n.set(t.id,{tunnelUrl:i,keyId:o.keyId,secret:o.secret}),c.add(i)}const u=function(e){const t=e.controlPlaneTunnelUrl||process.env.TASK_HANDOFF_CONTROL_PLANE_TUNNEL_URL;return t?new URL(t).toString():void 0}(t);if(u&&!c.has(u)){const e=o.reverseTunnelSecret(process.env.TASK_HANDOFF_CONTROL_PLANE_URL,t.remoteSecret||process.env.TASK_HANDOFF_NODE_AGENT_REMOTE_SECRET,t.remoteKeyId||process.env.TASK_HANDOFF_NODE_AGENT_REMOTE_KEY_ID);n.set(`explicit:${u}`,{tunnelUrl:u,keyId:e?.keyId,secret:e?.secret}),c.add(u)}const m=i.hasPersistedAccess?void 0:function(){const e=process.env.TASK_HANDOFF_CONTROL_PLANE_URL;if(!e)return;const t=new URL(ao,e);return t.protocol="https:"===t.protocol?"wss:":"ws:",t.toString()}();if(m&&!c.has(m)){const e=o.reverseTunnelSecret(process.env.TASK_HANDOFF_CONTROL_PLANE_URL,t.remoteSecret||process.env.TASK_HANDOFF_NODE_AGENT_REMOTE_SECRET,t.remoteKeyId||process.env.TASK_HANDOFF_NODE_AGENT_REMOTE_KEY_ID);n.set(`bootstrap:${m}`,{tunnelUrl:m,keyId:e?.keyId,secret:e?.secret})}(e=>{for(const[t,n]of s)e.has(t)||(n.retry.cancel(),s.delete(t),n.socket?.close(1e3,"Reverse tunnel configuration removed."));for(const[t,n]of e){const e=s.get(t);e&&l(e.config,n)||d(t,n)}})(n)},state:e=>{const t=s.get(e);if(t)return{status:t.status,...t.lastConnectedAt?{lastConnectedAt:t.lastConnectedAt}:{},...t.lastDisconnectedAt?{lastDisconnectedAt:t.lastDisconnectedAt}:{},...t.error?{error:t.error}:{}}},closeAll:()=>{a=!0;for(const e of s.values())e.retry.cancel(),e.socket?.close(1001,"Node agent shutting down.");s.clear()}}}({log:s.log,inject:e=>s.inject(e),nodeAgentEventForwarder:s.nodeAgentEventForwarder,nodeAgentState:a},r,o,c);s.decorate("nodeAgentReverseTunnels",p);const g=new Hs({app:s,state:a,settings:l,config:u,source:d?"persisted":"bootstrap"});let h;s.decorate("nodeAgentListenerManager",g),function(e){let t=!1;const n=async n=>{if(!t){t=!0,p.closeAll(),h?.close();try{await e.close()}finally{process.exitCode=n?0:process.exitCode}}},r=()=>{n("SIGINT")},i=()=>{n("SIGTERM")};process.once("SIGINT",r),process.once("SIGTERM",i),e.addHook("onClose",async()=>{process.off("SIGINT",r),process.off("SIGTERM",i)})}(s),s.addHook("onClose",async()=>{h?.close(),m.release()});try{await s.ready();const r=e.ipcPath||process.env.TASK_HANDOFF_NODE_AGENT_IPC_PATH||_i(o.dataDir);h=await async function(e,r){!function(e,r=process.platform){if("win32"!==r){t.mkdirSync(n.dirname(e),{recursive:!0,mode:448});try{t.chmodSync(n.dirname(e),448)}catch{}try{t.unlinkSync(e)}catch(e){if("ENOENT"!==e.code)throw e}}}(r);const o=i.createServer((t,n)=>{e.server.emit("request",t,n)});return o.on("upgrade",(t,n,r)=>{e.server.emit("upgrade",t,n,r)}),await new Promise((e,t)=>{o.once("error",t),o.listen(r,()=>{o.off("error",t),e()})}),o}(s,r),await g.start(),p.connectConfigured(),s.nodeAgentStartRecoverySupervisor?.()}catch(e){throw await s.close(),e}}catch(e){throw m.release(),e}}function Js(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 Ws(e){if("local-ipc"!==e&&"local-loopback"!==e)throw new Error("Connection mode must be local-ipc or local-loopback.");return e}function Ys(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",Js,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",Ws).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 Gs({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",Ys).option("--json","Print raw JSON output").action(async e=>{const n=t.opts(),r=e.ipcPath||n.ipcPath||process.env.TASK_HANDOFF_NODE_AGENT_IPC_PATH,o=e.dataDir||n.dataDir||process.env.TASK_HANDOFF_NODE_AGENT_DATA_DIR,s=e.endpoint?void 0:r||_i(o||fi()),a=await async function(e){const t={"content-type":"application/json",...e.token?{authorization:`Bearer ${e.token}`}:{}},n=JSON.stringify({...e.expiresInMs?{expiresInMs:e.expiresInMs}:{}}),r=e.endpoint?await fetch(`${e.endpoint.replace(/\/$/,"")}/api/node-agent/pairing/invites`,{method:"POST",headers:t,body:n}):await async function(e,t,n={}){const r=n.method||"GET",o="string"==typeof n.body||n.body instanceof Buffer?n.body:void 0===n.body||null===n.body?void 0:String(n.body),s=new Headers(n.headers||{});return void 0===o||s.has("content-length")||s.set("content-length",String(Buffer.byteLength(o))),new Promise((a,d)=>{const l=i.request({socketPath:e,method:r,path:`/api/node-agent${t}`,headers:Object.fromEntries(s.entries())},e=>{const t=e.statusCode||500;a(new Response("HEAD"!==r&&204!==t&&205!==t&&304!==t?c.Readable.toWeb(e):null,{status:t,headers:e.headers}))});l.on("error",d);const u=()=>l.destroy(new DOMException("The operation was aborted.","AbortError"));n.signal?.aborted?u():n.signal?.addEventListener("abort",u,{once:!0}),l.once("close",()=>n.signal?.removeEventListener("abort",u)),void 0!==o&&l.write(o),l.end()})}(e.ipcPath,"/pairing/invites",{method:"POST",headers:t,body:n}),o=await r.json().catch(()=>({}));if(!r.ok)throw new Error(o.error?.message||`Node agent pairing invite failed with HTTP ${r.status}`);const s="string"==typeof o.data?.joinToken?o.data.joinToken:"";if(!s)throw new Error("Node agent pairing invite response did not include a join token.");return{nodeId:"string"==typeof o.data?.nodeId?o.data.nodeId:"",joinToken:s,expiresAt:"string"==typeof o.data?.expiresAt?o.data.expiresAt:""}}({endpoint:e.endpoint,ipcPath:s,token:e.token,expiresInMs:e.expiresInMs});e.json?console.log(JSON.stringify(a,null,2)):(a.nodeId&&console.log(`Node: ${a.nodeId}`),console.log(`Join token: ${a.joinToken}`),a.expiresAt&&console.log(`Expires: ${a.expiresAt}`))}),await t.parseAsync(process.argv)})().catch(e=>{console.error(e instanceof Error?e.message:String(e)),process.exitCode=1});