@task-handoff/node-agent 0.0.10 → 0.0.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -1 +1 @@
1
- "use strict";var e=require("commander"),t=require("node:fs"),n=require("node:path"),i=require("node:crypto"),r=require("node:http"),s=require("node:net"),o=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"),I=require("node:fs/promises"),y=require("node:stream/promises"),A=require("tar"),b="undefined"!=typeof document?document.currentScript:null;function w(e,n){try{const i=JSON.parse(t.readFileSync(e,"utf8"));if(n&&i.name!==n)return;return"string"==typeof i.version&&i.version.trim()?i.version.trim():void 0}catch{return}}function z(e,t=process.env,i=e){const r=t.TASK_HANDOFF_VERSION?.trim();if(r)return r;const s=i.split("/").at(-1),o=[process.argv[1]?n.dirname(n.resolve(process.argv[1])):void 0,process.cwd()].filter(e=>Boolean(e));for(const t of new Set(o)){let i=t;for(;;){const t=w(n.join(i,"package.json"),e);if(t)return t;const r=n.dirname(i);if(r===i)break;i=r}}let a;for(const e of new Set(o)){let t=e;for(;;){if(s){const e=w(n.join(t,"packages",s,"package.json"),i);if(e)return e}a||=w(n.join(t,"package.json"));const e=n.dirname(t);if(e===t)break;t=e}}return a||"unknown"}class N extends Error{code;lockPath;owner;constructor(e,t,n={}){const i=t?.pid?` pid ${t.pid}`:"";super(`${n.label||"Process"} is already running${i}. Lock: ${e}`),this.name="ProcessSingletonError",this.code=n.code||"PROCESS_ALREADY_RUNNING",this.lockPath=e,this.owner=t}}function v(e){return n.join(e,"owner.json")}function S(e){return n.join(e,"initializing.json")}function E(e){return n.join(e,"recovering.json")}function _(e){return Number.isInteger(e)&&Number(e)>0}function T(e,n=process.platform){if(_(e)){if("linux"===n)try{const n=t.readFileSync(`/proc/${e}/stat`,"utf8"),i=n.lastIndexOf(")");if(i<0)return;const r=n.slice(i+2).trim().split(/\s+/)[19];return r?`linux:${r}`:void 0}catch{return}if(["darwin","freebsd","openbsd","aix","sunos"].includes(n)){const t=a.spawnSync("ps",["-o","lstart=","-p",String(e)],{encoding:"utf8",timeout:1e3}),i=0===t.status?t.stdout.trim().replace(/\s+/g," "):"";return i?`${n}:${i}`:void 0}if("win32"===n){const t=`(Get-Process -Id ${e} -ErrorAction Stop).StartTime.ToUniversalTime().Ticks`,n=a.spawnSync("powershell.exe",["-NoProfile","-NonInteractive","-Command",t],{encoding:"utf8",timeout:2e3}),i=0===n.status?n.stdout.trim():"";return/^\d+$/.test(i)?`win32:${i}`:void 0}}}function k(e){try{const n=JSON.parse(t.readFileSync(v(e),"utf8"));if(_(n.pid)&&"string"==typeof n.startTime){const e=n;return{pid:e.pid,hostname:"string"==typeof e.hostname&&e.hostname?e.hostname: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(!(_(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=k;function C(e){if(!_(e))return!1;try{return process.kill(Number(e),0),!0}catch(e){return"EPERM"===e.code}}function O(e){if(!e||!C(e.pid))return!1;if(!e.startIdentity)return!0;const t=T(e.pid);return void 0===t||t===e.startIdentity}function R(e,i){const r=n.join(e,`.owner-${i.token}.tmp`);t.writeFileSync(r,`${JSON.stringify(i,null,2)}\n`,{encoding:"utf8",mode:384,flag:"wx"});const s=D(e);if(s?.token!==i.token)throw j(r),new Error(`Process lock initialization was superseded: ${e}`);t.renameSync(r,v(e)),j(S(e))}function D(e){try{return JSON.parse(t.readFileSync(S(e),"utf8"))}catch{return}}function P(e){const t=D(e);return _(t?.pid)&&O({pid:t.pid,startIdentity:t.startIdentity})}function j(e){try{t.unlinkSync(e)}catch(e){if("ENOENT"!==e.code)throw e}}function M(){Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,20)}function L(e){try{const n=D(e),i=Date.parse(n?.startedAt||"");return Number.isFinite(i)?Math.max(0,Date.now()-i):Math.max(0,Date.now()-t.statSync(e).mtimeMs)}catch{return 0}}function $(e,r){try{return t.writeFileSync(E(e),`${JSON.stringify({token:r,pid:process.pid,startedAt:(new Date).toISOString()})}\n`,{encoding:"utf8",mode:384,flag:"wx"}),!0}catch(s){if("EEXIST"===s.code)return!!function(e){const r=E(e),s=F(r),o=Date.parse(s?.startedAt||"");if(C(s?.pid)||Number.isFinite(o)&&Date.now()-o<2e3)return!1;const a=n.join(e,`.recovering-${i.randomUUID()}.stale`);try{t.renameSync(r,a)}catch(e){if(["ENOENT","EEXIST"].includes(e.code||""))return!1;throw e}const c=F(a);if(c?.token===s?.token)return j(a),!0;try{t.linkSync(a,r)}catch(e){if("EEXIST"!==e.code)throw e}finally{j(a)}return!1}(e)&&$(e,r);if("ENOENT"===s.code)return!1;throw s}}function F(e){try{return JSON.parse(t.readFileSync(e,"utf8"))}catch{return}}function U(e,t){return F(E(e))?.token===t}const V=41943040,H="ai.sessions",q=m.z.string().trim().min(1).max(80),B=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 K=m.z.enum(["thinking","tool","editing","approval","responding","unknown"]),G=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(),J=m.z.enum(["pending-init","running","interrupted","completed","errored","shutdown","not-found"]),W=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:J,activity:W.optional(),message:m.z.string().trim().max(1e3).optional(),updatedAt:m.z.string().datetime()}).strict(),X=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(),Q=m.z.enum(["image","file"]),ee=m.z.object({id:m.z.string().trim().min(1).max(120),kind:Q,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)}),te=m.z.union([ee.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.`})}),ee.extend({source:m.z.object({type:m.z.literal("runtime-path"),path:m.z.string().trim().min(1).max(4096)}).strict()}).strict()]),ne=ee.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:Q.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:Q,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()]),re=m.z.enum(["auto","queue","steer","immediate"]),se=m.z.enum(["ask","auto-review","full-access"]),oe=m.z.enum(["review","rename","goal","compact"]);m.z.object({command:oe,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:oe,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 ae=m.z.object({name:m.z.string().trim().min(1).max(240),path:m.z.string().trim().min(1).max(4096)}),ce=m.z.discriminatedUnion("kind",[ae.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(),ae.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(),ae.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()]),de=m.z.array(ce).max(20).default([]),le=m.z.enum(["plugin","skill","file","directory","app"]),ue=m.z.object({kind:le,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."})}),me=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(ue).max(1e3).default([]),diagnostics:m.z.array(me).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(ue.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 pe=m.z.object({message:m.z.string().trim().min(1).max(2e4),mode:re.optional(),permissionMode:se.optional()});pe.extend({attachments:m.z.array(te).max(6).default([]),references:de}).strict().superRefine((e,t)=>{e.attachments.reduce((e,t)=>e+("inline"===t.source.type?t.size:0),0)>V&&t.addIssue({code:m.z.ZodIssueCode.custom,path:["attachments"],message:"Inline attachments must be 41943040 bytes or less in total."})}),pe.extend({attachments:m.z.array(ie).max(6).default([]),references:de}).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 ge=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(ne).max(6).default([]),references:de,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(),he=m.z.object({pendingCount:m.z.number().int().min(0).default(0),items:m.z.array(ge).max(100).default([])}).strict().default({pendingCount:0,items:[]}),fe=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(),ye=m.z.object({id:m.z.string().trim().min(1).max(240),providerTurnId:m.z.string().trim().max(240).optional(),source:fe.optional(),userPrompt:m.z.string().trim().optional(),status:m.z.enum(["queued","running","waiting","completed","failed"]).default("running"),phase:K.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(),Ae=ye.pick({id:!0,providerTurnId:!0,userPrompt:!0,status:!0,phase:!0,summary:!0,lastMessage:!0,contextCompactions:!0,startedAt:!0,updatedAt:!0,completedAt:!0}).strict(),be=m.z.object({id:m.z.string().trim().min(1).max(120),agent:q,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(ye).max(50).optional(),status:B.default("running"),phase:K.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:G.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:X,queue:he}).strict();m.z.object({session:be,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 we=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(we).max(50).default([])}).strict(),m.z.object({items:m.z.array(we).max(50).default([])}).strict(),m.z.object({item:we,turns:m.z.array(Ae).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=be.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}),Ne=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:Ne}).strict(),Ne.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 ve=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:ve}).strict(),Ee=m.z.object({meta:Se,snapshot:Ne}).strict(),_e=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(),Te=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:Ee}).strict(),m.z.object({type:m.z.literal("ai-session.patch"),payload:_e}).strict(),m.z.object({type:m.z.literal("ai-session.removed"),payload:Te}).strict()])).default([])}).strict();const ke=m.z.object({source:fe,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=ke.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(ye).max(50).optional(),status:B.optional(),phase:K.optional(),summary:m.z.string().trim().max(1e3).optional(),lastMessage:m.z.string().trim().optional(),lastMessageItemId:m.z.string().trim().max(240).optional(),currentTool:G.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(),Ce=ke.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:B.optional(),phase:K.optional(),summary:m.z.string().trim().max(1e3).optional(),error:m.z.string().trim().max(4e3).optional(),currentTool:G.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,Ce]);const Oe=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()]),Re=m.z.union([Oe,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()]),De=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:Re,action:De,policy:Pe.default({maxConcurrentRuns:1,whenBusy:"skip"}),createdAt:m.z.string().datetime(),updatedAt:m.z.string().datetime()}).strict(),Me=m.z.object({type:m.z.literal("ai-session"),aiSessionId:m.z.string().trim().min(1).max(160)}).strict(),Le=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:Me,localName:m.z.string().trim().min(1).max(160).optional(),createdAt:m.z.string().datetime(),updatedAt:m.z.string().datetime()}).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),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(),Fe=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:Me,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(Le).default([]),runtime:m.z.array($e).default([]),recentRuns:m.z.array(Fe).default([])}).strict();const Ue="2026-07-29",Ve=m.z.string(),He=m.z.string().trim().min(1).max(120).regex(/^[a-zA-Z0-9][a-zA-Z0-9_.:-]*$/),qe=m.z.string().datetime(),Be=m.z.record(m.z.string(),m.z.string()).default({}),Ke=m.z.record(m.z.string(),m.z.string()).default({}),Ge=m.z.string().regex(/^\d{4}-\d{2}-\d{2}$/,"Protocol version must use YYYY-MM-DD format."),Je=/^[A-Za-z0-9_][A-Za-z0-9_.-]{0,127}$/,We=/^sha256:([a-fA-F0-9]{64})$/,Ye=/^(?:localhost|[a-z0-9](?:[a-z0-9.-]*[a-z0-9])?)(?::[1-9][0-9]{0,4})?$/,Xe=/^[a-z0-9]+(?:(?:[._]|__|-+)[a-z0-9]+)*$/;function Ze(e){const t=e.trim();if(!t||t.length>512||t.includes("://")||/\s/.test(t))throw new Error("Docker image reference must not contain a URL scheme or whitespace.");const n=t.indexOf("@");if(-1!==n&&n!==t.lastIndexOf("@"))throw new Error("Docker image reference contains more than one digest separator.");const i=-1===n?void 0:t.slice(n+1),r=-1===n?t:t.slice(0,n),s=i?We.exec(i):void 0;if(i&&!s)throw new Error("Docker image digest must use sha256 followed by 64 hexadecimal characters.");const o=r.lastIndexOf("/"),a=r.lastIndexOf(":"),c=a>o,d=c?r.slice(a+1):void 0,l=c?r.slice(0,a):r;if(d&&!Je.test(d))throw new Error("Docker image tag is invalid.");if(!d&&!s)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=>!Xe.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=s?`sha256:${s[1].toLowerCase()}`:void 0;return`${g}${d?`:${d}`:""}${h?`@${h}`:""}`}function Qe(e){const t=Ze(e),n=t.indexOf("@"),i=-1===n?void 0:t.slice(n+1),r=-1===n?t:t.slice(0,n),s=r.lastIndexOf("/"),o=r.lastIndexOf(":"),a=o>s;return{reference:t,repository:a?r.slice(0,o):r,tag:a?r.slice(o+1):void 0,digest:i}}const et=m.z.string().trim().min(1).max(512).transform((e,t)=>{try{return Ze(e)}catch(e){return t.addIssue({code:"custom",message:e instanceof Error?e.message:String(e)}),m.z.NEVER}}),tt=m.z.string().trim().transform((e,t)=>{const n=We.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)}),nt=m.z.object({codexModelHash:He.nullable().optional(),claudeModelHash:He.nullable().optional()}).strict().default({}),it=m.z.object({imageId:He,tag:m.z.string().trim().min(1).max(128).regex(Je).optional()}).strict(),rt={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&&rt[t.imageId]||t.imageId,..."string"==typeof t.tag?{tag:t.tag}:{}}}if("string"==typeof t)return{imageId:rt[t]||t}}function ot(e){if(!e||"object"!=typeof e||Array.isArray(e))return e;const t=e,{defaultImageId:n,...i}=t;return{...i,defaultImageSelection:st(t.defaultImageSelection,n)}}const at=m.z.object({id:He,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(),ct=m.z.object({code:m.z.enum(["APP_CATALOG_INVALID"]),message:m.z.string().trim().min(1).max(500)}).strict(),dt=m.z.object({items:m.z.array(at).max(256),observedAt:qe,issues:m.z.array(ct).max(32).default([])}).strict(),lt=m.z.enum(["linux","darwin","win32","freebsd","openbsd","aix","sunos","unknown"]),ut=m.z.enum(["x64","arm64","arm","ia32","ppc64","s390x","riscv64","unknown"]),mt=m.z.enum(["apt","dnf","brew","npm"]),pt=m.z.enum(["user","passwordless-sudo","root"]),gt=m.z.object({platform:lt,arch:ut,installers:m.z.array(mt).max(8),privilege:pt,installerAccess:m.z.object({npmGlobalWritable:m.z.boolean().optional()}).strict().optional()}).strict(),ht=m.z.enum(["installed","not-installed","broken","unsupported"]),ft=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(),yt=m.z.object({id:He,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:ht,managementSource:ft,version:m.z.string().trim().max(120).optional(),canInstall:m.z.boolean(),canUninstall:m.z.boolean(),installReason:It.optional(),uninstallReason:It.optional(),activeJobId:He.optional()}).strict(),At=m.z.enum(["install","uninstall"]),bt=m.z.enum(["queued","running","succeeded","failed","cancelled","interrupted"]),wt=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"]}),zt=m.z.object({executable:m.z.string().trim().min(1).max(4096),args:m.z.array(m.z.string().max(4096)).max(128)}).strict(),Nt=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(He).max(64).optional()}).strict(),vt=m.z.object({id:He,requestId:He.optional(),appId:He,operation:At,state:bt,phase:m.z.string().trim().min(1).max(120).optional(),progress:wt.optional(),command:zt.optional(),logTail:m.z.string().max(32768).optional(),logTruncated:m.z.boolean().optional(),error:Nt.optional(),requestedAt:qe,startedAt:qe.optional(),finishedAt:qe.optional(),updatedAt:qe}).strict(),St=m.z.object({streamId:He,sequence:m.z.number().int().nonnegative(),capabilities:gt,apps:m.z.array(yt).max(256),activeJobs:m.z.array(vt).max(256),recentJobs:m.z.array(vt).max(256),observedAt:qe}).strict();m.z.object({requestId:He.optional()}).strict(),m.z.object({job:vt}).strict(),m.z.object({type:m.z.literal("app-management"),streamId:He,sequence:m.z.number().int().nonnegative(),observedAt:qe,job:vt.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 Et=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:Ve.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(),_t=m.z.enum(["stable","beta","alpha"]),Tt=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(),kt=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:qe.optional(),matchedAt:qe.optional(),error:kt.optional()}).strict(),Ct=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(He).max(1024).default([]),stoppedInstanceIds:m.z.array(He).max(1024).default([]),activeInstanceIds:m.z.array(He).max(1024).default([])}).strict(),Ot=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(He).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(),Rt=m.z.object({channel:_t.default("stable")}).strict(),Dt=m.z.object({source:m.z.literal("npm"),channel:_t,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(Tt).default([]),impact:Ct,updateAvailable:m.z.boolean(),supported:m.z.boolean().default(!0),reason:m.z.string().trim().max(2048).optional(),checkedAt:qe,preflightToken:m.z.string().trim().min(16).max(240).optional()}).strict(),Pt=m.z.object({id:He,nodeId:He,source:m.z.literal("npm"),channel:_t,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(Tt).default([]),impact:Ct,rollout:Ot,status:m.z.enum(["queued","updating-node","restarting-node","converging-instances","succeeded","degraded","failed"]),error:kt.optional(),startedAt:qe.optional(),completedAt:qe.optional(),createdAt:qe,updatedAt:qe}).strict(),jt=m.z.object({channel:_t,targetVersion:m.z.string().trim().min(1).max(240),preflightToken:m.z.string().trim().min(16).max(240)}).strict(),Mt=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(),Lt=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(),$t=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:He,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:Mt.default({type:"branch",name:"main"}),auth:Lt.default({type:"none"}),clone:$t.default({submodules:!1,lfs:!1,subdirectory:""}),defaultImageSelection:it.optional(),labels:Be,createdAt:qe,updatedAt:qe}).strict();const Ft=m.z.object({id:He,nodeId:He,name:m.z.string().trim().min(1).max(160),path:m.z.string().trim().min(1).max(4096),defaultImageSelection:it.optional(),labels:Be,createdAt:qe,updatedAt:qe}).strict(),Ut=m.z.discriminatedUnion("type",[m.z.object({type:m.z.literal("git-repository"),repositoryId:He.optional(),url:m.z.string().trim().min(1).max(2048),provider:m.z.string().trim().max(80).optional(),ref:Mt.default({type:"branch",name:"main"}),auth:Lt.default({type:"none"}),clone:$t.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:Mt.default({type:"branch",name:"main"}),auth:Lt.default({type:"none"}),clone:$t.default({submodules:!1,lfs:!1,subdirectory:""})}).strict(),m.z.object({type:m.z.literal("local-folder"),localFolderId:He.optional(),path:m.z.string().trim().min(1).max(4096),ownerNodeId:He.optional()}).strict()]),Vt=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(),Ht=m.z.enum(["codex","claude"]),qt=m.z.object({id:He,name:m.z.string().trim().min(1).max(160),source:Ut,defaultImageSelection:it.optional(),defaultNodeId:He.optional(),defaultRuntimeId:He.optional(),workspacePolicy:Vt,labels:Be,createdAt:qe,updatedAt:qe}).strict(),Bt=m.z.object({id:He,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:Ht,enabled:m.z.boolean().default(!0),order:m.z.number().int().min(0).max(1e6).default(0),labels:Be,createdAt:qe,updatedAt:qe}).strict(),Kt=Bt,Gt=Bt.omit({key:!0}).extend({keyPreview:m.z.string().trim().min(1).max(160),keySet:m.z.boolean()}).strict(),Jt=Gt.extend({referenceCount:m.z.number().int().min(0)}).strict(),Wt=m.z.object({instanceId:He,codexModelHash:He.optional(),claudeModelHash:He.optional(),updatedAt:qe}).strict(),Yt=m.z.discriminatedUnion("type",[m.z.object({type:m.z.literal("control-plane"),name:Bt.shape.name,enabled:Bt.shape.enabled,order:Bt.shape.order}).strict(),m.z.object({type:m.z.literal("node"),nodeId:He,name:Bt.shape.name,enabled:Bt.shape.enabled,order:Bt.shape.order,referenceCount:m.z.number().int().min(0)}).strict()]),Xt=m.z.object({id:He,model:Gt,locations:m.z.array(Yt).min(1),referenceCount:m.z.number().int().min(0).default(0)}).strict(),Zt=m.z.object({nodeId:He,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(Xt),nodeDiagnostics:m.z.array(Zt).default([]),updatedAt:qe}).strict();const Qt=Bt.omit({id:!0,createdAt:!0,updatedAt:!0}).strict(),en=Qt.partial().strict(),tn=Bt,nn=m.z.object({modelSelection:nt,codexModelHash:He.optional(),claudeModelHash:He.optional()}).strict();function rn(e){const t={app:Ht.parse(e.app),endpoint:Bt.shape.endpoint.parse(e.endpoint),key:Bt.shape.key.parse(e.key),model:Bt.shape.model.parse(e.model)};return`mdl_${i.createHash("sha256").update(JSON.stringify(t)).digest("hex")}`}const sn=m.z.enum(["market","custom"]),on=m.z.enum(["active","deprecated","yanked"]),an=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:tt.optional()}).strict()]),cn=m.z.array(m.z.string().trim().min(1).max(80)).default([]),dn=m.z.array(m.z.string().trim().min(1).max(120)).default([]),ln=m.z.record(m.z.string().trim().min(2).max(35),m.z.string().trim().min(1).max(4096)),un=m.z.object({os:m.z.string().trim().min(1).max(40),architecture:m.z.string().trim().min(1).max(40),digest:tt.optional(),downloadSizeBytes:m.z.number().int().positive().optional(),unpackedSizeBytes:m.z.number().int().positive().optional()}).strict(),mn=m.z.object({name:m.z.string().trim().min(1).max(128).regex(Je),version:m.z.string().trim().min(1).max(160).optional(),reference:et,manifestDigest:tt.optional(),publishedAt:qe.optional(),platforms:m.z.array(un).default([]),status:on.default("active")}).strict(),pn=m.z.object({id:He,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:ln.optional(),cover:an.optional(),repository:m.z.string().trim().min(1).max(512),defaultTag:m.z.string().trim().min(1).max(128).regex(Je),tags:m.z.array(mn).min(1),capabilities:cn,optionalApps:dn,defaultEnv:Ke,labels:Be,status:on.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:Ge,catalogId:He,revision:m.z.string().trim().min(1).max(240),source:m.z.enum(["embedded","remote","cache"]),generatedAt:qe,expiresAt:qe.optional(),items:m.z.array(pn)}).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:qe,error:m.z.string().trim().max(4096).optional()}).strict(),m.z.object({id:He,origin:m.z.literal("custom"),name:m.z.string().trim().min(1).max(160),description:m.z.string().trim().max(4096).optional(),localizedDescriptions:ln.optional(),cover:an.optional(),reference:et,repository:m.z.string().trim().min(1).max(512),tag:m.z.string().trim().min(1).max(128).regex(Je).optional(),pullPolicy:m.z.literal("if-not-present").default("if-not-present"),capabilities:cn,optionalApps:dn,defaultEnv:Ke,labels:Be,createdAt:qe,updatedAt:qe}).strict();const gn=m.z.object({name:m.z.string().trim().min(1).max(128).regex(Je),version:m.z.string().trim().min(1).max(160).optional(),reference:et,manifestDigest:tt.optional(),status:on}).strict(),hn=m.z.object({id:He,origin:sn,name:m.z.string().trim().min(1).max(160),description:m.z.string().trim().max(4096).optional(),localizedDescriptions:ln.optional(),cover:an,repository:m.z.string().trim().min(1).max(512),tag:m.z.string().trim().min(1).max(128).regex(Je).optional(),availableTags:m.z.array(gn),reference:et,digest:tt.optional(),downloadSizeBytes:m.z.number().int().positive().optional(),unpackedSizeBytes:m.z.number().int().positive().optional(),capabilities:cn,optionalApps:dn,defaultEnv:Ke,labels:Be,readOnly:m.z.boolean(),lifecycleStatus:on.optional(),market:m.z.object({catalogId:He,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(),fn=m.z.object({id:He,origin:sn,name:m.z.string().trim().min(1).max(160),description:m.z.string().trim().max(4096).optional(),localizedDescriptions:ln.optional(),cover:an.optional(),repository:m.z.string().trim().min(1).max(512),tag:m.z.string().trim().min(1).max(128).regex(Je).optional(),requestedReference:et,resolvedDigest:tt.optional(),resolvedReference:et.optional(),downloadSizeBytes:m.z.number().int().positive().optional(),pullPolicy:m.z.literal("if-not-present").default("if-not-present"),capabilities:cn,optionalApps:dn,defaultEnv:Ke,labels:Be,market:m.z.object({catalogId:He,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:qe,updatedAt:qe}).strict(),In=m.z.object({phase:m.z.enum(["checking-image","pulling-image","resolving-image","ready","failed"]),requestedReference:et,generation:m.z.number().int().nonnegative().default(0),error:m.z.string().trim().max(4096).optional(),startedAt:qe,updatedAt:qe}).strict(),yn="image.pull.terminal.output",An="image.pull.terminal.finished",bn=m.z.object({instanceId:He,generation:m.z.number().int().nonnegative(),requestedReference:et,sequence:m.z.number().int().nonnegative(),observedAt:qe}).strict(),wn=bn.extend({data:m.z.string().min(1).max(65536),replay:m.z.boolean().optional()}).strict(),zn=bn.extend({outcome:m.z.enum(["succeeded","failed"])}).strict();bn.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 Nn=m.z.object({id:He,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:He.optional(),secret:m.z.string().trim().max(4096).optional(),pairedAt:qe.optional(),pairing:m.z.object({status:m.z.enum(["pending","paired","expired"]).default("pending"),joinToken:m.z.string().trim().max(4096).optional(),expiresAt:qe.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:dt.optional(),labels:Be,lastSeenAt:qe.optional(),createdAt:qe,updatedAt:qe}).strict(),vn=m.z.object({id:He,nodeId:He,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:Be,createdAt:qe,updatedAt:qe}).strict(),Sn=m.z.object({instanceId:He,runtimeKind:m.z.literal("docker"),state:m.z.enum(["pending","available","stopped","unavailable"]),sampledAt:qe,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:He.optional(),platform:lt.optional()}).passthrough();const En=m.z.object({bindScope:m.z.enum(["loopback","all-ipv4"]),port:m.z.number().int().min(1).max(65535)}).strict(),_n=En.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(),Tn=En;m.z.object({nodeId:He,joinToken:m.z.string().trim().min(1),expiresAt:qe}).passthrough(),m.z.object({id:He,keyId:He,url:m.z.string().trim().min(1).max(2048).optional(),name:m.z.string().trim().min(1).max(160).optional(),pairedAt:qe,updatedAt:qe.optional(),active:m.z.boolean().optional(),current:m.z.boolean().optional()}).passthrough(),m.z.object({remote:m.z.object({id:He,url:m.z.string().trim().min(1).max(2048).optional(),keyId:He,pairedAt:qe,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 kn=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:hn,status:m.z.enum(["available","pull-required","unknown"]),localImage:kn.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 Cn=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(),On=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"}),Rn=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(),Dn=m.z.object({id:He,name:m.z.string().trim().min(1).max(160),projectId:He.optional(),source:Ut,sourceSnapshot:m.z.record(m.z.string(),m.z.unknown()).default({}),modelSelection:nt,nodeId:He,runtimeId:He,imageSelection:it.optional(),imageSnapshot:fn.optional(),imageProvisioning:In.optional(),stateRevision:m.z.number().int().min(0).default(0),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:Ve.optional(),instanceVersion:m.z.string().trim().max(80).optional(),build:Et.optional(),runtimeVersion:xt.optional(),ready:m.z.boolean().default(!1),capabilities:m.z.record(m.z.string(),m.z.unknown()).default({}),appInventory:dt.optional(),config:m.z.object({autoImportAgentConfigs:m.z.boolean().default(!0),defaultCodexPermissionMode:se.default("ask")}).strict().default({autoImportAgentConfigs:!0,defaultCodexPermissionMode:"ask"}),workspace:Rn.default({status:"unknown"}),target:Cn.default({strategy:"direct-port",status:"unknown"}),access:On,apps:m.z.object({runningCount:m.z.number().int().min(0).default(0),problemCount:m.z.number().int().min(0).default(0),updatedAt:qe.optional(),revision:m.z.number().int().min(0).optional()}).strict().default({runningCount:0,problemCount:0}),aiSessions:Ne.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(Le).default([]),runtime:m.z.array($e).default([])}).strict()).default([]),recentRuns:m.z.array(Fe).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:qe.optional(),createdAt:qe,updatedAt:qe}).strict(),Pn="instance.lifecycle.snapshot",jn=m.z.object({instanceId:Dn.shape.id,revision:m.z.number().int().min(0),updatedAt:qe,status:Dn.shape.status.unwrap(),health:Dn.shape.health.unwrap(),connectionStatus:Dn.shape.connectionStatus.unwrap(),accessStatus:m.z.enum(["reachable","endpoint-unreachable"]),imageProvisioning:In.optional(),workspace:Rn,runtime:Dn.shape.runtime.unwrap(),runtimeVersion:xt.optional(),ready:m.z.boolean(),lastHeartbeatAt:qe.optional()}).strict();function Mn(e,t){return Dn.safeParse(Ln(e,t))}function Ln(e,t){if(!e||"object"!=typeof e||Array.isArray(e))return e;const n=e,i=new Set(Object.keys(Dn.shape)),r={};for(const[e,s]of Object.entries(n))i.has(e)?r[e]=s:t?.({instanceId:"string"==typeof n.id?n.id:void 0,field:e});if(n.capabilities&&"object"==typeof n.capabilities&&!Array.isArray(n.capabilities)){const e={...n.capabilities};Object.prototype.hasOwnProperty.call(e,"apps")&&(t?.({instanceId:"string"==typeof n.id?n.id:void 0,field:"capabilities.apps"}),delete e.apps),r.capabilities=e}else r.capabilities={};r.appInventory=function(e,t,n){if(!e||"object"!=typeof e||Array.isArray(e))return;const i=e;Object.keys(i).some(e=>!["observedAt","items","issues"].includes(e))&&t?.({instanceId:n,field:"appInventory"});const r={observedAt:i.observedAt,items:Array.isArray(i.items)?i.items.map(e=>{e&&"object"==typeof e&&!Array.isArray(e)&&Object.keys(e).some(e=>!["id","name","kind","source","availability","capabilities","diagnosticCode"].includes(e))&&t?.({instanceId:n,field:"appInventory.items"});const i=Un(e,["id","name","kind","source","availability","diagnosticCode"]);return!i||"object"!=typeof i||Array.isArray(i)?i:{...i,capabilities:Un(e.capabilities,["automation","supportsCwdSelection"])}}):i.items,issues:Array.isArray(i.issues)?i.issues.map(e=>Un(e,["code","message"])):i.issues},s=dt.safeParse(r);return s.success?s.data:void 0}(n.appInventory,t,"string"==typeof n.id?n.id:void 0),r.source=function(e,t,n){if(!e||"object"!=typeof e||Array.isArray(e))return e;const i=e,r=i.type,s=Ut.options.find(e=>e.shape.type.value===r);if(!s)return e;const o="local-folder"===r?["type","localFolderId","path","ownerNodeId"]:"git-template"===r?["type","url","templateId","ref","auth","clone"]:["type","repositoryId","url","provider","ref","auth","clone"],a=Un(i,o);if("local-folder"!==r){const e=$n(Mt,Un(i.ref,["type","name","commit"]),"source.ref",t,n),r=$n(Lt,Un(i.auth,["type","secretId"]),"source.auth",t,n),s=$n($t,Un(i.clone,["depth","submodules","lfs","subdirectory"]),"source.clone",t,n);e?a.ref=e:delete a.ref,r?a.auth=r:delete a.auth,s?a.clone=s:delete a.clone}const c=$n(s,a,"source",t,n);return c?(Object.keys(i).some(e=>!o.includes(e))&&t?.({instanceId:n,field:"source"}),c):a}(n.source,t,"string"==typeof n.id?n.id:void 0),r.sourceSnapshot=n.sourceSnapshot&&"object"==typeof n.sourceSnapshot&&!Array.isArray(n.sourceSnapshot)?n.sourceSnapshot:{},r.build=$n(Et,n.build,"build",t,"string"==typeof n.id?n.id:void 0),r.aiSessions=function(e,t,n){if(!e||"object"!=typeof e||Array.isArray(e))return;const i=e,r=Array.isArray(i.sessions)?i.sessions.flatMap((e,i)=>{const r=$n(ze,e,`aiSessions.sessions.${i}`,t,n);return r?[r]:[]}):[],s={runningCount:"number"==typeof i.runningCount&&Number.isInteger(i.runningCount)&&i.runningCount>=0?i.runningCount:0,waitingCount:"number"==typeof i.waitingCount&&Number.isInteger(i.waitingCount)&&i.waitingCount>=0?i.waitingCount:0,staleCount:"number"==typeof i.staleCount&&Number.isInteger(i.staleCount)&&i.staleCount>=0?i.staleCount:0,sessions:r,updatedAt:qe.safeParse(i.updatedAt).success?i.updatedAt:(new Date).toISOString()};return Object.keys(i).some(e=>!["runningCount","waitingCount","staleCount","sessions","updatedAt"].includes(e))&&t?.({instanceId:n,field:"aiSessions"}),Ne.parse(s)}(n.aiSessions,t,"string"==typeof n.id?n.id:void 0),r.triggers=function(e,t,n){if(!e||"object"!=typeof e||Array.isArray(e))return;const i=e;Object.keys(i).some(e=>!["enabledCount","runningCount","errorCount","configs","recentRuns"].includes(e))&&t?.({instanceId:n,field:"triggers"});const r=(e,i,r)=>Array.isArray(e)?e.flatMap((e,s)=>{const o=$n(i,e,`${r}.${s}`,t,n);return o?[o]:[]}):[],s=Array.isArray(i.configs)?i.configs.flatMap((e,i)=>{if(!e||"object"!=typeof e||Array.isArray(e))return[];const s=e;Object.keys(s).some(e=>!["configHash","config","deployments","runtime"].includes(e))&&t?.({instanceId:n,field:`triggers.configs.${i}`});const o=function(e,t,n,i){if(!e||"object"!=typeof e||Array.isArray(e))return;const r=e,s=Un(r,["configHash","name","description","createdAt","updatedAt"]);if(r.source&&"object"==typeof r.source&&!Array.isArray(r.source)){const e=r.source,t="schedule"===e.type?"interval"===e.scheduleKind?["type","scheduleKind","intervalMs"]:"daily"===e.scheduleKind?["type","scheduleKind","timeOfDay","timezone"]:["type","scheduleKind","weekdays","timeOfDay","timezone"]:"file-change"===e.type?["type","roots","globs","ignore","debounceMs"]:["type","agent","statuses","phases"];s.source=Un(e,t)}return s.action=Un(r.action,["promptTemplate"]),s.policy=Un(r.policy,["cooldownMs","maxConcurrentRuns","whenBusy"]),$n(je,s,t,n,i)}(s.config,`triggers.configs.${i}.config`,t,n);return"string"==typeof s.configHash&&o?[{configHash:s.configHash,config:o,deployments:r(s.deployments,Le,`triggers.configs.${i}.deployments`),runtime:r(s.runtime,$e,`triggers.configs.${i}.runtime`)}]:[]}):[];return{enabledCount:"number"==typeof i.enabledCount&&Number.isInteger(i.enabledCount)&&i.enabledCount>=0?i.enabledCount:0,runningCount:"number"==typeof i.runningCount&&Number.isInteger(i.runningCount)&&i.runningCount>=0?i.runningCount:0,errorCount:"number"==typeof i.errorCount&&Number.isInteger(i.errorCount)&&i.errorCount>=0?i.errorCount:0,configs:s,recentRuns:r(i.recentRuns,Fe,"triggers.recentRuns")}}(n.triggers,t,"string"==typeof n.id?n.id:void 0),r.apps=$n(Dn.shape.apps.unwrap(),Un(n.apps,["runningCount","problemCount","updatedAt","revision"]),"apps",t,"string"==typeof n.id?n.id:void 0)||{runningCount:0,problemCount:0},r.config=$n(Dn.shape.config.unwrap(),Un(n.config,["autoImportAgentConfigs","defaultCodexPermissionMode"]),"config",t,"string"==typeof n.id?n.id:void 0)||{autoImportAgentConfigs:!0,defaultCodexPermissionMode:"ask"},r.modelSelection=$n(nt.unwrap(),Un(n.modelSelection,["codexModelHash","claudeModelHash"]),"modelSelection",t,"string"==typeof n.id?n.id:void 0)||{},r.imageSnapshot=function(e,t,n,i){if(!e||"object"!=typeof e||Array.isArray(e))return e;const r=e,s=function(e){if(!e||"object"!=typeof e||Array.isArray(e))return e;const t=e,n=new Set(["id","origin","name","description","localizedDescriptions","cover","reference","repository","tag","image","registry","pullPolicy","capabilities","optionalApps","defaultEnv","labels","createdAt","updatedAt"]);for(const e of Object.keys(t))n.has(e);"string"==typeof t.id&&t.id;const i="string"==typeof t.image?t.image:void 0;Object.prototype.hasOwnProperty.call(t,"registry");let r,s="string"==typeof t.reference?t.reference:i;if(s)try{s=Ze(s)}catch{if(!s.includes("@")&&s.lastIndexOf(":")<=s.lastIndexOf("/"))try{s=Ze(`${s}:latest`)}catch{}}try{r=s?Qe(s):void 0}catch{}return{id:t.id,origin:"custom",name:t.name,description:t.description,localizedDescriptions:t.localizedDescriptions,cover:Un(t.cover,["kind","key","url","mediaType","digest"]),reference:r?.reference??s,repository:r?.repository??t.repository,tag:r?.tag??t.tag,pullPolicy:t.pullPolicy??"if-not-present",capabilities:t.capabilities,optionalApps:t.optionalApps,defaultEnv:t.defaultEnv,labels:t.labels,createdAt:t.createdAt,updatedAt:t.updatedAt}}(r),{reference:o,...a}=s,c=r.requestedReference??o;let d;try{d="string"==typeof c?Qe(c):void 0}catch{}const l={img_default:"market_taskhandoff_browser",img_codex:"market_taskhandoff_codex",img_ai:"market_taskhandoff_ai"},u="string"==typeof r.id?r.id:"string"==typeof t?t:void 0,m="market"===r.origin||u&&l[u]?"market":"custom";return void 0===r.image&&void 0===r.reference||n?.({instanceId:i,field:"imageSnapshot.reference"}),{...a,id:u&&l[u]?l[u]:u,origin:m,repository:d?.repository??r.repository,tag:d?.tag??r.tag,requestedReference:d?.reference??c,resolvedDigest:r.resolvedDigest,resolvedReference:r.resolvedReference,downloadSizeBytes:r.downloadSizeBytes,market:"market"===m?Un(r.market,["catalogId","catalogRevision","publisher","version"])??{catalogId:"task_handoff_embedded",catalogRevision:"legacy",publisher:"task-handoff"}:void 0}}(n.imageSnapshot,n.imageId,t,"string"==typeof n.id?n.id:void 0);const s="string"==typeof n.imageId?{img_default:"market_taskhandoff_browser",img_codex:"market_taskhandoff_codex",img_ai:"market_taskhandoff_ai"}[n.imageId]||n.imageId:void 0,o=Un(n.imageSelection,["imageId","tag"]);r.imageSelection=o||(s?{imageId:s,tag:r.imageSnapshot?.tag}:void 0),r.imageProvisioning=$n(In,Un(n.imageProvisioning,["phase","requestedReference","generation","error","startedAt","updatedAt"]),"imageProvisioning",t,"string"==typeof n.id?n.id:void 0),r.runtimeVersion=function(e,t,n){if(!e||"object"!=typeof e||Array.isArray(e))return;const i=e,r=e=>{if("string"!=typeof e)return;const t=e.trim();return t&&t.length<=80?t:void 0},s=r(i.desiredVersion);if(!s)return void t?.({instanceId:n,field:"runtimeVersion.desiredVersion"});const o=new Set(xt.shape.phase.options),a="string"==typeof i.phase?i.phase:"pending",c=o.has(a)?a:{idle:"pending",queued:"pending",checking:"pending",downloading:"installing",updating:"installing",completed:"matched",succeeded:"matched",ready:"matched",error:"failed"}[a]||"pending";let d;if(c!==a&&t?.({instanceId:n,field:"runtimeVersion.phase"}),i.error&&"object"==typeof i.error&&!Array.isArray(i.error)){const e=i.error,s="string"==typeof e.message?e.message.trim().slice(0,4096):"";if(s){const i=new Set(kt.shape.code.options),o="string"==typeof e.code&&i.has(e.code)?e.code:"INSTANCE_RUNTIME_INSTALL_FAILED";o!==e.code&&t?.({instanceId:n,field:"runtimeVersion.error.code"});const a=r(e.expectedVersion),c=r(e.actualVersion);d={code:o,message:s,...a?{expectedVersion:a}:{},...c?{actualVersion:c}:{},retryable:!0===e.retryable}}else t?.({instanceId:n,field:"runtimeVersion.error"})}"string"==typeof i.error&&i.error.trim()&&(d={code:"INSTANCE_RUNTIME_INSTALL_FAILED",message:i.error.trim().slice(0,4096),expectedVersion:s,...r(i.actualVersion)?{actualVersion:r(i.actualVersion)}:{},retryable:!1});const l=r(i.actualVersion),u=qe.safeParse(i.lastAttemptAt),m=qe.safeParse(i.matchedAt);return void 0===i.lastAttemptAt||u.success||t?.({instanceId:n,field:"runtimeVersion.lastAttemptAt"}),void 0===i.matchedAt||m.success||t?.({instanceId:n,field:"runtimeVersion.matchedAt"}),{desiredVersion:s,...l?{actualVersion:l}:{},phase:c,attempt:"number"==typeof i.attempt&&Number.isInteger(i.attempt)&&i.attempt>=0?i.attempt:0,...u.success?{lastAttemptAt:u.data}:{},...m.success?{matchedAt:m.data}:{},...d?{error:d}:{}}}(n.runtimeVersion,t,"string"==typeof n.id?n.id:void 0),r.workspace=$n(Rn,n.workspace,"workspace",t,"string"==typeof n.id?n.id:void 0)||{status:"unknown"},r.runtime=$n(Dn.shape.runtime.unwrap(),Un(n.runtime,["kind","containerName","containerId","workspacePath","pid","port","labels"]),"runtime",t,"string"==typeof n.id?n.id:void 0)||{labels:{}},r.target=$n(Cn,Un(n.target??n.endpoints,["strategy","web","api","vnc","tty","logs","status"]),"target",t,"string"==typeof n.id?n.id:void 0)||{strategy:"direct-port",status:"unknown"},r.access=$n(On,Un(n.access,["strategy","web","api","ws","status"]),"access",t,"string"==typeof n.id?n.id:void 0)||{strategy:"control-plane-proxy",status:"unknown"};for(const[e,i]of Object.entries(Dn.shape))Object.prototype.hasOwnProperty.call(r,e)&&!i.safeParse(r[e]).success&&i.safeParse(void 0).success&&(delete r[e],t?.({instanceId:"string"==typeof n.id?n.id:void 0,field:e}));return r}function $n(e,t,n,i,r){if(!t||"object"!=typeof t||Array.isArray(t))return;let s=structuredClone(t),o=!1;for(let t=0;t<20;t+=1){const t=e.safeParse(s);if(t.success)return o&&i?.({instanceId:r,field:n}),t.data;let a=!1;for(const e of t.error.issues){if("unrecognized_keys"!==e.code)continue;const t=Fn(s,e.path);if(t&&"object"==typeof t&&!Array.isArray(t))for(const n of e.keys)Object.prototype.hasOwnProperty.call(t,n)&&(delete t[n],a=!0,o=!0)}if(!a){const o=structuredClone(s);let a=!1;for(const e of t.error.issues){if(!e.path.length||"string"!=typeof e.path.at(-1))continue;const t=Fn(o,e.path.slice(0,-1)),n=e.path.at(-1);t&&"object"==typeof t&&!Array.isArray(t)&&Object.prototype.hasOwnProperty.call(t,n)&&(delete t[n],a=!0)}if(a){const t=e.safeParse(o);if(t.success)return i?.({instanceId:r,field:n}),t.data}break}}i?.({instanceId:r,field:n})}function Fn(e,t){let n=e;for(const e of t){if(!n||"object"!=typeof n)return;n=n[e]}return n}function Un(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 Vn=m.z.object({instanceId:He.optional(),projectId:He.optional(),source:Ut.optional(),nodeId:He.optional(),runtimeId:He.optional(),imageSelection:it.optional(),instanceVersion:m.z.string().trim().max(80).optional(),protocolVersion:Ve,build:Et.optional(),controlMode:m.z.enum(["standalone","controlled"]).default("controlled"),capabilities:m.z.record(m.z.string(),m.z.unknown()).default({}),appInventory:dt.optional(),target:Cn.default({strategy:"direct-port",status:"unknown"}),workspace:Rn.default({status:"unknown"}),registrationToken:m.z.string().trim().max(240).optional()}).strict().superRefine((e,t)=>{e.protocolVersion!==Ue||e.appInventory||t.addIssue({code:"custom",path:["appInventory"],message:"Current protocol register payload requires appInventory."})}),Hn=m.z.object({status:Dn.shape.status.optional(),health:Dn.shape.health.optional(),protocolVersion:Ve,build:Et.optional(),capabilities:Dn.shape.capabilities.optional(),appInventory:dt.optional(),apps:Dn.shape.apps.optional(),aiSessions:Dn.shape.aiSessions.optional(),triggers:Dn.shape.triggers.optional(),workspace:Rn.optional(),target:Cn.partial().optional()}).strict().superRefine((e,t)=>{e.protocolVersion!==Ue||e.appInventory||t.addIssue({code:"custom",path:["appInventory"],message:"Current protocol heartbeat payload requires appInventory."})}),qn=m.z.enum(["web","telegram","wechat","dingding"]);function Bn(e){return e.readyState===(e.OPEN??1)}function Kn(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 Gn(e,t){e.send(t.data,{binary:t.isBinary})}function Jn(e,t){if(Bn(e))for(const n of t.splice(0))Gn(e,n)}function Wn(e,t,n={}){return new Promise((i,r)=>{const s=a.spawn(e,t,{stdio:["ignore","pipe","pipe"]}),o=[],c=[];let d=!1;const l=n.timeoutMs?setTimeout(()=>{d=!0,s.kill("SIGKILL")},n.timeoutMs):void 0;l?.unref?.(),s.stdout.on("data",e=>o.push(Buffer.from(e))),s.stderr.on("data",e=>c.push(Buffer.from(e))),s.on("error",e=>{l&&clearTimeout(l),r(e)}),s.on("close",t=>{l&&clearTimeout(l);const s={stdout:Buffer.concat(o).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:s}),void r(t)}if(0===t)return void i(s);const a=new Error(s.stderr||`${e} exited with code ${t}`);Object.assign(a,{statusCode:502,code:"RUNTIME_EXECUTOR_FAILED",details:s}),r(a)})})}m.z.object({id:He,channel:qn,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:qe,updatedAt:qe}).strict(),m.z.object({id:He,channel:qn,bridgeId:He.optional(),chatSessionId:m.z.string().trim().min(1).max(240),userId:m.z.string().trim().max(240).optional(),activeProjectId:He.optional(),activeInstanceId:He.optional(),activeAiSessionId:m.z.string().trim().min(1).max(120).optional(),lastUsedAt:qe,createdAt:qe,updatedAt:qe}).strict(),m.z.object({source:m.z.object({type:m.z.literal("chat-gateway").default("chat-gateway"),channel:qn,bridgeId:He.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(te).max(6).default([])}).strict().superRefine((e,t)=>{e.attachments.reduce((e,t)=>e+("inline"===t.source.type?t.size:0),0)>V&&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:He,aiSessionId:m.z.string().trim().min(1).max(120)}).strict().optional()}).strict(),m.z.object({id:He,instanceId:He,projectId:He.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:qe}).strict();const Yn=(e,t,n={})=>new Promise((i,r)=>{const s=[];let o,a=!1;try{o=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 r(e)}const c=n.timeoutMs?setTimeout(()=>{a=!0,o.kill("SIGKILL")},n.timeoutMs):void 0;c?.unref?.(),o.onData(e=>{s.push(e),n.onData?.(e)}),o.onExit(({exitCode:t})=>{c&&clearTimeout(c);const o={stdout:s.join(""),stderr:""};a?r(Object.assign(new Error(`${e} timed out after ${n.timeoutMs}ms`),{statusCode:504,code:"RUNTIME_COMMAND_TIMEOUT",details:o})):0!==t?r(Object.assign(new Error(o.stdout.replace(/\u001b\[[0-?]*[ -/]*[@-~]/g,"").split(/\r?\n/).map(e=>e.trim()).filter(Boolean).at(-1)||`${e} exited with code ${t}`),{statusCode:502,code:"RUNTIME_EXECUTOR_FAILED",details:o})):i(o)})});class Xn{inFlight=new Map;runCommand;runTerminalCommand;constructor(e=Wn,t){this.runCommand=e,this.runTerminalCommand=t||function(e){return e===Wn?Yn:async(t,n,i={})=>{const r=await e(t,n,{timeoutMs:i.timeoutMs});return r.stdout&&i.onData?.(r.stdout),r.stderr&&i.onData?.(r.stderr),r}}(e)}ensure(e,t,n){const i=Ze(e),r=this.inFlight.get(i);if(r)return t&&(r.phaseListeners.add(t),r.phase&&t(r.phase)),n&&(r.terminalListeners.add(n),r.terminalTail&&n({sequence:r.terminalSequence,data:r.terminalTail,replay:!0})),r.promise;const s=new Set,o=new Set;t&&s.add(t),n&&o.add(n);const a={promise:Promise.resolve(void 0),phaseListeners:s,terminalListeners:o,terminalSequence:0,terminalTail:""};return a.promise=this.ensureOnce(i,e=>{a.phase=e,s.forEach(t=>t(e))},e=>{a.terminalSequence+=1,a.terminalTail=`${a.terminalTail}${e}`.slice(-262144);const t={sequence:a.terminalSequence,data:e};o.forEach(e=>e(t))}).finally(()=>this.inFlight.delete(i)),this.inFlight.set(i,a),a.promise}async ensureOnce(e,t,n){t("checking-image");let i=await this.inspect(e).catch(()=>{}),r=!1;i||(t("pulling-image"),await this.runTerminalCommand("docker",["pull",e],{cols:120,rows:40,onData:n}),r=!0,i=await this.inspect(e)),t("resolving-image");const s=(o=i,Array.isArray(o.RepoDigests)?o.RepoDigests.filter(e=>"string"==typeof e):[]).find(e=>/@sha256:[a-fA-F0-9]{64}$/.test(e));var o;const a=s?.split("@").at(-1)?.toLowerCase();return{requestedReference:e,...a?{resolvedDigest:a}:{},resolvedReference:s||e,pulled:r}}async inspect(e){const t=await this.runCommand("docker",["image","inspect",e,"--format","{{json .}}"]);return JSON.parse(t.stdout.trim()||"{}")}}function Zn(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 Qn{runCommand;publishHost;images;launcherAssetsDir;constructor(e=Wn,i={}){this.runCommand=e,this.images=i.imageService||new Xn(e),this.publishHost=i.publishHost||"127.0.0.1",this.launcherAssetsDir=i.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(o.fileURLToPath("undefined"==typeof document?require("url").pathToFileURL(__filename).href:b&&"SCRIPT"===b.tagName.toUpperCase()&&b.src||new URL("cli.js",document.baseURI).href)):__dirname,i=[n.resolve(e,"../../../../../docker"),n.resolve(e,"../docker"),n.resolve(e,"../../docker")];return i.find(e=>t.existsSync(n.join(e,"runtime-installer.mjs")))||i[0]}()}async start(e){si(e);const t=e.instance.runtime.containerName||ii(e.instance.id);if(await this.runCommand("docker",["start",t]).catch(()=>{}))return this.runningResult(e,t,e.instance.runtime.containerId);await this.images.ensure(e.image.resolvedReference||e.image.requestedReference);const n=await this.runCommand("docker",function(e,t,n={}){const i=n.publishHost||"127.0.0.1",r=e.node?.id||"node_unset",s=e.runtime?.id||"runtime_local_docker",o=["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=${r}`,"--label",`task-handoff.runtime-id=${s}`,"--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",`${i}::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:r,TASK_HANDOFF_RUNTIME_ID:s,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))ri(o,e,t);"local-folder"===e.project.source.type?o.push("-v",`${e.project.source.path}:${e.project.workspacePolicy.path||"/workspace"}:${e.project.workspacePolicy.readOnly?"ro":"rw"}`):(ri(o,"TASK_HANDOFF_PROJECT_SOURCE",JSON.stringify(e.project.source)),ri(o,"TASK_HANDOFF_WORKSPACE_POLICY",JSON.stringify(e.project.workspacePolicy)),ri(o,"TASK_HANDOFF_GIT_URL",e.project.source.url),e.project.source.ref?.commit?ri(o,"TASK_HANDOFF_GIT_COMMIT",e.project.source.ref.commit):e.project.source.ref?.name&&ri(o,"TASK_HANDOFF_GIT_REF",e.project.source.ref.name),e.project.source.clone?.depth&&ri(o,"TASK_HANDOFF_GIT_DEPTH",String(e.project.source.clone.depth)),ri(o,"TASK_HANDOFF_GIT_SUBMODULES",e.project.source.clone?.submodules?"true":"false"),ri(o,"TASK_HANDOFF_GIT_LFS",e.project.source.clone?.lfs?"true":"false"),e.project.source.clone?.subdirectory&&ri(o,"TASK_HANDOFF_WORKSPACE_SUBDIRECTORY",e.project.source.clone.subdirectory));for(const[t,n]of Object.entries(e.image.defaultEnv))ri(o,t,n);for(const[t,n]of Object.entries(e.modelEnv||{}))ri(o,t,n);return o.push(e.image.resolvedReference||e.image.requestedReference),o}(e,t,{publishHost:this.publishHost}));return this.runningResult(e,t,n.stdout||void 0)}async runningResult(e,t,n){const i=await this.containerPort(t,"8080/tcp"),r=i?`http://127.0.0.1:${i}`:void 0,s=e.node?.id||"node_unset",o=e.runtime?.id||"runtime_local_docker";return{status:"registering",health:"unknown",connectionStatus:r?"online":"unknown",agentStatus:"unknown",targetStatus:"unknown",uiAccessStatus:"unknown",target:{strategy:"direct-port",status:r?"reachable":"unknown",...r?{web:r,api:`${r}/api`}:{}},workspace:{mode:e.project.workspacePolicy.mode,status:"pending",path:e.project.workspacePolicy.path},runtime:{...e.instance.runtime,kind:"docker",containerName:t,...n?{containerId:n}:{},labels:{...e.instance.runtime.labels,"task-handoff.instance-id":e.instance.id,"task-handoff.project-id":e.project.id,"task-handoff.node-id":s,"task-handoff.runtime-id":o,"task-handoff.image-id":e.image.id}}}}async stop(e){return await this.runCommand("docker",["stop",e.instance.runtime.containerName||ii(e.instance.id)]).catch(()=>({stdout:"",stderr:""})),{status:"stopped",health:"unknown",connectionStatus:"offline",target:{...e.instance.target,status:"unknown"},runtime:e.instance.runtime}}async restart(e,t){si(e);const n=e.instance.runtime.containerName||ii(e.instance.id),i=await this.inspectContainerId(n);if(!i)throw ei("INSTANCE_RUNTIME_RESTART_FAILED",`Docker container ${n} does not exist.`);ti(n,i,t,"before restart","INSTANCE_RUNTIME_RESTART_FAILED"),await this.runCommand("docker",["restart",n]);const r=await this.inspectContainerId(n);if(!r||r!==i)throw ei("INSTANCE_RUNTIME_RESTART_FAILED",`Docker container identity changed while restarting ${n}.`);return ti(n,r,t,"after restart","INSTANCE_RUNTIME_RESTART_FAILED"),this.runningResult(e,n,r)}async delete(e){return await this.runCommand("docker",["rm","-f",e.instance.runtime.containerName||ii(e.instance.id)]).catch(()=>({stdout:"",stderr:""})),{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);ti(e.containerName,t,e.expectedContainerId,"before runtime restart","INSTANCE_RUNTIME_RESTART_FAILED");try{await this.runCommand("docker",["restart",e.containerName])}catch(t){throw ei("INSTANCE_RUNTIME_RESTART_FAILED",`Could not restart Docker container ${e.containerName}.`,t)}const n=await this.inspectContainerId(e.containerName);if(!n||n!==t)throw ei("INSTANCE_RUNTIME_RESTART_FAILED",`Docker container identity changed while updating ${e.containerName}.`);return ti(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 ei("INSTANCE_RUNTIME_INSTALL_FAILED",`Docker container ${e.containerName} does not exist.`);ti(e.containerName,t,e.expectedContainerId,"before runtime install","INSTANCE_RUNTIME_INSTALL_FAILED");const n=`/opt/task-handoff/instance-runtime/incoming/task-handoff-runtime-${i=e.identity.version,i.replace(/[^0-9A-Za-z.+_-]/g,"-")}-${e.identity.sha256.slice(0,12)}.tar.gz`;var i;await this.runCommand("docker",["exec","--user","0",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 ei("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 r=await this.inspectContainerId(e.containerName);if(!r||r!==t)throw ei("INSTANCE_RUNTIME_INSTALL_FAILED",`Docker container identity changed while installing ${e.containerName}.`);return ti(e.containerName,r,e.expectedContainerId,"after runtime install","INSTANCE_RUNTIME_INSTALL_FAILED"),t}async inspectRuntimeVersion(e){const t=await this.inspectContainerId(e);if(!t)return{};const n=await this.runCommand("docker",["exec","--user","agent",e,"task-handoff-runtime","verify-active"]).catch(()=>{});if(!n?.stdout)return{containerId:t};try{const e=Tt.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 i=await this.runCommand("docker",["inspect","--format","{{json .}}",e]).then(e=>JSON.parse(e.stdout.trim()||"{}")).catch(()=>{});if(t=i?.Platform,"string"==typeof i?.Image&&i.Image){const e=await this.runCommand("docker",["image","inspect","--format","{{json .}}",i.Image]).then(e=>JSON.parse(e.stdout.trim()||"{}")).catch(()=>{});t=e?.Os||t,n=e?.Architecture}}if(!t||!n){const e=await this.runCommand("docker",["info","--format","{{json .}}"]).then(e=>JSON.parse(e.stdout.trim()||"{}")).catch(e=>{throw ei("INSTANCE_BASE_RUNTIME_INCOMPATIBLE","Could not inspect the Docker runtime target.",e)});t||=e.OSType,n||=e.Architecture}const i="linux"===(r=t)||"darwin"===r?r:"windows"===r||"win32"===r?"win32":void 0;var r;const s=function(e){return"amd64"===e||"x86_64"===e||"x64"===e?"x64":"arm64"===e||"aarch64"===e?"arm64":void 0}(n);if(!i||!s)throw ei("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Docker reported an unsupported runtime target ${String(t||"unknown")}/${String(n||"unknown")}.`);return{platform:i,arch:s,launcherAbi:1}}async rollbackRuntime(e){const t=await this.inspectContainerId(e);if(!t)throw ei("INSTANCE_RUNTIME_RESTART_FAILED",`Docker container ${e} does not exist.`);try{await this.runCommand("docker",["exec","--user","0",e,"task-handoff-runtime","rollback"]),await this.runCommand("docker",["restart",e])}catch(t){throw ei("INSTANCE_RUNTIME_RESTART_FAILED",`Could not roll back ${e} to its previous controlled-instance release.`,t)}const n=await this.inspectContainerId(e);if(!n||n!==t)throw ei("INSTANCE_RUNTIME_RESTART_FAILED",`Docker container identity changed while rolling back ${e}.`);return this.inspectRuntimeVersion(e)}async installRuntimeLauncher(e){const t=await this.inspectContainerId(e);if(!t)throw ei("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Docker container ${e} does not exist.`);const i=[[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 i)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 ei("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Could not install the runtime launcher in ${e}.`,t)}if(await this.inspectContainerId(e)!==t)throw ei("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Docker container identity changed while installing the runtime launcher in ${e}.`)}async inspectContainerId(e){const t=await this.runCommand("docker",["inspect","--format","{{.Id}}",e]).catch(()=>{});return t?.stdout.trim()||void 0}async containerPort(e,t){const n=(await this.runCommand("docker",["port",e,t]).catch(()=>({stdout:"",stderr:""}))).stdout.split(/\r?\n/).find(Boolean),i=n?.match(/:(\d+)$/);return i?.[1]}}function ei(e,t,n){const i=function(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}(n),r=new Error(i?`${t} Cause: ${i}`:t,void 0===n?void 0:{cause:n});return Object.assign(r,{statusCode:502,code:e}),r}function ti(e,t,n,i,r){if(n&&t!==n)throw ei(r,`Docker container ${e} identity mismatch ${i}: expected ${n}, got ${t}.`)}async function ni(e=Wn){return async function(e=Wn){return(await e("docker",["images","--digests","--format","{{json .}}"])).stdout.split(/\r?\n/).map(e=>e.trim()).filter(Boolean).map(e=>{const t=JSON.parse(e),n=t.Repository||"<none>",i=t.Tag||"<none>",r=t.ID||t.IDShort||"",s="<none>"!==n&&"<none>"!==i?`${n}:${i}`:r,o="<none>"!==n&&t.Digest&&"<none>"!==t.Digest?[`${n}@${t.Digest}`]:[];return{repository:n,tag:i,id:r,createdSince:t.CreatedSince,size:t.Size,sizeBytes:Zn(t.Size),reference:s,repoDigests:o}}).filter(e=>Boolean(e.reference))}(e)}function ii(e){return`task-handoff-${e.replace(/[^a-zA-Z0-9_.-]/g,"-")}`}function ri(e,t,n){e.push("-e",`${t}=${n}`)}function si(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 oi=m.z.enum(["created","starting","running","stopping","stopped","exited","failed","closed","terminated","unknown"]),ai=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(),ci=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:oi.default("unknown"),bindings:m.z.array(ai).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()})),di=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(ci).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:di}).strict(),di.pick({runningCount:!0,problemCount:!0,updatedAt:!0}).extend({revision:m.z.number().int().min(0).optional()});const li=m.z.enum(["app-session-created","app-session-updated","app-session-deleted","app-session-recovered","control-action","heartbeat-sync","startup"]),ui=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:li}).strict(),mi=m.z.object({meta:ui,snapshot:di}).strict(),pi=m.z.object({meta:ui,session:ci}).strict(),gi=m.z.object({meta:ui,sessionId:m.z.string().trim().min(1).max(160),tombstone:ci.optional(),expiresAt:m.z.string().datetime().optional()}).strict();function hi(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:mi}).strict(),m.z.object({type:m.z.literal("app-session.patch"),payload:pi}).strict(),m.z.object({type:m.z.literal("app-session.removed"),payload:gi}).strict()])).default([])}).strict();const fi=m.z.enum(["ai.sessions","app.sessions"]),Ii=m.z.object({topic:fi,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(),yi=m.z.object({protocolVersion:m.z.literal(1),streams:m.z.array(Ii)}).strict();class Ai{attempt=0;timer;get pending(){return Boolean(this.timer)}get attempts(){return this.attempt}schedule(e,t={}){if(this.timer)return;const n=function(e,t=Math.random){const n=Math.min(3e4,1e3*2**Math.max(0,e));return Math.min(3e4,Math.round(n*(.75+.5*t())))}(this.attempt,t.random);this.attempt+=1;const i=t.setTimeoutFn||setTimeout;return this.timer=i(()=>{this.timer=void 0,e()},n),{attempt:this.attempt,delay:n}}reset(e=clearTimeout){this.timer&&e(this.timer),this.timer=void 0,this.attempt=0}cancel(e=clearTimeout){this.timer&&e(this.timer),this.timer=void 0}}function bi(e,t=6e4){const n=[];for(let i=0;i<e.length;i+=t)n.push(e.slice(i,i+t));return n}class wi{sockets=new Map;socketUrls=new Map;retries=new Map;outputs=new Set;imagePullTerminalByInstance=new Map;state;token;logger;safetyIntervalMs;lastAiSessionEventByInstance=new Map;lastAppSessionEventByInstance=new Map;timer;reconnectAttempts=0;safetyReconciliations=0;localSequence=0;createSocket;setIntervalFn;clearIntervalFn;constructor(e,t,n={}){var i;this.state=e,this.token=t,this.logger=n.logger,this.safetyIntervalMs=(i=n.safetyIntervalMs,Math.min(6e4,Math.max(3e4,i??45e3))),this.createSocket=n.createSocket||((e,t)=>new 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=zi(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)bi(n.tail).forEach((i,r)=>this.sendForwarded(e,this.createEvent(yn,{...n.output,sequence:n.output.sequence+r,data:i,...0===r?{replay:!0}:{}},{instanceId:t}))),n.finished&&this.sendForwarded(e,this.createEvent(An,n.finished,{instanceId:t}));return this.syncNow(),()=>{this.outputs.delete(e)}}publish(e,t,n={}){this.rememberImagePullTerminal(e,t);const i=this.createEvent(e,t,n);for(const e of this.outputs)this.sendForwarded(e,i)}rememberImagePullTerminal(e,t){if(e===yn){const e=wn.safeParse(t);if(!e.success)return;const n=e.data,i=this.imagePullTerminalByInstance.get(n.instanceId);if(i&&n.generation<i.output.generation)return;const r=i?.output.generation===n.generation,s=n.replay||!r?n.data:`${i.tail}${n.data}`.slice(-262144);return void this.imagePullTerminalByInstance.set(n.instanceId,{output:n,tail:s})}if(e===An){const e=zn.safeParse(t);if(!e.success)return;const n=e.data,i=this.imagePullTerminalByInstance.get(n.instanceId);i?.output.generation===n.generation&&(i.finished=n)}}publishInstanceLifecycle(e){this.publish(Pn,function(e){return jn.parse(Ni(e))}(e),{instanceId:e.id});const t=this.imagePullTerminalByInstance.get(e.id);"ready"===e.imageProvisioning?.phase&&"succeeded"===t?.finished?.outcome&&this.imagePullTerminalByInstance.delete(e.id)}createEvent(e,t,n){const i=++this.localSequence;return{v:1,id:`node_evt_${Date.now().toString(36)}_${i.toString(36)}`,seq:i,type:e,topic:hi(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=Si(e);if(!n)continue;t.add(e.id);const i=this.retries.get(e.id);i?.timer.pending&&i.url!==n&&(i.timer.cancel(),this.retries.delete(e.id)),this.socketUrls.get(e.id)!==n&&this.sockets.has(e.id)&&(this.sockets.get(e.id)?.close(),this.sockets.delete(e.id)),this.sockets.has(e.id)||this.retries.get(e.id)?.timer.pending||this.connect(e.id,n)}for(const[e,n]of this.sockets)if(!t.has(e)){n.close(),this.sockets.delete(e),this.socketUrls.delete(e);const t=this.retries.get(e);t?.timer.cancel(),this.retries.delete(e)}for(const[e,n]of this.retries)t.has(e)||(n.timer.cancel(),this.retries.delete(e),this.socketUrls.delete(e))}connect(e,t){const n=this.token?{authorization:`Bearer ${this.token}`}:void 0,i=this.createSocket(t,{headers:n});this.sockets.set(e,i),this.socketUrls.set(e,t),i.on("open",()=>{const n=this.retries.get(e);n?.timer.reset(),this.retries.set(e,{timer:n?.timer||new Ai,url:t}),i.readyState===u.OPEN&&(i.send(JSON.stringify({v:1,type:"subscribe",topics:[H,"app.sessions","apps","instances"]})),this.logger?.info?.({instanceId:e,url:t},"ai-session.event.forward.connect"),this.logger?.info?.({instanceId:e,url:t},"app-session.event.forward.connect"))}),i.on("message",t=>{const n=function(e,t){try{const n=JSON.parse(String(e));if(!n||"object"!=typeof n||Array.isArray(n))return;const i=n,r="string"==typeof i.type?i.type:"";if(!r||"events.connected"===r)return;const s=i.scope&&"object"==typeof i.scope&&!Array.isArray(i.scope)?i.scope:{};return{v:1,id:"string"==typeof i.id?i.id:`evt_${Date.now().toString(36)}`,seq:Number(i.seq)||0,type:r,topic:"string"==typeof i.topic?i.topic:hi(r),createdAt:"string"==typeof i.createdAt?i.createdAt:(new Date).toISOString(),payload:"payload"in i?i.payload:{},scope:{...s,instanceId:t}}}catch{return}}(t,e);if(!n)return;if("streams.hello"===n.type){const t=yi.safeParse(n.payload);if(!t.success)return this.logger?.warn?.({instanceId:e,issues:t.error.issues},"session-stream.handshake.invalid"),void i.close(1002,"Incompatible session stream handshake.");const r=JSON.stringify({type:"node-agent.streams.hello",instanceId:e,payload:t.data});for(const e of this.outputs)e.readyState===u.OPEN&&e.send(r);return}this.recordAiSessionEvent(e,n),this.recordAppSessionEvent(e,n);const r=JSON.stringify({type:"node-agent.event.forwarded",event:n});for(const e of this.outputs)e.readyState===u.OPEN&&e.send(r)}),i.on("close",()=>{this.sockets.get(e)===i&&(this.sockets.delete(e),this.socketUrls.delete(e),this.scheduleReconnect(e))}),i.on("error",()=>{this.logger?.warn?.({instanceId:e,url:t},"ai-session.event.forward.error"),this.logger?.warn?.({instanceId:e,url:t},"app-session.event.forward.error"),i.close()})}scheduleReconnect(e){const t=this.state.listInstances().find(t=>t.id===e),n=t&&Si(t);if(!n||!this.outputs.size)return;const i=this.retries.get(e)??{timer:new Ai};if(i.timer.pending)return;i.url=n;const r=i.timer.schedule(()=>{this.sockets.has(e)||this.connect(e,n)});r&&(this.reconnectAttempts+=1,this.logger?.info?.({instanceId:e,url:n,attempt:r.attempt,delay:r.delay,reconnectAttempts:this.reconnectAttempts},"session-stream.connection.reconnect-scheduled")),this.retries.set(e,i)}recordAiSessionEvent(e,t){if(t.topic!==H)return;if("ai-session.message-delta"===t.type)return;const n=vi(t.payload),i=this.lastAiSessionEventByInstance.get(e);i?.streamId===n.streamId&&void 0!==i.revision&&void 0!==n.revision&&n.revision>i.revision+1&&this.logger?.warn?.({instanceId:e,traceId:n.traceId,streamId:n.streamId,previousRevision:i.revision,revision:n.revision},"ai-session.event.forward.gap"),this.lastAiSessionEventByInstance.set(e,{streamId:n.streamId??i?.streamId,revision:n.revision??i?.revision}),this.logger?.info?.({instanceId:e,traceId:n.traceId,eventType:t.type,streamId:n.streamId,revision:n.revision},"ai-session.event.forward.message")}recordAppSessionEvent(e,t){if("app.sessions"!==t.topic)return;const n=vi(t.payload),i=this.lastAppSessionEventByInstance.get(e);i?.streamId===n.streamId&&void 0!==i.revision&&void 0!==n.revision&&n.revision>i.revision+1&&this.logger?.warn?.({instanceId:e,traceId:n.traceId,streamId:n.streamId,previousRevision:i.revision,revision:n.revision},"app-session.event.forward.gap"),this.lastAppSessionEventByInstance.set(e,{streamId:n.streamId??i?.streamId,revision:n.revision??i?.revision}),this.logger?.info?.({instanceId:e,traceId:n.traceId,eventType:t.type,streamId:n.streamId,revision:n.revision},"app-session.event.forward.message")}}function zi(e){const t=jn.safeParse(Ni(e));return t.success?t.data:void 0}function Ni(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 vi(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 Si(e){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 Ei=new Set(["provisioning","starting","registering","registered","running","unhealthy"]),_i=JSON.stringify({id:"{{.ID}}",name:"{{.Name}}",cpu:"{{.CPUPerc}}",memory:"{{.MemUsage}}",memoryPercent:"{{.MemPerc}}",network:"{{.NetIO}}",blockIo:"{{.BlockIO}}",pids:"{{.PIDs}}"});class Ti{snapshots=new Map;runCommand;targets;publish;intervalMs;timer;inFlight;pendingTargets=new Map;constructor(e,t,n,i=3e3){this.runCommand=e,this.targets=t,this.publish=n,this.intervalMs=i}start(){this.collect().catch(()=>{}),this.timer=setInterval(()=>{this.collect().catch(()=>{})},this.intervalMs)}stop(){this.timer&&clearInterval(this.timer),this.timer=void 0}async snapshot(e){const t=this.targets().find(t=>t.id===e);if(t)return Ei.has(t.status)?(await this.collect([t]),this.snapshots.get(e)):Ri(t.id)}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)this.pendingTargets.set(e.id,e);this.inFlight||(this.inFlight=this.drain().finally(()=>{this.inFlight=void 0})),await this.inFlight,this.pendingTargets.size&&await this.collect([])}async drain(){for(;this.pendingTargets.size;){const e=[...this.pendingTargets.values()];this.pendingTargets.clear(),await this.collectOnce(e)}}async collectOnce(e){const t=e.filter(e=>Ei.has(e.status)&&(e.runtime.containerId||e.runtime.containerName));for(const t of e.filter(e=>Ei.has(e.status)&&!e.runtime.containerId&&!e.runtime.containerName))this.update(Di(t.id));for(const t of e.filter(e=>!Ei.has(e.status)))this.update(Ri(t.id));if(!t.length)return;const n=t.map(e=>e.runtime.containerId||e.runtime.containerName),i=(new Date).toISOString();try{const e=await this.runCommand("docker",["stats","--no-stream","--format",_i,...n],{timeoutMs:5e3});this.applyDockerOutput(t,e.stdout,i)}catch(e){if(1===t.length)return void this.update(Pi(t[0].id,i,e instanceof Error?e.message:String(e)));await Promise.all(t.map(async e=>{const t=e.runtime.containerId||e.runtime.containerName;try{const n=await this.runCommand("docker",["stats","--no-stream","--format",_i,t],{timeoutMs:5e3});this.applyDockerOutput([e],n.stdout,i)}catch(t){this.update(Pi(e.id,i,t instanceof Error?t.message:String(t)))}}))}}applyDockerOutput(e,t,n){const i=function(e,t=(new Date).toISOString()){const n=new Map;for(const i of e.split(/\r?\n/).filter(Boolean)){let e;try{e=JSON.parse(i)}catch{continue}const r=Oi(e.id),s=Oi(e.name),o=r||s;if(!o)continue;const a=ki(Oi(e.memory)),c=ki(Oi(e.network)),d=ki(Oi(e.blockIo)),l=Sn.parse({instanceId:o,runtimeKind:"docker",state:"available",sampledAt:t,cpu:xi(e.cpu,"usagePercent"),memory:a?{usageBytes:a[0],...void 0!==a[1]?{limitBytes:a[1]}:{},...xi(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:Ci(e.pids)});r&&n.set(r,l),s&&n.set(s,l)}return n}(t,n);for(const t of e){const e=[t.runtime.containerId,t.runtime.containerName].filter(Boolean),r=[...i.entries()].find(([t])=>e.some(e=>e===t||e.startsWith(t)||t.startsWith(e)))?.[1];this.update(r?{...r,instanceId:t.id}:Pi(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 ki(e){if(!e)return;const[t,n]=e.split("/").map(e=>function(e){const t=e.trim().match(/^([0-9]+(?:\.[0-9]+)?)\s*([kmgtpe]?i?b)$/i);if(!t)return;const n=Number(t[1]),i=t[2].toLowerCase(),r=i.includes("i"),s="b"===i[0]?"":i[0],o=s?"kmgtpe".indexOf(s)+1:0;return Math.round(n*(r?1024:1e3)**o)}(e||""));return void 0===t?void 0:[t,n]}function xi(e,t){const n=Number(Oi(e).replace(/%$/,""));return Number.isFinite(n)&&n>=0?{[t]:n}:void 0}function Ci(e){const t=Number(Oi(e));return Number.isFinite(t)&&t>=0?t:void 0}function Oi(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 Di(e){return{instanceId:e,runtimeKind:"docker",state:"pending",sampledAt:(new Date).toISOString()}}function Pi(e,t,n){return{instanceId:e,runtimeKind:"docker",state:"unavailable",sampledAt:t,error:n.slice(0,2048)}}function ji(e){try{return t.statSync(e).isDirectory()}catch{return!1}}function Mi(e,i){let r;try{r=t.statSync(e)}catch{return}if(!r.isDirectory())return;const s=n.resolve(e),o=n.basename(s)||s;let a=[];try{a=i>0?t.readdirSync(s,{withFileTypes:!0}):[]}catch{a=[]}const c=i>0?a.filter(e=>e.isDirectory()||e.isSymbolicLink()&&ji(n.join(s,e.name))).sort((e,t)=>e.name.localeCompare(t.name)).slice(0,80).flatMap(e=>{const t=Mi(n.join(s,e.name),i-1);return t?[t]:[]}):[];return{name:o,path:s,children:c}}function Li(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(ji)}()).flatMap(t=>{const n=Mi(t,e.depth);return n?[n]:[]})}const $i=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(),Fi=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(),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(),Vi=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:fn.optional(),source:Ut,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:Dn.shape.modelSelection}).strict(),Hi=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:Dn.shape.modelSelection.optional()}).strict(),qi=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(),Bi=qi.omit({id:!0}).partial().strict();function Ki(){return process.env.TASK_HANDOFF_NODE_AGENT_DATA_DIR||n.join(p.homedir(),".config","task-handoff","node-agent")}function Gi(e=Ki()){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 Ji(e){t.mkdirSync(e,{recursive:!0})}function Wi(e,t){Ji(n.dirname(e)),h.sync(e,`${JSON.stringify(t,null,2)}\n`,{encoding:"utf8"})}function Yi(e,t){console.warn(JSON.stringify({message:e,...t}))}function Xi(e){return e&&"object"==typeof e&&"issues"in e?{issues:e.issues}:{error:e instanceof Error?e.message:String(e)}}function Zi(e,n){const i=n.logger||Yi;let r;try{r=JSON.parse(t.readFileSync(e,"utf8"))}catch(t){return void i("stored JSON could not be read",{filePath:e,...Xi(t)})}if(!n.schema)return r;const s=n.sanitize?n.sanitize(r):r,o=n.schema.safeParse(s);if(o.success)return o.data;const a="strip"in n.schema&&"function"==typeof n.schema.strip?n.schema.strip().safeParse(s):void 0;if(a?.success)return i("unknown stored fields were ignored",{filePath:e,issues:o.error.issues}),a.data;i("stored record failed validation and was isolated",{filePath:e,issues:o.error.issues})}function Qi(e){return`${e}_${i.randomUUID().replace(/-/g,"").slice(0,20)}`}function er(){return i.randomBytes(24).toString("base64url")}class tr{directory;options;constructor(e,t={}){this.directory=e,this.options=t}init(){Ji(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=Zi(n.join(this.directory,e),this.options);return t?[t]:[]})}get(e){const n=this.filePath(e);return t.existsSync(n)?Zi(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 Wi(this.filePath(n.id),n),n}patch(e,t){const n=this.get(e);if(!n)return;const i={...n,...t,id:n.id,createdAt:n.createdAt,updatedAt:(new Date).toISOString()};return this.put(i)}delete(e){const n=this.filePath(e);return!!t.existsSync(n)&&(t.unlinkSync(n),!0)}}class nr{filePathValue;defaults;options;constructor(e,t,n={}){this.filePathValue=e,this.defaults=t,this.options=n}init(){Ji(n.dirname(this.filePathValue)),t.existsSync(this.filePathValue)||this.put(this.defaults())}get(){return this.init(),t.existsSync(this.filePathValue)?Zi(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 Wi(this.filePathValue,n),n}}function ir(e,t=process.platform){const r=n.resolve(e),s=i.createHash("sha256").update(r).digest("hex").slice(0,16);return"win32"===t?`\\\\.\\pipe\\task-handoff-node-agent-${s}`:n.join("/tmp",`task-handoff-node-agent-${process.getuid?.()??"user"}`,`${s}.sock`)}const rr="TASK_HANDOFF_NODE_AGENT_V1";function sr(e=""){return i.createHash("sha256").update(e).digest("hex")}function or(e,t){return i.createHmac("sha256",e).update(function(e){return[rr,e.keyId,e.method.toUpperCase(),e.pathWithQuery,e.timestamp,e.nonce,e.bodySha256].join("\n")}(t)).digest("hex")}function ar(e){const t=e.timestamp||(new Date).toISOString(),n=e.nonce||i.randomBytes(18).toString("base64url"),r=sr(e.body||""),s=or(e.secret,{keyId:e.keyId,method:e.method,pathWithQuery:e.pathWithQuery,timestamp:t,nonce:n,bodySha256:r});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":r,"x-taskhandoff-signature":s}}const cr=new Set(["DELETE","GET","HEAD","PATCH","POST","PUT","OPTIONS"]);function dr(e){return"string"==typeof e&&cr.has(e.toUpperCase())?e.toUpperCase():"GET"}function lr(){return(new Date).toISOString()}function ur(){return process.env.TASK_HANDOFF_NPM_COMMAND||"npm"}function mr(e){if(!e||"object"!=typeof e||Array.isArray(e))return e;const t=e,n="string"==typeof t.updatedAt?t.updatedAt:lr(),i=t.target&&"object"==typeof t.target&&!Array.isArray(t.target)?t.target:void 0,r="controlled-instance"===i?.component,s={updating:"updating-node",downloading:"updating-node",installing:"updating-node",restarting:"restarting-node",completed:"succeeded",success:"succeeded",error:"failed"},o=new Set(["queued","updating-node","restarting-node","converging-instances","succeeded","degraded","failed"]),a="string"==typeof t.status?t.status:"queued",c=r?"failed":o.has(a)?a:s[a]||"failed",d="string"==typeof t.toVersion&&t.toVersion?t.toVersion:"unknown",l=Ct.strip().safeParse(t.impact).success?Ct.strip().parse(t.impact):{runningInstanceCount:0,stoppedInstanceCount:0,activeInstanceCount:0,restartInstanceCount:0,runningInstanceIds:[],stoppedInstanceIds:[],activeInstanceIds:[]},u=r?{code:"LEGACY_INSTANCE_UPDATE_RETIRED",message:"Independent controlled-instance update jobs were retired in favor of Node reconciliation.",retryable:!1}:"failed"!==c||t.error||o.has(a)||a in s?"string"==typeof t.error?{code:"NODE_UPDATE_FAILED",message:t.error,retryable:!1}:kt.strip().safeParse(t.error).success?kt.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:r||"failed"===c?1:0,deferredInstanceCount:0},f=Ot.strip().safeParse(t.rollout);return{...g,source:"npm",status:c,impact:l,runtimeArtifacts:Array.isArray(t.runtimeArtifacts)?t.runtimeArtifacts.flatMap(e=>{const t=Tt.strip().safeParse(e);return t.success?[t.data]:[]}):[],rollout:f.success?f.data:h,...u?{error:u}:{},...r?{completedAt:t.completedAt||n}:{}}}class pr{records;constructor(e){this.records=new tr(e.updatesDir,{schema:Pt,sanitize:mr})}init(){this.records.init()}list(){return this.records.list().sort((e,t)=>t.createdAt.localeCompare(e.createdAt))}create(e,t){const n=lr();return this.records.put(Pt.parse({id:Qi("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:lr()}))}reconcileRollouts(e,t){const n=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))){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 r=i.rollout.expectedInstanceIds,s=r.map(e=>n.get(e)),o=s.filter(e=>e?.ready&&"matched"===e.runtimeVersion?.phase&&e.runtimeVersion.actualVersion===i.toVersion).length,a=s.filter(e=>e&&["created","stopped","failed"].includes(e.status||"")&&"failed"!==e.runtimeVersion?.phase).length,c=s.filter(e=>!e||"failed"===e.runtimeVersion?.phase).length,d=Math.max(0,r.length-o-c-a),l=c>0?"degraded":0===d?"succeeded":"converging-instances";this.patch(i.id,{status:l,rollout:{...i.rollout,phase:l,nodeVersion:t,expectedInstanceCount:r.length,matchedInstanceCount:o,pendingInstanceCount:d,failedInstanceCount:c,deferredInstanceCount:i.impact.stoppedInstanceCount+a},..."succeeded"===l||"degraded"===l?{completedAt:lr()}:{}})}}run(e,t){(async()=>{this.patch(e.id,{status:"updating-node",rollout:{...e.rollout,phase:"updating-node"},startedAt:lr(),error:void 0});try{await t(e),this.patch(e.id,{status:"succeeded",completedAt:lr()})}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:lr()})}})()}}const gr="runtime-manifest.json";class hr 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 fr(e,t=""){const i=[],r=await I.readdir(n.join(e,t),{withFileTypes:!0});for(const s of r){const r=t?n.posix.join(t,s.name):s.name;if(!t&&r===gr)continue;const o=n.join(e,...r.split("/"));if(s.isDirectory()){i.push(...await fr(e,r));continue}if(s.isSymbolicLink()){const t=await I.readlink(o);if(n.isAbsolute(t))throw new hr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload symlink is absolute: ${r}`);const s=n.resolve(n.dirname(o),t),a=n.relative(n.resolve(e),s);if(!a||".."===a||a.startsWith(`..${n.sep}`)||n.isAbsolute(a))throw new hr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload symlink escapes the artifact: ${r}`);if(!await I.lstat(s).catch(()=>{}))throw new hr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload symlink is broken: ${r}`);i.push({absolutePath:o,relativePath:r,kind:"symlink",target:t,size:Buffer.byteLength(t)});continue}if(!s.isFile())throw new hr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload contains unsupported entry: ${r}`);const a=await I.lstat(o);i.push({absolutePath:o,relativePath:r,kind:"file",size:a.size})}return i}async function Ir(e){const n=(await fr(e)).sort((e,t)=>function(e,t){return Buffer.compare(Buffer.from(e,"utf8"),Buffer.from(t,"utf8"))}(e.relativePath,t.relativePath)),r=i.createHash("sha256");for(const e of n){if(r.update("file"===e.kind?"F":"L","ascii"),r.update(Buffer.from(e.relativePath,"utf8")),r.update(Buffer.from([0])),r.update(Buffer.from(String(e.size),"ascii")),r.update(Buffer.from([0])),"file"===e.kind)for await(const n of t.createReadStream(e.absolutePath))r.update(n);else r.update(Buffer.from(e.target,"utf8"));r.update(Buffer.from([0]))}return r.digest("hex")}function yr(e){for(const[t,n]of[["version",e.version],["platform",e.platform],["arch",e.arch]])if(!/^[0-9A-Za-z._-]+$/.test(n))throw new hr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Invalid runtime artifact ${t}: ${n}`);return`${e.version}-${e.platform}-${e.arch}`}function Ar(e,t){return`${yr(e)}-${e.sha256}-${t}`}async function br(e){const n=i.createHash("sha256");for await(const i of t.createReadStream(e))n.update(i);return n.digest("hex")}class wr{#e;#t;#n=new Map;constructor(e){this.#e=e.cacheDir,this.#t=e.fetchImpl??fetch}resolve(e,t){const n=Tt.parse(e);if(!/^[a-f0-9]{64}$/.test(t.archiveSha256))throw new hr("INSTANCE_RUNTIME_ARTIFACT_INVALID","Runtime archive SHA-256 is invalid.");if((t.archiveUrl?1:0)+(t.archivePath?1:0)!=1)throw new hr("INSTANCE_RUNTIME_ARTIFACT_INVALID","Runtime artifact source must specify exactly one archive location.");const i=Ar(n,t.archiveSha256),r=this.#n.get(i);if(r)return r;const s=this.#i(n,t).finally(()=>this.#n.delete(i));return this.#n.set(i,s),s}async#i(e,r){if(!/^[a-f0-9]{64}$/.test(r.archiveSha256))throw new hr("INSTANCE_RUNTIME_ARTIFACT_INVALID","Runtime archive SHA-256 is invalid.");const s=Ar(e,r.archiveSha256),o=n.join(this.#e,"archives"),a=n.join(o,`${s}.tar.gz`);if(await I.mkdir(o,{recursive:!0}),await this.#r(a,e,r.archiveSha256))return{identity:e,archivePath:a,cacheHit:!0};await I.rm(a,{force:!0});const c=n.join(o,`.${s}.${i.randomUUID()}.part`);try{const n=await I.open(c,"wx");if(r.archivePath)await y.pipeline(t.createReadStream(r.archivePath),n.createWriteStream());else{const e=await this.#t(r.archiveUrl);if(!e.ok||!e.body)throw await n.close(),new hr("INSTANCE_RUNTIME_ARTIFACT_UNAVAILABLE",`Runtime artifact download failed with HTTP ${e.status}.`,{retryable:e.status>=500});await y.pipeline(e.body,n.createWriteStream())}if(await br(c)!==r.archiveSha256)throw new hr("INSTANCE_RUNTIME_ARTIFACT_INVALID","Downloaded runtime archive SHA-256 does not match release metadata.");return await this.#s(c,e),await I.rename(c,a),{identity:e,archivePath:a,cacheHit:!1}}catch(e){if(e instanceof hr)throw e;throw new hr("INSTANCE_RUNTIME_ARTIFACT_UNAVAILABLE","Could not download runtime artifact.",{cause:e,retryable:!0})}finally{await I.rm(c,{force:!0})}}async#r(e,t,n){try{return await br(e)===n&&(await this.#s(e,t),!0)}catch{return!1}}async#s(e,t){const r=n.join(this.#e,"validation",`${yr(t)}-${i.randomUUID()}`);try{await async function(e,t){await I.mkdir(t,{recursive:!0});try{await A.extract({file:e,cwd:t,strict:!0,preservePaths:!1,filter:(e,t)=>{const i=n.posix.normalize(e.replace(/^\.\//,""));if(!i||".."===i||i.startsWith("../")||n.posix.isAbsolute(i))throw new hr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime archive entry escapes the artifact root: ${e}`);const r=t.type;if("File"!==r&&"OldFile"!==r&&"Directory"!==r&&"SymbolicLink"!==r)throw new hr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime archive contains unsupported entry type ${r??"unknown"}: ${e}`);return!0}})}catch(e){throw new hr("INSTANCE_RUNTIME_ARTIFACT_INVALID","Could not extract runtime artifact safely.",{cause:e})}}(e,r),await async function(e,t,i){const r=await async function(e){let t;try{t=JSON.parse(await I.readFile(n.join(e,gr),"utf8"))}catch(e){throw new hr("INSTANCE_RUNTIME_ARTIFACT_INVALID","Runtime artifact manifest is missing or invalid JSON.",{cause:e})}const i=Tt.safeParse(t);if(!i.success)throw new hr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime artifact manifest is invalid: ${i.error.message}`);return i.data}(e);if(function(e,t){for(const n of["packageName","version","platform","arch","formatVersion","launcherAbi","entrypoint","sha256"])if(e[n]!==t[n])throw new hr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime artifact ${"sha256"===n?"SHA-256":n} mismatch: expected ${t[n]}, got ${e[n]}.`)}(r,t),1!==r.formatVersion)throw new hr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Unsupported runtime artifact format ${r.formatVersion}.`);if(i?.platform&&"universal"!==r.platform&&r.platform!==i.platform)throw new hr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime artifact platform ${r.platform} does not match ${i.platform}.`);if(i?.arch&&"universal"!==r.arch&&r.arch!==i.arch)throw new hr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime artifact architecture ${r.arch} does not match ${i.arch}.`);if(void 0!==i?.launcherAbi&&r.launcherAbi>i.launcherAbi)throw new hr("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Runtime requires launcher ABI ${r.launcherAbi}, but the base runtime provides ${i.launcherAbi}.`);const s=function(e,t){if(!e||e.includes("\\")||n.posix.isAbsolute(e))throw new hr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`${t} must be a non-empty POSIX relative path.`);const i=n.posix.normalize(e);if("."===i||".."===i||i.startsWith("../"))throw new hr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`${t} escapes the runtime root.`);return i}(r.entrypoint,"Runtime entrypoint"),o=await I.lstat(n.join(e,...s.split("/"))).catch(()=>{});if(!o?.isFile())throw new hr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime entrypoint is missing: ${s}`);const a=await Ir(e);if(a!==r.sha256)throw new hr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload SHA-256 mismatch: expected ${r.sha256}, got ${a}.`);return r}(r,t,{platform:t.platform,arch:t.arch})}finally{await I.rm(r,{recursive:!0,force:!0})}}}async function zr(e,t,i,r=fetch){if("linux"!==t||!["x64","arm64"].includes(i))throw new hr("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Managed controlled-instance updates require a Linux x64 or arm64 target, received ${t}/${i}.`);const s=await async function(e){const t=`controlled-instance-runtime-${e}-linux-universal`,i=function(){const e=process.env.TASK_HANDOFF_BUNDLED_RUNTIME_DIR?.trim();return n.resolve(e||n.join(n.dirname(process.argv[1]||process.cwd()),"..","runtime-artifacts"))}();try{const[r,s]=await Promise.all([I.readFile(n.join(i,`${t}.manifest.json`),"utf8"),I.readFile(n.join(i,`${t}.tar.gz.sha256`),"utf8")]),o=Tt.safeParse(JSON.parse(r));if(!o.success||o.data.version!==e||"linux"!==o.data.platform||"universal"!==o.data.arch)throw new hr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Bundled controlled-instance ${e} has an invalid Linux manifest.`);const a=s.trim().split(/\s+/)[0]?.toLowerCase();if(!a||!/^[a-f0-9]{64}$/.test(a))throw new hr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Bundled controlled-instance ${e} has an invalid archive checksum.`);return{identity:o.data,source:{archivePath:n.join(i,`${t}.tar.gz`),archiveSha256:a}}}catch(t){if("ENOENT"===t.code)return;if(t instanceof hr)throw t;throw new hr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Could not read bundled controlled-instance ${e}.`,{cause:t})}}(e);if(s)return s;const o=`controlled-instance-runtime-${e}-linux-universal`,a=function(e){const t=process.env.TASK_HANDOFF_RUNTIME_RELEASE_BASE_URL?.trim();return t?t.replaceAll("{version}",e).replace(/\/$/,""):`https://github.com/edgestorage/task-handoff/releases/download/v${e}`}(e),c=`${a}/${o}.manifest.json`,d=`${a}/${o}.tar.gz`,l=`${a}/${o}.tar.gz.sha256`,[u,m]=await Promise.all([r(c),r(l)]).catch(t=>{throw new hr("INSTANCE_RUNTIME_ARTIFACT_UNAVAILABLE",`Could not read release metadata for controlled-instance ${e}.`,{cause:t,retryable:!0})});if(!u.ok||!m.ok)throw new hr("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 hr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Release manifest for controlled-instance ${e} is not valid JSON.`,{cause:t})}const g=Tt.safeParse(p);if(!g.success)throw new hr("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 hr("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 hr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Release checksum for controlled-instance ${e} is invalid.`);return{identity:g.data,source:{archiveUrl:d,archiveSha256:h}}}class Nr{store;desiredVersion;hooks;inFlight=new Map;requests=new Map;cancelled=new Set;now;delay;drainTimeoutMs;verificationTimeoutMs;pollIntervalMs;maxAttempts;retryBaseDelayMs;retryMaxDelayMs;constructor(e,t,n,i={}){this.store=e,this.desiredVersion=t,this.hooks=n,this.now=i.now||(()=>new Date),this.delay=i.delay||(e=>new Promise(t=>setTimeout(t,e))),this.drainTimeoutMs=i.drainTimeoutMs??3e5,this.verificationTimeoutMs=i.verificationTimeoutMs??6e4,this.pollIntervalMs=i.pollIntervalMs??250,this.maxAttempts=function(e){if(!Number.isInteger(e)||e<=0)throw new TypeError("maxAttempts must be a positive integer.");return e}(i.maxAttempts??3),this.retryBaseDelayMs=Cr(i.retryBaseDelayMs??1e3,"retryBaseDelayMs"),this.retryMaxDelayMs=Cr(i.retryMaxDelayMs??3e4,"retryMaxDelayMs")}schedule(e,t={}){const n=this.requests.get(e)||{startRequested:!1,resumeCancelled:!1};n.startRequested||=!0===t.startRequested,n.resumeCancelled||=!0===t.resumeCancelled||!0===t.startRequested,n.resumeCancelled&&this.cancelled.delete(e),this.requests.set(e,n);const i=this.inFlight.get(e);if(i)return i;const r=Promise.resolve().then(()=>this.reconcile(e,n)).finally(()=>{this.inFlight.delete(e),this.requests.delete(e)});return this.inFlight.set(e,r),r}isRunning(e){return this.inFlight.has(e)}cancel(e){return this.cancelled.add(e),this.inFlight.get(e)}async reconcile(e,t){let n=this.requireInstance(e);const i=this.desiredVersion();if(this.cancelled.has(e)&&!t.resumeCancelled)return this.storePhase(n,"pending");const r=vr(n),s=r===i&&(await(this.hooks.isInstalled?.(n,i))??!0);if(this.cancelled.has(e))return this.storePhase(this.requireInstance(e),"pending");if(r===i&&s)return this.storeState(n,{desiredVersion:i,actualVersion:r,phase:"matched",attempt:n.runtimeVersion?.attempt||0,matchedAt:this.timestamp()},!Er(n)&&"failed"!==n.health);if(n.runtimeVersion?.desiredVersion===i&&(n.runtimeVersion?.attempt||0)>=this.maxAttempts)return"failed"===n.runtimeVersion?.phase&&n.runtimeVersion.error?n:this.storePermanentFailure(n,i,xr(i,r,this.maxAttempts,n.runtimeVersion?.error));if(n=this.storeState(n,function(e,t,n,i=!1){const r=e.runtimeVersion;return{desiredVersion:t,...n?{actualVersion:n}:{},phase:"pending",attempt:r?.desiredVersion===t&&"matched"!==r.phase?r.attempt:0,error:n!==t||i?_r(t,n):Tr("INSTANCE_RUNTIME_VERIFICATION_FAILED",`Controlled-instance ${t} is running, but the active runtime artifact does not match the desired release identity.`,t,n,!0)}}(n,i,r,s),!1),Er(n)&&!t.startRequested)return n;for(;(n.runtimeVersion?.attempt||0)<this.maxAttempts;){if(this.cancelled.has(e))return this.storePhase(this.requireInstance(e),"pending");let r,s=!1;try{if(Sr(n)){n=this.storePhase(n,"draining");const t=await this.waitUntil(e,this.drainTimeoutMs,e=>!Sr(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,i),s=!0,this.cancelled.has(e)||Er(this.requireInstance(e))&&!t.startRequested)return this.storePhase(this.requireInstance(e),"pending");if(n=this.storePhase(this.requireInstance(e),"restarting"),await this.hooks.restart(n),this.cancelled.has(e))return this.storePhase(this.requireInstance(e),"pending");n=this.storePhase(this.requireInstance(e),"verifying");const r=await this.waitUntil(e,this.verificationTimeoutMs,e=>vr(e)===i);if(this.cancelled.has(e))return this.storePhase(this.requireInstance(e),"pending");if(!r)throw Tr("INSTANCE_RUNTIME_VERIFICATION_FAILED",`Instance ${e} did not register controlled-instance ${i} after restart.`,i,vr(this.requireInstance(e)),!0);const o=this.requireInstance(e);if(this.hooks.isInstalled&&!await this.hooks.isInstalled(o,i))throw Tr("INSTANCE_RUNTIME_VERIFICATION_FAILED",`Instance ${e} reported controlled-instance ${i}, but its active runtime release is missing.`,i,vr(o),!0);return this.storeState(o,{desiredVersion:i,actualVersion:i,phase:"matched",attempt:o.runtimeVersion?.attempt||1,matchedAt:this.timestamp()},!Er(o)&&"failed"!==o.health)}catch(t){if(this.cancelled.has(e))return this.storePhase(this.requireInstance(e),"pending");if(r=kr(t,i,vr(this.store.get(e))),s&&this.hooks.rollback)try{await this.hooks.rollback(this.requireInstance(e))}catch(e){r.message=`${r.message} Rollback failed: ${e instanceof Error?e.message:String(e)}`,r.retryable=!1}}n=this.requireInstance(e);const o=n.runtimeVersion?.attempt||1;if(!r.retryable||o>=this.maxAttempts)return this.storePermanentFailure(n,i,o>=this.maxAttempts&&r.retryable?xr(i,vr(n),this.maxAttempts,r):r);n=this.storeState(n,{desiredVersion:i,...vr(n)?{actualVersion:vr(n)}:{},phase:"pending",attempt:o,lastAttemptAt:this.timestamp(),error:r},!1),await this.delay(this.retryDelayMs(o))}return this.storePermanentFailure(n,i,xr(i,vr(n),this.maxAttempts,n.runtimeVersion?.error))}storePermanentFailure(e,t,n){const i=vr(e);return this.storeState(e,{desiredVersion:t,...i?{actualVersion:i}:{},phase:"failed",attempt:e.runtimeVersion?.attempt||0,lastAttemptAt:this.timestamp(),error:{...n,retryable:!1}},!1)}retryDelayMs(e){return Math.min(this.retryMaxDelayMs,this.retryBaseDelayMs*2**Math.max(0,e-1))}storePhase(e,t,n=!1){const i=this.desiredVersion(),r=vr(e);return this.storeState(e,{desiredVersion:i,...r?{actualVersion:r}:{},phase:t,attempt:(e.runtimeVersion?.attempt||0)+(n?1:0),lastAttemptAt:this.timestamp(),..."pending"===t?{error:_r(i,r)}:{}},!1)}storeState(e,t,n){const i=this.store.get(e.id)||e;return this.store.put(Dn.parse({...i,runtimeVersion:t,ready:n,...n?{}:{health:"failed"===i.health?"failed":"degraded"},updatedAt:this.timestamp()}))}async waitUntil(e,t,n){const i=this.now().getTime()+t;for(;;){const t=this.store.get(e);if(t&&n(t))return!0;if(this.cancelled.has(e))return!1;if(this.now().getTime()>=i)return!1;await this.delay(Math.min(this.pollIntervalMs,Math.max(0,i-this.now().getTime())))}}requireInstance(e){const t=this.store.get(e);if(!t)throw new Error(`Instance ${e} was removed during runtime reconciliation.`);return t}timestamp(){return this.now().toISOString()}}function vr(e){return e?.build?.packageVersion||e?.instanceVersion}function Sr(e){return e.apps.runningCount>0||e.aiSessions.runningCount>0}function Er(e){return["created","stopped","failed"].includes(e.status)}function _r(e,t){return Tr("INSTANCE_RUNTIME_VERSION_MISMATCH",`Expected controlled-instance ${e}, received ${t||"an unknown version"}.`,e,t,!0)}function Tr(e,t,n,i,r){return{code:e,message:t,expectedVersion:n,...i?{actualVersion:i}:{},retryable:r}}function kr(e,t,n){if(e&&"object"==typeof e&&"code"in e&&"message"in e){const i=e;return Tr(i.code,i.message,t,n,i.retryable??!0)}return Tr("INSTANCE_RUNTIME_INSTALL_FAILED",e instanceof Error?e.message:String(e),t,n,!0)}function xr(e,t,n,i){const r=i?.message?` Last error: ${i.message}`:"";return Tr(i?.code||"INSTANCE_RUNTIME_INSTALL_FAILED",`Runtime convergence exhausted ${n} attempts.${r}`,e,t,!1)}function Cr(e,t){if(!Number.isFinite(e)||e<0)throw new TypeError(`${t} must be a nonnegative finite number.`);return e}const Or=m.z.record(m.z.string(),m.z.string()),Rr=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 Dr{directory;constructor(e){this.directory=e}get(e){try{return Or.parse(JSON.parse(t.readFileSync(this.filePath(e),"utf8")))}catch(t){if(t&&"object"==typeof t&&"code"in t&&"ENOENT"===t.code)return{};throw new Error(`Stored model environment for instance ${e} is invalid: ${t instanceof Error?t.message:String(t)}`)}}has(e){return t.existsSync(this.filePath(e))}listInstanceIds(){return t.existsSync(this.directory)?t.readdirSync(this.directory).filter(e=>e.endsWith(".json")).map(e=>e.slice(0,-5)).sort():[]}put(e,n){const i=Or.parse(n);t.mkdirSync(this.directory,{recursive:!0,mode:448});const r=this.filePath(e);return h.sync(r,`${JSON.stringify(i,null,2)}\n`,{encoding:"utf8",mode:384}),t.chmodSync(r,384),i}delete(e){t.rmSync(this.filePath(e),{force:!0})}filePath(e){return n.join(this.directory,`${e}.json`)}}class Pr{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=Kt.parse(e);this.init();const i=this.filePath(n.id);return h.sync(i,`${JSON.stringify(n,null,2)}\n`,{encoding:"utf8",mode:384}),t.chmodSync(i,384),n}delete(e){const n=this.filePath(e);return!!t.existsSync(n)&&(t.unlinkSync(n),!0)}read(e){try{const i=JSON.parse(t.readFileSync(e,"utf8")),r=n.basename(e,".json"),s=Kt.safeParse(i);if(s.success&&s.data.id===r&&rn(s.data)===s.data.id)return s.data;const o=Kt.strip().safeParse(i);return o.success&&o.data.id===r&&rn(o.data)===o.data.id?(console.warn(JSON.stringify({message:"unknown stored node model fields were ignored",nodeId:this.nodeId,filePath:e})),o.data):void console.warn(JSON.stringify({message:"stored node model failed validation and was isolated",nodeId:this.nodeId,filePath:e}))}catch(t){return void console.warn(JSON.stringify({message:"stored node model could not be read",nodeId:this.nodeId,filePath:e,error:t instanceof Error?t.message:String(t)}))}}filePath(e){return n.join(this.directory,`${e}.json`)}}class jr{directory;constructor(e){this.directory=e}init(){t.mkdirSync(this.directory,{recursive:!0,mode:448}),t.chmodSync(this.directory,448)}get(e){const n=this.filePath(e);if(t.existsSync(n))try{const i=JSON.parse(t.readFileSync(n,"utf8")),r=Wt.safeParse(i);if(r.success)return r.data;const s=Wt.strip().safeParse(i);if(s.success)return console.warn(JSON.stringify({message:"unknown stored model assignment fields were ignored",instanceId:e,filePath:n})),s.data;throw r.error}catch(t){throw Object.assign(new Error(`Stored model assignment for instance ${e} is invalid.`),{statusCode:409,code:"NODE_MODEL_ASSIGNMENT_INVALID",cause:t})}}put(e){const n=Wt.parse(e);this.init();const i=this.filePath(n.instanceId);return h.sync(i,`${JSON.stringify(n,null,2)}\n`,{encoding:"utf8",mode:384}),t.chmodSync(i,384),n}delete(e){t.rmSync(this.filePath(e),{force:!0})}filePath(e){return n.join(this.directory,`${e}.json`)}}class Mr{usedNonces=new Map;identity;nodeId;overrideSecret;overrideKeyId;nowMs;constructor(e,t,n,i,r=Date.now){this.identity=e,this.nodeId=t,this.overrideSecret=n,this.overrideKeyId=i,this.nowMs=r}hasRemoteSecrets(){return this.identity.remoteSecrets(this.overrideSecret,this.overrideKeyId).length>0}verify(e){const t=function(e){const t=new Map;for(const[n,i]of Object.entries(e)){const e=Array.isArray(i)?i.join(","):"string"==typeof i?i:void 0===i?"":String(i);t.set(n.toLowerCase(),e)}return{nodeId:t.get("x-taskhandoff-node-id")||"",keyId:t.get("x-taskhandoff-key-id")||"",timestamp:t.get("x-taskhandoff-timestamp")||"",nonce:t.get("x-taskhandoff-nonce")||"",bodySha256:t.get("x-taskhandoff-body-sha256")||"",signature:t.get("x-taskhandoff-signature")||""}}(e.headers);if(!t.nodeId&&!t.signature)return!1;const n=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 r=n.filter(e=>t.keyId===e.keyId);if(!r.length)throw Object.assign(new Error("Invalid node agent HMAC key id."),{statusCode:401,code:"NODE_AGENT_HMAC_KEY_INVALID"});const s=Date.parse(t.timestamp);if(!Number.isFinite(s)||Math.abs(this.nowMs()-s)>6e4)throw Object.assign(new Error("Node agent HMAC timestamp is outside the allowed window."),{statusCode:401,code:"NODE_AGENT_HMAC_TIMESTAMP_INVALID"});if(!t.nonce)throw Object.assign(new Error("Node agent HMAC nonce is missing."),{statusCode:401,code:"NODE_AGENT_HMAC_NONCE_MISSING"});this.pruneNonces();const o=`${t.nodeId}:${t.keyId}:${t.nonce}`;if(this.usedNonces.has(o))throw Object.assign(new Error("Node agent HMAC nonce was already used."),{statusCode:401,code:"NODE_AGENT_HMAC_NONCE_REPLAY"});const a=sr(null==(c=e.body)?"":"string"==typeof c||Buffer.isBuffer(c)?c:JSON.stringify(c));var c;if(t.bodySha256!==a)throw Object.assign(new Error("Node agent HMAC body hash mismatch."),{statusCode:401,code:"NODE_AGENT_HMAC_BODY_HASH_INVALID"});if(!r.some(n=>function(e,t){const n=Buffer.from(e,"hex"),r=Buffer.from(t,"hex");return n.length===r.length&&i.timingSafeEqual(n,r)}(t.signature,or(n.secret,{keyId:t.keyId,method:e.method,pathWithQuery:e.url,timestamp:t.timestamp,nonce:t.nonce,bodySha256:a}))))throw Object.assign(new Error("Invalid node agent HMAC signature."),{statusCode:401,code:"NODE_AGENT_HMAC_SIGNATURE_INVALID"});return this.usedNonces.set(o,s+6e4+1),t.keyId}pruneNonces(){const e=this.nowMs();for(const[t,n]of this.usedNonces)n<=e&&this.usedNonces.delete(t)}}const Lr=m.z.string().trim().min(1).max(160),$r=m.z.string().datetime(),Fr=m.z.string().min(1).max(4096),Ur=m.z.string().trim().url().max(2048),Vr=m.z.object({tokenHash:m.z.string().trim().min(1).max(256),expiresAt:$r,createdAt:$r,controlPlaneName:m.z.string().trim().min(1).max(160).optional(),controlPlaneUrl:Ur.optional()}).strip(),Hr=m.z.object({id:Lr,keyId:Lr,name:m.z.string().trim().min(1).max(160).optional(),url:Ur.optional(),secret:Fr,pairedAt:$r,updatedAt:$r,active:m.z.boolean().default(!0)}).strip(),qr=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(),Br=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(),Kr=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 Gr(){return(new Date).toISOString()}const Jr=new Set(["nodeId","createdAt","updatedAt","pairingInvites","remoteControlPlanes"]),Wr=new Set(["tokenHash","expiresAt","createdAt","controlPlaneName","controlPlaneUrl"]),Yr=new Set(["id","keyId","name","url","secret","pairedAt","updatedAt","active"]);function Xr(e,t){console.warn(JSON.stringify({message:e,...t}))}function Zr(e,t){return Object.assign(new Error(e,void 0===t?void 0:{cause:t}),{code:"NODE_AGENT_IDENTITY_INVALID"})}function Qr(e,t){return Object.keys(e).filter(e=>!t.has(e))}function es(e,t,n){const i=$r.safeParse(e);return i.success?i.data:(n("invalid node agent identity timestamp was replaced",{field:t}),Gr())}function ts(e,t){if(!e||"object"!=typeof e||Array.isArray(e))throw Zr("Node agent identity must be a JSON object.");const n=e,i=Lr.safeParse(n.nodeId);if(!i.success)throw Zr("Node agent identity has an invalid nodeId.",i.error);const r=i.data,s=Qr(n,Jr);return s.length&&t("unknown node agent identity fields were ignored",{fields:s}),{nodeId:r,createdAt:es(n.createdAt,"createdAt",t),updatedAt:es(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=Qr(e,Wr);n.length&&t("unknown node agent pairing invite fields were ignored",{fields:n});const i=Vr.safeParse(e);return i.success?[i.data]:(t("invalid node agent pairing invite was ignored",{issues:i.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=Qr(e,Yr);n.length&&t("unknown node agent remote control-plane fields were ignored",{fields:n});const i=Hr.safeParse(e);return i.success?[i.data]:(t("invalid node agent remote control-plane was ignored",{issues:i.error.issues}),[])}):[]}}class ns{paths;logger;constructor(e,t={}){this.paths=e,this.logger=t.logger||Xr}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 Zr(`Node agent identity contains invalid JSON: ${this.paths.identityPath}`,e)}return ts(n,this.logger)}write(e){t.mkdirSync(n.dirname(this.paths.identityPath),{recursive:!0});const i=ts({...e,updatedAt:Gr()},this.logger);h.sync(this.paths.identityPath,`${JSON.stringify(i,null,2)}\n`,{encoding:"utf8",mode:384})}}function is(){return(new Date).toISOString()}class rs{store;constructor(e){this.store=new ns(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=Qi("node");return this.writeNodeId(n),n}createPairingInvite(e){const t=this.prunePairingInvites(this.store.read()||this.newIdentity()),n=is(),i=new Date(Date.now()+(e.expiresInMs||6e5)).toISOString(),r=er(),s={tokenHash:sr(r),createdAt:n,expiresAt:i,...e.controlPlaneName?{controlPlaneName:e.controlPlaneName}:{},...e.controlPlaneUrl?{controlPlaneUrl:e.controlPlaneUrl}:{}};return this.store.write({...t,pairingInvites:[...t.pairingInvites||[],s]}),{...s,token:r}}completePairingInvite(e){const t=this.prunePairingInvites(this.store.read()||this.newIdentity()),n=sr(e.joinToken),i=(t.pairingInvites||[]).find(e=>e.tokenHash===n);if(!i){const e=new Error("Node agent pairing invite is invalid or expired.");throw Object.assign(e,{statusCode:401,code:"NODE_AGENT_PAIRING_INVITE_INVALID"}),e}const r=is(),s={id:e.controlPlaneId||Qi("cp"),keyId:Qi("key"),...e.controlPlaneName||i.controlPlaneName?{name:e.controlPlaneName||i.controlPlaneName}:{},...e.controlPlaneUrl||i.controlPlaneUrl?{url:e.controlPlaneUrl||i.controlPlaneUrl}:{},secret:er(),pairedAt:r,updatedAt:r,active:!0};return this.store.write({...t,pairingInvites:(t.pairingInvites||[]).filter(e=>e.tokenHash!==n),remoteControlPlanes:[...(t.remoteControlPlanes||[]).filter(e=>e.id!==s.id),s]}),s}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=is();return{id:Qi("cp"),keyId:Qi("key"),...e.name?{name:e.name}:{},url:e.url,secret:er(),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 i=(n.remoteControlPlanes||[]).filter(t=>t.keyId!==e);return i.length!==(n.remoteControlPlanes||[]).length&&(this.store.write({...n,remoteControlPlanes:i}),!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 i=this.store.read()?.remoteControlPlanes||[];if(!i.length)return;if(e){const t=e.replace(/\/$/,""),n=i.find(e=>e.url?.replace(/\/$/,"")===t);if(n)return{keyId:n.keyId,secret:n.secret}}const r=[...i].sort((e,t)=>t.updatedAt.localeCompare(e.updatedAt))[0];return r?{keyId:r.keyId,secret:r.secret}:void 0}newIdentity(){return{nodeId:this.resolveNodeId(),createdAt:is(),updatedAt:is(),pairingInvites:[],remoteControlPlanes:[]}}writeNodeId(e){const t=this.store.read();this.store.write({...t||{createdAt:is()},nodeId:e,updatedAt:is(),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 ss=new Set(["content-encoding","content-length","transfer-encoding"]),os=["codex","claude"],as=5e3,cs="runtime_local_host",ds="task-handoff.node-agent.builtin",ls=new Set(["linux","darwin","win32","freebsd","openbsd","aix","sunos"]);function us(e){return ls.has(e)?e:"unknown"}function ms(e){const t={...e};return delete t[ds],t}const ps=m.z.object({version:m.z.literal(1),externalListener:En}).strict(),gs=m.z.object({}).strict().default({}),hs=jt.strict();function fs(e){const t=process.env[e]?.trim();return t||void 0}const Is=function(e,t=process.env,n=e){let i;return()=>{const r=t.TASK_HANDOFF_VERSION?.trim();return r||(i||=z(e,t,n),i)}}("@task-handoff/node-agent",process.env,"@task-handoff/control-plane");function ys(e){const t=Is();return e===t?{desiredVersion:t,actualVersion:e,phase:"matched",attempt:0,matchedAt:_s()}:{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 As(e,t,n=!0){if(!n)return ys(t);const i=Is(),r=e.runtimeVersion;return r&&r.desiredVersion===i?xt.parse({...r,desiredVersion:i,...t?{actualVersion:t}:{actualVersion:void 0},..."pending"===r.phase&&t!==i?{error:{code:"INSTANCE_RUNTIME_VERSION_MISMATCH",message:`Expected controlled-instance ${i}, received ${t||"an unknown version"}.`,expectedVersion:i,...t?{actualVersion:t}:{},retryable:!0}}:"pending"===r.phase?{error:void 0}:{}}):ys(t)}function bs(e){return Object.fromEntries([...e.entries()].filter(([e])=>!ss.has(e.toLowerCase())))}function ws(e){return e.bodyBase64?Buffer.from(e.bodyBase64,"base64"):e.body}const zs=67108864;function Ns(){const e=Number(process.env.TASK_HANDOFF_INSTANCE_PROXY_MAX_RESPONSE_BYTES);return Number.isSafeInteger(e)&&e>0?e:67108864}function vs(e){const t=e.authorization;return"string"==typeof t&&t.startsWith("Bearer ")?t.slice(7).trim():void 0}function Ss(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 Es(e){return!e.ip&&!e.socket.remoteAddress&&!e.socket.remoteFamily}function _s(){return(new Date).toISOString()}function Ts(e){return"all-ipv4"===e?"0.0.0.0":"127.0.0.1"}function ks(e){if(!e||"object"!=typeof e||Array.isArray(e))return e;const t=e,n=t.externalListener&&"object"==typeof t.externalListener&&!Array.isArray(t.externalListener)?t.externalListener:{},i=Object.keys(t).filter(e=>"version"!==e&&"externalListener"!==e),r=Object.keys(n).filter(e=>"bindScope"!==e&&"port"!==e);return(i.length||r.length)&&console.warn(JSON.stringify({message:"unknown stored node agent runtime setting fields were ignored",filePath:"runtime-settings.json",fields:[...i,...r.map(e=>`externalListener.${e}`)]})),{version:t.version,externalListener:{bindScope:n.bindScope,port:n.port}}}function xs(e){return"local-folder"===e.type?Vt.parse({mode:"local-bind",path:"/workspace",readOnly:!1}):Vt.parse({mode:"git-clone",path:"/workspace",readOnly:!1})}function Cs(e){const t=Ut.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 qt.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:xs(t),labels:{},createdAt:e.createdAt,updatedAt:e.updatedAt})}async function Os(e,t){if(!t.target.web)return"unknown";const n=new AbortController,i=setTimeout(()=>n.abort(),2e3);try{return(await e(`${js(t)}/api/health`,{signal:n.signal})).ok?"reachable":"endpoint-unreachable"}catch{return"endpoint-unreachable"}finally{clearTimeout(i)}}async function Rs(e,t,n,i){const r=new AbortController,s=setTimeout(()=>r.abort(),i);try{return await e(t,{...n,signal:r.signal})}finally{clearTimeout(s)}}async function Ds(e,t,n,i){if(!t.config.autoImportAgentConfigs)return void i.diagnostic({instanceId:t.id,action:n},"node instance config auto-import skipped");if("reachable"!==t.targetStatus)return;const r=js(t),s=Number(process.env.TASK_HANDOFF_CONFIG_AUTO_IMPORT_TIMEOUT_MS||as);for(const o of os)try{const a=await Rs(e,`${r}/api/config-sync/import/${encodeURIComponent(o)}`,{method:"POST"},Number.isFinite(s)&&s>0?s:as);if(!a.ok){i.warn({instanceId:t.id,action:n,preset:o,statusCode:a.status},"node instance config auto-import failed");continue}i.diagnostic({instanceId:t.id,action:n,preset:o},"node instance config auto-import completed")}catch(e){i.warn({instanceId:t.id,action:n,preset:o,error:e instanceof Error?e.message:String(e)},"node instance config auto-import failed")}}async function Ps(e,t,n){const i=t.requireInstance(n);if("reachable"!==i.targetStatus||!i.target.web)return!1;const r=await Rs(e,`${js(i)}/api/internal/model-environment`,{method:"PUT",headers:{"content-type":"application/json",authorization:`Bearer ${i.registrationToken}`},body:JSON.stringify(t.resolvedAssignedModelEnvironment(n))},as);if(!r.ok)throw Object.assign(new Error(`Instance ${n} rejected its managed model environment with HTTP ${r.status}.`),{statusCode:502,code:"INSTANCE_MODEL_ENVIRONMENT_APPLY_FAILED"});return!0}function js(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 Ms(e,t){const n=new Error(t);throw Object.assign(n,{statusCode:403,code:e}),n}function Ls(e,t){e!==Ue&&console.warn(JSON.stringify({message:"protocol version mismatch",peer:t,expectedProtocolVersion:Ue,actualProtocolVersion:e||"missing",errorCode:"PROTOCOL_VERSION_MISMATCH"}))}function $s(e){return"none"!==e.capabilities.artifactKind}function Fs(e={}){return{...e,requiresImage:!1,supportsControlledInstanceApi:!0,supportsContainerLifecycle:!1,supportsAppSessions:!0,supportsHostSessions:!0,artifactKind:"none",isolation:"none"}}function Us(e){return new Promise(t=>{const n=s.createServer();n.once("error",()=>t(!1)),n.listen({host:"127.0.0.1",port:e},()=>{n.close(()=>t(!0))})})}function Vs(e,t=3e3){return null!==e.exitCode||null!==e.signalCode?Promise.resolve():new Promise(n=>{const i=setTimeout(()=>{null===e.exitCode&&null===e.signalCode&&e.kill("SIGKILL"),n()},t);i.unref(),e.once("exit",()=>{clearTimeout(i),n()})})}const Hs="task-handoff.local-process-nonce",qs=1e3;function Bs(e){return e.runtime.port?`http://127.0.0.1:${e.runtime.port}`:e.target.web}async function Ks(e,t){try{const n=await fetch(`${e}/api/internal/node-agent/process-identity`,{headers:{authorization:`Bearer ${t}`},signal:AbortSignal.timeout(qs)});if(!n.ok)return;const i=(await n.json()).data;if("string"!=typeof i?.instanceId||"number"!=typeof i.pid||"string"!=typeof i.processNonce)return;return{instanceId:i.instanceId,pid:i.pid,processNonce:i.processNonce,startIdentity:"string"==typeof i.startIdentity?i.startIdentity:void 0}}catch{return}}async function Gs(e,t){if(T(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 i=Date.now()+1e3;for(;Date.now()<i;){try{process.kill(e,0)}catch{return!0}await new Promise(e=>setTimeout(e,50))}return!1}function Js(e,t){return Object.assign(new Error(t),{statusCode:503,code:"LOCAL_INSTANCE_STOP_UNCONFIRMED",instanceId:e.id})}async function Ws(e,t,i){const r=t.get(e.id);if(r&&!r.killed)return r.kill("SIGTERM"),t.delete(e.id),void await Vs(r);const s=await async function(e){const t=Bs(e),n=e.runtime.labels?.[Hs];if(!t||!n||!e.registrationToken)return;const i=await Ks(t,e.registrationToken);if(i&&i.instanceId===e.id&&i.processNonce===n)try{return(await fetch(`${t}/api/internal/node-agent/shutdown`,{method:"POST",headers:{authorization:`Bearer ${e.registrationToken}`},signal:AbortSignal.timeout(qs)})).ok?i:void 0}catch{return}}(e);if(s){const t=Bs(e),n=Date.now()+3e3;for(;t&&Date.now()<n;){if(!await Ks(t,e.registrationToken))return;await new Promise(e=>setTimeout(e,50))}const i=t?await Ks(t,e.registrationToken):void 0;if(i&&i.instanceId===s.instanceId&&i.pid===s.pid&&i.processNonce===s.processNonce&&i.startIdentity===s.startIdentity&&i.startIdentity&&await Gs(i.pid,i.startIdentity))return;throw Js(e,`Controlled instance ${e.id} accepted shutdown but its exit could not be confirmed.`)}const o=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 k(e)}(i),a=await async function(e){const t=Bs(e);if(t)try{const[n,i]=await Promise.all([fetch(`${t}/api/instance/status`,{signal:AbortSignal.timeout(qs)}),fetch(`${t}/api/diagnostics`,{signal:AbortSignal.timeout(qs)})]);if(!n.ok||!i.ok)return;const r=await n.json(),s=await i.json(),o=s.data?.runtime?.pid;if(r.data?.id!==e.id||"controlled"!==r.data.controlMode||"number"!=typeof o||!Number.isInteger(o)||o<=0)return;const a=T(o);return a?{pid:o,startIdentity:a}:void 0}catch{return}}(e);if(a){if(await Gs(a.pid,a.startIdentity))return;throw Js(e,`Legacy controlled instance ${e.id} did not exit after termination.`)}if(o?.instanceId===e.id)throw Js(e,`Local controlled instance ${e.id} is still owned by pid ${o.pid}, but its process identity could not be verified.`)}const Ys=new Set(["provisioning","starting","registering","registered","running"]);async function Xs(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 Zs(e){return!0===e.managedArtifacts}class Qs{managedArtifacts=!0;executor;platform;arch;runCommand;constructor(e,t,n,i){this.executor=e,this.runCommand=t,this.platform=n,this.arch=i}artifactTarget(e){return this.executor.inspectRuntimeTarget(e?.instance.runtime.containerName)}async installRuntime(e,t){const n=e.instance.runtime.containerName;if(!n)throw Object.assign(new Error(`Instance ${e.instance.id} does not have a Docker container.`),{code:"INSTANCE_RUNTIME_INSTALL_FAILED"});await this.executor.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)}async rollbackRuntime(e,t){const n=e.instance.runtime.containerName;n&&await this.executor.rollbackRuntime(n)}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:us(this.platform),...t?{serverVersion:t}:{}}}}}catch(t){return{status:"offline",capabilities:{...e.capabilities,daemon:{status:"offline",hostPlatform:us(this.platform),error:t instanceof Error?t.message:String(t)}}}}}}class eo{runCommand;paths;nodeAgentUrl;processByInstanceId=new Map;commandOverride;lockPath;constructor(e,t,n,i,r){this.runCommand=e,this.paths=t,this.nodeAgentUrl=n,this.commandOverride=i,this.lockPath=r}async start(e){const r=function(e){if("local-folder"!==e.source.type){const e=new Error("Localhost runtime currently supports local folder sources only.");throw Object.assign(e,{statusCode:400,code:"LOCAL_RUNTIME_REQUIRES_LOCAL_FOLDER"}),e}return n.resolve(e.source.path)}(e.instance),s=e.instance.runtime.port||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 Us(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}(),o=n.join(this.paths.dataDir,"local-instances",e.instance.id),c=n.join(o,"logs");t.mkdirSync(c,{recursive:!0});const[d,...l]=function(e){if(e)return e;const i=n.resolve(process.cwd(),"bin","task-handoff.js");if(t.existsSync(i))return[process.execPath,i,"web"];throw Object.assign(new Error("The bundled controlled-instance command is unavailable."),{statusCode:500,code:"LOCAL_CONTROLLED_COMMAND_MISSING"})}(this.commandOverride),u=[...l,"--host","127.0.0.1","--port",String(s)],m=i.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:r,detached:!1,stdio:["ignore",p,g],env:{...process.env,TASK_HANDOFF_CONTROL_MODE:"controlled",TASK_HANDOFF_RUNTIME_KIND:"local",...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:r,TASK_HANDOFF_WORKSPACE_MODE:"local-bind",TASK_HANDOFF_DATA_DIR:o,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(s),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 i=()=>{e.off("error",r),t()},r=t=>{e.off("spawn",i),n(t)};e.once("spawn",i),e.once("error",r)})}(h)}catch(e){const i=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=${r} error=${i}\n`)}catch{}throw Object.assign(new Error(`Controlled instance process could not start with command ${d} in ${r}: ${i}`),{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",(i,r)=>{this.processByInstanceId.delete(e.instance.id);try{t.appendFileSync(n.join(c,"controlled-instance.lifecycle.log"),`[${(new Date).toISOString()}] exited pid=${h.pid??""} code=${i??""} signal=${r??""}\n`)}catch{}});const f=`http://127.0.0.1:${s}`,I=h.pid?T(h.pid):void 0,y=!(!h.pid||!e.instance.registrationToken)&&await async function(e,t,n,i,r=3e3){const s=Date.now()+r;for(;Date.now()<s;){if(null!==n.exitCode||null!==n.signalCode)return!1;const r=await Ks(e,i);if(r&&r.instanceId===t.instanceId&&r.pid===t.pid&&r.processNonce===t.processNonce&&r.startIdentity===t.startIdentity)return!0;await new Promise(e=>setTimeout(e,100))}return!1}(f,{instanceId:e.instance.id,pid:h.pid,processNonce:m,startIdentity:I},h,e.instance.registrationToken);if(!y)throw this.processByInstanceId.get(e.instance.id)===h&&this.processByInstanceId.delete(e.instance.id),null===h.exitCode&&null===h.signalCode&&h.kill("SIGTERM"),await Vs(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:r},runtime:{kind:"local",workspacePath:r,pid:h.pid,port:s,labels:{...e.instance.runtime.labels,"task-handoff.runtime-kind":"local",[Hs]:m}}}}async stop(e){return await Ws(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 Ws(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([Xs(this.runCommand,"codex"),Xs(this.runCommand,"claude")]);return{status:"online",capabilities:Fs({...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=>Vs(e)))}}class to{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(Zs)}async stopAll(){this.local instanceof eo&&await this.local.stopAll()}}class no extends tr{onStored;setOnStored(e){this.onStored=e}put(e){const t=super.get(e.id)?.stateRevision||0,n=super.put(Dn.parse({...e,stateRevision:Math.max(e.stateRevision||0,t)+1}));return this.onStored?.(n),n}}class io{nodeId;paths;localFolders;nodeRuntimes;controlledInstances;models;modelAssignments;modelEnvironments;updateJobs;node;listenerPort;containerUrlOverride;platform;constructor(e,t,n,i,r,s){this.paths=e,this.nodeId=t,this.localFolders=new tr(e.localFoldersDir,{schema:Ft,sanitize:ot}),this.nodeRuntimes=new tr(e.nodeRuntimesDir,{schema:vn}),this.controlledInstances=new no(e.controlledInstancesDir,{schema:Dn,sanitize:e=>Ln(e,e=>{console.warn(JSON.stringify({message:"legacy controlled instance field was ignored",...e}))})}),this.models=new Pr(e.nodeModelsDir,t),this.modelAssignments=new jr(e.modelAssignmentsDir),this.modelEnvironments=new Dr(e.modelEnvironmentsDir),this.updateJobs=new pr(e),this.listenerPort=r,this.platform=s,this.containerUrlOverride=i;const o=_s();this.node=Nn.parse({id:t,name:t,connectionMode:"direct-http",endpoint:n,controlEndpoint:n,containerEndpoint:this.containerUrl,publicWebBase:n?n.replace(/:\d+$/,""):void 0,status:"online",health:"ok",capabilities:{},labels:{},createdAt:o,updatedAt:o})}init(){this.localFolders.init();for(const e of this.localFolders.list())this.localFolders.put(e);if(this.nodeRuntimes.init(),this.controlledInstances.init(),this.models.init(),this.modelAssignments.init(),this.migrateLegacyModelEnvironments(),this.updateJobs.init(),this.updateJobs.reconcileRollouts(this.controlledInstances.list(),Is()),!this.nodeRuntimes.get("runtime_local_docker")){const e=_s();this.nodeRuntimes.put(vn.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(cs),t=_s();this.nodeRuntimes.put(vn.parse({id:cs,nodeId:this.nodeId,name:"Local Runtime",type:"local",status:e?.status||"unknown",accessStrategy:"node-proxy",capabilities:Fs(e?.capabilities),labels:{...e?.labels,[ds]:"true"},createdAt:e?.createdAt||t,updatedAt:e?.updatedAt||t}))}for(const e of this.nodeRuntimes.list())e.nodeId!==this.nodeId&&this.nodeRuntimes.put(vn.parse({...e,nodeId:this.nodeId,updatedAt:_s()}));for(const e of this.localFolders.list())e.nodeId!==this.nodeId&&this.localFolders.put(Ft.parse({...e,nodeId:this.nodeId,updatedAt:_s()}));this.normalizeInstanceRuntimeVersions()}normalizeInstanceRuntimeVersions(){for(const e of this.controlledInstances.list()){const t=ys(e.build?.packageVersion||e.instanceVersion),n=$s(this.requireRuntime(e.runtimeId)),i=["created","stopped","failed"].includes(e.status),r=n&&e.runtimeVersion?.desiredVersion===t.desiredVersion?e.runtimeVersion:void 0,s=n?"matched"===t.phase?i?t:{...t,phase:"verifying",matchedAt:void 0}:"failed"===r?.phase&&!1===r.error?.retryable?{...t,phase:"failed",attempt:r.attempt,lastAttemptAt:r.lastAttemptAt,error:r.error}:{...t,attempt:r?.attempt||0,lastAttemptAt:r?.lastAttemptAt}:t;this.controlledInstances.put(Dn.parse({...e,ready:!1,runtimeVersion:s,updatedAt:_s()}))}}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=_s()}runningInstanceCount(){const e=new Set(["created","stopped","failed"]);return this.listInstances().filter(t=>!e.has(t.status)).length}createLocalFolder(e){const t=_s(),n=Ft.parse({...e,id:e.id||Qi("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=_s(),n=vn.parse({...e,id:e.id||Qi("runtime"),nodeId:this.nodeId,accessStrategy:e.accessStrategy||(i=e.type,"docker"===i?"direct-port":"node-proxy"),capabilities:e.capabilities||{},labels:ms(e.labels),createdAt:t,updatedAt:t});var i;return this.nodeRuntimes.put(n)}updateRuntime(e,t){const n=this.requireRuntime(e);if("true"===n.labels[ds]){const t=new Error(`Built-in runtime ${e} cannot be modified.`);throw Object.assign(t,{statusCode:400,code:"NODE_RUNTIME_BUILTIN"}),t}if("local"===n.type||"local"===t.type){const e="win32"===this.platform,t=new Error(e?"Local Runtime is not supported on Windows.":"Local Runtime is built in and cannot be configured manually.");throw Object.assign(t,{statusCode:e?400:409,code:e?"LOCAL_RUNTIME_UNSUPPORTED":"LOCAL_RUNTIME_BUILTIN"}),t}const i=vn.parse({...n,...t,id:n.id,nodeId:this.nodeId,accessStrategy:t.accessStrategy||n.accessStrategy,capabilities:t.capabilities||n.capabilities,labels:t.labels?ms(t.labels):n.labels,createdAt:n.createdAt,updatedAt:_s()});return this.nodeRuntimes.put(i)}deleteRuntime(e){if("true"===this.requireRuntime(e).labels[ds]){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=vn.parse({...n,...e,id:n.id,nodeId:this.nodeId,createdAt:n.createdAt,updatedAt:_s()});return this.nodeRuntimes.put(t)}):this.nodeRuntimes.put(vn.parse({...n,status:"unknown",updatedAt:_s()}))}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=Mn(t);if(!n.success)throw function(e,t){const n=t.map(e=>`${e.path.join(".")||"body"}: ${e.message}`).join("; "),i=new Error(`Stored instance ${e} is not compatible with protocol ${Ue}: ${n}`);return Object.assign(i,{statusCode:409,code:"NODE_INSTANCE_PAYLOAD_INVALID"}),i}(e,n.error.issues);return n.data}listInstances(){return this.controlledInstances.list().flatMap(e=>{const t=Mn(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=_s(),n=rn(e),i=this.models.get(n),r=Kt.parse({...e,id:n,enabled:e.enabled??!0,order:e.order??this.nextModelOrder(),labels:e.labels||{},createdAt:i?.createdAt||t,updatedAt:t});return this.publicModel(this.models.put(r),this.modelReferenceIds(n).length)}deployModel(e){const t=rn(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(Kt.parse(e));return this.publicModel(n,this.modelReferenceIds(n.id).length)}updateModel(e,t){const n=this.requireModel(e),i=Kt.parse({...n,...t,key:t.key?.trim()?t.key:n.key,createdAt:n.createdAt,updatedAt:_s()}),r=rn(i),s=this.models.put(Kt.parse({...i,id:r}));return this.publicModel(s,this.modelReferenceIds(r).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 i=this.modelAssignments.get(e),r=Wt.parse({instanceId:e,codexModelHash:t.codexModelHash,claudeModelHash:t.claudeModelHash,updatedAt:_s()});this.modelAssignments.put(r);try{return{assignment:r,instance:this.controlledInstances.put(Dn.parse({...n,modelSelection:t.modelSelection,updatedAt:_s()}))}}catch(t){throw i?this.modelAssignments.put(i):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(rn(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,...i}=e;return Jt.parse({...i,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=>!Rr.has(e))){this.warnLegacyModelMigration(e,"unknown-fields");continue}const n=[];try{const i=this.migrateLegacyModelForApp(t,"codex",n),r=this.migrateLegacyModelForApp(t,"claude",n);if(!i&&!r)throw new Error("no complete model configuration");const s={...i?{codexModelHash:i}:{},...r?{claudeModelHash:r}:{}};this.assignModels(e,{modelSelection:s,codexModelHash:i,claudeModelHash:r}),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 i=e["codex"===t?"OPENAI_API_KEY":"ANTHROPIC_API_KEY"],r="codex"===t?e.TASK_HANDOFF_CODEX_BASE_URL||e.OPENAI_BASE_URL:e.ANTHROPIC_BASE_URL,s="codex"===t?e.TASK_HANDOFF_CODEX_MODEL||e.CODEX_MODEL:e.TASK_HANDOFF_CLAUDE_MODEL||e.CLAUDE_MODEL;if(!Boolean(i||r||s))return;if(!i||!r||!s)throw new Error("model configuration incomplete");const o=rn({app:t,endpoint:r,key:i,model:s}),a=this.models.get(o);if(a){if(a.app!==t||a.key!==i||a.endpoint!==r||a.model!==s||!a.enabled)throw new Error("existing model conflicts with legacy environment");return o}const c=_s();return this.models.put(Kt.parse({id:o,name:`Migrated ${"codex"===t?"Codex":"Claude"} model`,endpoint:r,key:i,model:s,app:t,enabled:!0,order:this.nextModelOrder(),labels:{migratedFrom:"instance-model-environment"},createdAt:c,updatedAt:c})),n.push(o),o}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),i=_s(),r=e.id||Qi("inst"),s=Ut.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"!==s.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 o=e.image?fn.parse(e.image):void 0,a="local"===t.type&&"local-folder"===s.type?n.resolve(s.path):void 0,c=Dn.parse({id:r,name:e.name||`instance-${r.replace(/^inst_?/,"").slice(0,6)}`,source:s,sourceSnapshot:e.sourceSnapshot||{},modelSelection:e.modelSelection,projectId:e.projectId,nodeId:this.nodeId,runtimeId:t.id,imageSelection:e.imageSelection,imageSnapshot:o,imageProvisioning:o&&"docker"===t.type?{phase:"checking-image",requestedReference:o.requestedReference,generation:0,startedAt:i,updatedAt:i}:void 0,status:o&&"docker"===t.type?"provisioning":"created",health:"unknown",connectionStatus:"unknown",agentStatus:"unknown",targetStatus:"unknown",uiAccessStatus:"unknown",controlMode:"controlled",ready:!1,runtimeVersion:ys(),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:er(),createdAt:i,updatedAt:i});return this.controlledInstances.put(c)}registerInstance(e,t,n){const i=Vn.parse(t),r=_s(),s=this.controlledInstances.get(e);if(!s){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}this.validateInstanceReport(s,i,n),Ls(i.protocolVersion,`Instance ${e}`);const o=i.build?.packageVersion||i.instanceVersion,a=$s(this.requireRuntime(s.runtimeId)),c=As(s,o,a),d=Dn.parse({...s,status:"registered",health:o===Is()?"ok":"degraded",ready:!a&&o===Is(),connectionStatus:"online",agentStatus:"online",targetStatus:"endpoint-unreachable"===i.target.status?"endpoint-unreachable":"reachable"===i.target.status?"reachable":s.targetStatus,uiAccessStatus:"endpoint-unreachable"===i.target.status?"endpoint-unreachable":s.uiAccessStatus,controlMode:i.controlMode,protocolVersion:i.protocolVersion,instanceVersion:i.instanceVersion,build:i.build,runtimeVersion:c,capabilities:i.capabilities,appInventory:i.appInventory,workspace:i.workspace,target:{...s.target,...i.target},registrationToken:s.registrationToken||i.registrationToken,lastHeartbeatAt:r,updatedAt:r});return this.controlledInstances.put(d)}heartbeatInstance(e,t,n){const i=this.requireInstance(e);this.validateInstanceToken(i,n);const r=Hn.parse(t);Ls(r.protocolVersion,`Instance ${e}`);const s=_s(),o=r.target?{...i.target,...r.target}:i.target,a={...o,status:"unknown"===o.status&&(o.web||o.api)?"reachable":o.status},c="endpoint-unreachable"===a.status?"endpoint-unreachable":"reachable"===a.status?"reachable":i.targetStatus,d=r.build?.packageVersion||i.build?.packageVersion||i.instanceVersion,l=$s(this.requireRuntime(i.runtimeId)),u=As(i,d,l),m=d===Is()&&(!l||i.ready&&"matched"===i.runtimeVersion?.phase),p=Dn.parse({...i,...r,target:a,ready:m&&"failed"!==r.health,health:d===Is()?r.health||i.health:"degraded",runtimeVersion:u,agentStatus:"online",targetStatus:c,uiAccessStatus:c,connectionStatus:"online",build:r.build||i.build,lastHeartbeatAt:s,updatedAt:s});return this.controlledInstances.put(p)}validateInstanceReport(e,t,n){this.validateInstanceToken(e,n||t.registrationToken),t.instanceId&&t.instanceId!==e.id&&Ms("INSTANCE_ID_MISMATCH",`Instance ${t.instanceId} cannot register as ${e.id}.`),t.nodeId&&t.nodeId!==this.nodeId&&Ms("INSTANCE_NODE_MISMATCH",`Instance ${e.id} belongs to node ${this.nodeId}.`),t.runtimeId&&t.runtimeId!==e.runtimeId&&Ms("INSTANCE_RUNTIME_MISMATCH",`Instance ${e.id} belongs to runtime ${e.runtimeId}.`),t.imageSelection&&t.imageSelection.imageId!==e.imageSelection?.imageId&&Ms("INSTANCE_IMAGE_MISMATCH",`Instance ${e.id} belongs to image ${e.imageSelection?.imageId}.`)}validateInstanceToken(e,t){e.registrationToken&&t===e.registrationToken||Ms("INSTANCE_REGISTRATION_TOKEN_INVALID",`Invalid registration token for instance ${e.id}.`)}context(e,t=this.resolvedAssignedModelEnvironment(e.id)){const n=e.imageSnapshot||fn.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:Cs(e),image:n,node:this.node,runtime:this.requireRuntime(e.runtimeId),instance:e,nodeAgentUrl:this.containerUrl,modelEnv:t}}}class ro{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 _n.parse({...this.config,host:Ts(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:Ts(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=Tn.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 i=new Error(`Failed to bind node agent TCP listener at ${Ts(t.bindScope)}:${t.port}: ${e instanceof Error?e.message:String(e)}`);throw Object.assign(i,{statusCode:409,code:"NODE_AGENT_LISTENER_BIND_FAILED"}),i}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 i=e=>{this.app.server.off("listening",r),n(e)},r=()=>{this.app.server.off("error",i),t()};this.app.server.once("error",i),this.app.server.once("listening",r),this.app.server.listen({host:Ts(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 so(e,t,n,i,r,s="request"){const o=e.requireInstance(i);if(o.imageProvisioning&&"ready"!==o.imageProvisioning.phase&&"docker"===e.requireRuntime(o.runtimeId).type)return r.diagnostic({instanceId:i,action:"start",reason:s,runtimeId:o.runtimeId,imageId:o.imageSelection?.imageId,imagePhase:o.imageProvisioning.phase},"node instance start queued until image provisioning completes"),e.controlledInstances.put(Dn.parse({...o,status:"starting",updatedAt:_s()}));r.diagnostic({instanceId:i,action:"start",reason:s,runtimeId:o.runtimeId,imageId:o.imageSelection?.imageId},"node instance start requested");const a=e.controlledInstances.put(Dn.parse({...o,status:"starting",ready:!1,updatedAt:_s()})),c=t.forRuntime(e.requireRuntime(a.runtimeId)),d=await c.start(e.context(a)),l=await Os(n,Dn.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:_s()})),u=oo(a,e.requireInstance(i),{...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 r.diagnostic({instanceId:i,action:"start",reason:s,status:m.status,connectionStatus:m.connectionStatus,targetStatus:m.targetStatus,targetWeb:m.target.web,containerName:m.runtime.containerName},"node instance start completed"),m}function oo(e,t,n){const i=t.stateRevision>e.stateRevision&&t.lastHeartbeatAt!==e.lastHeartbeatAt&&"online"===t.agentStatus;return Dn.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:_s()})}function ao(e,t){const n=t instanceof Error?t.message:String(t);return Dn.parse({...e,status:"failed",ready:!1,health:"failed",connectionStatus:"offline",agentStatus:"offline",targetStatus:"unknown",uiAccessStatus:"unknown",workspace:{...e.workspace,error:n},updatedAt:_s()})}function co(e){return Dn.parse({...e,health:"unknown",connectionStatus:"offline",agentStatus:"offline",targetStatus:"unknown",uiAccessStatus:"unknown",target:{...e.target,status:"unknown"},updatedAt:_s()})}async function lo(e={}){const i=e.token||process.env.TASK_HANDOFF_NODE_AGENT_TOKEN,r=Number(e.port||process.env.TASK_HANDOFF_NODE_AGENT_PORT||"8091"),s=`http://127.0.0.1:${r}`,a=e.containerUrl||process.env.TASK_HANDOFF_NODE_AGENT_CONTAINER_URL,p=Gi(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,I=new rs(p),y=I.resolveNodeId(e.nodeId||process.env.TASK_HANDOFF_NODE_ID),A=e.connectionMode||("local-ipc"===process.env.TASK_HANDOFF_NODE_AGENT_CONNECTION_MODE?"local-ipc":"local-loopback"),w=e.ipcPath||process.env.TASK_HANDOFF_NODE_AGENT_IPC_PATH||ir(p.dataDir),z="local-ipc"===A?`ipc://${encodeURIComponent(w)}`:s,N=e.platform||process.platform,v=e.arch||process.arch,S=new io(p,y,s,a,r,N);S.node.connectionMode=A,S.node.controlEndpoint=z,S.node.endpoint=z,S.init();const E=e.dockerCommandRunner||Wn,_=new Xn(E,e.dockerTerminalCommandRunner),T=new Qn(E,{publishHost:"127.0.0.1",imageService:_}),k=new to(new Qs(T,E,N,v),new eo(e.dockerCommandRunner||Wn,p,()=>S.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)),x=e.updateCommandRunner||e.dockerCommandRunner||Wn,C=e.fetchImpl||fetch,O=new wr({cacheDir:n.join(p.dataDir,"runtime-artifacts"),fetchImpl:C}),R=e.resolveRuntimeArtifactRelease||((e,t,n)=>zr(e,t,n,C)),D=async(t,n,i)=>{const r=await n.artifactTarget(i);if(e.resolveRuntimeArtifact)return e.resolveRuntimeArtifact(t,r.platform,r.arch);const s=await R(t,r.platform,r.arch);if(s.identity.launcherAbi>r.launcherAbi)throw Object.assign(new Error(`Runtime requires launcher ABI ${s.identity.launcherAbi}, but ${r.platform}-${r.arch} provides ABI ${r.launcherAbi}.`),{code:"INSTANCE_BASE_RUNTIME_INCOMPATIBLE",retryable:!1});return O.resolve(s.identity,s.source)},P=e=>k.forRuntime(S.requireRuntime(e.runtimeId)),j=e=>{const t=P(e);return Zs(t)?t:void 0},M=e=>{const t=j(e);if(t)return t;throw Object.assign(new Error(`Runtime for instance ${e.id} does not use managed artifacts.`),{code:"INSTANCE_RUNTIME_ARTIFACT_UNMANAGED",retryable:!1})},L=e=>Boolean(j(e)),$=(e,t)=>{const n=S.context(e);return D(t,M(e),n)},F=d({logger:e.logger??!0}),U={requests:0,active:0,completed:0,aborted:0,limitRejected:0,responseBytes:0,totalDurationMs:0,maxResponseBytes:Ns()};F.decorate("nodeAgentState",S),await F.register(l);const V=new wi(S,i,{logger:F.log,safetyIntervalMs:Number(process.env.TASK_HANDOFF_EVENT_CONNECTION_SAFETY_INTERVAL_MS)||void 0}),H=new Nr(S.controlledInstances,Is,{isInstalled:async(e,t)=>{const n=await $(e,t);return M(e).inspectRuntime(S.context(e),n.identity)},install:async(e,t)=>{const n=M(e);await n.installRuntime(S.context(e),await $(e,t))},restart:async e=>{const t=P(e),n=S.requireInstance(e.id),i=S.controlledInstances.put(Dn.parse({...n,build:void 0,instanceVersion:void 0,ready:!1,updatedAt:_s()})),r=await t.restart(S.context(i)),s=S.requireInstance(e.id);S.controlledInstances.put(oo(i,s,r))},rollback:async e=>M(e).rollbackRuntime(S.context(e)),onForcedDrain:e=>F.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});S.controlledInstances.setOnStored(e=>{V.publishInstanceLifecycle(e),S.updateJobs.reconcileRollouts(S.listInstances(),Is())}),V.start();for(const e of S.listInstances())L(e)&&!["created","stopped","failed","provisioning"].includes(e.status)&&H.schedule(e.id).catch(t=>F.log.error({instanceId:e.id,error:t},"runtime convergence recovery failed"));F.decorate("nodeAgentEventForwarder",V);const q=new Ti(E,()=>S.listInstances().filter(e=>"docker"===S.requireRuntime(e.runtimeId).type),e=>V.publish("instance.metrics.snapshot",e,{instanceId:e.instanceId}));q.start(),F.decorate("nodeAgentRuntimeMetrics",q);const B=(ne=process.env.TASK_HANDOFF_DIAGNOSTIC_LOGS,["1","true","yes","on"].includes(String(ne||"").trim().toLowerCase())),K=new Mr(I,y,g,h),G=(e,t)=>{B&&F.log.info(e,t)},J={diagnostic:G,warn:(e,t)=>F.log.warn(e,t)},W=(e,t,n)=>{const i=n&&"object"==typeof n&&!Array.isArray(n)?n.protocolVersion:void 0;if("string"!=typeof i||i===Ue)return n;const r=({field:n,action:r})=>F.log.warn({instanceId:e,report:t,protocolVersion:i,expectedProtocolVersion:Ue,field:n,action:r},"cross-version controlled instance report sanitized");return"register"===t?function(e,t){if(!e||"object"!=typeof e||Array.isArray(e))return e;const n=e,i=["instanceId","projectId","source","nodeId","runtimeId","imageSelection","instanceVersion","protocolVersion","build","controlMode","capabilities","appInventory","target","workspace","registrationToken"],r=new Set([...i,"imageId"]);for(const e of Object.keys(n))r.has(e)||t?.({field:e,action:"ignored"});return Object.prototype.hasOwnProperty.call(n,"imageId")&&t?.({field:"imageId",action:"migrated"}),{...Un(n,i),imageSelection:st(n.imageSelection,n.imageId)}}(n,r):function(e,t){if(!e||"object"!=typeof e||Array.isArray(e))return e;const n=["status","health","protocolVersion","build","capabilities","appInventory","apps","aiSessions","triggers","workspace","target"],i=new Set(n);for(const n of Object.keys(e))i.has(n)||t?.({field:n,action:"ignored"});return Un(e,n)}(n,r)},Y=async(e,t)=>{try{let n=S.requireInstance(e);"failed"===n.runtimeVersion?.phase&&L(n)&&(n=S.controlledInstances.put(Dn.parse({...n,ready:!1,runtimeVersion:ys(vr(n)),updatedAt:_s()})));const i=S.requireRuntime(n.runtimeId);await so(S,k,C,e,J);const r=S.requireInstance(e);if("docker"===i.type&&"ready"!==r.imageProvisioning?.phase)return V.syncNow(),r;let s=S.requireInstance(e);if(L(s)){try{s=await H.schedule(e,{startRequested:!0})}catch(n){s=S.requireInstance(e),J.warn({instanceId:e,action:"runtime.converge",reason:t,error:n instanceof Error?n.message:String(n)},"node instance runtime convergence failed after start")}"failed"===s.runtimeVersion?.phase&&J.warn({instanceId:e,action:"runtime.converge",reason:t,error:s.runtimeVersion.error},"node instance started with failed runtime convergence")}return await Ds(C,s,"start",J),V.syncNow(),s}catch(n){const i=ao(S.requireInstance(e),n);throw S.controlledInstances.put(i),V.syncNow(),J.warn({instanceId:e,action:"start",reason:t,error:n instanceof Error?n.message:String(n)},"node instance start failed"),n}},X=e=>{e.imageProvisioning&&async function(t,n,i,r,s,o,a){const c=e=>{const n=t.controlledInstances.get(i);n&&n.imageProvisioning?.generation===r&&n.imageSnapshot&&(t.controlledInstances.put(Dn.parse({...n,status:"starting"===n.status?"starting":"provisioning",imageProvisioning:{...n.imageProvisioning,phase:e,error:void 0,updatedAt:_s()},updatedAt:_s()})),s())},d=t.controlledInstances.get(i);if(!d?.imageSnapshot||d.imageProvisioning?.generation!==r)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(i);if(!p?.imageSnapshot||p.imageProvisioning?.generation!==r)return;t.controlledInstances.put(Dn.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:_s()},updatedAt:_s()})),s(),o.diagnostic({instanceId:i,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(i);if(!n?.imageProvisioning||n.imageProvisioning.generation!==r)return;const c=e instanceof Error?e.message:String(e);t.controlledInstances.put(Dn.parse({...n,status:"failed",health:"failed",imageProvisioning:{...n.imageProvisioning,phase:"failed",error:c,updatedAt:_s()},updatedAt:_s()})),s(),o.warn({instanceId:i,action:"image.provision",reference:n.imageProvisioning.requestedReference,error:c},"node instance image provisioning failed")}}(S,_,e.id,e.imageProvisioning.generation,()=>V.syncNow(),J,t=>{const n={instanceId:e.id,generation:e.imageProvisioning.generation,requestedReference:e.imageProvisioning.requestedReference,observedAt:_s()};if("outcome"in t)V.publish(An,{...n,sequence:1e3*t.sequence,outcome:t.outcome},{instanceId:e.id});else for(const[i,r]of function(e,t=6e4){const n=[];for(let i=0;i<e.length;i+=t)n.push(e.slice(i,i+t));return n}(t.data).entries())V.publish(yn,{...n,sequence:1e3*t.sequence+i,data:r,...t.replay?{replay:!0}:{}},{instanceId:e.id})})},Z=async e=>{const t=new Map;for(const e of k.managedAdapters()){const n=await e.artifactTarget();t.set(`${n.platform}-${n.arch}`,{adapter:e})}for(const e of S.listInstances()){const n=j(e);if(!n)continue;const i=S.context(e),r=await n.artifactTarget(i);t.set(`${r.platform}-${r.arch}`,{adapter:n,context:i})}return(await Promise.all([...t.values()].map(({adapter:t,context:n})=>D(e,t,n)))).sort((e,t)=>`${e.identity.platform}/${e.identity.arch}`.localeCompare(`${t.identity.platform}/${t.identity.arch}`))},Q=async e=>{const t=ee(),n=await async function(e){const t=await async function(e,t,n){const i=function(e){return"stable"===e?"latest":e}(n),r=await e(ur(),["view",`${t}@${i}`,"version","--json"]).catch(e=>{if(!function(e){if(!e||"object"!=typeof e)return!1;const t=e,n=[t.message,t.details?.stdout,t.details?.stderr].filter(e=>"string"==typeof e).join("\n");return/\bE404\b/i.test(n)}(e))throw e});if(!r)return;const s=JSON.parse(r.stdout);if("string"!=typeof s)throw new Error(`npm did not resolve ${t}@${i} to one version.`);return s}(e.runCommand,"@task-handoff/node-agent",e.channel);if(!t)return function(e){return Dt.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:lr()})}({channel:e.channel,currentVersion:e.currentVersion,impact:e.impact});const n=function(e,t){if(!e)return!0;const n=f.valid(e),i=f.valid(t);return n&&i?f.gt(i,n):e!==t}(e.currentVersion,t),i=n?await async function(e,t,n){const i=await e(ur(),["view",`${t}@${n}`,"dist.integrity","--json"]),r=JSON.parse(i.stdout);if("string"!=typeof r||!/^sha(?:256|384|512)-[A-Za-z0-9+/=]+$/.test(r))throw Object.assign(new Error(`npm did not return immutable integrity metadata for ${t}@${n}.`),{statusCode:502,code:"NODE_UPDATE_PREFLIGHT_FAILED",retryable:!0});return r}(e.runCommand,"@task-handoff/node-agent",t):void 0;return Dt.parse({source:"npm",channel:e.channel,currentVersion:e.currentVersion,availableVersion:t,...i?{artifactRef:`npm:@task-handoff/node-agent@${t}#${i}`}:{},runtimeArtifacts:e.runtimeArtifacts||[],impact:e.impact||{runningInstanceCount:0,stoppedInstanceCount:0,activeInstanceCount:0,restartInstanceCount:0,runningInstanceIds:[],stoppedInstanceIds:[],activeInstanceIds:[]},updateAvailable:n,checkedAt:lr()})}({channel:e.channel,currentVersion:Is(),runCommand:x,impact:t});if(!n.updateAvailable)return n;const i=await Z(n.availableVersion),r={...n,runtimeArtifacts:i.map(e=>e.identity),preflightToken:er()};return te.set(r.preflightToken,{result:r,expiresAt:Date.now()+6e5}),r},ee=()=>{const e=S.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()}},te=new Map;var ne;F.setErrorHandler((e,t,n)=>{const i=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);(B||i.statusCode>=500)&&(i.statusCode>=500?F.log.error.bind(F.log):F.log.warn.bind(F.log))({method:t.method,url:t.url,statusCode:i.statusCode,errorCode:i.code,error:i.message},"node agent request failed"),n.code(i.statusCode).send({error:{code:i.code,message:i.message,...e&&"object"==typeof e&&"string"==typeof e.expectedVersion?{expectedVersion:e.expectedVersion}:{},...e&&"object"==typeof e&&"string"==typeof e.actualVersion?{actualVersion:e.actualVersion}:{},...e&&"object"==typeof e&&"string"==typeof e.phase?{phase:e.phase}:{},...e&&"object"==typeof e&&"boolean"==typeof e.retryable?{retryable:e.retryable}:{},...e&&"object"==typeof e&&"number"==typeof e.blockingInstanceCount?{blockingInstanceCount:e.blockingInstanceCount}:{}}})}),F.addHook("preHandler",async e=>{const t=K.verify(e);if(t)e.nodeAgentAuthKeyId=t;else if(Es(e)){if(i&&vs(e.headers)!==i){const e=new Error("Invalid node agent token.");throw Object.assign(e,{statusCode:401,code:"NODE_AGENT_UNAUTHORIZED"}),e}}else if("/api/node-agent/pairing/complete"!==e.url.split("?")[0]&&!function(e){const t=e.split("?")[0];return/^\/api\/node-agent\/instances\/[^/]+\/(register|heartbeat)$/.test(t)}(e.url)){if(K.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 Ss(e.ip)||Ss(e.socket.remoteAddress)||!e.ip&&!e.socket.remoteAddress&&!e.socket.remoteFamily}(e)){const e=new Error("Local node agent access is only accepted from loopback or local IPC connections.");throw Object.assign(e,{statusCode:401,code:"NODE_AGENT_LOCAL_TOKEN_REQUIRES_LOOPBACK"}),e}if(i&&vs(e.headers)!==i){const e=new Error("Invalid node agent token.");throw Object.assign(e,{statusCode:401,code:"NODE_AGENT_UNAUTHORIZED"}),e}}}),F.addHook("onClose",async()=>{q.stop(),V.stop();for(const e of S.listInstances())H.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(co(t))}(S,k)}),F.decorate("nodeAgentRestoreLocalInstances",async()=>{for(const e of S.listInstances().filter(e=>["provisioning","starting"].includes(e.status)&&"ready"!==e.imageProvisioning?.phase&&"docker"===S.requireRuntime(e.runtimeId).type))X(e);const e=S.listInstances().filter(e=>"local"===S.requireRuntime(e.runtimeId).type&&Ys.has(e.status));for(const t of e)try{await so(S,k,C,t.id,J,"restore"),await Ds(C,S.requireInstance(t.id),"start",J)}catch(e){S.controlledInstances.put(ao(S.requireInstance(t.id),e)),G({instanceId:t.id,action:"restore",error:e instanceof Error?e.message:String(e)},"node local instance restore failed")}}),F.get("/api/node-agent/health",async()=>{return{data:{ok:!0,role:"node-agent",nodeId:y,platform:us(N),arch:process.arch,protocolVersion:Ue,build:(e="node-agent",{component:e,packageName:"@task-handoff/node-agent",packageVersion:Is(),protocolVersion:Ue,buildId:fs("TASK_HANDOFF_BUILD_ID"),builtAt:fs("TASK_HANDOFF_BUILT_AT"),gitCommit:fs("TASK_HANDOFF_GIT_COMMIT"),imageRef:fs("TASK_HANDOFF_IMAGE_REF"),imageDigest:fs("TASK_HANDOFF_IMAGE_DIGEST")}),instanceProxy:{...U},serverTime:(new Date).toISOString()}};var e});const ie=e=>{if(!Es(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(!F.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 F.nodeAgentListenerManager};return F.get("/api/node-agent/settings/external-listener",async e=>({data:ie(e).current()})),F.patch("/api/node-agent/settings/external-listener",async e=>({data:await ie(e).update(e.body)})),F.get("/api/node-agent/updates/jobs",async()=>({data:S.updateJobs.list()})),F.post("/api/node-agent/updates/check",async e=>({data:await Q(Rt.parse(e.body))})),F.post("/api/node-agent/updates/apply",async(e,i)=>{const r=hs.parse(e.body),s=await(async e=>{const t=te.get(e.preflightToken);if(te.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;if(n.channel!==e.channel||n.availableVersion!==e.targetVersion||n.currentVersion!==Is()||JSON.stringify(n.impact)!==JSON.stringify(ee())){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})(r);if(!s.supported){const e=new Error(s.reason||"The requested update is not supported.");throw Object.assign(e,{statusCode:400,code:"UPDATE_UNSUPPORTED"}),e}if(!s.updateAvailable){const e=new Error(s.reason||"No update is available for the selected channel.");throw Object.assign(e,{statusCode:409,code:"UPDATE_NOT_AVAILABLE"}),e}const a=S.updateJobs.create(y,s),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(o.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,i=t.existsSync){const r=[n.resolve(e,"..","bin","task-handoff-node-update-worker"),n.resolve(e,"..","..","bin","task-handoff-node-update-worker")],s=r.find(i),o=n.resolve(e,"..","..","..","..","scripts","node-update-worker.cjs");return s?{worker:s,packaged:!0,expectedWorker:r[0]}:i(o)?{worker:o,packaged:!1,expectedWorker:r[0]}:{worker:void 0,packaged:!1,expectedWorker:r[0]}}(c);if(!d){S.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:_s()});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 x("systemd-run",["--unit",`task-handoff-update-${a.id}`,"--collect","--property=Type=exec",...l?[d]:[process.execPath,d],"--job-file",S.updateJobs.records.filePath(a.id),"--target-version",a.toVersion,"--npm-command",ur()]),i.code(202).send({data:a})}),F.post("/api/node-agent/pairing/invites",async(e,t)=>{const n=I.createPairingInvite(qr.parse(e.body||{}));return t.code(201).send({data:{nodeId:y,joinToken:n.token,expiresAt:n.expiresAt}})}),F.post("/api/node-agent/pairing/complete",async(e,t)=>{const n=I.completePairingInvite(Br.parse(e.body));return t.code(201).send({data:{nodeId:y,keyId:n.keyId,secret:n.secret,pairedAt:n.pairedAt}})}),F.get("/api/node-agent/remotes",async e=>({data:I.listRemoteControlPlanes(e.nodeAgentAuthKeyId)})),F.delete("/api/node-agent/remotes/:keyId",async e=>{const t=m.z.string().trim().min(1).max(160).parse(e.params.keyId);return{data:{deleted:I.deleteRemoteControlPlane(t,e.nodeAgentAuthKeyId)}}}),F.post("/api/node-agent/remotes/connect",async(e,t)=>{const n=Kr.parse(e.body),i=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),r=I.createRemoteControlPlane({url:i,...n.controlPlaneName?{name:n.controlPlaneName}:{},active:!1!==n.activate}),s=await async function(e,t,n){const i=await e(new URL("/api/node-join/complete",t).toString(),{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(n)}),r=await i.json().catch(()=>({}));if(!i.ok){const e=new Error(r.error?.message||`Control-plane node join failed with HTTP ${i.status}.`);throw Object.assign(e,{statusCode:i.status,code:r.error?.code||"NODE_AGENT_REMOTE_JOIN_FAILED"}),e}return r.data||{}}(C,i,{joinToken:n.joinToken,nodeId:y,nodeName:S.node.name,keyId:r.keyId,secret:r.secret,pairedAt:r.pairedAt}),o=I.upsertRemoteControlPlane({...r,..."string"==typeof s.name&&s.name?{name:n.controlPlaneName||s.name}:{}});let a,c=!1!==o.active?"saved":"disabled";if(!1!==o.active&&F.nodeAgentReverseTunnels)try{F.nodeAgentReverseTunnels.connect({url:i,keyId:o.keyId,secret:o.secret}),c="connecting"}catch(e){c="failed",a=e instanceof Error?e.message:String(e)}return t.code(201).send({data:{remote:{id:o.id,url:o.url,keyId:o.keyId,pairedAt:o.pairedAt,active:!1!==o.active},tunnel:{status:c,...a?{error:a}:{}}}})}),F.get("/api/node-agent/runtimes",async()=>({data:S.nodeRuntimes.list()})),F.post("/api/node-agent/runtimes",async(e,t)=>t.code(201).send({data:S.createRuntime(qi.parse(e.body))})),F.patch("/api/node-agent/runtimes/:id",async e=>({data:S.updateRuntime(e.params.id,Bi.parse(e.body))})),F.delete("/api/node-agent/runtimes/:id",async e=>({data:{deleted:S.deleteRuntime(e.params.id)}})),F.post("/api/node-agent/runtimes/:id/check",async e=>{const t=S.requireRuntime(e.params.id);return{data:await S.checkRuntime(t.id,k.forRuntime(t))}}),F.get("/api/node-agent/local-folders",async()=>({data:S.localFolders.list()})),F.get("/api/node-agent/folders/tree",async e=>({data:Li(Ui.parse(e.query))})),F.post("/api/node-agent/local-folders",async(e,t)=>t.code(201).send({data:S.createLocalFolder(Fi.parse(e.body))})),F.delete("/api/node-agent/local-folders/:id",async e=>({data:{deleted:S.localFolders.delete(e.params.id)}})),F.get("/api/node-agent/models",async()=>({data:S.listModels()})),F.post("/api/node-agent/models",async(e,t)=>t.code(201).send({data:S.createModel(Qt.parse(e.body))})),F.put("/api/node-agent/models/:id/deploy",async e=>{const t=e.params.id,n=tn.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:S.deployModel(n)}}),F.patch("/api/node-agent/models/:id",async e=>({data:S.updateModel(e.params.id,en.parse(e.body))})),F.delete("/api/node-agent/models/:id",async e=>({data:{deleted:S.deleteModel(e.params.id)}})),F.get("/api/node-agent/instances",async()=>({data:S.listInstances()})),F.post("/api/node-agent/instances",async(e,t)=>{const n=S.createInstance(Vi.parse(e.body));return V.syncNow(),n.imageProvisioning&&X(n),t.code(201).send({data:n})}),F.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 i=_s();return e.controlledInstances.put(Dn.parse({...n,status:"provisioning",health:"unknown",imageProvisioning:{phase:"checking-image",requestedReference:n.imageSnapshot.requestedReference,generation:(n.imageProvisioning?.generation||0)+1,startedAt:i,updatedAt:i},updatedAt:i}))}(S,e.params.id);return V.syncNow(),X(t),{data:t}}),F.patch("/api/node-agent/instances/:id",async e=>{const t=e.params.id,n=S.requireInstance(t),i=Hi.parse(e.body),r=Dn.parse({...n,...i,...i.config?{config:{...n.config,...i.config}}:{},updatedAt:_s()}),s=S.controlledInstances.put(r);return V.syncNow(),{data:s}}),F.put("/api/node-agent/instances/:id/model-assignment",async e=>{const t=e.params.id,n=S.assignModels(t,nn.parse(e.body));return await Ps(C,S,t),{data:n}}),F.post("/api/node-agent/instances/:id/register",async(e,t)=>{const n=e.params.id,i=W(n,"register",e.body),r=S.registerInstance(n,Vn.parse(i),vs(e.headers));return V.syncNow(),G({instanceId:n,action:"register",protocolVersion:r.protocolVersion,build:r.build,targetStatus:r.targetStatus,targetStrategy:r.target.strategy},"node instance registered"),!L(r)||r.ready&&"matched"===r.runtimeVersion?.phase||H.schedule(n).catch(e=>F.log.error({instanceId:n,error:e},"runtime convergence after registration failed")),t.code(201).send({data:r})}),F.post("/api/node-agent/instances/:id/heartbeat",async e=>{const t=e.params.id,n=W(t,"heartbeat",e.body),i=S.heartbeatInstance(t,Hn.parse(n),vs(e.headers));return V.syncNow(),G({instanceId:t,action:"heartbeat",status:i.status,health:i.health,protocolVersion:i.protocolVersion,build:i.build,targetStatus:i.targetStatus,apps:i.apps.runningCount},"node instance heartbeat accepted"),!L(i)||i.ready&&"matched"===i.runtimeVersion?.phase||H.schedule(t).catch(e=>F.log.error({instanceId:t,error:e},"runtime convergence after heartbeat failed")),{data:i}}),F.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=V.addOutput(t);t.on("close",n),t.on("error",n)}),F.get("/api/node-agent/docker/images",async()=>({data:await ni(e.dockerCommandRunner)})),F.get("/api/node-agent/instances/:id/metrics",async e=>{const t=e.params.id,n=S.requireInstance(t);if("docker"!==S.requireRuntime(n.runtimeId).type){const e=new Error(`Runtime type ${S.requireRuntime(n.runtimeId).type} does not provide resource metrics.`);throw Object.assign(e,{statusCode:409,code:"INSTANCE_METRICS_UNSUPPORTED"}),e}return{data:await q.snapshot(t)}}),F.post("/api/node-agent/instances/:id/start",async e=>{const t=e.params.id;return gs.parse(e.body),{data:await Y(t,"request")}}),F.post("/api/node-agent/instances/:id/runtime/reconcile",async e=>{const t=e.params.id;gs.parse(e.body);const n=S.requireInstance(t);S.controlledInstances.put(Dn.parse({...n,ready:!1,runtimeVersion:ys(vr(n)),updatedAt:_s()}));const i=await H.schedule(t,{startRequested:!["created","stopped"].includes(n.status),resumeCancelled:!0});return V.syncNow(),{data:i}}),F.post("/api/node-agent/instances/:id/stop",async e=>{const t=e.params.id;await H.cancel(t);const n=S.requireInstance(t);G({instanceId:n.id,action:"stop",runtimeId:n.runtimeId,containerName:n.runtime.containerName},"node instance stop requested");const i=k.forRuntime(S.requireRuntime(n.runtimeId)),r=await i.stop(S.context(n)),s=Dn.parse({...n,...r,ready:!1,agentStatus:"offline",targetStatus:"unknown",uiAccessStatus:"unknown",updatedAt:_s()}),o=S.controlledInstances.put(s);return V.syncNow(),G({instanceId:n.id,action:"stop",status:o.status,connectionStatus:o.connectionStatus,containerName:o.runtime.containerName},"node instance stop completed"),{data:o}}),F.post("/api/node-agent/instances/:id/restart",async e=>{const t=e.params.id,n=S.requireInstance(t);if(gs.parse(e.body),L(n)&&(!n.ready||"matched"!==n.runtimeVersion?.phase)){const e=await H.schedule(t,{startRequested:!0});return V.syncNow(),{data:e}}G({instanceId:t,action:"restart",runtimeId:n.runtimeId,imageId:n.imageSelection?.imageId,containerName:n.runtime.containerName},"node instance restart requested");const i=k.forRuntime(S.requireRuntime(n.runtimeId)),r=await i.restart(S.context(n)),s=Dn.parse({...n,...r,target:r.target?{...n.target,...r.target}:n.target,updatedAt:_s()}),o=await Os(C,s),a=oo(n,S.requireInstance(t),{...r,target:r.target?{...r.target,status:o}:void 0,targetStatus:o,uiAccessStatus:o}),c=S.controlledInstances.put(a);return await Ds(C,c,"restart",J),V.syncNow(),G({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}}),F.post("/api/node-agent/instances/:id/delete",async e=>{const t=e.params.id,n=S.requireInstance(t);await H.cancel(t),G({instanceId:t,action:"delete",runtimeId:n.runtimeId,containerName:n.runtime.containerName},"node instance delete requested");const i=k.forRuntime(S.requireRuntime(n.runtimeId));await i.delete(S.context(n,{})),G({instanceId:t,action:"delete"},"node instance delete completed");const r=S.controlledInstances.delete(t);return S.modelAssignments.delete(t),S.modelEnvironments.delete(t),V.syncNow(),{data:{deleted:r}}}),F.post("/api/node-agent/instances/:id/proxy",async(e,t)=>{const n=e.params.id,i=$i.parse(e.body),r=js(S.requireInstance(n)),s=i.path.startsWith("/")?i.path:`/${i.path}`;"POST"===i.method&&"/api/apps/sessions"===s&&await Ps(C,S,n),G({instanceId:n,action:"proxy",method:i.method,path:s,instanceBase:r},"node instance proxy requested");const o=await C(`${r}${s}`,{method:i.method,headers:{...i.headers},body:ws(i)}),a=o.headers.get("content-type")||"application/octet-stream",c=await o.text();G({instanceId:n,action:"proxy",method:i.method,path:s,statusCode:o.status,contentType:a},"node instance proxy completed"),t.code(o.status).type(a).send(c)}),F.post("/api/node-agent/instances/:id/proxy/stream",{bodyLimit:zs},async(e,t)=>{const n=Date.now();U.requests+=1,U.active+=1;const i=new AbortController;let r=0,s=!1,o=!1;const a=e=>{o||(o=!0,U.active-=1,U.totalDurationMs+=Date.now()-n,U.responseBytes+=r,U[e]+=1)},d=()=>{i.abort(),s&&a("aborted")};e.raw.once("aborted",d),t.raw.once("close",d);try{const n=e.params.id,o=$i.parse(e.body),d=js(S.requireInstance(n)),l=o.path.startsWith("/")?o.path:`/${o.path}`;G({instanceId:n,action:"proxy.stream",method:o.method,path:l,instanceBase:d},"node instance streaming proxy requested");const u=await C(`${d}${l}`,{method:o.method,headers:{...o.headers},body:ws(o),signal:i.signal}),m=Number(u.headers.get("content-length"));if(Number.isFinite(m)&&m>U.maxResponseBytes)return U.limitRejected+=1,i.abort(),t.code(502).send({error:{code:"INSTANCE_PROXY_RESPONSE_TOO_LARGE",message:`Instance response exceeds ${U.maxResponseBytes} bytes.`}});t.code(u.status);for(const[e,n]of Object.entries(bs(u.headers)))t.header(e,n);if(!u.body||"HEAD"===o.method)return a("completed"),t.send();const p=new c.Transform({transform(e,t,n){if(r+=e.length,r>U.maxResponseBytes)return U.limitRejected+=1,i.abort(),void n(Object.assign(new Error("Instance proxy response limit exceeded."),{code:"INSTANCE_PROXY_RESPONSE_TOO_LARGE"}));n(null,e)}});return s=!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),s||a("completed")}}),F.post("/api/node-agent/instances/:id/proxy/raw",{bodyLimit:zs},async(e,t)=>{const n=e.params.id,i=$i.parse(e.body),r=js(S.requireInstance(n)),s=i.path.startsWith("/")?i.path:`/${i.path}`;G({instanceId:n,action:"proxy.raw",method:i.method,path:s,instanceBase:r},"node instance raw proxy requested");const o=await C(`${r}${s}`,{method:i.method,headers:{...i.headers},body:ws(i)}),a=Number(o.headers.get("content-length"));if(Number.isFinite(a)&&a>U.maxResponseBytes)return U.limitRejected+=1,t.code(502).send({error:{code:"INSTANCE_PROXY_RESPONSE_TOO_LARGE",message:`Instance response exceeds ${U.maxResponseBytes} bytes.`}});let c;try{c=await async function(e,t){if(!e.body)return Buffer.alloc(0);const n=[];let i=0;const r=e.body.getReader();for(;;){const{done:e,value:s}=await r.read();if(e)break;if(i+=s.byteLength,i>t)throw await r.cancel("Instance proxy response limit exceeded.").catch(()=>{}),Object.assign(new Error("Instance proxy response limit exceeded."),{code:"INSTANCE_PROXY_RESPONSE_TOO_LARGE"});n.push(Buffer.from(s))}return Buffer.concat(n,i)}(o,U.maxResponseBytes)}catch(e){if(!(e instanceof Error)||"INSTANCE_PROXY_RESPONSE_TOO_LARGE"!==e.code)throw e;return U.limitRejected+=1,t.code(502).send({error:{code:"INSTANCE_PROXY_RESPONSE_TOO_LARGE",message:`Instance response exceeds ${U.maxResponseBytes} bytes.`}})}return G({instanceId:n,action:"proxy.raw",method:i.method,path:s,statusCode:o.status,byteLength:c.length},"node instance raw proxy completed"),{data:{status:o.status,headers:bs(o.headers),bodyBase64:c.toString("base64")}}}),F.get("/api/node-agent/instances/:id/proxy/ws/*",{websocket:!0},(e,t)=>{const n=t.params.id,i=t.params["*"]||"",r=t.url.indexOf("?"),s=r>=0?t.url.slice(r):"";let o;try{const r=js(S.requireInstance(n)),a=new URL(`/${i}${s}`,`${r}/`);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);G({instanceId:n,action:"proxy.ws",path:`/${i}${s}`,upstreamUrl:a.toString(),protocols:c||[]},"node instance websocket proxy opening"),o=c?new u(a,c):new u(a),o.on("open",()=>{G({instanceId:n,action:"proxy.ws",path:`/${i}${s}`},"node instance websocket proxy opened"),e.on("message",(e,t)=>o?.readyState===u.OPEN&&o.send(function(e,t){return t?e:e.toString()}(e,t))),e.on("close",()=>o?.close()),e.on("error",()=>o?.close())}),o.on("message",(t,n)=>{e.readyState===u.OPEN&&e.send(n?t:t.toString())}),o.on("close",()=>{G({instanceId:n,action:"proxy.ws",path:`/${i}${s}`},"node instance websocket proxy closed"),e.close()}),o.on("error",t=>{G({instanceId:n,action:"proxy.ws",path:`/${i}${s}`,error:t instanceof Error?t.message:String(t)},"node instance websocket proxy failed"),e.close(1011,"Instance websocket proxy failed.")})}catch(t){G({instanceId:n,action:"proxy.ws",path:`/${i}${s}`,error:t instanceof Error?t.message:String(t)},"node instance websocket endpoint unavailable"),o?.close(),e.close(1011,"Instance websocket endpoint is not reachable.")}}),F}function uo(e){const t=new URL("/api/node-agent/tunnel",e);return t.protocol="https:"===t.protocol?"wss:":"ws:",t.toString()}function mo(e,t){const n=new URL(t.tunnelUrl);n.searchParams.set("nodeId",t.nodeId);const i=t.secret?ar({nodeId:t.nodeId,keyId:t.keyId,secret:t.secret,method:"GET",pathWithQuery:`${n.pathname}${n.search}`}):{},r=new u(n,{headers:i}),s=new Map,o=new Map;let a;const c=e=>{const n=e.startsWith("/")?e:`/${e}`,i="function"==typeof t.port?t.port():t.port,r=new URL(`/api/node-agent${n}`,`http://127.0.0.1:${i}`);return r.protocol="ws:",r},d=e=>t.secret?ar({nodeId:t.nodeId,keyId:t.keyId,secret:t.secret,method:"GET",pathWithQuery:`${e.pathname}${e.search}`}):{},l=(e,t=1e3,n="")=>{const i=s.get(e);s.delete(e),i?.upstream?.close(t,n),i?.tunnel?.close(t,n)},m=(e,t,n=!1)=>new Promise((i,r)=>{e.send(t,{binary:n},e=>e?r(e):i())});return r.on("open",()=>{r.send(JSON.stringify({type:"node-agent.identify",nodeId:t.nodeId,serverTime:(new Date).toISOString()})),a=e.nodeAgentEventForwarder?.addOutput(r)}),r.on("close",()=>{for(const e of s.keys())l(e,1001,"Reverse tunnel disconnected.");for(const[e,t]of o)o.delete(e),t.controller.abort(),t.tunnel.close(1001,"Reverse tunnel disconnected.");a?.(),a=void 0}),r.on("message",async i=>{let a;try{a=JSON.parse(String(i))}catch{return void r.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:"",i="string"==typeof p.route&&p.route.startsWith("/")?p.route:"/health",r=p.init&&"object"==typeof p.init?p.init:{},s=r.headers&&"object"==typeof r.headers?r.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 o.set(e,{tunnel:l,controller:a}),l.on("open",async()=>{try{const n=await fetch((e=>{const n=e.startsWith("/")?e:`/${e}`,i="function"==typeof t.port?t.port():t.port;return new URL(`/api/node-agent${n}`,`http://127.0.0.1:${i}`)})(i),{method:dr(r.method),headers:{...s,...t.token?{authorization:`Bearer ${t.token}`}:{}},body:"string"==typeof r.body?r.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{o.delete(e)}}),l.on("close",()=>{a.abort(),o.delete(e)}),void l.on("error",()=>a.abort())}if("control-plane.websocket.open"===p.type){const e="string"==typeof p.streamId?p.streamId:"",i="string"==typeof p.route?p.route:"",o=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=o?.length?new u(c(i),o,{headers:a}):new u(c(i),{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)});s.set(e,{upstream:l,tunnel:p,close:(e=1e3,t="")=>{l.close(e,t),p.close(e,t)}}),l.on("open",()=>{r.send(JSON.stringify({type:"node-agent.websocket.open",streamId:e,protocol:l.protocol}))}),function(e,t,n={}){const i=n.pendingFrameLimit??256;let r=!1,s=Bn(t);const o=[],a=[];let c;const d=()=>{c&&(clearTimeout(c),c=void 0)},l=(n,r)=>{if(n.length>=i)return Kn(e,1011,"WebSocket bridge pending frame limit exceeded."),void Kn(t,1011,"WebSocket bridge pending frame limit exceeded.");n.push(r)};n.upstreamOpenTimeoutMs&&!s&&(c=setTimeout(()=>{s||r||(Kn(e,1011,"Upstream websocket did not open."),Kn(t))},n.upstreamOpenTimeoutMs)),e.on("open",()=>Jn(e,a)),t.on("open",()=>{d(),s=!0,n.onUpstreamOpen?.(),Jn(t,o)}),e.on("message",(e,n=!1)=>{const i={data:e,isBinary:Boolean(n)};Bn(t)?Gn(t,i):l(o,i)}),t.on("message",(t,n=!1)=>{const i={data:t,isBinary:Boolean(n)};Bn(e)?Gn(e,i):l(a,i)}),t.on("close",(t,i)=>{d(),n.onUpstreamClose?.(t,i),(s||r||!n.onUpstreamCloseBeforeOpen?.())&&Kn(e,t,i)}),t.on("error",t=>{n.onUpstreamError?.(t),(s||r||!n.onUpstreamErrorBeforeOpen?.(t))&&Kn(e)}),e.on("close",(e,i)=>{d(),r=!0,n.onClientClose?.(e,i),Kn(t,e,i)}),e.on("error",e=>{d(),r=!0,n.onClientError?.(e),Kn(t,1011,"WebSocket bridge client failed.")})}(p,l,{pendingFrameLimit:256,upstreamOpenTimeoutMs:1e4,onClientClose:()=>{s.delete(e)},onClientError:t=>{s.delete(e),r.send(JSON.stringify({type:"node-agent.websocket.error",streamId:e,message:t instanceof Error?t.message:String(t)}))},onUpstreamClose:(t,n)=>{s.delete(e),r.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=>{s.delete(e),r.send(JSON.stringify({type:"node-agent.websocket.error",streamId:e,message:t instanceof Error?t.message:String(t)}))}})}catch(t){r.send(JSON.stringify({type:"node-agent.websocket.error",streamId:e,message:t instanceof Error?t.message:String(t)}))}return}if("control-plane.websocket.close"===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:"",i=p.init&&"object"==typeof p.init?p.init:{},s="string"==typeof p.route&&p.route.startsWith("/")?p.route:"/health",o=i.headers&&"object"==typeof i.headers?i.headers:{};try{const a=await e.inject({method:dr(i.method),url:`/api/node-agent${s}`,headers:{...o,...t.token?{authorization:`Bearer ${t.token}`}:{}},payload:"string"==typeof i.body?i.body:void 0});r.send(JSON.stringify({type:"node-agent.response",requestId:n,status:a.statusCode,headers:a.headers,body:a.body}))}catch(e){r.send(JSON.stringify({type:"node-agent.response",requestId:n,status:502,error:{code:"NODE_AGENT_REVERSE_INJECT_FAILED",message:e instanceof Error?e.message:String(e)}}))}}}),r}async function po(e){const s=Gi(e.dataDir),o=(a=e.host,c=e.port,En.parse({bindScope:"0.0.0.0"===a.trim()?"all-ipv4":"loopback",port:c}));var a,c;const d=t.existsSync(s.settingsPath),l=function(e,t){return new nr(e.settingsPath,()=>({version:1,externalListener:t}),{schema:ps,sanitize:ks})}(s,o),u=l.get().externalListener,m=function(e,r={}){return function(e,r={}){t.mkdirSync(n.dirname(e),{recursive:!0});const s={pid:process.pid,hostname:p.hostname(),component:r.component,command:process.argv.join(" "),acquiredAt:(new Date).toISOString(),token:i.randomUUID(),startIdentity:T(process.pid),dataDir:r.dataDir,host:r.host,port:r.port,instanceId:r.instanceId};for(let n=0;n<5;n+=1)try{return t.mkdirSync(e),t.writeFileSync(S(e),`${JSON.stringify({token:s.token,pid:s.pid,startIdentity:s.startIdentity,startedAt:(new Date).toISOString()})}\n`,{encoding:"utf8",mode:384,flag:"wx"}),R(e,s),{lockPath:e,owner:s,release(){const n=x(e);n?.token===s.token&&t.rmSync(e,{recursive:!0,force:!0})}}}catch(s){if("EEXIST"!==s.code)throw s;const o=x(e);if(O(o))throw new N(e,o,r.error);if(!o&&(P(e)||L(e)<(r.incompleteLockStaleMs??2e3))){if(n+1<5){M();continue}throw new N(e,void 0,r.error)}const a=i.randomUUID();if(!$(e,a)){if(n+1<5){M();continue}throw new N(e,x(e),r.error)}const c=x(e);if(O(c))throw j(E(e)),new N(e,c,r.error);if(o?.token&&c?.token!==o.token){j(E(e));continue}if(!U(e,a))continue;t.rmSync(e,{recursive:!0,force:!0})}const o=x(e);throw new N(e,o,r.error)}(e,{...r,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:s.dataDir,host:Ts(u.bindScope),port:u.port});try{const i={...e,port:u.port},o=await lo(i),a=function(e,t,n,i){const r=t.token||process.env.TASK_HANDOFF_NODE_AGENT_TOKEN,s=new rs(n),o=new Map,a=t=>{const n=t.url.replace(/\/$/,"");o.get(n)?.close(1e3,"Reverse tunnel reconnecting.");const s=mo(e,{tunnelUrl:uo(t.url),nodeId:i,port:()=>e.nodeAgentState.currentListenerPort,token:r,keyId:t.keyId,secret:t.secret});return o.set(n,s),s.on("close",()=>{o.get(n)===s&&o.delete(n)}),s};return{connect:a,connectConfigured:()=>{const 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 i=new URL("/api/node-agent/tunnel",n);return i.protocol="https:"===i.protocol?"wss:":"ws:",i.toString()}(t);if(n){const a=s.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),c=(process.env.TASK_HANDOFF_CONTROL_PLANE_URL||n).replace(/\/$/,"");o.get(c)?.close(1e3,"Reverse tunnel reconnecting.");const d=mo(e,{tunnelUrl:n,nodeId:i,port:()=>e.nodeAgentState.currentListenerPort,token:r,keyId:a?.keyId,secret:a?.secret});o.set(c,d)}for(const e of s.configuredRemoteControlPlanes())e.url&&!1!==e.active&&a({url:e.url,keyId:e.keyId,secret:e.secret})},closeAll:()=>{for(const e of o.values())e.close(1001,"Node agent shutting down.");o.clear()}}}(o,i,s,new rs(s).resolveNodeId(e.nodeId||process.env.TASK_HANDOFF_NODE_ID));o.decorate("nodeAgentReverseTunnels",a);const c=new ro({app:o,state:o.nodeAgentState,settings:l,config:u,source:d?"persisted":"bootstrap"});let p;o.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}}},i=()=>{n("SIGINT")},r=()=>{n("SIGTERM")};process.once("SIGINT",i),process.once("SIGTERM",r),e.addHook("onClose",async()=>{process.off("SIGINT",i),process.off("SIGTERM",r)})}(o),o.addHook("onClose",async()=>{p?.close(),m.release()});try{await o.ready();const i=e.ipcPath||process.env.TASK_HANDOFF_NODE_AGENT_IPC_PATH||ir(s.dataDir);p=await async function(e,i){!function(e,i=process.platform){if("win32"!==i){t.mkdirSync(n.dirname(e),{recursive:!0,mode:448});try{t.chmodSync(n.dirname(e),448)}catch{}try{t.unlinkSync(e)}catch(e){if("ENOENT"!==e.code)throw e}}}(i);const s=r.createServer((t,n)=>{e.server.emit("request",t,n)});return s.on("upgrade",(t,n,i)=>{e.server.emit("upgrade",t,n,i)}),await new Promise((e,t)=>{s.once("error",t),s.listen(i,()=>{s.off("error",t),e()})}),s}(o,i),await c.start(),a.connectConfigured(),await(o.nodeAgentRestoreLocalInstances?.())}catch(e){throw await o.close(),e}}catch(e){throw m.release(),e}}function go(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 ho(e){if("local-ipc"!==e&&"local-loopback"!==e)throw new Error("Connection mode must be local-ipc or local-loopback.");return e}function fo(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",go,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",ho).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 po({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",fo).option("--json","Print raw JSON output").action(async e=>{const n=t.opts(),i=e.ipcPath||n.ipcPath||process.env.TASK_HANDOFF_NODE_AGENT_IPC_PATH,s=e.dataDir||n.dataDir||process.env.TASK_HANDOFF_NODE_AGENT_DATA_DIR,o=e.endpoint?void 0:i||ir(s||Ki()),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}:{}}),i=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 i=n.method||"GET",s="string"==typeof n.body||n.body instanceof Buffer?n.body:void 0===n.body||null===n.body?void 0:String(n.body),o=new Headers(n.headers||{});return void 0===s||o.has("content-length")||o.set("content-length",String(Buffer.byteLength(s))),new Promise((a,d)=>{const l=r.request({socketPath:e,method:i,path:`/api/node-agent${t}`,headers:Object.fromEntries(o.entries())},e=>{const t=e.statusCode||500;a(new Response("HEAD"!==i&&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!==s&&l.write(s),l.end()})}(e.ipcPath,"/pairing/invites",{method:"POST",headers:t,body:n}),s=await i.json().catch(()=>({}));if(!i.ok)throw new Error(s.error?.message||`Node agent pairing invite failed with HTTP ${i.status}`);const o="string"==typeof s.data?.joinToken?s.data.joinToken:"";if(!o)throw new Error("Node agent pairing invite response did not include a join token.");return{nodeId:"string"==typeof s.data?.nodeId?s.data.nodeId:"",joinToken:o,expiresAt:"string"==typeof s.data?.expiresAt?s.data.expiresAt:""}}({endpoint:e.endpoint,ipcPath:o,token:e.token,expiresInMs:e.expiresInMs});e.json?console.log(JSON.stringify(a,null,2)):(a.nodeId&&console.log(`Node: ${a.nodeId}`),console.log(`Join token: ${a.joinToken}`),a.expiresAt&&console.log(`Expires: ${a.expiresAt}`))}),await t.parseAsync(process.argv)})().catch(e=>{console.error(e instanceof Error?e.message:String(e)),process.exitCode=1});
1
+ "use strict";var e=require("commander"),t=require("node:fs"),n=require("node:path"),i=require("node:crypto"),r=require("node:http"),s=require("node:net"),o=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"),I=require("node:fs/promises"),y=require("node:stream/promises"),A=require("tar"),b="undefined"!=typeof document?document.currentScript:null;function w(e,n){try{const i=JSON.parse(t.readFileSync(e,"utf8"));if(n&&i.name!==n)return;return"string"==typeof i.version&&i.version.trim()?i.version.trim():void 0}catch{return}}function z(e,t=process.env,i=e){const r=t.TASK_HANDOFF_VERSION?.trim();if(r)return r;const s=i.split("/").at(-1),o=[process.argv[1]?n.dirname(n.resolve(process.argv[1])):void 0,process.cwd()].filter(e=>Boolean(e));for(const t of new Set(o)){let i=t;for(;;){const t=w(n.join(i,"package.json"),e);if(t)return t;const r=n.dirname(i);if(r===i)break;i=r}}let a;for(const e of new Set(o)){let t=e;for(;;){if(s){const e=w(n.join(t,"packages",s,"package.json"),i);if(e)return e}a||=w(n.join(t,"package.json"));const e=n.dirname(t);if(e===t)break;t=e}}return a||"unknown"}class N extends Error{code;lockPath;owner;constructor(e,t,n={}){const i=t?.pid?` pid ${t.pid}`:"";super(`${n.label||"Process"} is already running${i}. Lock: ${e}`),this.name="ProcessSingletonError",this.code=n.code||"PROCESS_ALREADY_RUNNING",this.lockPath=e,this.owner=t}}function v(e){return n.join(e,"owner.json")}function S(e){return n.join(e,"initializing.json")}function E(e){return n.join(e,"recovering.json")}function _(e){return Number.isInteger(e)&&Number(e)>0}function T(e,n=process.platform){if(_(e)){if("linux"===n)try{const n=t.readFileSync(`/proc/${e}/stat`,"utf8"),i=n.lastIndexOf(")");if(i<0)return;const r=n.slice(i+2).trim().split(/\s+/)[19];return r?`linux:${r}`:void 0}catch{return}if(["darwin","freebsd","openbsd","aix","sunos"].includes(n)){const t=a.spawnSync("ps",["-o","lstart=","-p",String(e)],{encoding:"utf8",timeout:1e3}),i=0===t.status?t.stdout.trim().replace(/\s+/g," "):"";return i?`${n}:${i}`:void 0}if("win32"===n){const t=`(Get-Process -Id ${e} -ErrorAction Stop).StartTime.ToUniversalTime().Ticks`,n=a.spawnSync("powershell.exe",["-NoProfile","-NonInteractive","-Command",t],{encoding:"utf8",timeout:2e3}),i=0===n.status?n.stdout.trim():"";return/^\d+$/.test(i)?`win32:${i}`:void 0}}}function k(e){try{const n=JSON.parse(t.readFileSync(v(e),"utf8"));if(_(n.pid)&&"string"==typeof n.startTime){const e=n;return{pid:e.pid,hostname:"string"==typeof e.hostname&&e.hostname?e.hostname: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(!(_(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=k;function C(e){if(!_(e))return!1;try{return process.kill(Number(e),0),!0}catch(e){return"EPERM"===e.code}}function O(e){if(!e||!C(e.pid))return!1;if(!e.startIdentity)return!0;const t=T(e.pid);return void 0===t||t===e.startIdentity}function R(e,i){const r=n.join(e,`.owner-${i.token}.tmp`);t.writeFileSync(r,`${JSON.stringify(i,null,2)}\n`,{encoding:"utf8",mode:384,flag:"wx"});const s=D(e);if(s?.token!==i.token)throw j(r),new Error(`Process lock initialization was superseded: ${e}`);t.renameSync(r,v(e)),j(S(e))}function D(e){try{return JSON.parse(t.readFileSync(S(e),"utf8"))}catch{return}}function P(e){const t=D(e);return _(t?.pid)&&O({pid:t.pid,startIdentity:t.startIdentity})}function j(e){try{t.unlinkSync(e)}catch(e){if("ENOENT"!==e.code)throw e}}function M(){Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,20)}function L(e){try{const n=D(e),i=Date.parse(n?.startedAt||"");return Number.isFinite(i)?Math.max(0,Date.now()-i):Math.max(0,Date.now()-t.statSync(e).mtimeMs)}catch{return 0}}function $(e,r){try{return t.writeFileSync(E(e),`${JSON.stringify({token:r,pid:process.pid,startedAt:(new Date).toISOString()})}\n`,{encoding:"utf8",mode:384,flag:"wx"}),!0}catch(s){if("EEXIST"===s.code)return!!function(e){const r=E(e),s=F(r),o=Date.parse(s?.startedAt||"");if(C(s?.pid)||Number.isFinite(o)&&Date.now()-o<2e3)return!1;const a=n.join(e,`.recovering-${i.randomUUID()}.stale`);try{t.renameSync(r,a)}catch(e){if(["ENOENT","EEXIST"].includes(e.code||""))return!1;throw e}const c=F(a);if(c?.token===s?.token)return j(a),!0;try{t.linkSync(a,r)}catch(e){if("EEXIST"!==e.code)throw e}finally{j(a)}return!1}(e)&&$(e,r);if("ENOENT"===s.code)return!1;throw s}}function F(e){try{return JSON.parse(t.readFileSync(e,"utf8"))}catch{return}}function U(e,t){return F(E(e))?.token===t}const V=41943040,H="ai.sessions",q=m.z.string().trim().min(1).max(80),B=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 K=m.z.enum(["thinking","tool","editing","approval","responding","unknown"]),G=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(),J=m.z.enum(["pending-init","running","interrupted","completed","errored","shutdown","not-found"]),W=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:J,activity:W.optional(),message:m.z.string().trim().max(1e3).optional(),updatedAt:m.z.string().datetime()}).strict(),X=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(),Q=m.z.enum(["image","file"]),ee=m.z.object({id:m.z.string().trim().min(1).max(120),kind:Q,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)}),te=m.z.union([ee.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.`})}),ee.extend({source:m.z.object({type:m.z.literal("runtime-path"),path:m.z.string().trim().min(1).max(4096)}).strict()}).strict()]),ne=ee.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:Q.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:Q,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()]),re=m.z.enum(["auto","queue","steer","immediate"]),se=m.z.enum(["ask","auto-review","full-access"]),oe=m.z.enum(["review","rename","goal","compact"]);m.z.object({command:oe,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:oe,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 ae=m.z.object({name:m.z.string().trim().min(1).max(240),path:m.z.string().trim().min(1).max(4096)}),ce=m.z.discriminatedUnion("kind",[ae.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(),ae.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(),ae.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()]),de=m.z.array(ce).max(20).default([]),le=m.z.enum(["plugin","skill","file","directory","app"]),ue=m.z.object({kind:le,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."})}),me=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(ue).max(1e3).default([]),diagnostics:m.z.array(me).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(ue.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 pe=m.z.object({message:m.z.string().trim().min(1).max(2e4),mode:re.optional(),permissionMode:se.optional()});pe.extend({attachments:m.z.array(te).max(6).default([]),references:de}).strict().superRefine((e,t)=>{e.attachments.reduce((e,t)=>e+("inline"===t.source.type?t.size:0),0)>V&&t.addIssue({code:m.z.ZodIssueCode.custom,path:["attachments"],message:"Inline attachments must be 41943040 bytes or less in total."})}),pe.extend({attachments:m.z.array(ie).max(6).default([]),references:de}).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 ge=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(ne).max(6).default([]),references:de,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(),he=m.z.object({pendingCount:m.z.number().int().min(0).default(0),items:m.z.array(ge).max(100).default([])}).strict().default({pendingCount:0,items:[]}),fe=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(),ye=m.z.object({id:m.z.string().trim().min(1).max(240),providerTurnId:m.z.string().trim().max(240).optional(),source:fe.optional(),userPrompt:m.z.string().trim().optional(),status:m.z.enum(["queued","running","waiting","completed","failed"]).default("running"),phase:K.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(),Ae=ye.pick({id:!0,providerTurnId:!0,userPrompt:!0,status:!0,phase:!0,summary:!0,lastMessage:!0,contextCompactions:!0,startedAt:!0,updatedAt:!0,completedAt:!0}).strict(),be=m.z.object({id:m.z.string().trim().min(1).max(120),agent:q,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(ye).max(50).optional(),status:B.default("running"),phase:K.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:G.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:X,queue:he}).strict();m.z.object({session:be,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 we=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(we).max(50).default([])}).strict(),m.z.object({items:m.z.array(we).max(50).default([])}).strict(),m.z.object({item:we,turns:m.z.array(Ae).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=be.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}),Ne=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:Ne}).strict(),Ne.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 ve=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:ve}).strict(),Ee=m.z.object({meta:Se,snapshot:Ne}).strict(),_e=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(),Te=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:Ee}).strict(),m.z.object({type:m.z.literal("ai-session.patch"),payload:_e}).strict(),m.z.object({type:m.z.literal("ai-session.removed"),payload:Te}).strict()])).default([])}).strict();const ke=m.z.object({source:fe,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=ke.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(ye).max(50).optional(),status:B.optional(),phase:K.optional(),summary:m.z.string().trim().max(1e3).optional(),lastMessage:m.z.string().trim().optional(),lastMessageItemId:m.z.string().trim().max(240).optional(),currentTool:G.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(),Ce=ke.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:B.optional(),phase:K.optional(),summary:m.z.string().trim().max(1e3).optional(),error:m.z.string().trim().max(4e3).optional(),currentTool:G.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,Ce]);const Oe=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()]),Re=m.z.union([Oe,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()]),De=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:Re,action:De,policy:Pe.default({maxConcurrentRuns:1,whenBusy:"skip"}),createdAt:m.z.string().datetime(),updatedAt:m.z.string().datetime()}).strict(),Me=m.z.object({type:m.z.literal("ai-session"),aiSessionId:m.z.string().trim().min(1).max(160)}).strict(),Le=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:Me,localName:m.z.string().trim().min(1).max(160).optional(),createdAt:m.z.string().datetime(),updatedAt:m.z.string().datetime()}).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),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(),Fe=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:Me,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(Le).default([]),runtime:m.z.array($e).default([]),recentRuns:m.z.array(Fe).default([])}).strict();const Ue="2026-07-29",Ve=m.z.string(),He=m.z.string().trim().min(1).max(120).regex(/^[a-zA-Z0-9][a-zA-Z0-9_.:-]*$/),qe=m.z.string().datetime(),Be=m.z.record(m.z.string(),m.z.string()).default({}),Ke=m.z.record(m.z.string(),m.z.string()).default({}),Ge=m.z.string().regex(/^\d{4}-\d{2}-\d{2}$/,"Protocol version must use YYYY-MM-DD format."),Je=/^[A-Za-z0-9_][A-Za-z0-9_.-]{0,127}$/,We=/^sha256:([a-fA-F0-9]{64})$/,Ye=/^(?:localhost|[a-z0-9](?:[a-z0-9.-]*[a-z0-9])?)(?::[1-9][0-9]{0,4})?$/,Xe=/^[a-z0-9]+(?:(?:[._]|__|-+)[a-z0-9]+)*$/;function Ze(e){const t=e.trim();if(!t||t.length>512||t.includes("://")||/\s/.test(t))throw new Error("Docker image reference must not contain a URL scheme or whitespace.");const n=t.indexOf("@");if(-1!==n&&n!==t.lastIndexOf("@"))throw new Error("Docker image reference contains more than one digest separator.");const i=-1===n?void 0:t.slice(n+1),r=-1===n?t:t.slice(0,n),s=i?We.exec(i):void 0;if(i&&!s)throw new Error("Docker image digest must use sha256 followed by 64 hexadecimal characters.");const o=r.lastIndexOf("/"),a=r.lastIndexOf(":"),c=a>o,d=c?r.slice(a+1):void 0,l=c?r.slice(0,a):r;if(d&&!Je.test(d))throw new Error("Docker image tag is invalid.");if(!d&&!s)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=>!Xe.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=s?`sha256:${s[1].toLowerCase()}`:void 0;return`${g}${d?`:${d}`:""}${h?`@${h}`:""}`}function Qe(e){const t=Ze(e),n=t.indexOf("@"),i=-1===n?void 0:t.slice(n+1),r=-1===n?t:t.slice(0,n),s=r.lastIndexOf("/"),o=r.lastIndexOf(":"),a=o>s;return{reference:t,repository:a?r.slice(0,o):r,tag:a?r.slice(o+1):void 0,digest:i}}const et=m.z.string().trim().min(1).max(512).transform((e,t)=>{try{return Ze(e)}catch(e){return t.addIssue({code:"custom",message:e instanceof Error?e.message:String(e)}),m.z.NEVER}}),tt=m.z.string().trim().transform((e,t)=>{const n=We.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)}),nt=m.z.object({codexModelHash:He.nullable().optional(),claudeModelHash:He.nullable().optional()}).strict().default({}),it=m.z.object({imageId:He,tag:m.z.string().trim().min(1).max(128).regex(Je).optional()}).strict(),rt={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&&rt[t.imageId]||t.imageId,..."string"==typeof t.tag?{tag:t.tag}:{}}}if("string"==typeof t)return{imageId:rt[t]||t}}function ot(e){if(!e||"object"!=typeof e||Array.isArray(e))return e;const t=e,{defaultImageId:n,...i}=t;return{...i,defaultImageSelection:st(t.defaultImageSelection,n)}}const at=m.z.object({id:He,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(),ct=m.z.object({code:m.z.enum(["APP_CATALOG_INVALID"]),message:m.z.string().trim().min(1).max(500)}).strict(),dt=m.z.object({items:m.z.array(at).max(256),observedAt:qe,issues:m.z.array(ct).max(32).default([])}).strict(),lt=m.z.enum(["linux","darwin","win32","freebsd","openbsd","aix","sunos","unknown"]),ut=m.z.enum(["x64","arm64","arm","ia32","ppc64","s390x","riscv64","unknown"]),mt=m.z.enum(["apt","dnf","brew","npm"]),pt=m.z.enum(["user","passwordless-sudo","root"]),gt=m.z.object({platform:lt,arch:ut,installers:m.z.array(mt).max(8),privilege:pt,installerAccess:m.z.object({npmGlobalWritable:m.z.boolean().optional()}).strict().optional()}).strict(),ht=m.z.enum(["installed","not-installed","broken","unsupported"]),ft=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(),yt=m.z.object({id:He,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:ht,managementSource:ft,version:m.z.string().trim().max(120).optional(),canInstall:m.z.boolean(),canUninstall:m.z.boolean(),installReason:It.optional(),uninstallReason:It.optional(),activeJobId:He.optional()}).strict(),At=m.z.enum(["install","uninstall"]),bt=m.z.enum(["queued","running","succeeded","failed","cancelled","interrupted"]),wt=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"]}),zt=m.z.object({executable:m.z.string().trim().min(1).max(4096),args:m.z.array(m.z.string().max(4096)).max(128)}).strict(),Nt=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(He).max(64).optional()}).strict(),vt=m.z.object({id:He,requestId:He.optional(),appId:He,operation:At,state:bt,phase:m.z.string().trim().min(1).max(120).optional(),progress:wt.optional(),command:zt.optional(),logTail:m.z.string().max(32768).optional(),logTruncated:m.z.boolean().optional(),error:Nt.optional(),requestedAt:qe,startedAt:qe.optional(),finishedAt:qe.optional(),updatedAt:qe}).strict(),St=m.z.object({streamId:He,sequence:m.z.number().int().nonnegative(),capabilities:gt,apps:m.z.array(yt).max(256),activeJobs:m.z.array(vt).max(256),recentJobs:m.z.array(vt).max(256),observedAt:qe}).strict();m.z.object({requestId:He.optional()}).strict(),m.z.object({job:vt}).strict(),m.z.object({type:m.z.literal("app-management"),streamId:He,sequence:m.z.number().int().nonnegative(),observedAt:qe,job:vt.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 Et=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:Ve.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(),_t=m.z.enum(["stable","beta","alpha"]),Tt=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(),kt=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:qe.optional(),matchedAt:qe.optional(),error:kt.optional()}).strict(),Ct=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(He).max(1024).default([]),stoppedInstanceIds:m.z.array(He).max(1024).default([]),activeInstanceIds:m.z.array(He).max(1024).default([])}).strict(),Ot=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(He).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(),Rt=m.z.object({channel:_t.default("stable")}).strict(),Dt=m.z.object({source:m.z.literal("npm"),channel:_t,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(Tt).default([]),impact:Ct,updateAvailable:m.z.boolean(),supported:m.z.boolean().default(!0),reason:m.z.string().trim().max(2048).optional(),checkedAt:qe,preflightToken:m.z.string().trim().min(16).max(240).optional()}).strict(),Pt=m.z.object({id:He,nodeId:He,source:m.z.literal("npm"),channel:_t,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(Tt).default([]),impact:Ct,rollout:Ot,status:m.z.enum(["queued","updating-node","restarting-node","converging-instances","succeeded","degraded","failed"]),error:kt.optional(),startedAt:qe.optional(),completedAt:qe.optional(),createdAt:qe,updatedAt:qe}).strict(),jt=m.z.object({channel:_t,targetVersion:m.z.string().trim().min(1).max(240),preflightToken:m.z.string().trim().min(16).max(240)}).strict(),Mt=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(),Lt=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(),$t=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:He,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:Mt.default({type:"branch",name:"main"}),auth:Lt.default({type:"none"}),clone:$t.default({submodules:!1,lfs:!1,subdirectory:""}),defaultImageSelection:it.optional(),labels:Be,createdAt:qe,updatedAt:qe}).strict();const Ft=m.z.object({id:He,nodeId:He,name:m.z.string().trim().min(1).max(160),path:m.z.string().trim().min(1).max(4096),defaultImageSelection:it.optional(),labels:Be,createdAt:qe,updatedAt:qe}).strict(),Ut=m.z.discriminatedUnion("type",[m.z.object({type:m.z.literal("git-repository"),repositoryId:He.optional(),url:m.z.string().trim().min(1).max(2048),provider:m.z.string().trim().max(80).optional(),ref:Mt.default({type:"branch",name:"main"}),auth:Lt.default({type:"none"}),clone:$t.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:Mt.default({type:"branch",name:"main"}),auth:Lt.default({type:"none"}),clone:$t.default({submodules:!1,lfs:!1,subdirectory:""})}).strict(),m.z.object({type:m.z.literal("local-folder"),localFolderId:He.optional(),path:m.z.string().trim().min(1).max(4096),ownerNodeId:He.optional()}).strict()]),Vt=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(),Ht=m.z.enum(["codex","claude"]),qt=m.z.object({id:He,name:m.z.string().trim().min(1).max(160),source:Ut,defaultImageSelection:it.optional(),defaultNodeId:He.optional(),defaultRuntimeId:He.optional(),workspacePolicy:Vt,labels:Be,createdAt:qe,updatedAt:qe}).strict(),Bt=m.z.object({id:He,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:Ht,enabled:m.z.boolean().default(!0),order:m.z.number().int().min(0).max(1e6).default(0),labels:Be,createdAt:qe,updatedAt:qe}).strict(),Kt=Bt,Gt=Bt.omit({key:!0}).extend({keyPreview:m.z.string().trim().min(1).max(160),keySet:m.z.boolean()}).strict(),Jt=Gt.extend({referenceCount:m.z.number().int().min(0)}).strict(),Wt=m.z.object({instanceId:He,codexModelHash:He.optional(),claudeModelHash:He.optional(),updatedAt:qe}).strict(),Yt=m.z.discriminatedUnion("type",[m.z.object({type:m.z.literal("control-plane"),name:Bt.shape.name,enabled:Bt.shape.enabled,order:Bt.shape.order}).strict(),m.z.object({type:m.z.literal("node"),nodeId:He,name:Bt.shape.name,enabled:Bt.shape.enabled,order:Bt.shape.order,referenceCount:m.z.number().int().min(0)}).strict()]),Xt=m.z.object({id:He,model:Gt,locations:m.z.array(Yt).min(1),referenceCount:m.z.number().int().min(0).default(0)}).strict(),Zt=m.z.object({nodeId:He,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(Xt),nodeDiagnostics:m.z.array(Zt).default([]),updatedAt:qe}).strict();const Qt=Bt.omit({id:!0,createdAt:!0,updatedAt:!0}).strict(),en=Qt.partial().strict(),tn=Bt,nn=m.z.object({modelSelection:nt,codexModelHash:He.optional(),claudeModelHash:He.optional()}).strict();function rn(e){const t={app:Ht.parse(e.app),endpoint:Bt.shape.endpoint.parse(e.endpoint),key:Bt.shape.key.parse(e.key),model:Bt.shape.model.parse(e.model)};return`mdl_${i.createHash("sha256").update(JSON.stringify(t)).digest("hex")}`}const sn=m.z.enum(["market","custom"]),on=m.z.enum(["active","deprecated","yanked"]),an=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:tt.optional()}).strict()]),cn=m.z.array(m.z.string().trim().min(1).max(80)).default([]),dn=m.z.array(m.z.string().trim().min(1).max(120)).default([]),ln=m.z.record(m.z.string().trim().min(2).max(35),m.z.string().trim().min(1).max(4096)),un=m.z.object({os:m.z.string().trim().min(1).max(40),architecture:m.z.string().trim().min(1).max(40),digest:tt.optional(),downloadSizeBytes:m.z.number().int().positive().optional(),unpackedSizeBytes:m.z.number().int().positive().optional()}).strict(),mn=m.z.object({name:m.z.string().trim().min(1).max(128).regex(Je),version:m.z.string().trim().min(1).max(160).optional(),reference:et,manifestDigest:tt.optional(),publishedAt:qe.optional(),platforms:m.z.array(un).default([]),status:on.default("active")}).strict(),pn=m.z.object({id:He,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:ln.optional(),cover:an.optional(),repository:m.z.string().trim().min(1).max(512),defaultTag:m.z.string().trim().min(1).max(128).regex(Je),tags:m.z.array(mn).min(1),capabilities:cn,optionalApps:dn,defaultEnv:Ke,labels:Be,status:on.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:Ge,catalogId:He,revision:m.z.string().trim().min(1).max(240),source:m.z.enum(["embedded","remote","cache"]),generatedAt:qe,expiresAt:qe.optional(),items:m.z.array(pn)}).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:qe,error:m.z.string().trim().max(4096).optional()}).strict(),m.z.object({id:He,origin:m.z.literal("custom"),name:m.z.string().trim().min(1).max(160),description:m.z.string().trim().max(4096).optional(),localizedDescriptions:ln.optional(),cover:an.optional(),reference:et,repository:m.z.string().trim().min(1).max(512),tag:m.z.string().trim().min(1).max(128).regex(Je).optional(),pullPolicy:m.z.literal("if-not-present").default("if-not-present"),capabilities:cn,optionalApps:dn,defaultEnv:Ke,labels:Be,createdAt:qe,updatedAt:qe}).strict();const gn=m.z.object({name:m.z.string().trim().min(1).max(128).regex(Je),version:m.z.string().trim().min(1).max(160).optional(),reference:et,manifestDigest:tt.optional(),status:on}).strict(),hn=m.z.object({id:He,origin:sn,name:m.z.string().trim().min(1).max(160),description:m.z.string().trim().max(4096).optional(),localizedDescriptions:ln.optional(),cover:an,repository:m.z.string().trim().min(1).max(512),tag:m.z.string().trim().min(1).max(128).regex(Je).optional(),availableTags:m.z.array(gn),reference:et,digest:tt.optional(),downloadSizeBytes:m.z.number().int().positive().optional(),unpackedSizeBytes:m.z.number().int().positive().optional(),capabilities:cn,optionalApps:dn,defaultEnv:Ke,labels:Be,readOnly:m.z.boolean(),lifecycleStatus:on.optional(),market:m.z.object({catalogId:He,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(),fn=m.z.object({id:He,origin:sn,name:m.z.string().trim().min(1).max(160),description:m.z.string().trim().max(4096).optional(),localizedDescriptions:ln.optional(),cover:an.optional(),repository:m.z.string().trim().min(1).max(512),tag:m.z.string().trim().min(1).max(128).regex(Je).optional(),requestedReference:et,resolvedDigest:tt.optional(),resolvedReference:et.optional(),downloadSizeBytes:m.z.number().int().positive().optional(),pullPolicy:m.z.literal("if-not-present").default("if-not-present"),capabilities:cn,optionalApps:dn,defaultEnv:Ke,labels:Be,market:m.z.object({catalogId:He,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:qe,updatedAt:qe}).strict(),In=m.z.object({phase:m.z.enum(["checking-image","pulling-image","resolving-image","ready","failed"]),requestedReference:et,generation:m.z.number().int().nonnegative().default(0),error:m.z.string().trim().max(4096).optional(),startedAt:qe,updatedAt:qe}).strict(),yn="image.pull.terminal.output",An="image.pull.terminal.finished",bn=m.z.object({instanceId:He,generation:m.z.number().int().nonnegative(),requestedReference:et,sequence:m.z.number().int().nonnegative(),observedAt:qe}).strict(),wn=bn.extend({data:m.z.string().min(1).max(65536),replay:m.z.boolean().optional()}).strict(),zn=bn.extend({outcome:m.z.enum(["succeeded","failed"])}).strict();bn.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 Nn=m.z.object({id:He,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:He.optional(),secret:m.z.string().trim().max(4096).optional(),pairedAt:qe.optional(),pairing:m.z.object({status:m.z.enum(["pending","paired","expired"]).default("pending"),joinToken:m.z.string().trim().max(4096).optional(),expiresAt:qe.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:dt.optional(),labels:Be,lastSeenAt:qe.optional(),createdAt:qe,updatedAt:qe}).strict(),vn=m.z.object({id:He,nodeId:He,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:Be,createdAt:qe,updatedAt:qe}).strict(),Sn=m.z.object({instanceId:He,runtimeKind:m.z.literal("docker"),state:m.z.enum(["pending","available","stopped","unavailable"]),sampledAt:qe,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:He.optional(),platform:lt.optional()}).passthrough();const En=m.z.object({bindScope:m.z.enum(["loopback","all-ipv4"]),port:m.z.number().int().min(1).max(65535)}).strict(),_n=En.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(),Tn=En;m.z.object({nodeId:He,joinToken:m.z.string().trim().min(1),expiresAt:qe}).passthrough(),m.z.object({id:He,keyId:He,url:m.z.string().trim().min(1).max(2048).optional(),name:m.z.string().trim().min(1).max(160).optional(),pairedAt:qe,updatedAt:qe.optional(),active:m.z.boolean().optional(),current:m.z.boolean().optional()}).passthrough(),m.z.object({remote:m.z.object({id:He,url:m.z.string().trim().min(1).max(2048).optional(),keyId:He,pairedAt:qe,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 kn=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:hn,status:m.z.enum(["available","pull-required","unknown"]),localImage:kn.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 Cn=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(),On=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"}),Rn=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(),Dn=m.z.object({id:He,name:m.z.string().trim().min(1).max(160),projectId:He.optional(),source:Ut,sourceSnapshot:m.z.record(m.z.string(),m.z.unknown()).default({}),modelSelection:nt,nodeId:He,runtimeId:He,imageSelection:it.optional(),imageSnapshot:fn.optional(),imageProvisioning:In.optional(),stateRevision:m.z.number().int().min(0).default(0),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:Ve.optional(),instanceVersion:m.z.string().trim().max(80).optional(),build:Et.optional(),runtimeVersion:xt.optional(),ready:m.z.boolean().default(!1),capabilities:m.z.record(m.z.string(),m.z.unknown()).default({}),appInventory:dt.optional(),config:m.z.object({autoImportAgentConfigs:m.z.boolean().default(!0),defaultCodexPermissionMode:se.default("ask")}).strict().default({autoImportAgentConfigs:!0,defaultCodexPermissionMode:"ask"}),workspace:Rn.default({status:"unknown"}),target:Cn.default({strategy:"direct-port",status:"unknown"}),access:On,apps:m.z.object({runningCount:m.z.number().int().min(0).default(0),problemCount:m.z.number().int().min(0).default(0),updatedAt:qe.optional(),revision:m.z.number().int().min(0).optional()}).strict().default({runningCount:0,problemCount:0}),aiSessions:Ne.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(Le).default([]),runtime:m.z.array($e).default([])}).strict()).default([]),recentRuns:m.z.array(Fe).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:qe.optional(),createdAt:qe,updatedAt:qe}).strict(),Pn="instance.lifecycle.snapshot",jn=m.z.object({instanceId:Dn.shape.id,revision:m.z.number().int().min(0),updatedAt:qe,status:Dn.shape.status.unwrap(),health:Dn.shape.health.unwrap(),connectionStatus:Dn.shape.connectionStatus.unwrap(),accessStatus:m.z.enum(["reachable","endpoint-unreachable"]),imageProvisioning:In.optional(),workspace:Rn,runtime:Dn.shape.runtime.unwrap(),runtimeVersion:xt.optional(),ready:m.z.boolean(),lastHeartbeatAt:qe.optional()}).strict();function Mn(e,t){return Dn.safeParse(Ln(e,t))}function Ln(e,t){if(!e||"object"!=typeof e||Array.isArray(e))return e;const n=e,i=new Set(Object.keys(Dn.shape)),r={};for(const[e,s]of Object.entries(n))i.has(e)?r[e]=s:t?.({instanceId:"string"==typeof n.id?n.id:void 0,field:e});if(n.capabilities&&"object"==typeof n.capabilities&&!Array.isArray(n.capabilities)){const e={...n.capabilities};Object.prototype.hasOwnProperty.call(e,"apps")&&(t?.({instanceId:"string"==typeof n.id?n.id:void 0,field:"capabilities.apps"}),delete e.apps),r.capabilities=e}else r.capabilities={};r.appInventory=function(e,t,n){if(!e||"object"!=typeof e||Array.isArray(e))return;const i=e;Object.keys(i).some(e=>!["observedAt","items","issues"].includes(e))&&t?.({instanceId:n,field:"appInventory"});const r={observedAt:i.observedAt,items:Array.isArray(i.items)?i.items.map(e=>{e&&"object"==typeof e&&!Array.isArray(e)&&Object.keys(e).some(e=>!["id","name","kind","source","availability","capabilities","diagnosticCode"].includes(e))&&t?.({instanceId:n,field:"appInventory.items"});const i=Un(e,["id","name","kind","source","availability","diagnosticCode"]);return!i||"object"!=typeof i||Array.isArray(i)?i:{...i,capabilities:Un(e.capabilities,["automation","supportsCwdSelection"])}}):i.items,issues:Array.isArray(i.issues)?i.issues.map(e=>Un(e,["code","message"])):i.issues},s=dt.safeParse(r);return s.success?s.data:void 0}(n.appInventory,t,"string"==typeof n.id?n.id:void 0),r.source=function(e,t,n){if(!e||"object"!=typeof e||Array.isArray(e))return e;const i=e,r=i.type,s=Ut.options.find(e=>e.shape.type.value===r);if(!s)return e;const o="local-folder"===r?["type","localFolderId","path","ownerNodeId"]:"git-template"===r?["type","url","templateId","ref","auth","clone"]:["type","repositoryId","url","provider","ref","auth","clone"],a=Un(i,o);if("local-folder"!==r){const e=$n(Mt,Un(i.ref,["type","name","commit"]),"source.ref",t,n),r=$n(Lt,Un(i.auth,["type","secretId"]),"source.auth",t,n),s=$n($t,Un(i.clone,["depth","submodules","lfs","subdirectory"]),"source.clone",t,n);e?a.ref=e:delete a.ref,r?a.auth=r:delete a.auth,s?a.clone=s:delete a.clone}const c=$n(s,a,"source",t,n);return c?(Object.keys(i).some(e=>!o.includes(e))&&t?.({instanceId:n,field:"source"}),c):a}(n.source,t,"string"==typeof n.id?n.id:void 0),r.sourceSnapshot=n.sourceSnapshot&&"object"==typeof n.sourceSnapshot&&!Array.isArray(n.sourceSnapshot)?n.sourceSnapshot:{},r.build=$n(Et,n.build,"build",t,"string"==typeof n.id?n.id:void 0),r.aiSessions=function(e,t,n){if(!e||"object"!=typeof e||Array.isArray(e))return;const i=e,r=Array.isArray(i.sessions)?i.sessions.flatMap((e,i)=>{const r=$n(ze,e,`aiSessions.sessions.${i}`,t,n);return r?[r]:[]}):[],s={runningCount:"number"==typeof i.runningCount&&Number.isInteger(i.runningCount)&&i.runningCount>=0?i.runningCount:0,waitingCount:"number"==typeof i.waitingCount&&Number.isInteger(i.waitingCount)&&i.waitingCount>=0?i.waitingCount:0,staleCount:"number"==typeof i.staleCount&&Number.isInteger(i.staleCount)&&i.staleCount>=0?i.staleCount:0,sessions:r,updatedAt:qe.safeParse(i.updatedAt).success?i.updatedAt:(new Date).toISOString()};return Object.keys(i).some(e=>!["runningCount","waitingCount","staleCount","sessions","updatedAt"].includes(e))&&t?.({instanceId:n,field:"aiSessions"}),Ne.parse(s)}(n.aiSessions,t,"string"==typeof n.id?n.id:void 0),r.triggers=function(e,t,n){if(!e||"object"!=typeof e||Array.isArray(e))return;const i=e;Object.keys(i).some(e=>!["enabledCount","runningCount","errorCount","configs","recentRuns"].includes(e))&&t?.({instanceId:n,field:"triggers"});const r=(e,i,r)=>Array.isArray(e)?e.flatMap((e,s)=>{const o=$n(i,e,`${r}.${s}`,t,n);return o?[o]:[]}):[],s=Array.isArray(i.configs)?i.configs.flatMap((e,i)=>{if(!e||"object"!=typeof e||Array.isArray(e))return[];const s=e;Object.keys(s).some(e=>!["configHash","config","deployments","runtime"].includes(e))&&t?.({instanceId:n,field:`triggers.configs.${i}`});const o=function(e,t,n,i){if(!e||"object"!=typeof e||Array.isArray(e))return;const r=e,s=Un(r,["configHash","name","description","createdAt","updatedAt"]);if(r.source&&"object"==typeof r.source&&!Array.isArray(r.source)){const e=r.source,t="schedule"===e.type?"interval"===e.scheduleKind?["type","scheduleKind","intervalMs"]:"daily"===e.scheduleKind?["type","scheduleKind","timeOfDay","timezone"]:["type","scheduleKind","weekdays","timeOfDay","timezone"]:"file-change"===e.type?["type","roots","globs","ignore","debounceMs"]:["type","agent","statuses","phases"];s.source=Un(e,t)}return s.action=Un(r.action,["promptTemplate"]),s.policy=Un(r.policy,["cooldownMs","maxConcurrentRuns","whenBusy"]),$n(je,s,t,n,i)}(s.config,`triggers.configs.${i}.config`,t,n);return"string"==typeof s.configHash&&o?[{configHash:s.configHash,config:o,deployments:r(s.deployments,Le,`triggers.configs.${i}.deployments`),runtime:r(s.runtime,$e,`triggers.configs.${i}.runtime`)}]:[]}):[];return{enabledCount:"number"==typeof i.enabledCount&&Number.isInteger(i.enabledCount)&&i.enabledCount>=0?i.enabledCount:0,runningCount:"number"==typeof i.runningCount&&Number.isInteger(i.runningCount)&&i.runningCount>=0?i.runningCount:0,errorCount:"number"==typeof i.errorCount&&Number.isInteger(i.errorCount)&&i.errorCount>=0?i.errorCount:0,configs:s,recentRuns:r(i.recentRuns,Fe,"triggers.recentRuns")}}(n.triggers,t,"string"==typeof n.id?n.id:void 0),r.apps=$n(Dn.shape.apps.unwrap(),Un(n.apps,["runningCount","problemCount","updatedAt","revision"]),"apps",t,"string"==typeof n.id?n.id:void 0)||{runningCount:0,problemCount:0},r.config=$n(Dn.shape.config.unwrap(),Un(n.config,["autoImportAgentConfigs","defaultCodexPermissionMode"]),"config",t,"string"==typeof n.id?n.id:void 0)||{autoImportAgentConfigs:!0,defaultCodexPermissionMode:"ask"},r.modelSelection=$n(nt.unwrap(),Un(n.modelSelection,["codexModelHash","claudeModelHash"]),"modelSelection",t,"string"==typeof n.id?n.id:void 0)||{},r.imageSnapshot=function(e,t,n,i){if(!e||"object"!=typeof e||Array.isArray(e))return e;const r=e,s=function(e){if(!e||"object"!=typeof e||Array.isArray(e))return e;const t=e,n=new Set(["id","origin","name","description","localizedDescriptions","cover","reference","repository","tag","image","registry","pullPolicy","capabilities","optionalApps","defaultEnv","labels","createdAt","updatedAt"]);for(const e of Object.keys(t))n.has(e);"string"==typeof t.id&&t.id;const i="string"==typeof t.image?t.image:void 0;Object.prototype.hasOwnProperty.call(t,"registry");let r,s="string"==typeof t.reference?t.reference:i;if(s)try{s=Ze(s)}catch{if(!s.includes("@")&&s.lastIndexOf(":")<=s.lastIndexOf("/"))try{s=Ze(`${s}:latest`)}catch{}}try{r=s?Qe(s):void 0}catch{}return{id:t.id,origin:"custom",name:t.name,description:t.description,localizedDescriptions:t.localizedDescriptions,cover:Un(t.cover,["kind","key","url","mediaType","digest"]),reference:r?.reference??s,repository:r?.repository??t.repository,tag:r?.tag??t.tag,pullPolicy:t.pullPolicy??"if-not-present",capabilities:t.capabilities,optionalApps:t.optionalApps,defaultEnv:t.defaultEnv,labels:t.labels,createdAt:t.createdAt,updatedAt:t.updatedAt}}(r),{reference:o,...a}=s,c=r.requestedReference??o;let d;try{d="string"==typeof c?Qe(c):void 0}catch{}const l={img_default:"market_taskhandoff_browser",img_codex:"market_taskhandoff_codex",img_ai:"market_taskhandoff_ai"},u="string"==typeof r.id?r.id:"string"==typeof t?t:void 0,m="market"===r.origin||u&&l[u]?"market":"custom";return void 0===r.image&&void 0===r.reference||n?.({instanceId:i,field:"imageSnapshot.reference"}),{...a,id:u&&l[u]?l[u]:u,origin:m,repository:d?.repository??r.repository,tag:d?.tag??r.tag,requestedReference:d?.reference??c,resolvedDigest:r.resolvedDigest,resolvedReference:r.resolvedReference,downloadSizeBytes:r.downloadSizeBytes,market:"market"===m?Un(r.market,["catalogId","catalogRevision","publisher","version"])??{catalogId:"task_handoff_embedded",catalogRevision:"legacy",publisher:"task-handoff"}:void 0}}(n.imageSnapshot,n.imageId,t,"string"==typeof n.id?n.id:void 0);const s="string"==typeof n.imageId?{img_default:"market_taskhandoff_browser",img_codex:"market_taskhandoff_codex",img_ai:"market_taskhandoff_ai"}[n.imageId]||n.imageId:void 0,o=Un(n.imageSelection,["imageId","tag"]);r.imageSelection=o||(s?{imageId:s,tag:r.imageSnapshot?.tag}:void 0),r.imageProvisioning=$n(In,Un(n.imageProvisioning,["phase","requestedReference","generation","error","startedAt","updatedAt"]),"imageProvisioning",t,"string"==typeof n.id?n.id:void 0),r.runtimeVersion=function(e,t,n){if(!e||"object"!=typeof e||Array.isArray(e))return;const i=e,r=e=>{if("string"!=typeof e)return;const t=e.trim();return t&&t.length<=80?t:void 0},s=r(i.desiredVersion);if(!s)return void t?.({instanceId:n,field:"runtimeVersion.desiredVersion"});const o=new Set(xt.shape.phase.options),a="string"==typeof i.phase?i.phase:"pending",c=o.has(a)?a:{idle:"pending",queued:"pending",checking:"pending",downloading:"installing",updating:"installing",completed:"matched",succeeded:"matched",ready:"matched",error:"failed"}[a]||"pending";let d;if(c!==a&&t?.({instanceId:n,field:"runtimeVersion.phase"}),i.error&&"object"==typeof i.error&&!Array.isArray(i.error)){const e=i.error,s="string"==typeof e.message?e.message.trim().slice(0,4096):"";if(s){const i=new Set(kt.shape.code.options),o="string"==typeof e.code&&i.has(e.code)?e.code:"INSTANCE_RUNTIME_INSTALL_FAILED";o!==e.code&&t?.({instanceId:n,field:"runtimeVersion.error.code"});const a=r(e.expectedVersion),c=r(e.actualVersion);d={code:o,message:s,...a?{expectedVersion:a}:{},...c?{actualVersion:c}:{},retryable:!0===e.retryable}}else t?.({instanceId:n,field:"runtimeVersion.error"})}"string"==typeof i.error&&i.error.trim()&&(d={code:"INSTANCE_RUNTIME_INSTALL_FAILED",message:i.error.trim().slice(0,4096),expectedVersion:s,...r(i.actualVersion)?{actualVersion:r(i.actualVersion)}:{},retryable:!1});const l=r(i.actualVersion),u=qe.safeParse(i.lastAttemptAt),m=qe.safeParse(i.matchedAt);return void 0===i.lastAttemptAt||u.success||t?.({instanceId:n,field:"runtimeVersion.lastAttemptAt"}),void 0===i.matchedAt||m.success||t?.({instanceId:n,field:"runtimeVersion.matchedAt"}),{desiredVersion:s,...l?{actualVersion:l}:{},phase:c,attempt:"number"==typeof i.attempt&&Number.isInteger(i.attempt)&&i.attempt>=0?i.attempt:0,...u.success?{lastAttemptAt:u.data}:{},...m.success?{matchedAt:m.data}:{},...d?{error:d}:{}}}(n.runtimeVersion,t,"string"==typeof n.id?n.id:void 0),r.workspace=$n(Rn,n.workspace,"workspace",t,"string"==typeof n.id?n.id:void 0)||{status:"unknown"},r.runtime=$n(Dn.shape.runtime.unwrap(),Un(n.runtime,["kind","containerName","containerId","workspacePath","pid","port","labels"]),"runtime",t,"string"==typeof n.id?n.id:void 0)||{labels:{}},r.target=$n(Cn,Un(n.target??n.endpoints,["strategy","web","api","vnc","tty","logs","status"]),"target",t,"string"==typeof n.id?n.id:void 0)||{strategy:"direct-port",status:"unknown"},r.access=$n(On,Un(n.access,["strategy","web","api","ws","status"]),"access",t,"string"==typeof n.id?n.id:void 0)||{strategy:"control-plane-proxy",status:"unknown"};for(const[e,i]of Object.entries(Dn.shape))Object.prototype.hasOwnProperty.call(r,e)&&!i.safeParse(r[e]).success&&i.safeParse(void 0).success&&(delete r[e],t?.({instanceId:"string"==typeof n.id?n.id:void 0,field:e}));return r}function $n(e,t,n,i,r){if(!t||"object"!=typeof t||Array.isArray(t))return;let s=structuredClone(t),o=!1;for(let t=0;t<20;t+=1){const t=e.safeParse(s);if(t.success)return o&&i?.({instanceId:r,field:n}),t.data;let a=!1;for(const e of t.error.issues){if("unrecognized_keys"!==e.code)continue;const t=Fn(s,e.path);if(t&&"object"==typeof t&&!Array.isArray(t))for(const n of e.keys)Object.prototype.hasOwnProperty.call(t,n)&&(delete t[n],a=!0,o=!0)}if(!a){const o=structuredClone(s);let a=!1;for(const e of t.error.issues){if(!e.path.length||"string"!=typeof e.path.at(-1))continue;const t=Fn(o,e.path.slice(0,-1)),n=e.path.at(-1);t&&"object"==typeof t&&!Array.isArray(t)&&Object.prototype.hasOwnProperty.call(t,n)&&(delete t[n],a=!0)}if(a){const t=e.safeParse(o);if(t.success)return i?.({instanceId:r,field:n}),t.data}break}}i?.({instanceId:r,field:n})}function Fn(e,t){let n=e;for(const e of t){if(!n||"object"!=typeof n)return;n=n[e]}return n}function Un(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 Vn=m.z.object({instanceId:He.optional(),projectId:He.optional(),source:Ut.optional(),nodeId:He.optional(),runtimeId:He.optional(),imageSelection:it.optional(),instanceVersion:m.z.string().trim().max(80).optional(),protocolVersion:Ve,build:Et.optional(),controlMode:m.z.enum(["standalone","controlled"]).default("controlled"),capabilities:m.z.record(m.z.string(),m.z.unknown()).default({}),appInventory:dt.optional(),target:Cn.default({strategy:"direct-port",status:"unknown"}),workspace:Rn.default({status:"unknown"}),registrationToken:m.z.string().trim().max(240).optional()}).strict().superRefine((e,t)=>{e.protocolVersion!==Ue||e.appInventory||t.addIssue({code:"custom",path:["appInventory"],message:"Current protocol register payload requires appInventory."})}),Hn=m.z.object({status:Dn.shape.status.optional(),health:Dn.shape.health.optional(),protocolVersion:Ve,build:Et.optional(),capabilities:Dn.shape.capabilities.optional(),appInventory:dt.optional(),apps:Dn.shape.apps.optional(),aiSessions:Dn.shape.aiSessions.optional(),triggers:Dn.shape.triggers.optional(),workspace:Rn.optional(),target:Cn.partial().optional()}).strict().superRefine((e,t)=>{e.protocolVersion!==Ue||e.appInventory||t.addIssue({code:"custom",path:["appInventory"],message:"Current protocol heartbeat payload requires appInventory."})}),qn=m.z.enum(["web","telegram","wechat","dingding"]);function Bn(e){return e.readyState===(e.OPEN??1)}function Kn(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 Gn(e,t){e.send(t.data,{binary:t.isBinary})}function Jn(e,t){if(Bn(e))for(const n of t.splice(0))Gn(e,n)}function Wn(e,t,n={}){return new Promise((i,r)=>{const s=a.spawn(e,t,{stdio:["ignore","pipe","pipe"]}),o=[],c=[];let d=!1;const l=n.timeoutMs?setTimeout(()=>{d=!0,s.kill("SIGKILL")},n.timeoutMs):void 0;l?.unref?.(),s.stdout.on("data",e=>o.push(Buffer.from(e))),s.stderr.on("data",e=>c.push(Buffer.from(e))),s.on("error",e=>{l&&clearTimeout(l),r(e)}),s.on("close",t=>{l&&clearTimeout(l);const s={stdout:Buffer.concat(o).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:s}),void r(t)}if(0===t)return void i(s);const a=new Error(s.stderr||`${e} exited with code ${t}`);Object.assign(a,{statusCode:502,code:"RUNTIME_EXECUTOR_FAILED",details:s}),r(a)})})}m.z.object({id:He,channel:qn,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:qe,updatedAt:qe}).strict(),m.z.object({id:He,channel:qn,bridgeId:He.optional(),chatSessionId:m.z.string().trim().min(1).max(240),userId:m.z.string().trim().max(240).optional(),activeProjectId:He.optional(),activeInstanceId:He.optional(),activeAiSessionId:m.z.string().trim().min(1).max(120).optional(),lastUsedAt:qe,createdAt:qe,updatedAt:qe}).strict(),m.z.object({source:m.z.object({type:m.z.literal("chat-gateway").default("chat-gateway"),channel:qn,bridgeId:He.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(te).max(6).default([])}).strict().superRefine((e,t)=>{e.attachments.reduce((e,t)=>e+("inline"===t.source.type?t.size:0),0)>V&&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:He,aiSessionId:m.z.string().trim().min(1).max(120)}).strict().optional()}).strict(),m.z.object({id:He,instanceId:He,projectId:He.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:qe}).strict();const Yn=(e,t,n={})=>new Promise((i,r)=>{const s=[];let o,a=!1;try{o=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 r(e)}const c=n.timeoutMs?setTimeout(()=>{a=!0,o.kill("SIGKILL")},n.timeoutMs):void 0;c?.unref?.(),o.onData(e=>{s.push(e),n.onData?.(e)}),o.onExit(({exitCode:t})=>{c&&clearTimeout(c);const o={stdout:s.join(""),stderr:""};a?r(Object.assign(new Error(`${e} timed out after ${n.timeoutMs}ms`),{statusCode:504,code:"RUNTIME_COMMAND_TIMEOUT",details:o})):0!==t?r(Object.assign(new Error(o.stdout.replace(/\u001b\[[0-?]*[ -/]*[@-~]/g,"").split(/\r?\n/).map(e=>e.trim()).filter(Boolean).at(-1)||`${e} exited with code ${t}`),{statusCode:502,code:"RUNTIME_EXECUTOR_FAILED",details:o})):i(o)})});class Xn{inFlight=new Map;runCommand;runTerminalCommand;constructor(e=Wn,t){this.runCommand=e,this.runTerminalCommand=t||function(e){return e===Wn?Yn:async(t,n,i={})=>{const r=await e(t,n,{timeoutMs:i.timeoutMs});return r.stdout&&i.onData?.(r.stdout),r.stderr&&i.onData?.(r.stderr),r}}(e)}ensure(e,t,n){const i=Ze(e),r=this.inFlight.get(i);if(r)return t&&(r.phaseListeners.add(t),r.phase&&t(r.phase)),n&&(r.terminalListeners.add(n),r.terminalTail&&n({sequence:r.terminalSequence,data:r.terminalTail,replay:!0})),r.promise;const s=new Set,o=new Set;t&&s.add(t),n&&o.add(n);const a={promise:Promise.resolve(void 0),phaseListeners:s,terminalListeners:o,terminalSequence:0,terminalTail:""};return a.promise=this.ensureOnce(i,e=>{a.phase=e,s.forEach(t=>t(e))},e=>{a.terminalSequence+=1,a.terminalTail=`${a.terminalTail}${e}`.slice(-262144);const t={sequence:a.terminalSequence,data:e};o.forEach(e=>e(t))}).finally(()=>this.inFlight.delete(i)),this.inFlight.set(i,a),a.promise}async ensureOnce(e,t,n){t("checking-image");let i=await this.inspect(e).catch(()=>{}),r=!1;i||(t("pulling-image"),await this.runTerminalCommand("docker",["pull",e],{cols:120,rows:40,onData:n}),r=!0,i=await this.inspect(e)),t("resolving-image");const s=(o=i,Array.isArray(o.RepoDigests)?o.RepoDigests.filter(e=>"string"==typeof e):[]).find(e=>/@sha256:[a-fA-F0-9]{64}$/.test(e));var o;const a=s?.split("@").at(-1)?.toLowerCase();return{requestedReference:e,...a?{resolvedDigest:a}:{},resolvedReference:s||e,pulled:r}}async inspect(e){const t=await this.runCommand("docker",["image","inspect",e,"--format","{{json .}}"]);return JSON.parse(t.stdout.trim()||"{}")}}function Zn(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 Qn{runCommand;publishHost;images;launcherAssetsDir;constructor(e=Wn,i={}){this.runCommand=e,this.images=i.imageService||new Xn(e),this.publishHost=i.publishHost||"127.0.0.1",this.launcherAssetsDir=i.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(o.fileURLToPath("undefined"==typeof document?require("url").pathToFileURL(__filename).href:b&&"SCRIPT"===b.tagName.toUpperCase()&&b.src||new URL("cli.js",document.baseURI).href)):__dirname,i=[n.resolve(e,"../../../../../docker"),n.resolve(e,"../docker"),n.resolve(e,"../../docker")];return i.find(e=>t.existsSync(n.join(e,"runtime-installer.mjs")))||i[0]}()}async start(e){si(e);const t=e.instance.runtime.containerName||ii(e.instance.id);if(await this.runCommand("docker",["start",t]).catch(()=>{}))return this.runningResult(e,t,e.instance.runtime.containerId);await this.images.ensure(e.image.resolvedReference||e.image.requestedReference);const n=await this.runCommand("docker",function(e,t,n={}){const i=n.publishHost||"127.0.0.1",r=e.node?.id||"node_unset",s=e.runtime?.id||"runtime_local_docker",o=["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=${r}`,"--label",`task-handoff.runtime-id=${s}`,"--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",`${i}::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:r,TASK_HANDOFF_RUNTIME_ID:s,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))ri(o,e,t);"local-folder"===e.project.source.type?o.push("-v",`${e.project.source.path}:${e.project.workspacePolicy.path||"/workspace"}:${e.project.workspacePolicy.readOnly?"ro":"rw"}`):(ri(o,"TASK_HANDOFF_PROJECT_SOURCE",JSON.stringify(e.project.source)),ri(o,"TASK_HANDOFF_WORKSPACE_POLICY",JSON.stringify(e.project.workspacePolicy)),ri(o,"TASK_HANDOFF_GIT_URL",e.project.source.url),e.project.source.ref?.commit?ri(o,"TASK_HANDOFF_GIT_COMMIT",e.project.source.ref.commit):e.project.source.ref?.name&&ri(o,"TASK_HANDOFF_GIT_REF",e.project.source.ref.name),e.project.source.clone?.depth&&ri(o,"TASK_HANDOFF_GIT_DEPTH",String(e.project.source.clone.depth)),ri(o,"TASK_HANDOFF_GIT_SUBMODULES",e.project.source.clone?.submodules?"true":"false"),ri(o,"TASK_HANDOFF_GIT_LFS",e.project.source.clone?.lfs?"true":"false"),e.project.source.clone?.subdirectory&&ri(o,"TASK_HANDOFF_WORKSPACE_SUBDIRECTORY",e.project.source.clone.subdirectory));for(const[t,n]of Object.entries(e.image.defaultEnv))ri(o,t,n);for(const[t,n]of Object.entries(e.modelEnv||{}))ri(o,t,n);return o.push(e.image.resolvedReference||e.image.requestedReference),o}(e,t,{publishHost:this.publishHost}));return this.runningResult(e,t,n.stdout||void 0)}async runningResult(e,t,n){const i=await this.containerPort(t,"8080/tcp"),r=i?`http://127.0.0.1:${i}`:void 0,s=e.node?.id||"node_unset",o=e.runtime?.id||"runtime_local_docker";return{status:"registering",health:"unknown",connectionStatus:r?"online":"unknown",agentStatus:"unknown",targetStatus:"unknown",uiAccessStatus:"unknown",target:{strategy:"direct-port",status:r?"reachable":"unknown",...r?{web:r,api:`${r}/api`}:{}},workspace:{mode:e.project.workspacePolicy.mode,status:"pending",path:e.project.workspacePolicy.path},runtime:{...e.instance.runtime,kind:"docker",containerName:t,...n?{containerId:n}:{},labels:{...e.instance.runtime.labels,"task-handoff.instance-id":e.instance.id,"task-handoff.project-id":e.project.id,"task-handoff.node-id":s,"task-handoff.runtime-id":o,"task-handoff.image-id":e.image.id}}}}async stop(e){return await this.runCommand("docker",["stop",e.instance.runtime.containerName||ii(e.instance.id)]).catch(()=>({stdout:"",stderr:""})),{status:"stopped",health:"unknown",connectionStatus:"offline",target:{...e.instance.target,status:"unknown"},runtime:e.instance.runtime}}async restart(e,t){si(e);const n=e.instance.runtime.containerName||ii(e.instance.id),i=await this.inspectContainerId(n);if(!i)throw ei("INSTANCE_RUNTIME_RESTART_FAILED",`Docker container ${n} does not exist.`);ti(n,i,t,"before restart","INSTANCE_RUNTIME_RESTART_FAILED"),await this.runCommand("docker",["restart",n]);const r=await this.inspectContainerId(n);if(!r||r!==i)throw ei("INSTANCE_RUNTIME_RESTART_FAILED",`Docker container identity changed while restarting ${n}.`);return ti(n,r,t,"after restart","INSTANCE_RUNTIME_RESTART_FAILED"),this.runningResult(e,n,r)}async delete(e){return await this.runCommand("docker",["rm","-f",e.instance.runtime.containerName||ii(e.instance.id)]).catch(()=>({stdout:"",stderr:""})),{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);ti(e.containerName,t,e.expectedContainerId,"before runtime restart","INSTANCE_RUNTIME_RESTART_FAILED");try{await this.runCommand("docker",["restart",e.containerName])}catch(t){throw ei("INSTANCE_RUNTIME_RESTART_FAILED",`Could not restart Docker container ${e.containerName}.`,t)}const n=await this.inspectContainerId(e.containerName);if(!n||n!==t)throw ei("INSTANCE_RUNTIME_RESTART_FAILED",`Docker container identity changed while updating ${e.containerName}.`);return ti(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 ei("INSTANCE_RUNTIME_INSTALL_FAILED",`Docker container ${e.containerName} does not exist.`);ti(e.containerName,t,e.expectedContainerId,"before runtime install","INSTANCE_RUNTIME_INSTALL_FAILED");const n=`/opt/task-handoff/instance-runtime/incoming/task-handoff-runtime-${i=e.identity.version,i.replace(/[^0-9A-Za-z.+_-]/g,"-")}-${e.identity.sha256.slice(0,12)}.tar.gz`;var i;await this.runCommand("docker",["exec","--user","0",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 ei("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 r=await this.inspectContainerId(e.containerName);if(!r||r!==t)throw ei("INSTANCE_RUNTIME_INSTALL_FAILED",`Docker container identity changed while installing ${e.containerName}.`);return ti(e.containerName,r,e.expectedContainerId,"after runtime install","INSTANCE_RUNTIME_INSTALL_FAILED"),t}async inspectRuntimeVersion(e){const t=await this.inspectContainerId(e);if(!t)return{};const n=await this.runCommand("docker",["exec","--user","agent",e,"task-handoff-runtime","verify-active"]).catch(()=>{});if(!n?.stdout)return{containerId:t};try{const e=Tt.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 i=await this.runCommand("docker",["inspect","--format","{{json .}}",e]).then(e=>JSON.parse(e.stdout.trim()||"{}")).catch(()=>{});if(t=i?.Platform,"string"==typeof i?.Image&&i.Image){const e=await this.runCommand("docker",["image","inspect","--format","{{json .}}",i.Image]).then(e=>JSON.parse(e.stdout.trim()||"{}")).catch(()=>{});t=e?.Os||t,n=e?.Architecture}}if(!t||!n){const e=await this.runCommand("docker",["info","--format","{{json .}}"]).then(e=>JSON.parse(e.stdout.trim()||"{}")).catch(e=>{throw ei("INSTANCE_BASE_RUNTIME_INCOMPATIBLE","Could not inspect the Docker runtime target.",e)});t||=e.OSType,n||=e.Architecture}const i="linux"===(r=t)||"darwin"===r?r:"windows"===r||"win32"===r?"win32":void 0;var r;const s=function(e){return"amd64"===e||"x86_64"===e||"x64"===e?"x64":"arm64"===e||"aarch64"===e?"arm64":void 0}(n);if(!i||!s)throw ei("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Docker reported an unsupported runtime target ${String(t||"unknown")}/${String(n||"unknown")}.`);return{platform:i,arch:s,launcherAbi:1}}async rollbackRuntime(e){const t=await this.inspectContainerId(e);if(!t)throw ei("INSTANCE_RUNTIME_RESTART_FAILED",`Docker container ${e} does not exist.`);try{await this.runCommand("docker",["exec","--user","0",e,"task-handoff-runtime","rollback"]),await this.runCommand("docker",["restart",e])}catch(t){throw ei("INSTANCE_RUNTIME_RESTART_FAILED",`Could not roll back ${e} to its previous controlled-instance release.`,t)}const n=await this.inspectContainerId(e);if(!n||n!==t)throw ei("INSTANCE_RUNTIME_RESTART_FAILED",`Docker container identity changed while rolling back ${e}.`);return this.inspectRuntimeVersion(e)}async installRuntimeLauncher(e){const t=await this.inspectContainerId(e);if(!t)throw ei("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Docker container ${e} does not exist.`);const i=[[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 i)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 ei("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Could not install the runtime launcher in ${e}.`,t)}if(await this.inspectContainerId(e)!==t)throw ei("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Docker container identity changed while installing the runtime launcher in ${e}.`)}async inspectContainerId(e){const t=await this.runCommand("docker",["inspect","--format","{{.Id}}",e]).catch(()=>{});return t?.stdout.trim()||void 0}async containerPort(e,t){const n=(await this.runCommand("docker",["port",e,t]).catch(()=>({stdout:"",stderr:""}))).stdout.split(/\r?\n/).find(Boolean),i=n?.match(/:(\d+)$/);return i?.[1]}}function ei(e,t,n){const i=function(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}(n),r=new Error(i?`${t} Cause: ${i}`:t,void 0===n?void 0:{cause:n});return Object.assign(r,{statusCode:502,code:e}),r}function ti(e,t,n,i,r){if(n&&t!==n)throw ei(r,`Docker container ${e} identity mismatch ${i}: expected ${n}, got ${t}.`)}async function ni(e=Wn){return async function(e=Wn){return(await e("docker",["images","--digests","--format","{{json .}}"])).stdout.split(/\r?\n/).map(e=>e.trim()).filter(Boolean).map(e=>{const t=JSON.parse(e),n=t.Repository||"<none>",i=t.Tag||"<none>",r=t.ID||t.IDShort||"",s="<none>"!==n&&"<none>"!==i?`${n}:${i}`:r,o="<none>"!==n&&t.Digest&&"<none>"!==t.Digest?[`${n}@${t.Digest}`]:[];return{repository:n,tag:i,id:r,createdSince:t.CreatedSince,size:t.Size,sizeBytes:Zn(t.Size),reference:s,repoDigests:o}}).filter(e=>Boolean(e.reference))}(e)}function ii(e){return`task-handoff-${e.replace(/[^a-zA-Z0-9_.-]/g,"-")}`}function ri(e,t,n){e.push("-e",`${t}=${n}`)}function si(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 oi=m.z.enum(["created","starting","running","stopping","stopped","exited","failed","closed","terminated","unknown"]),ai=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(),ci=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:oi.default("unknown"),bindings:m.z.array(ai).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()})),di=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(ci).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:di}).strict(),di.pick({runningCount:!0,problemCount:!0,updatedAt:!0}).extend({revision:m.z.number().int().min(0).optional()});const li=m.z.enum(["app-session-created","app-session-updated","app-session-deleted","app-session-recovered","control-action","heartbeat-sync","startup"]),ui=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:li}).strict(),mi=m.z.object({meta:ui,snapshot:di}).strict(),pi=m.z.object({meta:ui,session:ci}).strict(),gi=m.z.object({meta:ui,sessionId:m.z.string().trim().min(1).max(160),tombstone:ci.optional(),expiresAt:m.z.string().datetime().optional()}).strict();function hi(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:mi}).strict(),m.z.object({type:m.z.literal("app-session.patch"),payload:pi}).strict(),m.z.object({type:m.z.literal("app-session.removed"),payload:gi}).strict()])).default([])}).strict();const fi=m.z.enum(["ai.sessions","app.sessions"]),Ii=m.z.object({topic:fi,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(),yi=m.z.object({protocolVersion:m.z.literal(1),streams:m.z.array(Ii)}).strict();class Ai{attempt=0;timer;get pending(){return Boolean(this.timer)}get attempts(){return this.attempt}schedule(e,t={}){if(this.timer)return;const n=function(e,t=Math.random){const n=Math.min(3e4,1e3*2**Math.max(0,e));return Math.min(3e4,Math.round(n*(.75+.5*t())))}(this.attempt,t.random);this.attempt+=1;const i=t.setTimeoutFn||setTimeout;return this.timer=i(()=>{this.timer=void 0,e()},n),{attempt:this.attempt,delay:n}}reset(e=clearTimeout){this.timer&&e(this.timer),this.timer=void 0,this.attempt=0}cancel(e=clearTimeout){this.timer&&e(this.timer),this.timer=void 0}}function bi(e,t=6e4){const n=[];for(let i=0;i<e.length;i+=t)n.push(e.slice(i,i+t));return n}class wi{sockets=new Map;socketUrls=new Map;retries=new Map;outputs=new Set;imagePullTerminalByInstance=new Map;state;token;logger;safetyIntervalMs;lastAiSessionEventByInstance=new Map;lastAppSessionEventByInstance=new Map;timer;reconnectAttempts=0;safetyReconciliations=0;localSequence=0;createSocket;setIntervalFn;clearIntervalFn;constructor(e,t,n={}){var i;this.state=e,this.token=t,this.logger=n.logger,this.safetyIntervalMs=(i=n.safetyIntervalMs,Math.min(6e4,Math.max(3e4,i??45e3))),this.createSocket=n.createSocket||((e,t)=>new 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=zi(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)bi(n.tail).forEach((i,r)=>this.sendForwarded(e,this.createEvent(yn,{...n.output,sequence:n.output.sequence+r,data:i,...0===r?{replay:!0}:{}},{instanceId:t}))),n.finished&&this.sendForwarded(e,this.createEvent(An,n.finished,{instanceId:t}));return this.syncNow(),()=>{this.outputs.delete(e)}}publish(e,t,n={}){this.rememberImagePullTerminal(e,t);const i=this.createEvent(e,t,n);for(const e of this.outputs)this.sendForwarded(e,i)}rememberImagePullTerminal(e,t){if(e===yn){const e=wn.safeParse(t);if(!e.success)return;const n=e.data,i=this.imagePullTerminalByInstance.get(n.instanceId);if(i&&n.generation<i.output.generation)return;const r=i?.output.generation===n.generation,s=n.replay||!r?n.data:`${i.tail}${n.data}`.slice(-262144);return void this.imagePullTerminalByInstance.set(n.instanceId,{output:n,tail:s})}if(e===An){const e=zn.safeParse(t);if(!e.success)return;const n=e.data,i=this.imagePullTerminalByInstance.get(n.instanceId);i?.output.generation===n.generation&&(i.finished=n)}}publishInstanceLifecycle(e){this.publish(Pn,function(e){return jn.parse(Ni(e))}(e),{instanceId:e.id});const t=this.imagePullTerminalByInstance.get(e.id);"ready"===e.imageProvisioning?.phase&&"succeeded"===t?.finished?.outcome&&this.imagePullTerminalByInstance.delete(e.id)}createEvent(e,t,n){const i=++this.localSequence;return{v:1,id:`node_evt_${Date.now().toString(36)}_${i.toString(36)}`,seq:i,type:e,topic:hi(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=Si(e);if(!n)continue;t.add(e.id);const i=this.retries.get(e.id);i?.timer.pending&&i.url!==n&&(i.timer.cancel(),this.retries.delete(e.id)),this.socketUrls.get(e.id)!==n&&this.sockets.has(e.id)&&(this.sockets.get(e.id)?.close(),this.sockets.delete(e.id)),this.sockets.has(e.id)||this.retries.get(e.id)?.timer.pending||this.connect(e.id,n)}for(const[e,n]of this.sockets)if(!t.has(e)){n.close(),this.sockets.delete(e),this.socketUrls.delete(e);const t=this.retries.get(e);t?.timer.cancel(),this.retries.delete(e)}for(const[e,n]of this.retries)t.has(e)||(n.timer.cancel(),this.retries.delete(e),this.socketUrls.delete(e))}connect(e,t){const n=this.token?{authorization:`Bearer ${this.token}`}:void 0,i=this.createSocket(t,{headers:n});this.sockets.set(e,i),this.socketUrls.set(e,t),i.on("open",()=>{const n=this.retries.get(e);n?.timer.reset(),this.retries.set(e,{timer:n?.timer||new Ai,url:t}),i.readyState===u.OPEN&&(i.send(JSON.stringify({v:1,type:"subscribe",topics:[H,"app.sessions","apps","instances"]})),this.logger?.info?.({instanceId:e,url:t},"ai-session.event.forward.connect"),this.logger?.info?.({instanceId:e,url:t},"app-session.event.forward.connect"))}),i.on("message",t=>{const n=function(e,t){try{const n=JSON.parse(String(e));if(!n||"object"!=typeof n||Array.isArray(n))return;const i=n,r="string"==typeof i.type?i.type:"";if(!r||"events.connected"===r)return;const s=i.scope&&"object"==typeof i.scope&&!Array.isArray(i.scope)?i.scope:{};return{v:1,id:"string"==typeof i.id?i.id:`evt_${Date.now().toString(36)}`,seq:Number(i.seq)||0,type:r,topic:"string"==typeof i.topic?i.topic:hi(r),createdAt:"string"==typeof i.createdAt?i.createdAt:(new Date).toISOString(),payload:"payload"in i?i.payload:{},scope:{...s,instanceId:t}}}catch{return}}(t,e);if(!n)return;if("streams.hello"===n.type){const t=yi.safeParse(n.payload);if(!t.success)return this.logger?.warn?.({instanceId:e,issues:t.error.issues},"session-stream.handshake.invalid"),void i.close(1002,"Incompatible session stream handshake.");const r=JSON.stringify({type:"node-agent.streams.hello",instanceId:e,payload:t.data});for(const e of this.outputs)e.readyState===u.OPEN&&e.send(r);return}this.recordAiSessionEvent(e,n),this.recordAppSessionEvent(e,n);const r=JSON.stringify({type:"node-agent.event.forwarded",event:n});for(const e of this.outputs)e.readyState===u.OPEN&&e.send(r)}),i.on("close",()=>{this.sockets.get(e)===i&&(this.sockets.delete(e),this.socketUrls.delete(e),this.scheduleReconnect(e))}),i.on("error",()=>{this.logger?.warn?.({instanceId:e,url:t},"ai-session.event.forward.error"),this.logger?.warn?.({instanceId:e,url:t},"app-session.event.forward.error"),i.close()})}scheduleReconnect(e){const t=this.state.listInstances().find(t=>t.id===e),n=t&&Si(t);if(!n||!this.outputs.size)return;const i=this.retries.get(e)??{timer:new Ai};if(i.timer.pending)return;i.url=n;const r=i.timer.schedule(()=>{this.sockets.has(e)||this.connect(e,n)});r&&(this.reconnectAttempts+=1,this.logger?.info?.({instanceId:e,url:n,attempt:r.attempt,delay:r.delay,reconnectAttempts:this.reconnectAttempts},"session-stream.connection.reconnect-scheduled")),this.retries.set(e,i)}recordAiSessionEvent(e,t){if(t.topic!==H)return;if("ai-session.message-delta"===t.type)return;const n=vi(t.payload),i=this.lastAiSessionEventByInstance.get(e);i?.streamId===n.streamId&&void 0!==i.revision&&void 0!==n.revision&&n.revision>i.revision+1&&this.logger?.warn?.({instanceId:e,traceId:n.traceId,streamId:n.streamId,previousRevision:i.revision,revision:n.revision},"ai-session.event.forward.gap"),this.lastAiSessionEventByInstance.set(e,{streamId:n.streamId??i?.streamId,revision:n.revision??i?.revision}),this.logger?.info?.({instanceId:e,traceId:n.traceId,eventType:t.type,streamId:n.streamId,revision:n.revision},"ai-session.event.forward.message")}recordAppSessionEvent(e,t){if("app.sessions"!==t.topic)return;const n=vi(t.payload),i=this.lastAppSessionEventByInstance.get(e);i?.streamId===n.streamId&&void 0!==i.revision&&void 0!==n.revision&&n.revision>i.revision+1&&this.logger?.warn?.({instanceId:e,traceId:n.traceId,streamId:n.streamId,previousRevision:i.revision,revision:n.revision},"app-session.event.forward.gap"),this.lastAppSessionEventByInstance.set(e,{streamId:n.streamId??i?.streamId,revision:n.revision??i?.revision}),this.logger?.info?.({instanceId:e,traceId:n.traceId,eventType:t.type,streamId:n.streamId,revision:n.revision},"app-session.event.forward.message")}}function zi(e){const t=jn.safeParse(Ni(e));return t.success?t.data:void 0}function Ni(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 vi(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 Si(e){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 Ei=new Set(["provisioning","starting","registering","registered","running","unhealthy"]),_i=JSON.stringify({id:"{{.ID}}",name:"{{.Name}}",cpu:"{{.CPUPerc}}",memory:"{{.MemUsage}}",memoryPercent:"{{.MemPerc}}",network:"{{.NetIO}}",blockIo:"{{.BlockIO}}",pids:"{{.PIDs}}"});class Ti{snapshots=new Map;runCommand;targets;publish;intervalMs;timer;inFlight;pendingTargets=new Map;constructor(e,t,n,i=3e3){this.runCommand=e,this.targets=t,this.publish=n,this.intervalMs=i}start(){this.collect().catch(()=>{}),this.timer=setInterval(()=>{this.collect().catch(()=>{})},this.intervalMs)}stop(){this.timer&&clearInterval(this.timer),this.timer=void 0}async snapshot(e){const t=this.targets().find(t=>t.id===e);if(t)return Ei.has(t.status)?(await this.collect([t]),this.snapshots.get(e)):Ri(t.id)}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)this.pendingTargets.set(e.id,e);this.inFlight||(this.inFlight=this.drain().finally(()=>{this.inFlight=void 0})),await this.inFlight,this.pendingTargets.size&&await this.collect([])}async drain(){for(;this.pendingTargets.size;){const e=[...this.pendingTargets.values()];this.pendingTargets.clear(),await this.collectOnce(e)}}async collectOnce(e){const t=e.filter(e=>Ei.has(e.status)&&(e.runtime.containerId||e.runtime.containerName));for(const t of e.filter(e=>Ei.has(e.status)&&!e.runtime.containerId&&!e.runtime.containerName))this.update(Di(t.id));for(const t of e.filter(e=>!Ei.has(e.status)))this.update(Ri(t.id));if(!t.length)return;const n=t.map(e=>e.runtime.containerId||e.runtime.containerName),i=(new Date).toISOString();try{const e=await this.runCommand("docker",["stats","--no-stream","--format",_i,...n],{timeoutMs:5e3});this.applyDockerOutput(t,e.stdout,i)}catch(e){if(1===t.length)return void this.update(Pi(t[0].id,i,e instanceof Error?e.message:String(e)));await Promise.all(t.map(async e=>{const t=e.runtime.containerId||e.runtime.containerName;try{const n=await this.runCommand("docker",["stats","--no-stream","--format",_i,t],{timeoutMs:5e3});this.applyDockerOutput([e],n.stdout,i)}catch(t){this.update(Pi(e.id,i,t instanceof Error?t.message:String(t)))}}))}}applyDockerOutput(e,t,n){const i=function(e,t=(new Date).toISOString()){const n=new Map;for(const i of e.split(/\r?\n/).filter(Boolean)){let e;try{e=JSON.parse(i)}catch{continue}const r=Oi(e.id),s=Oi(e.name),o=r||s;if(!o)continue;const a=ki(Oi(e.memory)),c=ki(Oi(e.network)),d=ki(Oi(e.blockIo)),l=Sn.parse({instanceId:o,runtimeKind:"docker",state:"available",sampledAt:t,cpu:xi(e.cpu,"usagePercent"),memory:a?{usageBytes:a[0],...void 0!==a[1]?{limitBytes:a[1]}:{},...xi(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:Ci(e.pids)});r&&n.set(r,l),s&&n.set(s,l)}return n}(t,n);for(const t of e){const e=[t.runtime.containerId,t.runtime.containerName].filter(Boolean),r=[...i.entries()].find(([t])=>e.some(e=>e===t||e.startsWith(t)||t.startsWith(e)))?.[1];this.update(r?{...r,instanceId:t.id}:Pi(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 ki(e){if(!e)return;const[t,n]=e.split("/").map(e=>function(e){const t=e.trim().match(/^([0-9]+(?:\.[0-9]+)?)\s*([kmgtpe]?i?b)$/i);if(!t)return;const n=Number(t[1]),i=t[2].toLowerCase(),r=i.includes("i"),s="b"===i[0]?"":i[0],o=s?"kmgtpe".indexOf(s)+1:0;return Math.round(n*(r?1024:1e3)**o)}(e||""));return void 0===t?void 0:[t,n]}function xi(e,t){const n=Number(Oi(e).replace(/%$/,""));return Number.isFinite(n)&&n>=0?{[t]:n}:void 0}function Ci(e){const t=Number(Oi(e));return Number.isFinite(t)&&t>=0?t:void 0}function Oi(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 Di(e){return{instanceId:e,runtimeKind:"docker",state:"pending",sampledAt:(new Date).toISOString()}}function Pi(e,t,n){return{instanceId:e,runtimeKind:"docker",state:"unavailable",sampledAt:t,error:n.slice(0,2048)}}function ji(e){try{return t.statSync(e).isDirectory()}catch{return!1}}function Mi(e,i){let r;try{r=t.statSync(e)}catch{return}if(!r.isDirectory())return;const s=n.resolve(e),o=n.basename(s)||s;let a=[];try{a=i>0?t.readdirSync(s,{withFileTypes:!0}):[]}catch{a=[]}const c=i>0?a.filter(e=>e.isDirectory()||e.isSymbolicLink()&&ji(n.join(s,e.name))).sort((e,t)=>e.name.localeCompare(t.name)).slice(0,80).flatMap(e=>{const t=Mi(n.join(s,e.name),i-1);return t?[t]:[]}):[];return{name:o,path:s,children:c}}function Li(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(ji)}()).flatMap(t=>{const n=Mi(t,e.depth);return n?[n]:[]})}const $i=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(),Fi=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(),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(),Vi=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:fn.optional(),source:Ut,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:Dn.shape.modelSelection}).strict(),Hi=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:Dn.shape.modelSelection.optional()}).strict(),qi=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(),Bi=qi.omit({id:!0}).partial().strict();function Ki(){return process.env.TASK_HANDOFF_NODE_AGENT_DATA_DIR||n.join(p.homedir(),".config","task-handoff","node-agent")}function Gi(e=Ki()){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 Ji(e){t.mkdirSync(e,{recursive:!0})}function Wi(e,t){Ji(n.dirname(e)),h.sync(e,`${JSON.stringify(t,null,2)}\n`,{encoding:"utf8"})}function Yi(e,t){console.warn(JSON.stringify({message:e,...t}))}function Xi(e){return e&&"object"==typeof e&&"issues"in e?{issues:e.issues}:{error:e instanceof Error?e.message:String(e)}}function Zi(e,n){const i=n.logger||Yi;let r;try{r=JSON.parse(t.readFileSync(e,"utf8"))}catch(t){return void i("stored JSON could not be read",{filePath:e,...Xi(t)})}if(!n.schema)return r;const s=n.sanitize?n.sanitize(r):r,o=n.schema.safeParse(s);if(o.success)return o.data;const a="strip"in n.schema&&"function"==typeof n.schema.strip?n.schema.strip().safeParse(s):void 0;if(a?.success)return i("unknown stored fields were ignored",{filePath:e,issues:o.error.issues}),a.data;i("stored record failed validation and was isolated",{filePath:e,issues:o.error.issues})}function Qi(e){return`${e}_${i.randomUUID().replace(/-/g,"").slice(0,20)}`}function er(){return i.randomBytes(24).toString("base64url")}class tr{directory;options;constructor(e,t={}){this.directory=e,this.options=t}init(){Ji(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=Zi(n.join(this.directory,e),this.options);return t?[t]:[]})}get(e){const n=this.filePath(e);return t.existsSync(n)?Zi(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 Wi(this.filePath(n.id),n),n}patch(e,t){const n=this.get(e);if(!n)return;const i={...n,...t,id:n.id,createdAt:n.createdAt,updatedAt:(new Date).toISOString()};return this.put(i)}delete(e){const n=this.filePath(e);return!!t.existsSync(n)&&(t.unlinkSync(n),!0)}}class nr{filePathValue;defaults;options;constructor(e,t,n={}){this.filePathValue=e,this.defaults=t,this.options=n}init(){Ji(n.dirname(this.filePathValue)),t.existsSync(this.filePathValue)||this.put(this.defaults())}get(){return this.init(),t.existsSync(this.filePathValue)?Zi(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 Wi(this.filePathValue,n),n}}function ir(e,t=process.platform){const r=n.resolve(e),s=i.createHash("sha256").update(r).digest("hex").slice(0,16);return"win32"===t?`\\\\.\\pipe\\task-handoff-node-agent-${s}`:n.join("/tmp",`task-handoff-node-agent-${process.getuid?.()??"user"}`,`${s}.sock`)}const rr="TASK_HANDOFF_NODE_AGENT_V1";function sr(e=""){return i.createHash("sha256").update(e).digest("hex")}function or(e,t){return i.createHmac("sha256",e).update(function(e){return[rr,e.keyId,e.method.toUpperCase(),e.pathWithQuery,e.timestamp,e.nonce,e.bodySha256].join("\n")}(t)).digest("hex")}function ar(e){const t=e.timestamp||(new Date).toISOString(),n=e.nonce||i.randomBytes(18).toString("base64url"),r=sr(e.body||""),s=or(e.secret,{keyId:e.keyId,method:e.method,pathWithQuery:e.pathWithQuery,timestamp:t,nonce:n,bodySha256:r});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":r,"x-taskhandoff-signature":s}}const cr=new Set(["DELETE","GET","HEAD","PATCH","POST","PUT","OPTIONS"]);function dr(e){return"string"==typeof e&&cr.has(e.toUpperCase())?e.toUpperCase():"GET"}function lr(){return(new Date).toISOString()}function ur(){return process.env.TASK_HANDOFF_NPM_COMMAND||"npm"}function mr(e){if(!e||"object"!=typeof e||Array.isArray(e))return e;const t=e,n="string"==typeof t.updatedAt?t.updatedAt:lr(),i=t.target&&"object"==typeof t.target&&!Array.isArray(t.target)?t.target:void 0,r="controlled-instance"===i?.component,s={updating:"updating-node",downloading:"updating-node",installing:"updating-node",restarting:"restarting-node",completed:"succeeded",success:"succeeded",error:"failed"},o=new Set(["queued","updating-node","restarting-node","converging-instances","succeeded","degraded","failed"]),a="string"==typeof t.status?t.status:"queued",c=r?"failed":o.has(a)?a:s[a]||"failed",d="string"==typeof t.toVersion&&t.toVersion?t.toVersion:"unknown",l=Ct.strip().safeParse(t.impact).success?Ct.strip().parse(t.impact):{runningInstanceCount:0,stoppedInstanceCount:0,activeInstanceCount:0,restartInstanceCount:0,runningInstanceIds:[],stoppedInstanceIds:[],activeInstanceIds:[]},u=r?{code:"LEGACY_INSTANCE_UPDATE_RETIRED",message:"Independent controlled-instance update jobs were retired in favor of Node reconciliation.",retryable:!1}:"failed"!==c||t.error||o.has(a)||a in s?"string"==typeof t.error?{code:"NODE_UPDATE_FAILED",message:t.error,retryable:!1}:kt.strip().safeParse(t.error).success?kt.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:r||"failed"===c?1:0,deferredInstanceCount:0},f=Ot.strip().safeParse(t.rollout);return{...g,source:"npm",status:c,impact:l,runtimeArtifacts:Array.isArray(t.runtimeArtifacts)?t.runtimeArtifacts.flatMap(e=>{const t=Tt.strip().safeParse(e);return t.success?[t.data]:[]}):[],rollout:f.success?f.data:h,...u?{error:u}:{},...r?{completedAt:t.completedAt||n}:{}}}class pr{records;constructor(e){this.records=new tr(e.updatesDir,{schema:Pt,sanitize:mr})}init(){this.records.init()}list(){return this.records.list().sort((e,t)=>t.createdAt.localeCompare(e.createdAt))}create(e,t){const n=lr();return this.records.put(Pt.parse({id:Qi("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:lr()}))}reconcileRollouts(e,t){const n=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))){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 r=i.rollout.expectedInstanceIds,s=r.map(e=>n.get(e)),o=s.filter(e=>e?.ready&&"matched"===e.runtimeVersion?.phase&&e.runtimeVersion.actualVersion===i.toVersion).length,a=s.filter(e=>e&&["created","stopped","failed"].includes(e.status||"")&&"failed"!==e.runtimeVersion?.phase).length,c=s.filter(e=>!e||"failed"===e.runtimeVersion?.phase).length,d=Math.max(0,r.length-o-c-a),l=c>0?"degraded":0===d?"succeeded":"converging-instances";this.patch(i.id,{status:l,rollout:{...i.rollout,phase:l,nodeVersion:t,expectedInstanceCount:r.length,matchedInstanceCount:o,pendingInstanceCount:d,failedInstanceCount:c,deferredInstanceCount:i.impact.stoppedInstanceCount+a},..."succeeded"===l||"degraded"===l?{completedAt:lr()}:{}})}}run(e,t){(async()=>{this.patch(e.id,{status:"updating-node",rollout:{...e.rollout,phase:"updating-node"},startedAt:lr(),error:void 0});try{await t(e),this.patch(e.id,{status:"succeeded",completedAt:lr()})}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:lr()})}})()}}const gr="runtime-manifest.json";class hr 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 fr(e,t=""){const i=[],r=await I.readdir(n.join(e,t),{withFileTypes:!0});for(const s of r){const r=t?n.posix.join(t,s.name):s.name;if(!t&&r===gr)continue;const o=n.join(e,...r.split("/"));if(s.isDirectory()){i.push(...await fr(e,r));continue}if(s.isSymbolicLink()){const t=await I.readlink(o);if(n.isAbsolute(t))throw new hr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload symlink is absolute: ${r}`);const s=n.resolve(n.dirname(o),t),a=n.relative(n.resolve(e),s);if(!a||".."===a||a.startsWith(`..${n.sep}`)||n.isAbsolute(a))throw new hr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload symlink escapes the artifact: ${r}`);if(!await I.lstat(s).catch(()=>{}))throw new hr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload symlink is broken: ${r}`);i.push({absolutePath:o,relativePath:r,kind:"symlink",target:t,size:Buffer.byteLength(t)});continue}if(!s.isFile())throw new hr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload contains unsupported entry: ${r}`);const a=await I.lstat(o);i.push({absolutePath:o,relativePath:r,kind:"file",size:a.size})}return i}async function Ir(e){const n=(await fr(e)).sort((e,t)=>function(e,t){return Buffer.compare(Buffer.from(e,"utf8"),Buffer.from(t,"utf8"))}(e.relativePath,t.relativePath)),r=i.createHash("sha256");for(const e of n){if(r.update("file"===e.kind?"F":"L","ascii"),r.update(Buffer.from(e.relativePath,"utf8")),r.update(Buffer.from([0])),r.update(Buffer.from(String(e.size),"ascii")),r.update(Buffer.from([0])),"file"===e.kind)for await(const n of t.createReadStream(e.absolutePath))r.update(n);else r.update(Buffer.from(e.target,"utf8"));r.update(Buffer.from([0]))}return r.digest("hex")}function yr(e){for(const[t,n]of[["version",e.version],["platform",e.platform],["arch",e.arch]])if(!/^[0-9A-Za-z._-]+$/.test(n))throw new hr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Invalid runtime artifact ${t}: ${n}`);return`${e.version}-${e.platform}-${e.arch}`}function Ar(e,t){return`${yr(e)}-${e.sha256}-${t}`}async function br(e){const n=i.createHash("sha256");for await(const i of t.createReadStream(e))n.update(i);return n.digest("hex")}class wr{#e;#t;#n=new Map;constructor(e){this.#e=e.cacheDir,this.#t=e.fetchImpl??fetch}resolve(e,t){const n=Tt.parse(e);if(!/^[a-f0-9]{64}$/.test(t.archiveSha256))throw new hr("INSTANCE_RUNTIME_ARTIFACT_INVALID","Runtime archive SHA-256 is invalid.");if((t.archiveUrl?1:0)+(t.archivePath?1:0)!=1)throw new hr("INSTANCE_RUNTIME_ARTIFACT_INVALID","Runtime artifact source must specify exactly one archive location.");const i=Ar(n,t.archiveSha256),r=this.#n.get(i);if(r)return r;const s=this.#i(n,t).finally(()=>this.#n.delete(i));return this.#n.set(i,s),s}async#i(e,r){if(!/^[a-f0-9]{64}$/.test(r.archiveSha256))throw new hr("INSTANCE_RUNTIME_ARTIFACT_INVALID","Runtime archive SHA-256 is invalid.");const s=Ar(e,r.archiveSha256),o=n.join(this.#e,"archives"),a=n.join(o,`${s}.tar.gz`);if(await I.mkdir(o,{recursive:!0}),await this.#r(a,e,r.archiveSha256))return{identity:e,archivePath:a,cacheHit:!0};await I.rm(a,{force:!0});const c=n.join(o,`.${s}.${i.randomUUID()}.part`);try{const n=await I.open(c,"wx");if(r.archivePath)await y.pipeline(t.createReadStream(r.archivePath),n.createWriteStream());else{const e=await this.#t(r.archiveUrl);if(!e.ok||!e.body)throw await n.close(),new hr("INSTANCE_RUNTIME_ARTIFACT_UNAVAILABLE",`Runtime artifact download failed with HTTP ${e.status}.`,{retryable:e.status>=500});await y.pipeline(e.body,n.createWriteStream())}if(await br(c)!==r.archiveSha256)throw new hr("INSTANCE_RUNTIME_ARTIFACT_INVALID","Downloaded runtime archive SHA-256 does not match release metadata.");return await this.#s(c,e),await I.rename(c,a),{identity:e,archivePath:a,cacheHit:!1}}catch(e){if(e instanceof hr)throw e;throw new hr("INSTANCE_RUNTIME_ARTIFACT_UNAVAILABLE","Could not download runtime artifact.",{cause:e,retryable:!0})}finally{await I.rm(c,{force:!0})}}async#r(e,t,n){try{return await br(e)===n&&(await this.#s(e,t),!0)}catch{return!1}}async#s(e,t){const r=n.join(this.#e,"validation",`${yr(t)}-${i.randomUUID()}`);try{await async function(e,t){await I.mkdir(t,{recursive:!0});try{await A.extract({file:e,cwd:t,strict:!0,preservePaths:!1,filter:(e,t)=>{const i=n.posix.normalize(e.replace(/^\.\//,""));if(!i||".."===i||i.startsWith("../")||n.posix.isAbsolute(i))throw new hr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime archive entry escapes the artifact root: ${e}`);const r=t.type;if("File"!==r&&"OldFile"!==r&&"Directory"!==r&&"SymbolicLink"!==r)throw new hr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime archive contains unsupported entry type ${r??"unknown"}: ${e}`);return!0}})}catch(e){throw new hr("INSTANCE_RUNTIME_ARTIFACT_INVALID","Could not extract runtime artifact safely.",{cause:e})}}(e,r),await async function(e,t,i){const r=await async function(e){let t;try{t=JSON.parse(await I.readFile(n.join(e,gr),"utf8"))}catch(e){throw new hr("INSTANCE_RUNTIME_ARTIFACT_INVALID","Runtime artifact manifest is missing or invalid JSON.",{cause:e})}const i=Tt.safeParse(t);if(!i.success)throw new hr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime artifact manifest is invalid: ${i.error.message}`);return i.data}(e);if(function(e,t){for(const n of["packageName","version","platform","arch","formatVersion","launcherAbi","entrypoint","sha256"])if(e[n]!==t[n])throw new hr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime artifact ${"sha256"===n?"SHA-256":n} mismatch: expected ${t[n]}, got ${e[n]}.`)}(r,t),1!==r.formatVersion)throw new hr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Unsupported runtime artifact format ${r.formatVersion}.`);if(i?.platform&&"universal"!==r.platform&&r.platform!==i.platform)throw new hr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime artifact platform ${r.platform} does not match ${i.platform}.`);if(i?.arch&&"universal"!==r.arch&&r.arch!==i.arch)throw new hr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime artifact architecture ${r.arch} does not match ${i.arch}.`);if(void 0!==i?.launcherAbi&&r.launcherAbi>i.launcherAbi)throw new hr("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Runtime requires launcher ABI ${r.launcherAbi}, but the base runtime provides ${i.launcherAbi}.`);const s=function(e,t){if(!e||e.includes("\\")||n.posix.isAbsolute(e))throw new hr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`${t} must be a non-empty POSIX relative path.`);const i=n.posix.normalize(e);if("."===i||".."===i||i.startsWith("../"))throw new hr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`${t} escapes the runtime root.`);return i}(r.entrypoint,"Runtime entrypoint"),o=await I.lstat(n.join(e,...s.split("/"))).catch(()=>{});if(!o?.isFile())throw new hr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime entrypoint is missing: ${s}`);const a=await Ir(e);if(a!==r.sha256)throw new hr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload SHA-256 mismatch: expected ${r.sha256}, got ${a}.`);return r}(r,t,{platform:t.platform,arch:t.arch})}finally{await I.rm(r,{recursive:!0,force:!0})}}}async function zr(e,t,i,r=fetch){if("linux"!==t||!["x64","arm64"].includes(i))throw new hr("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Managed controlled-instance updates require a Linux x64 or arm64 target, received ${t}/${i}.`);const s=await async function(e){const t=`controlled-instance-runtime-${e}-linux-universal`,i=function(){const e=process.env.TASK_HANDOFF_BUNDLED_RUNTIME_DIR?.trim();return n.resolve(e||n.join(n.dirname(process.argv[1]||process.cwd()),"..","runtime-artifacts"))}();try{const[r,s]=await Promise.all([I.readFile(n.join(i,`${t}.manifest.json`),"utf8"),I.readFile(n.join(i,`${t}.tar.gz.sha256`),"utf8")]),o=Tt.safeParse(JSON.parse(r));if(!o.success||o.data.version!==e||"linux"!==o.data.platform||"universal"!==o.data.arch)throw new hr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Bundled controlled-instance ${e} has an invalid Linux manifest.`);const a=s.trim().split(/\s+/)[0]?.toLowerCase();if(!a||!/^[a-f0-9]{64}$/.test(a))throw new hr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Bundled controlled-instance ${e} has an invalid archive checksum.`);return{identity:o.data,source:{archivePath:n.join(i,`${t}.tar.gz`),archiveSha256:a}}}catch(t){if("ENOENT"===t.code)return;if(t instanceof hr)throw t;throw new hr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Could not read bundled controlled-instance ${e}.`,{cause:t})}}(e);if(s)return s;const o=`controlled-instance-runtime-${e}-linux-universal`,a=function(e){const t=process.env.TASK_HANDOFF_RUNTIME_RELEASE_BASE_URL?.trim();return t?t.replaceAll("{version}",e).replace(/\/$/,""):`https://github.com/edgestorage/task-handoff/releases/download/v${e}`}(e),c=`${a}/${o}.manifest.json`,d=`${a}/${o}.tar.gz`,l=`${a}/${o}.tar.gz.sha256`,[u,m]=await Promise.all([r(c),r(l)]).catch(t=>{throw new hr("INSTANCE_RUNTIME_ARTIFACT_UNAVAILABLE",`Could not read release metadata for controlled-instance ${e}.`,{cause:t,retryable:!0})});if(!u.ok||!m.ok)throw new hr("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 hr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Release manifest for controlled-instance ${e} is not valid JSON.`,{cause:t})}const g=Tt.safeParse(p);if(!g.success)throw new hr("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 hr("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 hr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Release checksum for controlled-instance ${e} is invalid.`);return{identity:g.data,source:{archiveUrl:d,archiveSha256:h}}}class Nr{store;desiredVersion;hooks;inFlight=new Map;requests=new Map;cancelled=new Set;now;delay;drainTimeoutMs;verificationTimeoutMs;pollIntervalMs;maxAttempts;retryBaseDelayMs;retryMaxDelayMs;constructor(e,t,n,i={}){this.store=e,this.desiredVersion=t,this.hooks=n,this.now=i.now||(()=>new Date),this.delay=i.delay||(e=>new Promise(t=>setTimeout(t,e))),this.drainTimeoutMs=i.drainTimeoutMs??3e5,this.verificationTimeoutMs=i.verificationTimeoutMs??6e4,this.pollIntervalMs=i.pollIntervalMs??250,this.maxAttempts=function(e){if(!Number.isInteger(e)||e<=0)throw new TypeError("maxAttempts must be a positive integer.");return e}(i.maxAttempts??3),this.retryBaseDelayMs=Cr(i.retryBaseDelayMs??1e3,"retryBaseDelayMs"),this.retryMaxDelayMs=Cr(i.retryMaxDelayMs??3e4,"retryMaxDelayMs")}schedule(e,t={}){const n=this.requests.get(e)||{startRequested:!1,resumeCancelled:!1};n.startRequested||=!0===t.startRequested,n.resumeCancelled||=!0===t.resumeCancelled||!0===t.startRequested,n.resumeCancelled&&this.cancelled.delete(e),this.requests.set(e,n);const i=this.inFlight.get(e);if(i)return i;const r=Promise.resolve().then(()=>this.reconcile(e,n)).finally(()=>{this.inFlight.delete(e),this.requests.delete(e)});return this.inFlight.set(e,r),r}isRunning(e){return this.inFlight.has(e)}cancel(e){return this.cancelled.add(e),this.inFlight.get(e)}async reconcile(e,t){let n=this.requireInstance(e);const i=this.desiredVersion();if(this.cancelled.has(e)&&!t.resumeCancelled)return this.storePhase(n,"pending");const r=vr(n),s=r===i&&(await(this.hooks.isInstalled?.(n,i))??!0);if(this.cancelled.has(e))return this.storePhase(this.requireInstance(e),"pending");if(r===i&&s)return this.storeState(n,{desiredVersion:i,actualVersion:r,phase:"matched",attempt:n.runtimeVersion?.attempt||0,matchedAt:this.timestamp()},!Er(n)&&"failed"!==n.health);if(n.runtimeVersion?.desiredVersion===i&&(n.runtimeVersion?.attempt||0)>=this.maxAttempts)return"failed"===n.runtimeVersion?.phase&&n.runtimeVersion.error?n:this.storePermanentFailure(n,i,xr(i,r,this.maxAttempts,n.runtimeVersion?.error));if(n=this.storeState(n,function(e,t,n,i=!1){const r=e.runtimeVersion,s=r?.desiredVersion===t&&"matched"!==r.phase;return{desiredVersion:t,...n?{actualVersion:n}:{},phase:"pending",attempt:s?r.attempt:0,error:(s?r.error:void 0)||(n!==t||i?_r(t,n):Tr("INSTANCE_RUNTIME_VERIFICATION_FAILED",`Controlled-instance ${t} is running, but the active runtime artifact does not match the desired release identity.`,t,n,!0))}}(n,i,r,s),!1),Er(n)&&!t.startRequested)return n;for(;(n.runtimeVersion?.attempt||0)<this.maxAttempts;){if(this.cancelled.has(e))return this.storePhase(this.requireInstance(e),"pending");let r,s=!1;try{if(Sr(n)){n=this.storePhase(n,"draining");const t=await this.waitUntil(e,this.drainTimeoutMs,e=>!Sr(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,i),s=!0,this.cancelled.has(e)||Er(this.requireInstance(e))&&!t.startRequested)return this.storePhase(this.requireInstance(e),"pending");if(n=this.storePhase(this.requireInstance(e),"restarting"),await this.hooks.restart(n),this.cancelled.has(e))return this.storePhase(this.requireInstance(e),"pending");n=this.storePhase(this.requireInstance(e),"verifying");const r=await this.waitUntil(e,this.verificationTimeoutMs,e=>vr(e)===i);if(this.cancelled.has(e))return this.storePhase(this.requireInstance(e),"pending");if(!r)throw Tr("INSTANCE_RUNTIME_VERIFICATION_FAILED",`Instance ${e} did not register controlled-instance ${i} after restart.`,i,vr(this.requireInstance(e)),!0);const o=this.requireInstance(e);if(this.hooks.isInstalled&&!await this.hooks.isInstalled(o,i))throw Tr("INSTANCE_RUNTIME_VERIFICATION_FAILED",`Instance ${e} reported controlled-instance ${i}, but its active runtime release is missing.`,i,vr(o),!0);return this.storeState(o,{desiredVersion:i,actualVersion:i,phase:"matched",attempt:o.runtimeVersion?.attempt||1,matchedAt:this.timestamp()},!Er(o)&&"failed"!==o.health)}catch(t){if(this.cancelled.has(e))return this.storePhase(this.requireInstance(e),"pending");if(r=kr(t,i,vr(this.store.get(e))),s&&this.hooks.rollback)try{await this.hooks.rollback(this.requireInstance(e))}catch(e){r.message=`${r.message} Rollback failed: ${e instanceof Error?e.message:String(e)}`,r.retryable=!1}}n=this.requireInstance(e);const o=n.runtimeVersion?.attempt||1;if(!r.retryable||o>=this.maxAttempts)return this.storePermanentFailure(n,i,o>=this.maxAttempts&&r.retryable?xr(i,vr(n),this.maxAttempts,r):r);n=this.storeState(n,{desiredVersion:i,...vr(n)?{actualVersion:vr(n)}:{},phase:"pending",attempt:o,lastAttemptAt:this.timestamp(),error:r},!1),await this.delay(this.retryDelayMs(o))}return this.storePermanentFailure(n,i,xr(i,vr(n),this.maxAttempts,n.runtimeVersion?.error))}storePermanentFailure(e,t,n){const i=vr(e);return this.storeState(e,{desiredVersion:t,...i?{actualVersion:i}:{},phase:"failed",attempt:e.runtimeVersion?.attempt||0,lastAttemptAt:this.timestamp(),error:{...n,retryable:!1}},!1)}retryDelayMs(e){return Math.min(this.retryMaxDelayMs,this.retryBaseDelayMs*2**Math.max(0,e-1))}storePhase(e,t,n=!1){const i=this.desiredVersion(),r=vr(e),s=e.runtimeVersion?.desiredVersion===i?e.runtimeVersion.error:void 0;return this.storeState(e,{desiredVersion:i,...r?{actualVersion:r}:{},phase:t,attempt:(e.runtimeVersion?.attempt||0)+(n?1:0),lastAttemptAt:this.timestamp(),...s?{error:s}:"pending"===t?{error:_r(i,r)}:{}},!1)}storeState(e,t,n){const i=this.store.get(e.id)||e;return this.store.put(Dn.parse({...i,runtimeVersion:t,ready:n,...n?{}:{health:"failed"===i.health?"failed":"degraded"},updatedAt:this.timestamp()}))}async waitUntil(e,t,n){const i=this.now().getTime()+t;for(;;){const t=this.store.get(e);if(t&&n(t))return!0;if(this.cancelled.has(e))return!1;if(this.now().getTime()>=i)return!1;await this.delay(Math.min(this.pollIntervalMs,Math.max(0,i-this.now().getTime())))}}requireInstance(e){const t=this.store.get(e);if(!t)throw new Error(`Instance ${e} was removed during runtime reconciliation.`);return t}timestamp(){return this.now().toISOString()}}function vr(e){return e?.build?.packageVersion||e?.instanceVersion}function Sr(e){return e.apps.runningCount>0||e.aiSessions.runningCount>0}function Er(e){return["created","stopped","failed"].includes(e.status)}function _r(e,t){return Tr("INSTANCE_RUNTIME_VERSION_MISMATCH",`Expected controlled-instance ${e}, received ${t||"an unknown version"}.`,e,t,!0)}function Tr(e,t,n,i,r){return{code:e,message:t,expectedVersion:n,...i?{actualVersion:i}:{},retryable:r}}function kr(e,t,n){if(e&&"object"==typeof e&&"code"in e&&"message"in e){const i=e,r=kt.shape.code.safeParse(i.code);if(r.success&&"string"==typeof i.message)return Tr(r.data,i.message,t,n,"boolean"!=typeof i.retryable||i.retryable)}return Tr("INSTANCE_RUNTIME_INSTALL_FAILED",e instanceof Error?e.message:String(e),t,n,!0)}function xr(e,t,n,i){const r=i?.message?` Last error: ${i.message}`:"";return Tr(i?.code||"INSTANCE_RUNTIME_INSTALL_FAILED",`Runtime convergence exhausted ${n} attempts.${r}`,e,t,!1)}function Cr(e,t){if(!Number.isFinite(e)||e<0)throw new TypeError(`${t} must be a nonnegative finite number.`);return e}const Or=m.z.record(m.z.string(),m.z.string()),Rr=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 Dr{directory;constructor(e){this.directory=e}get(e){try{return Or.parse(JSON.parse(t.readFileSync(this.filePath(e),"utf8")))}catch(t){if(t&&"object"==typeof t&&"code"in t&&"ENOENT"===t.code)return{};throw new Error(`Stored model environment for instance ${e} is invalid: ${t instanceof Error?t.message:String(t)}`)}}has(e){return t.existsSync(this.filePath(e))}listInstanceIds(){return t.existsSync(this.directory)?t.readdirSync(this.directory).filter(e=>e.endsWith(".json")).map(e=>e.slice(0,-5)).sort():[]}put(e,n){const i=Or.parse(n);t.mkdirSync(this.directory,{recursive:!0,mode:448});const r=this.filePath(e);return h.sync(r,`${JSON.stringify(i,null,2)}\n`,{encoding:"utf8",mode:384}),t.chmodSync(r,384),i}delete(e){t.rmSync(this.filePath(e),{force:!0})}filePath(e){return n.join(this.directory,`${e}.json`)}}class Pr{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=Kt.parse(e);this.init();const i=this.filePath(n.id);return h.sync(i,`${JSON.stringify(n,null,2)}\n`,{encoding:"utf8",mode:384}),t.chmodSync(i,384),n}delete(e){const n=this.filePath(e);return!!t.existsSync(n)&&(t.unlinkSync(n),!0)}read(e){try{const i=JSON.parse(t.readFileSync(e,"utf8")),r=n.basename(e,".json"),s=Kt.safeParse(i);if(s.success&&s.data.id===r&&rn(s.data)===s.data.id)return s.data;const o=Kt.strip().safeParse(i);return o.success&&o.data.id===r&&rn(o.data)===o.data.id?(console.warn(JSON.stringify({message:"unknown stored node model fields were ignored",nodeId:this.nodeId,filePath:e})),o.data):void console.warn(JSON.stringify({message:"stored node model failed validation and was isolated",nodeId:this.nodeId,filePath:e}))}catch(t){return void console.warn(JSON.stringify({message:"stored node model could not be read",nodeId:this.nodeId,filePath:e,error:t instanceof Error?t.message:String(t)}))}}filePath(e){return n.join(this.directory,`${e}.json`)}}class jr{directory;constructor(e){this.directory=e}init(){t.mkdirSync(this.directory,{recursive:!0,mode:448}),t.chmodSync(this.directory,448)}get(e){const n=this.filePath(e);if(t.existsSync(n))try{const i=JSON.parse(t.readFileSync(n,"utf8")),r=Wt.safeParse(i);if(r.success)return r.data;const s=Wt.strip().safeParse(i);if(s.success)return console.warn(JSON.stringify({message:"unknown stored model assignment fields were ignored",instanceId:e,filePath:n})),s.data;throw r.error}catch(t){throw Object.assign(new Error(`Stored model assignment for instance ${e} is invalid.`),{statusCode:409,code:"NODE_MODEL_ASSIGNMENT_INVALID",cause:t})}}put(e){const n=Wt.parse(e);this.init();const i=this.filePath(n.instanceId);return h.sync(i,`${JSON.stringify(n,null,2)}\n`,{encoding:"utf8",mode:384}),t.chmodSync(i,384),n}delete(e){t.rmSync(this.filePath(e),{force:!0})}filePath(e){return n.join(this.directory,`${e}.json`)}}class Mr{usedNonces=new Map;identity;nodeId;overrideSecret;overrideKeyId;nowMs;constructor(e,t,n,i,r=Date.now){this.identity=e,this.nodeId=t,this.overrideSecret=n,this.overrideKeyId=i,this.nowMs=r}hasRemoteSecrets(){return this.identity.remoteSecrets(this.overrideSecret,this.overrideKeyId).length>0}verify(e){const t=function(e){const t=new Map;for(const[n,i]of Object.entries(e)){const e=Array.isArray(i)?i.join(","):"string"==typeof i?i:void 0===i?"":String(i);t.set(n.toLowerCase(),e)}return{nodeId:t.get("x-taskhandoff-node-id")||"",keyId:t.get("x-taskhandoff-key-id")||"",timestamp:t.get("x-taskhandoff-timestamp")||"",nonce:t.get("x-taskhandoff-nonce")||"",bodySha256:t.get("x-taskhandoff-body-sha256")||"",signature:t.get("x-taskhandoff-signature")||""}}(e.headers);if(!t.nodeId&&!t.signature)return!1;const n=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 r=n.filter(e=>t.keyId===e.keyId);if(!r.length)throw Object.assign(new Error("Invalid node agent HMAC key id."),{statusCode:401,code:"NODE_AGENT_HMAC_KEY_INVALID"});const s=Date.parse(t.timestamp);if(!Number.isFinite(s)||Math.abs(this.nowMs()-s)>6e4)throw Object.assign(new Error("Node agent HMAC timestamp is outside the allowed window."),{statusCode:401,code:"NODE_AGENT_HMAC_TIMESTAMP_INVALID"});if(!t.nonce)throw Object.assign(new Error("Node agent HMAC nonce is missing."),{statusCode:401,code:"NODE_AGENT_HMAC_NONCE_MISSING"});this.pruneNonces();const o=`${t.nodeId}:${t.keyId}:${t.nonce}`;if(this.usedNonces.has(o))throw Object.assign(new Error("Node agent HMAC nonce was already used."),{statusCode:401,code:"NODE_AGENT_HMAC_NONCE_REPLAY"});const a=sr(null==(c=e.body)?"":"string"==typeof c||Buffer.isBuffer(c)?c:JSON.stringify(c));var c;if(t.bodySha256!==a)throw Object.assign(new Error("Node agent HMAC body hash mismatch."),{statusCode:401,code:"NODE_AGENT_HMAC_BODY_HASH_INVALID"});if(!r.some(n=>function(e,t){const n=Buffer.from(e,"hex"),r=Buffer.from(t,"hex");return n.length===r.length&&i.timingSafeEqual(n,r)}(t.signature,or(n.secret,{keyId:t.keyId,method:e.method,pathWithQuery:e.url,timestamp:t.timestamp,nonce:t.nonce,bodySha256:a}))))throw Object.assign(new Error("Invalid node agent HMAC signature."),{statusCode:401,code:"NODE_AGENT_HMAC_SIGNATURE_INVALID"});return this.usedNonces.set(o,s+6e4+1),t.keyId}pruneNonces(){const e=this.nowMs();for(const[t,n]of this.usedNonces)n<=e&&this.usedNonces.delete(t)}}const Lr=m.z.string().trim().min(1).max(160),$r=m.z.string().datetime(),Fr=m.z.string().min(1).max(4096),Ur=m.z.string().trim().url().max(2048),Vr=m.z.object({tokenHash:m.z.string().trim().min(1).max(256),expiresAt:$r,createdAt:$r,controlPlaneName:m.z.string().trim().min(1).max(160).optional(),controlPlaneUrl:Ur.optional()}).strip(),Hr=m.z.object({id:Lr,keyId:Lr,name:m.z.string().trim().min(1).max(160).optional(),url:Ur.optional(),secret:Fr,pairedAt:$r,updatedAt:$r,active:m.z.boolean().default(!0)}).strip(),qr=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(),Br=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(),Kr=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 Gr(){return(new Date).toISOString()}const Jr=new Set(["nodeId","createdAt","updatedAt","pairingInvites","remoteControlPlanes"]),Wr=new Set(["tokenHash","expiresAt","createdAt","controlPlaneName","controlPlaneUrl"]),Yr=new Set(["id","keyId","name","url","secret","pairedAt","updatedAt","active"]);function Xr(e,t){console.warn(JSON.stringify({message:e,...t}))}function Zr(e,t){return Object.assign(new Error(e,void 0===t?void 0:{cause:t}),{code:"NODE_AGENT_IDENTITY_INVALID"})}function Qr(e,t){return Object.keys(e).filter(e=>!t.has(e))}function es(e,t,n){const i=$r.safeParse(e);return i.success?i.data:(n("invalid node agent identity timestamp was replaced",{field:t}),Gr())}function ts(e,t){if(!e||"object"!=typeof e||Array.isArray(e))throw Zr("Node agent identity must be a JSON object.");const n=e,i=Lr.safeParse(n.nodeId);if(!i.success)throw Zr("Node agent identity has an invalid nodeId.",i.error);const r=i.data,s=Qr(n,Jr);return s.length&&t("unknown node agent identity fields were ignored",{fields:s}),{nodeId:r,createdAt:es(n.createdAt,"createdAt",t),updatedAt:es(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=Qr(e,Wr);n.length&&t("unknown node agent pairing invite fields were ignored",{fields:n});const i=Vr.safeParse(e);return i.success?[i.data]:(t("invalid node agent pairing invite was ignored",{issues:i.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=Qr(e,Yr);n.length&&t("unknown node agent remote control-plane fields were ignored",{fields:n});const i=Hr.safeParse(e);return i.success?[i.data]:(t("invalid node agent remote control-plane was ignored",{issues:i.error.issues}),[])}):[]}}class ns{paths;logger;constructor(e,t={}){this.paths=e,this.logger=t.logger||Xr}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 Zr(`Node agent identity contains invalid JSON: ${this.paths.identityPath}`,e)}return ts(n,this.logger)}write(e){t.mkdirSync(n.dirname(this.paths.identityPath),{recursive:!0});const i=ts({...e,updatedAt:Gr()},this.logger);h.sync(this.paths.identityPath,`${JSON.stringify(i,null,2)}\n`,{encoding:"utf8",mode:384})}}function is(){return(new Date).toISOString()}class rs{store;constructor(e){this.store=new ns(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=Qi("node");return this.writeNodeId(n),n}createPairingInvite(e){const t=this.prunePairingInvites(this.store.read()||this.newIdentity()),n=is(),i=new Date(Date.now()+(e.expiresInMs||6e5)).toISOString(),r=er(),s={tokenHash:sr(r),createdAt:n,expiresAt:i,...e.controlPlaneName?{controlPlaneName:e.controlPlaneName}:{},...e.controlPlaneUrl?{controlPlaneUrl:e.controlPlaneUrl}:{}};return this.store.write({...t,pairingInvites:[...t.pairingInvites||[],s]}),{...s,token:r}}completePairingInvite(e){const t=this.prunePairingInvites(this.store.read()||this.newIdentity()),n=sr(e.joinToken),i=(t.pairingInvites||[]).find(e=>e.tokenHash===n);if(!i){const e=new Error("Node agent pairing invite is invalid or expired.");throw Object.assign(e,{statusCode:401,code:"NODE_AGENT_PAIRING_INVITE_INVALID"}),e}const r=is(),s={id:e.controlPlaneId||Qi("cp"),keyId:Qi("key"),...e.controlPlaneName||i.controlPlaneName?{name:e.controlPlaneName||i.controlPlaneName}:{},...e.controlPlaneUrl||i.controlPlaneUrl?{url:e.controlPlaneUrl||i.controlPlaneUrl}:{},secret:er(),pairedAt:r,updatedAt:r,active:!0};return this.store.write({...t,pairingInvites:(t.pairingInvites||[]).filter(e=>e.tokenHash!==n),remoteControlPlanes:[...(t.remoteControlPlanes||[]).filter(e=>e.id!==s.id),s]}),s}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=is();return{id:Qi("cp"),keyId:Qi("key"),...e.name?{name:e.name}:{},url:e.url,secret:er(),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 i=(n.remoteControlPlanes||[]).filter(t=>t.keyId!==e);return i.length!==(n.remoteControlPlanes||[]).length&&(this.store.write({...n,remoteControlPlanes:i}),!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 i=this.store.read()?.remoteControlPlanes||[];if(!i.length)return;if(e){const t=e.replace(/\/$/,""),n=i.find(e=>e.url?.replace(/\/$/,"")===t);if(n)return{keyId:n.keyId,secret:n.secret}}const r=[...i].sort((e,t)=>t.updatedAt.localeCompare(e.updatedAt))[0];return r?{keyId:r.keyId,secret:r.secret}:void 0}newIdentity(){return{nodeId:this.resolveNodeId(),createdAt:is(),updatedAt:is(),pairingInvites:[],remoteControlPlanes:[]}}writeNodeId(e){const t=this.store.read();this.store.write({...t||{createdAt:is()},nodeId:e,updatedAt:is(),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 ss=new Set(["content-encoding","content-length","transfer-encoding"]),os=["codex","claude"],as=5e3,cs="runtime_local_host",ds="task-handoff.node-agent.builtin",ls=new Set(["linux","darwin","win32","freebsd","openbsd","aix","sunos"]);function us(e){return ls.has(e)?e:"unknown"}function ms(e){const t={...e};return delete t[ds],t}const ps=m.z.object({version:m.z.literal(1),externalListener:En}).strict(),gs=m.z.object({}).strict().default({}),hs=jt.strict();function fs(e){const t=process.env[e]?.trim();return t||void 0}const Is=function(e,t=process.env,n=e){let i;return()=>{const r=t.TASK_HANDOFF_VERSION?.trim();return r||(i||=z(e,t,n),i)}}("@task-handoff/node-agent",process.env,"@task-handoff/control-plane");function ys(e){const t=Is();return e===t?{desiredVersion:t,actualVersion:e,phase:"matched",attempt:0,matchedAt:_s()}:{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 As(e,t,n=!0){if(!n)return ys(t);const i=Is(),r=e.runtimeVersion;if(!r||r.desiredVersion!==i)return ys(t);const s=()=>({code:"INSTANCE_RUNTIME_VERSION_MISMATCH",message:`Expected controlled-instance ${i}, received ${t||"an unknown version"}.`,expectedVersion:i,...t?{actualVersion:t}:{},retryable:!0}),o="INSTANCE_RUNTIME_VERSION_MISMATCH"!==r.error?.code?r.error:t===i?void 0:s();return xt.parse({...r,desiredVersion:i,...t?{actualVersion:t}:{actualVersion:void 0},..."pending"===r.phase?{error:o||(t!==i?s():void 0)}:{}})}function bs(e){return Object.fromEntries([...e.entries()].filter(([e])=>!ss.has(e.toLowerCase())))}function ws(e){return e.bodyBase64?Buffer.from(e.bodyBase64,"base64"):e.body}const zs=67108864;function Ns(){const e=Number(process.env.TASK_HANDOFF_INSTANCE_PROXY_MAX_RESPONSE_BYTES);return Number.isSafeInteger(e)&&e>0?e:67108864}function vs(e){const t=e.authorization;return"string"==typeof t&&t.startsWith("Bearer ")?t.slice(7).trim():void 0}function Ss(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 Es(e){return!e.ip&&!e.socket.remoteAddress&&!e.socket.remoteFamily}function _s(){return(new Date).toISOString()}function Ts(e){return"all-ipv4"===e?"0.0.0.0":"127.0.0.1"}function ks(e){if(!e||"object"!=typeof e||Array.isArray(e))return e;const t=e,n=t.externalListener&&"object"==typeof t.externalListener&&!Array.isArray(t.externalListener)?t.externalListener:{},i=Object.keys(t).filter(e=>"version"!==e&&"externalListener"!==e),r=Object.keys(n).filter(e=>"bindScope"!==e&&"port"!==e);return(i.length||r.length)&&console.warn(JSON.stringify({message:"unknown stored node agent runtime setting fields were ignored",filePath:"runtime-settings.json",fields:[...i,...r.map(e=>`externalListener.${e}`)]})),{version:t.version,externalListener:{bindScope:n.bindScope,port:n.port}}}function xs(e){return"local-folder"===e.type?Vt.parse({mode:"local-bind",path:"/workspace",readOnly:!1}):Vt.parse({mode:"git-clone",path:"/workspace",readOnly:!1})}function Cs(e){const t=Ut.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 qt.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:xs(t),labels:{},createdAt:e.createdAt,updatedAt:e.updatedAt})}async function Os(e,t){if(!t.target.web)return"unknown";const n=new AbortController,i=setTimeout(()=>n.abort(),2e3);try{return(await e(`${js(t)}/api/health`,{signal:n.signal})).ok?"reachable":"endpoint-unreachable"}catch{return"endpoint-unreachable"}finally{clearTimeout(i)}}async function Rs(e,t,n,i){const r=new AbortController,s=setTimeout(()=>r.abort(),i);try{return await e(t,{...n,signal:r.signal})}finally{clearTimeout(s)}}async function Ds(e,t,n,i){if(!t.config.autoImportAgentConfigs)return void i.diagnostic({instanceId:t.id,action:n},"node instance config auto-import skipped");if("reachable"!==t.targetStatus)return;const r=js(t),s=Number(process.env.TASK_HANDOFF_CONFIG_AUTO_IMPORT_TIMEOUT_MS||as);for(const o of os)try{const a=await Rs(e,`${r}/api/config-sync/import/${encodeURIComponent(o)}`,{method:"POST"},Number.isFinite(s)&&s>0?s:as);if(!a.ok){i.warn({instanceId:t.id,action:n,preset:o,statusCode:a.status},"node instance config auto-import failed");continue}i.diagnostic({instanceId:t.id,action:n,preset:o},"node instance config auto-import completed")}catch(e){i.warn({instanceId:t.id,action:n,preset:o,error:e instanceof Error?e.message:String(e)},"node instance config auto-import failed")}}async function Ps(e,t,n){const i=t.requireInstance(n);if("reachable"!==i.targetStatus||!i.target.web)return!1;const r=await Rs(e,`${js(i)}/api/internal/model-environment`,{method:"PUT",headers:{"content-type":"application/json",authorization:`Bearer ${i.registrationToken}`},body:JSON.stringify(t.resolvedAssignedModelEnvironment(n))},as);if(!r.ok)throw Object.assign(new Error(`Instance ${n} rejected its managed model environment with HTTP ${r.status}.`),{statusCode:502,code:"INSTANCE_MODEL_ENVIRONMENT_APPLY_FAILED"});return!0}function js(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 Ms(e,t){const n=new Error(t);throw Object.assign(n,{statusCode:403,code:e}),n}function Ls(e,t){e!==Ue&&console.warn(JSON.stringify({message:"protocol version mismatch",peer:t,expectedProtocolVersion:Ue,actualProtocolVersion:e||"missing",errorCode:"PROTOCOL_VERSION_MISMATCH"}))}function $s(e){return"none"!==e.capabilities.artifactKind}function Fs(e={}){return{...e,requiresImage:!1,supportsControlledInstanceApi:!0,supportsContainerLifecycle:!1,supportsAppSessions:!0,supportsHostSessions:!0,artifactKind:"none",isolation:"none"}}function Us(e){return new Promise(t=>{const n=s.createServer();n.once("error",()=>t(!1)),n.listen({host:"127.0.0.1",port:e},()=>{n.close(()=>t(!0))})})}function Vs(e,t=3e3){return null!==e.exitCode||null!==e.signalCode?Promise.resolve():new Promise(n=>{const i=setTimeout(()=>{null===e.exitCode&&null===e.signalCode&&e.kill("SIGKILL"),n()},t);i.unref(),e.once("exit",()=>{clearTimeout(i),n()})})}const Hs="task-handoff.local-process-nonce",qs=1e3;function Bs(e){return e.runtime.port?`http://127.0.0.1:${e.runtime.port}`:e.target.web}async function Ks(e,t){try{const n=await fetch(`${e}/api/internal/node-agent/process-identity`,{headers:{authorization:`Bearer ${t}`},signal:AbortSignal.timeout(qs)});if(!n.ok)return;const i=(await n.json()).data;if("string"!=typeof i?.instanceId||"number"!=typeof i.pid||"string"!=typeof i.processNonce)return;return{instanceId:i.instanceId,pid:i.pid,processNonce:i.processNonce,startIdentity:"string"==typeof i.startIdentity?i.startIdentity:void 0}}catch{return}}async function Gs(e,t){if(T(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 i=Date.now()+1e3;for(;Date.now()<i;){try{process.kill(e,0)}catch{return!0}await new Promise(e=>setTimeout(e,50))}return!1}function Js(e,t){return Object.assign(new Error(t),{statusCode:503,code:"LOCAL_INSTANCE_STOP_UNCONFIRMED",instanceId:e.id})}async function Ws(e,t,i){const r=t.get(e.id);if(r&&!r.killed)return r.kill("SIGTERM"),t.delete(e.id),void await Vs(r);const s=await async function(e){const t=Bs(e),n=e.runtime.labels?.[Hs];if(!t||!n||!e.registrationToken)return;const i=await Ks(t,e.registrationToken);if(i&&i.instanceId===e.id&&i.processNonce===n)try{return(await fetch(`${t}/api/internal/node-agent/shutdown`,{method:"POST",headers:{authorization:`Bearer ${e.registrationToken}`},signal:AbortSignal.timeout(qs)})).ok?i:void 0}catch{return}}(e);if(s){const t=Bs(e),n=Date.now()+3e3;for(;t&&Date.now()<n;){if(!await Ks(t,e.registrationToken))return;await new Promise(e=>setTimeout(e,50))}const i=t?await Ks(t,e.registrationToken):void 0;if(i&&i.instanceId===s.instanceId&&i.pid===s.pid&&i.processNonce===s.processNonce&&i.startIdentity===s.startIdentity&&i.startIdentity&&await Gs(i.pid,i.startIdentity))return;throw Js(e,`Controlled instance ${e.id} accepted shutdown but its exit could not be confirmed.`)}const o=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 k(e)}(i),a=await async function(e){const t=Bs(e);if(t)try{const[n,i]=await Promise.all([fetch(`${t}/api/instance/status`,{signal:AbortSignal.timeout(qs)}),fetch(`${t}/api/diagnostics`,{signal:AbortSignal.timeout(qs)})]);if(!n.ok||!i.ok)return;const r=await n.json(),s=await i.json(),o=s.data?.runtime?.pid;if(r.data?.id!==e.id||"controlled"!==r.data.controlMode||"number"!=typeof o||!Number.isInteger(o)||o<=0)return;const a=T(o);return a?{pid:o,startIdentity:a}:void 0}catch{return}}(e);if(a){if(await Gs(a.pid,a.startIdentity))return;throw Js(e,`Legacy controlled instance ${e.id} did not exit after termination.`)}if(o?.instanceId===e.id)throw Js(e,`Local controlled instance ${e.id} is still owned by pid ${o.pid}, but its process identity could not be verified.`)}const Ys=new Set(["provisioning","starting","registering","registered","running"]);async function Xs(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 Zs(e){return!0===e.managedArtifacts}class Qs{managedArtifacts=!0;executor;platform;arch;runCommand;constructor(e,t,n,i){this.executor=e,this.runCommand=t,this.platform=n,this.arch=i}artifactTarget(e){return this.executor.inspectRuntimeTarget(e?.instance.runtime.containerName)}async installRuntime(e,t){const n=e.instance.runtime.containerName;if(!n)throw Object.assign(new Error(`Instance ${e.instance.id} does not have a Docker container.`),{code:"INSTANCE_RUNTIME_INSTALL_FAILED"});await this.executor.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)}async rollbackRuntime(e,t){const n=e.instance.runtime.containerName;n&&await this.executor.rollbackRuntime(n)}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:us(this.platform),...t?{serverVersion:t}:{}}}}}catch(t){return{status:"offline",capabilities:{...e.capabilities,daemon:{status:"offline",hostPlatform:us(this.platform),error:t instanceof Error?t.message:String(t)}}}}}}class eo{runCommand;paths;nodeAgentUrl;processByInstanceId=new Map;commandOverride;lockPath;constructor(e,t,n,i,r){this.runCommand=e,this.paths=t,this.nodeAgentUrl=n,this.commandOverride=i,this.lockPath=r}async start(e){const r=function(e){if("local-folder"!==e.source.type){const e=new Error("Localhost runtime currently supports local folder sources only.");throw Object.assign(e,{statusCode:400,code:"LOCAL_RUNTIME_REQUIRES_LOCAL_FOLDER"}),e}return n.resolve(e.source.path)}(e.instance),s=e.instance.runtime.port||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 Us(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}(),o=n.join(this.paths.dataDir,"local-instances",e.instance.id),c=n.join(o,"logs");t.mkdirSync(c,{recursive:!0});const[d,...l]=function(e){if(e)return e;const i=n.resolve(process.cwd(),"bin","task-handoff.js");if(t.existsSync(i))return[process.execPath,i,"web"];throw Object.assign(new Error("The bundled controlled-instance command is unavailable."),{statusCode:500,code:"LOCAL_CONTROLLED_COMMAND_MISSING"})}(this.commandOverride),u=[...l,"--host","127.0.0.1","--port",String(s)],m=i.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:r,detached:!1,stdio:["ignore",p,g],env:{...process.env,TASK_HANDOFF_CONTROL_MODE:"controlled",TASK_HANDOFF_RUNTIME_KIND:"local",...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:r,TASK_HANDOFF_WORKSPACE_MODE:"local-bind",TASK_HANDOFF_DATA_DIR:o,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(s),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 i=()=>{e.off("error",r),t()},r=t=>{e.off("spawn",i),n(t)};e.once("spawn",i),e.once("error",r)})}(h)}catch(e){const i=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=${r} error=${i}\n`)}catch{}throw Object.assign(new Error(`Controlled instance process could not start with command ${d} in ${r}: ${i}`),{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",(i,r)=>{this.processByInstanceId.delete(e.instance.id);try{t.appendFileSync(n.join(c,"controlled-instance.lifecycle.log"),`[${(new Date).toISOString()}] exited pid=${h.pid??""} code=${i??""} signal=${r??""}\n`)}catch{}});const f=`http://127.0.0.1:${s}`,I=h.pid?T(h.pid):void 0,y=!(!h.pid||!e.instance.registrationToken)&&await async function(e,t,n,i,r=3e3){const s=Date.now()+r;for(;Date.now()<s;){if(null!==n.exitCode||null!==n.signalCode)return!1;const r=await Ks(e,i);if(r&&r.instanceId===t.instanceId&&r.pid===t.pid&&r.processNonce===t.processNonce&&r.startIdentity===t.startIdentity)return!0;await new Promise(e=>setTimeout(e,100))}return!1}(f,{instanceId:e.instance.id,pid:h.pid,processNonce:m,startIdentity:I},h,e.instance.registrationToken);if(!y)throw this.processByInstanceId.get(e.instance.id)===h&&this.processByInstanceId.delete(e.instance.id),null===h.exitCode&&null===h.signalCode&&h.kill("SIGTERM"),await Vs(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:r},runtime:{kind:"local",workspacePath:r,pid:h.pid,port:s,labels:{...e.instance.runtime.labels,"task-handoff.runtime-kind":"local",[Hs]:m}}}}async stop(e){return await Ws(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 Ws(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([Xs(this.runCommand,"codex"),Xs(this.runCommand,"claude")]);return{status:"online",capabilities:Fs({...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=>Vs(e)))}}class to{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(Zs)}async stopAll(){this.local instanceof eo&&await this.local.stopAll()}}class no extends tr{onStored;setOnStored(e){this.onStored=e}put(e){const t=super.get(e.id)?.stateRevision||0,n=super.put(Dn.parse({...e,stateRevision:Math.max(e.stateRevision||0,t)+1}));return this.onStored?.(n),n}}class io{nodeId;paths;localFolders;nodeRuntimes;controlledInstances;models;modelAssignments;modelEnvironments;updateJobs;node;listenerPort;containerUrlOverride;platform;constructor(e,t,n,i,r,s){this.paths=e,this.nodeId=t,this.localFolders=new tr(e.localFoldersDir,{schema:Ft,sanitize:ot}),this.nodeRuntimes=new tr(e.nodeRuntimesDir,{schema:vn}),this.controlledInstances=new no(e.controlledInstancesDir,{schema:Dn,sanitize:e=>Ln(e,e=>{console.warn(JSON.stringify({message:"legacy controlled instance field was ignored",...e}))})}),this.models=new Pr(e.nodeModelsDir,t),this.modelAssignments=new jr(e.modelAssignmentsDir),this.modelEnvironments=new Dr(e.modelEnvironmentsDir),this.updateJobs=new pr(e),this.listenerPort=r,this.platform=s,this.containerUrlOverride=i;const o=_s();this.node=Nn.parse({id:t,name:t,connectionMode:"direct-http",endpoint:n,controlEndpoint:n,containerEndpoint:this.containerUrl,publicWebBase:n?n.replace(/:\d+$/,""):void 0,status:"online",health:"ok",capabilities:{},labels:{},createdAt:o,updatedAt:o})}init(){this.localFolders.init();for(const e of this.localFolders.list())this.localFolders.put(e);if(this.nodeRuntimes.init(),this.controlledInstances.init(),this.models.init(),this.modelAssignments.init(),this.migrateLegacyModelEnvironments(),this.updateJobs.init(),this.updateJobs.reconcileRollouts(this.controlledInstances.list(),Is()),!this.nodeRuntimes.get("runtime_local_docker")){const e=_s();this.nodeRuntimes.put(vn.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(cs),t=_s();this.nodeRuntimes.put(vn.parse({id:cs,nodeId:this.nodeId,name:"Local Runtime",type:"local",status:e?.status||"unknown",accessStrategy:"node-proxy",capabilities:Fs(e?.capabilities),labels:{...e?.labels,[ds]:"true"},createdAt:e?.createdAt||t,updatedAt:e?.updatedAt||t}))}for(const e of this.nodeRuntimes.list())e.nodeId!==this.nodeId&&this.nodeRuntimes.put(vn.parse({...e,nodeId:this.nodeId,updatedAt:_s()}));for(const e of this.localFolders.list())e.nodeId!==this.nodeId&&this.localFolders.put(Ft.parse({...e,nodeId:this.nodeId,updatedAt:_s()}));this.normalizeInstanceRuntimeVersions()}normalizeInstanceRuntimeVersions(){for(const e of this.controlledInstances.list()){const t=ys(e.build?.packageVersion||e.instanceVersion),n=$s(this.requireRuntime(e.runtimeId)),i=["created","stopped","failed"].includes(e.status),r=n&&e.runtimeVersion?.desiredVersion===t.desiredVersion?e.runtimeVersion:void 0,s=n?"matched"===t.phase?i?t:{...t,phase:"verifying",matchedAt:void 0}:"failed"===r?.phase&&!1===r.error?.retryable?{...t,phase:"failed",attempt:r.attempt,lastAttemptAt:r.lastAttemptAt,error:r.error}:{...t,attempt:r?.attempt||0,lastAttemptAt:r?.lastAttemptAt}:t;this.controlledInstances.put(Dn.parse({...e,ready:!1,runtimeVersion:s,updatedAt:_s()}))}}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=_s()}runningInstanceCount(){const e=new Set(["created","stopped","failed"]);return this.listInstances().filter(t=>!e.has(t.status)).length}createLocalFolder(e){const t=_s(),n=Ft.parse({...e,id:e.id||Qi("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=_s(),n=vn.parse({...e,id:e.id||Qi("runtime"),nodeId:this.nodeId,accessStrategy:e.accessStrategy||(i=e.type,"docker"===i?"direct-port":"node-proxy"),capabilities:e.capabilities||{},labels:ms(e.labels),createdAt:t,updatedAt:t});var i;return this.nodeRuntimes.put(n)}updateRuntime(e,t){const n=this.requireRuntime(e);if("true"===n.labels[ds]){const t=new Error(`Built-in runtime ${e} cannot be modified.`);throw Object.assign(t,{statusCode:400,code:"NODE_RUNTIME_BUILTIN"}),t}if("local"===n.type||"local"===t.type){const e="win32"===this.platform,t=new Error(e?"Local Runtime is not supported on Windows.":"Local Runtime is built in and cannot be configured manually.");throw Object.assign(t,{statusCode:e?400:409,code:e?"LOCAL_RUNTIME_UNSUPPORTED":"LOCAL_RUNTIME_BUILTIN"}),t}const i=vn.parse({...n,...t,id:n.id,nodeId:this.nodeId,accessStrategy:t.accessStrategy||n.accessStrategy,capabilities:t.capabilities||n.capabilities,labels:t.labels?ms(t.labels):n.labels,createdAt:n.createdAt,updatedAt:_s()});return this.nodeRuntimes.put(i)}deleteRuntime(e){if("true"===this.requireRuntime(e).labels[ds]){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=vn.parse({...n,...e,id:n.id,nodeId:this.nodeId,createdAt:n.createdAt,updatedAt:_s()});return this.nodeRuntimes.put(t)}):this.nodeRuntimes.put(vn.parse({...n,status:"unknown",updatedAt:_s()}))}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=Mn(t);if(!n.success)throw function(e,t){const n=t.map(e=>`${e.path.join(".")||"body"}: ${e.message}`).join("; "),i=new Error(`Stored instance ${e} is not compatible with protocol ${Ue}: ${n}`);return Object.assign(i,{statusCode:409,code:"NODE_INSTANCE_PAYLOAD_INVALID"}),i}(e,n.error.issues);return n.data}listInstances(){return this.controlledInstances.list().flatMap(e=>{const t=Mn(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=_s(),n=rn(e),i=this.models.get(n),r=Kt.parse({...e,id:n,enabled:e.enabled??!0,order:e.order??this.nextModelOrder(),labels:e.labels||{},createdAt:i?.createdAt||t,updatedAt:t});return this.publicModel(this.models.put(r),this.modelReferenceIds(n).length)}deployModel(e){const t=rn(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(Kt.parse(e));return this.publicModel(n,this.modelReferenceIds(n.id).length)}updateModel(e,t){const n=this.requireModel(e),i=Kt.parse({...n,...t,key:t.key?.trim()?t.key:n.key,createdAt:n.createdAt,updatedAt:_s()}),r=rn(i),s=this.models.put(Kt.parse({...i,id:r}));return this.publicModel(s,this.modelReferenceIds(r).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 i=this.modelAssignments.get(e),r=Wt.parse({instanceId:e,codexModelHash:t.codexModelHash,claudeModelHash:t.claudeModelHash,updatedAt:_s()});this.modelAssignments.put(r);try{return{assignment:r,instance:this.controlledInstances.put(Dn.parse({...n,modelSelection:t.modelSelection,updatedAt:_s()}))}}catch(t){throw i?this.modelAssignments.put(i):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(rn(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,...i}=e;return Jt.parse({...i,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=>!Rr.has(e))){this.warnLegacyModelMigration(e,"unknown-fields");continue}const n=[];try{const i=this.migrateLegacyModelForApp(t,"codex",n),r=this.migrateLegacyModelForApp(t,"claude",n);if(!i&&!r)throw new Error("no complete model configuration");const s={...i?{codexModelHash:i}:{},...r?{claudeModelHash:r}:{}};this.assignModels(e,{modelSelection:s,codexModelHash:i,claudeModelHash:r}),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 i=e["codex"===t?"OPENAI_API_KEY":"ANTHROPIC_API_KEY"],r="codex"===t?e.TASK_HANDOFF_CODEX_BASE_URL||e.OPENAI_BASE_URL:e.ANTHROPIC_BASE_URL,s="codex"===t?e.TASK_HANDOFF_CODEX_MODEL||e.CODEX_MODEL:e.TASK_HANDOFF_CLAUDE_MODEL||e.CLAUDE_MODEL;if(!Boolean(i||r||s))return;if(!i||!r||!s)throw new Error("model configuration incomplete");const o=rn({app:t,endpoint:r,key:i,model:s}),a=this.models.get(o);if(a){if(a.app!==t||a.key!==i||a.endpoint!==r||a.model!==s||!a.enabled)throw new Error("existing model conflicts with legacy environment");return o}const c=_s();return this.models.put(Kt.parse({id:o,name:`Migrated ${"codex"===t?"Codex":"Claude"} model`,endpoint:r,key:i,model:s,app:t,enabled:!0,order:this.nextModelOrder(),labels:{migratedFrom:"instance-model-environment"},createdAt:c,updatedAt:c})),n.push(o),o}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),i=_s(),r=e.id||Qi("inst"),s=Ut.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"!==s.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 o=e.image?fn.parse(e.image):void 0,a="local"===t.type&&"local-folder"===s.type?n.resolve(s.path):void 0,c=Dn.parse({id:r,name:e.name||`instance-${r.replace(/^inst_?/,"").slice(0,6)}`,source:s,sourceSnapshot:e.sourceSnapshot||{},modelSelection:e.modelSelection,projectId:e.projectId,nodeId:this.nodeId,runtimeId:t.id,imageSelection:e.imageSelection,imageSnapshot:o,imageProvisioning:o&&"docker"===t.type?{phase:"checking-image",requestedReference:o.requestedReference,generation:0,startedAt:i,updatedAt:i}:void 0,status:o&&"docker"===t.type?"provisioning":"created",health:"unknown",connectionStatus:"unknown",agentStatus:"unknown",targetStatus:"unknown",uiAccessStatus:"unknown",controlMode:"controlled",ready:!1,runtimeVersion:ys(),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:er(),createdAt:i,updatedAt:i});return this.controlledInstances.put(c)}registerInstance(e,t,n){const i=Vn.parse(t),r=_s(),s=this.controlledInstances.get(e);if(!s){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}this.validateInstanceReport(s,i,n),Ls(i.protocolVersion,`Instance ${e}`);const o=i.build?.packageVersion||i.instanceVersion,a=$s(this.requireRuntime(s.runtimeId)),c=As(s,o,a),d=Dn.parse({...s,status:"registered",health:o===Is()?"ok":"degraded",ready:!a&&o===Is(),connectionStatus:"online",agentStatus:"online",targetStatus:"endpoint-unreachable"===i.target.status?"endpoint-unreachable":"reachable"===i.target.status?"reachable":s.targetStatus,uiAccessStatus:"endpoint-unreachable"===i.target.status?"endpoint-unreachable":s.uiAccessStatus,controlMode:i.controlMode,protocolVersion:i.protocolVersion,instanceVersion:i.instanceVersion,build:i.build,runtimeVersion:c,capabilities:i.capabilities,appInventory:i.appInventory,workspace:i.workspace,target:{...s.target,...i.target},registrationToken:s.registrationToken||i.registrationToken,lastHeartbeatAt:r,updatedAt:r});return this.controlledInstances.put(d)}heartbeatInstance(e,t,n){const i=this.requireInstance(e);this.validateInstanceToken(i,n);const r=Hn.parse(t);Ls(r.protocolVersion,`Instance ${e}`);const s=_s(),o=r.target?{...i.target,...r.target}:i.target,a={...o,status:"unknown"===o.status&&(o.web||o.api)?"reachable":o.status},c="endpoint-unreachable"===a.status?"endpoint-unreachable":"reachable"===a.status?"reachable":i.targetStatus,d=r.build?.packageVersion||i.build?.packageVersion||i.instanceVersion,l=$s(this.requireRuntime(i.runtimeId)),u=As(i,d,l),m=d===Is()&&(!l||i.ready&&"matched"===i.runtimeVersion?.phase),p=Dn.parse({...i,...r,target:a,ready:m&&"failed"!==r.health,health:d===Is()?r.health||i.health:"degraded",runtimeVersion:u,agentStatus:"online",targetStatus:c,uiAccessStatus:c,connectionStatus:"online",build:r.build||i.build,lastHeartbeatAt:s,updatedAt:s});return this.controlledInstances.put(p)}validateInstanceReport(e,t,n){this.validateInstanceToken(e,n||t.registrationToken),t.instanceId&&t.instanceId!==e.id&&Ms("INSTANCE_ID_MISMATCH",`Instance ${t.instanceId} cannot register as ${e.id}.`),t.nodeId&&t.nodeId!==this.nodeId&&Ms("INSTANCE_NODE_MISMATCH",`Instance ${e.id} belongs to node ${this.nodeId}.`),t.runtimeId&&t.runtimeId!==e.runtimeId&&Ms("INSTANCE_RUNTIME_MISMATCH",`Instance ${e.id} belongs to runtime ${e.runtimeId}.`),t.imageSelection&&t.imageSelection.imageId!==e.imageSelection?.imageId&&Ms("INSTANCE_IMAGE_MISMATCH",`Instance ${e.id} belongs to image ${e.imageSelection?.imageId}.`)}validateInstanceToken(e,t){e.registrationToken&&t===e.registrationToken||Ms("INSTANCE_REGISTRATION_TOKEN_INVALID",`Invalid registration token for instance ${e.id}.`)}context(e,t=this.resolvedAssignedModelEnvironment(e.id)){const n=e.imageSnapshot||fn.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:Cs(e),image:n,node:this.node,runtime:this.requireRuntime(e.runtimeId),instance:e,nodeAgentUrl:this.containerUrl,modelEnv:t}}}class ro{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 _n.parse({...this.config,host:Ts(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:Ts(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=Tn.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 i=new Error(`Failed to bind node agent TCP listener at ${Ts(t.bindScope)}:${t.port}: ${e instanceof Error?e.message:String(e)}`);throw Object.assign(i,{statusCode:409,code:"NODE_AGENT_LISTENER_BIND_FAILED"}),i}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 i=e=>{this.app.server.off("listening",r),n(e)},r=()=>{this.app.server.off("error",i),t()};this.app.server.once("error",i),this.app.server.once("listening",r),this.app.server.listen({host:Ts(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 so(e,t,n,i,r,s="request"){const o=e.requireInstance(i);if(o.imageProvisioning&&"ready"!==o.imageProvisioning.phase&&"docker"===e.requireRuntime(o.runtimeId).type)return r.diagnostic({instanceId:i,action:"start",reason:s,runtimeId:o.runtimeId,imageId:o.imageSelection?.imageId,imagePhase:o.imageProvisioning.phase},"node instance start queued until image provisioning completes"),e.controlledInstances.put(Dn.parse({...o,status:"starting",updatedAt:_s()}));r.diagnostic({instanceId:i,action:"start",reason:s,runtimeId:o.runtimeId,imageId:o.imageSelection?.imageId},"node instance start requested");const a=e.controlledInstances.put(Dn.parse({...o,status:"starting",ready:!1,updatedAt:_s()})),c=t.forRuntime(e.requireRuntime(a.runtimeId)),d=await c.start(e.context(a)),l=await Os(n,Dn.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:_s()})),u=oo(a,e.requireInstance(i),{...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 r.diagnostic({instanceId:i,action:"start",reason:s,status:m.status,connectionStatus:m.connectionStatus,targetStatus:m.targetStatus,targetWeb:m.target.web,containerName:m.runtime.containerName},"node instance start completed"),m}function oo(e,t,n){const i=t.stateRevision>e.stateRevision&&t.lastHeartbeatAt!==e.lastHeartbeatAt&&"online"===t.agentStatus;return Dn.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:_s()})}function ao(e,t){const n=t instanceof Error?t.message:String(t);return Dn.parse({...e,status:"failed",ready:!1,health:"failed",connectionStatus:"offline",agentStatus:"offline",targetStatus:"unknown",uiAccessStatus:"unknown",workspace:{...e.workspace,error:n},updatedAt:_s()})}function co(e){return Dn.parse({...e,health:"unknown",connectionStatus:"offline",agentStatus:"offline",targetStatus:"unknown",uiAccessStatus:"unknown",target:{...e.target,status:"unknown"},updatedAt:_s()})}async function lo(e={}){const i=e.token||process.env.TASK_HANDOFF_NODE_AGENT_TOKEN,r=Number(e.port||process.env.TASK_HANDOFF_NODE_AGENT_PORT||"8091"),s=`http://127.0.0.1:${r}`,a=e.containerUrl||process.env.TASK_HANDOFF_NODE_AGENT_CONTAINER_URL,p=Gi(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,I=new rs(p),y=I.resolveNodeId(e.nodeId||process.env.TASK_HANDOFF_NODE_ID),A=e.connectionMode||("local-ipc"===process.env.TASK_HANDOFF_NODE_AGENT_CONNECTION_MODE?"local-ipc":"local-loopback"),w=e.ipcPath||process.env.TASK_HANDOFF_NODE_AGENT_IPC_PATH||ir(p.dataDir),z="local-ipc"===A?`ipc://${encodeURIComponent(w)}`:s,N=e.platform||process.platform,v=e.arch||process.arch,S=new io(p,y,s,a,r,N);S.node.connectionMode=A,S.node.controlEndpoint=z,S.node.endpoint=z,S.init();const E=e.dockerCommandRunner||Wn,_=new Xn(E,e.dockerTerminalCommandRunner),T=new Qn(E,{publishHost:"127.0.0.1",imageService:_}),k=new to(new Qs(T,E,N,v),new eo(e.dockerCommandRunner||Wn,p,()=>S.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)),x=e.updateCommandRunner||e.dockerCommandRunner||Wn,C=e.fetchImpl||fetch,O=new wr({cacheDir:n.join(p.dataDir,"runtime-artifacts"),fetchImpl:C}),R=e.resolveRuntimeArtifactRelease||((e,t,n)=>zr(e,t,n,C)),D=async(t,n,i)=>{const r=await n.artifactTarget(i);if(e.resolveRuntimeArtifact)return e.resolveRuntimeArtifact(t,r.platform,r.arch);const s=await R(t,r.platform,r.arch);if(s.identity.launcherAbi>r.launcherAbi)throw Object.assign(new Error(`Runtime requires launcher ABI ${s.identity.launcherAbi}, but ${r.platform}-${r.arch} provides ABI ${r.launcherAbi}.`),{code:"INSTANCE_BASE_RUNTIME_INCOMPATIBLE",retryable:!1});return O.resolve(s.identity,s.source)},P=e=>k.forRuntime(S.requireRuntime(e.runtimeId)),j=e=>{const t=P(e);return Zs(t)?t:void 0},M=e=>{const t=j(e);if(t)return t;throw Object.assign(new Error(`Runtime for instance ${e.id} does not use managed artifacts.`),{code:"INSTANCE_RUNTIME_ARTIFACT_UNMANAGED",retryable:!1})},L=e=>Boolean(j(e)),$=(e,t)=>{const n=S.context(e);return D(t,M(e),n)},F=d({logger:e.logger??!0}),U={requests:0,active:0,completed:0,aborted:0,limitRejected:0,responseBytes:0,totalDurationMs:0,maxResponseBytes:Ns()};F.decorate("nodeAgentState",S),await F.register(l);const V=new wi(S,i,{logger:F.log,safetyIntervalMs:Number(process.env.TASK_HANDOFF_EVENT_CONNECTION_SAFETY_INTERVAL_MS)||void 0}),H=new Nr(S.controlledInstances,Is,{isInstalled:async(e,t)=>{const n=await $(e,t);return M(e).inspectRuntime(S.context(e),n.identity)},install:async(e,t)=>{const n=M(e);await n.installRuntime(S.context(e),await $(e,t))},restart:async e=>{const t=P(e),n=S.requireInstance(e.id),i=S.controlledInstances.put(Dn.parse({...n,build:void 0,instanceVersion:void 0,ready:!1,updatedAt:_s()})),r=await t.restart(S.context(i)),s=S.requireInstance(e.id);S.controlledInstances.put(oo(i,s,r))},rollback:async e=>M(e).rollbackRuntime(S.context(e)),onForcedDrain:e=>F.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});S.controlledInstances.setOnStored(e=>{V.publishInstanceLifecycle(e),S.updateJobs.reconcileRollouts(S.listInstances(),Is())}),V.start();for(const e of S.listInstances())L(e)&&!["created","stopped","failed","provisioning"].includes(e.status)&&H.schedule(e.id).catch(t=>F.log.error({instanceId:e.id,error:t},"runtime convergence recovery failed"));F.decorate("nodeAgentEventForwarder",V);const q=new Ti(E,()=>S.listInstances().filter(e=>"docker"===S.requireRuntime(e.runtimeId).type),e=>V.publish("instance.metrics.snapshot",e,{instanceId:e.instanceId}));q.start(),F.decorate("nodeAgentRuntimeMetrics",q);const B=(ne=process.env.TASK_HANDOFF_DIAGNOSTIC_LOGS,["1","true","yes","on"].includes(String(ne||"").trim().toLowerCase())),K=new Mr(I,y,g,h),G=(e,t)=>{B&&F.log.info(e,t)},J={diagnostic:G,warn:(e,t)=>F.log.warn(e,t)},W=(e,t,n)=>{const i=n&&"object"==typeof n&&!Array.isArray(n)?n.protocolVersion:void 0;if("string"!=typeof i||i===Ue)return n;const r=({field:n,action:r})=>F.log.warn({instanceId:e,report:t,protocolVersion:i,expectedProtocolVersion:Ue,field:n,action:r},"cross-version controlled instance report sanitized");return"register"===t?function(e,t){if(!e||"object"!=typeof e||Array.isArray(e))return e;const n=e,i=["instanceId","projectId","source","nodeId","runtimeId","imageSelection","instanceVersion","protocolVersion","build","controlMode","capabilities","appInventory","target","workspace","registrationToken"],r=new Set([...i,"imageId"]);for(const e of Object.keys(n))r.has(e)||t?.({field:e,action:"ignored"});return Object.prototype.hasOwnProperty.call(n,"imageId")&&t?.({field:"imageId",action:"migrated"}),{...Un(n,i),imageSelection:st(n.imageSelection,n.imageId)}}(n,r):function(e,t){if(!e||"object"!=typeof e||Array.isArray(e))return e;const n=["status","health","protocolVersion","build","capabilities","appInventory","apps","aiSessions","triggers","workspace","target"],i=new Set(n);for(const n of Object.keys(e))i.has(n)||t?.({field:n,action:"ignored"});return Un(e,n)}(n,r)},Y=async(e,t)=>{try{let n=S.requireInstance(e);"failed"===n.runtimeVersion?.phase&&L(n)&&(n=S.controlledInstances.put(Dn.parse({...n,ready:!1,runtimeVersion:ys(vr(n)),updatedAt:_s()})));const i=S.requireRuntime(n.runtimeId);await so(S,k,C,e,J);const r=S.requireInstance(e);if("docker"===i.type&&"ready"!==r.imageProvisioning?.phase)return V.syncNow(),r;let s=S.requireInstance(e);if(L(s)){try{s=await H.schedule(e,{startRequested:!0})}catch(n){s=S.requireInstance(e),J.warn({instanceId:e,action:"runtime.converge",reason:t,error:n instanceof Error?n.message:String(n)},"node instance runtime convergence failed after start")}"failed"===s.runtimeVersion?.phase&&J.warn({instanceId:e,action:"runtime.converge",reason:t,error:s.runtimeVersion.error},"node instance started with failed runtime convergence")}return await Ds(C,s,"start",J),V.syncNow(),s}catch(n){const i=ao(S.requireInstance(e),n);throw S.controlledInstances.put(i),V.syncNow(),J.warn({instanceId:e,action:"start",reason:t,error:n instanceof Error?n.message:String(n)},"node instance start failed"),n}},X=e=>{e.imageProvisioning&&async function(t,n,i,r,s,o,a){const c=e=>{const n=t.controlledInstances.get(i);n&&n.imageProvisioning?.generation===r&&n.imageSnapshot&&(t.controlledInstances.put(Dn.parse({...n,status:"starting"===n.status?"starting":"provisioning",imageProvisioning:{...n.imageProvisioning,phase:e,error:void 0,updatedAt:_s()},updatedAt:_s()})),s())},d=t.controlledInstances.get(i);if(!d?.imageSnapshot||d.imageProvisioning?.generation!==r)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(i);if(!p?.imageSnapshot||p.imageProvisioning?.generation!==r)return;t.controlledInstances.put(Dn.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:_s()},updatedAt:_s()})),s(),o.diagnostic({instanceId:i,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(i);if(!n?.imageProvisioning||n.imageProvisioning.generation!==r)return;const c=e instanceof Error?e.message:String(e);t.controlledInstances.put(Dn.parse({...n,status:"failed",health:"failed",imageProvisioning:{...n.imageProvisioning,phase:"failed",error:c,updatedAt:_s()},updatedAt:_s()})),s(),o.warn({instanceId:i,action:"image.provision",reference:n.imageProvisioning.requestedReference,error:c},"node instance image provisioning failed")}}(S,_,e.id,e.imageProvisioning.generation,()=>V.syncNow(),J,t=>{const n={instanceId:e.id,generation:e.imageProvisioning.generation,requestedReference:e.imageProvisioning.requestedReference,observedAt:_s()};if("outcome"in t)V.publish(An,{...n,sequence:1e3*t.sequence,outcome:t.outcome},{instanceId:e.id});else for(const[i,r]of function(e,t=6e4){const n=[];for(let i=0;i<e.length;i+=t)n.push(e.slice(i,i+t));return n}(t.data).entries())V.publish(yn,{...n,sequence:1e3*t.sequence+i,data:r,...t.replay?{replay:!0}:{}},{instanceId:e.id})})},Z=async e=>{const t=new Map;for(const e of k.managedAdapters()){const n=await e.artifactTarget();t.set(`${n.platform}-${n.arch}`,{adapter:e})}for(const e of S.listInstances()){const n=j(e);if(!n)continue;const i=S.context(e),r=await n.artifactTarget(i);t.set(`${r.platform}-${r.arch}`,{adapter:n,context:i})}return(await Promise.all([...t.values()].map(({adapter:t,context:n})=>D(e,t,n)))).sort((e,t)=>`${e.identity.platform}/${e.identity.arch}`.localeCompare(`${t.identity.platform}/${t.identity.arch}`))},Q=async e=>{const t=ee(),n=await async function(e){const t=await async function(e,t,n){const i=function(e){return"stable"===e?"latest":e}(n),r=await e(ur(),["view",`${t}@${i}`,"version","--json"]).catch(e=>{if(!function(e){if(!e||"object"!=typeof e)return!1;const t=e,n=[t.message,t.details?.stdout,t.details?.stderr].filter(e=>"string"==typeof e).join("\n");return/\bE404\b/i.test(n)}(e))throw e});if(!r)return;const s=JSON.parse(r.stdout);if("string"!=typeof s)throw new Error(`npm did not resolve ${t}@${i} to one version.`);return s}(e.runCommand,"@task-handoff/node-agent",e.channel);if(!t)return function(e){return Dt.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:lr()})}({channel:e.channel,currentVersion:e.currentVersion,impact:e.impact});const n=function(e,t){if(!e)return!0;const n=f.valid(e),i=f.valid(t);return n&&i?f.gt(i,n):e!==t}(e.currentVersion,t),i=n?await async function(e,t,n){const i=await e(ur(),["view",`${t}@${n}`,"dist.integrity","--json"]),r=JSON.parse(i.stdout);if("string"!=typeof r||!/^sha(?:256|384|512)-[A-Za-z0-9+/=]+$/.test(r))throw Object.assign(new Error(`npm did not return immutable integrity metadata for ${t}@${n}.`),{statusCode:502,code:"NODE_UPDATE_PREFLIGHT_FAILED",retryable:!0});return r}(e.runCommand,"@task-handoff/node-agent",t):void 0;return Dt.parse({source:"npm",channel:e.channel,currentVersion:e.currentVersion,availableVersion:t,...i?{artifactRef:`npm:@task-handoff/node-agent@${t}#${i}`}:{},runtimeArtifacts:e.runtimeArtifacts||[],impact:e.impact||{runningInstanceCount:0,stoppedInstanceCount:0,activeInstanceCount:0,restartInstanceCount:0,runningInstanceIds:[],stoppedInstanceIds:[],activeInstanceIds:[]},updateAvailable:n,checkedAt:lr()})}({channel:e.channel,currentVersion:Is(),runCommand:x,impact:t});if(!n.updateAvailable)return n;const i=await Z(n.availableVersion),r={...n,runtimeArtifacts:i.map(e=>e.identity),preflightToken:er()};return te.set(r.preflightToken,{result:r,expiresAt:Date.now()+6e5}),r},ee=()=>{const e=S.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()}},te=new Map;var ne;F.setErrorHandler((e,t,n)=>{const i=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);(B||i.statusCode>=500)&&(i.statusCode>=500?F.log.error.bind(F.log):F.log.warn.bind(F.log))({method:t.method,url:t.url,statusCode:i.statusCode,errorCode:i.code,error:i.message},"node agent request failed"),n.code(i.statusCode).send({error:{code:i.code,message:i.message,...e&&"object"==typeof e&&"string"==typeof e.expectedVersion?{expectedVersion:e.expectedVersion}:{},...e&&"object"==typeof e&&"string"==typeof e.actualVersion?{actualVersion:e.actualVersion}:{},...e&&"object"==typeof e&&"string"==typeof e.phase?{phase:e.phase}:{},...e&&"object"==typeof e&&"boolean"==typeof e.retryable?{retryable:e.retryable}:{},...e&&"object"==typeof e&&"number"==typeof e.blockingInstanceCount?{blockingInstanceCount:e.blockingInstanceCount}:{}}})}),F.addHook("preHandler",async e=>{const t=K.verify(e);if(t)e.nodeAgentAuthKeyId=t;else if(Es(e)){if(i&&vs(e.headers)!==i){const e=new Error("Invalid node agent token.");throw Object.assign(e,{statusCode:401,code:"NODE_AGENT_UNAUTHORIZED"}),e}}else if("/api/node-agent/pairing/complete"!==e.url.split("?")[0]&&!function(e){const t=e.split("?")[0];return/^\/api\/node-agent\/instances\/[^/]+\/(register|heartbeat)$/.test(t)}(e.url)){if(K.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 Ss(e.ip)||Ss(e.socket.remoteAddress)||!e.ip&&!e.socket.remoteAddress&&!e.socket.remoteFamily}(e)){const e=new Error("Local node agent access is only accepted from loopback or local IPC connections.");throw Object.assign(e,{statusCode:401,code:"NODE_AGENT_LOCAL_TOKEN_REQUIRES_LOOPBACK"}),e}if(i&&vs(e.headers)!==i){const e=new Error("Invalid node agent token.");throw Object.assign(e,{statusCode:401,code:"NODE_AGENT_UNAUTHORIZED"}),e}}}),F.addHook("onClose",async()=>{q.stop(),V.stop();for(const e of S.listInstances())H.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(co(t))}(S,k)}),F.decorate("nodeAgentRestoreLocalInstances",async()=>{for(const e of S.listInstances().filter(e=>["provisioning","starting"].includes(e.status)&&"ready"!==e.imageProvisioning?.phase&&"docker"===S.requireRuntime(e.runtimeId).type))X(e);const e=S.listInstances().filter(e=>"local"===S.requireRuntime(e.runtimeId).type&&Ys.has(e.status));for(const t of e)try{await so(S,k,C,t.id,J,"restore"),await Ds(C,S.requireInstance(t.id),"start",J)}catch(e){S.controlledInstances.put(ao(S.requireInstance(t.id),e)),G({instanceId:t.id,action:"restore",error:e instanceof Error?e.message:String(e)},"node local instance restore failed")}}),F.get("/api/node-agent/health",async()=>{return{data:{ok:!0,role:"node-agent",nodeId:y,platform:us(N),arch:process.arch,protocolVersion:Ue,build:(e="node-agent",{component:e,packageName:"@task-handoff/node-agent",packageVersion:Is(),protocolVersion:Ue,buildId:fs("TASK_HANDOFF_BUILD_ID"),builtAt:fs("TASK_HANDOFF_BUILT_AT"),gitCommit:fs("TASK_HANDOFF_GIT_COMMIT"),imageRef:fs("TASK_HANDOFF_IMAGE_REF"),imageDigest:fs("TASK_HANDOFF_IMAGE_DIGEST")}),instanceProxy:{...U},serverTime:(new Date).toISOString()}};var e});const ie=e=>{if(!Es(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(!F.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 F.nodeAgentListenerManager};return F.get("/api/node-agent/settings/external-listener",async e=>({data:ie(e).current()})),F.patch("/api/node-agent/settings/external-listener",async e=>({data:await ie(e).update(e.body)})),F.get("/api/node-agent/updates/jobs",async()=>({data:S.updateJobs.list()})),F.post("/api/node-agent/updates/check",async e=>({data:await Q(Rt.parse(e.body))})),F.post("/api/node-agent/updates/apply",async(e,i)=>{const r=hs.parse(e.body),s=await(async e=>{const t=te.get(e.preflightToken);if(te.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;if(n.channel!==e.channel||n.availableVersion!==e.targetVersion||n.currentVersion!==Is()||JSON.stringify(n.impact)!==JSON.stringify(ee())){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})(r);if(!s.supported){const e=new Error(s.reason||"The requested update is not supported.");throw Object.assign(e,{statusCode:400,code:"UPDATE_UNSUPPORTED"}),e}if(!s.updateAvailable){const e=new Error(s.reason||"No update is available for the selected channel.");throw Object.assign(e,{statusCode:409,code:"UPDATE_NOT_AVAILABLE"}),e}const a=S.updateJobs.create(y,s),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(o.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,i=t.existsSync){const r=[n.resolve(e,"..","bin","task-handoff-node-update-worker"),n.resolve(e,"..","..","bin","task-handoff-node-update-worker")],s=r.find(i),o=n.resolve(e,"..","..","..","..","scripts","node-update-worker.cjs");return s?{worker:s,packaged:!0,expectedWorker:r[0]}:i(o)?{worker:o,packaged:!1,expectedWorker:r[0]}:{worker:void 0,packaged:!1,expectedWorker:r[0]}}(c);if(!d){S.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:_s()});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 x("systemd-run",["--unit",`task-handoff-update-${a.id}`,"--collect","--property=Type=exec",...l?[d]:[process.execPath,d],"--job-file",S.updateJobs.records.filePath(a.id),"--target-version",a.toVersion,"--npm-command",ur()]),i.code(202).send({data:a})}),F.post("/api/node-agent/pairing/invites",async(e,t)=>{const n=I.createPairingInvite(qr.parse(e.body||{}));return t.code(201).send({data:{nodeId:y,joinToken:n.token,expiresAt:n.expiresAt}})}),F.post("/api/node-agent/pairing/complete",async(e,t)=>{const n=I.completePairingInvite(Br.parse(e.body));return t.code(201).send({data:{nodeId:y,keyId:n.keyId,secret:n.secret,pairedAt:n.pairedAt}})}),F.get("/api/node-agent/remotes",async e=>({data:I.listRemoteControlPlanes(e.nodeAgentAuthKeyId)})),F.delete("/api/node-agent/remotes/:keyId",async e=>{const t=m.z.string().trim().min(1).max(160).parse(e.params.keyId);return{data:{deleted:I.deleteRemoteControlPlane(t,e.nodeAgentAuthKeyId)}}}),F.post("/api/node-agent/remotes/connect",async(e,t)=>{const n=Kr.parse(e.body),i=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),r=I.createRemoteControlPlane({url:i,...n.controlPlaneName?{name:n.controlPlaneName}:{},active:!1!==n.activate}),s=await async function(e,t,n){const i=await e(new URL("/api/node-join/complete",t).toString(),{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(n)}),r=await i.json().catch(()=>({}));if(!i.ok){const e=new Error(r.error?.message||`Control-plane node join failed with HTTP ${i.status}.`);throw Object.assign(e,{statusCode:i.status,code:r.error?.code||"NODE_AGENT_REMOTE_JOIN_FAILED"}),e}return r.data||{}}(C,i,{joinToken:n.joinToken,nodeId:y,nodeName:S.node.name,keyId:r.keyId,secret:r.secret,pairedAt:r.pairedAt}),o=I.upsertRemoteControlPlane({...r,..."string"==typeof s.name&&s.name?{name:n.controlPlaneName||s.name}:{}});let a,c=!1!==o.active?"saved":"disabled";if(!1!==o.active&&F.nodeAgentReverseTunnels)try{F.nodeAgentReverseTunnels.connect({url:i,keyId:o.keyId,secret:o.secret}),c="connecting"}catch(e){c="failed",a=e instanceof Error?e.message:String(e)}return t.code(201).send({data:{remote:{id:o.id,url:o.url,keyId:o.keyId,pairedAt:o.pairedAt,active:!1!==o.active},tunnel:{status:c,...a?{error:a}:{}}}})}),F.get("/api/node-agent/runtimes",async()=>({data:S.nodeRuntimes.list()})),F.post("/api/node-agent/runtimes",async(e,t)=>t.code(201).send({data:S.createRuntime(qi.parse(e.body))})),F.patch("/api/node-agent/runtimes/:id",async e=>({data:S.updateRuntime(e.params.id,Bi.parse(e.body))})),F.delete("/api/node-agent/runtimes/:id",async e=>({data:{deleted:S.deleteRuntime(e.params.id)}})),F.post("/api/node-agent/runtimes/:id/check",async e=>{const t=S.requireRuntime(e.params.id);return{data:await S.checkRuntime(t.id,k.forRuntime(t))}}),F.get("/api/node-agent/local-folders",async()=>({data:S.localFolders.list()})),F.get("/api/node-agent/folders/tree",async e=>({data:Li(Ui.parse(e.query))})),F.post("/api/node-agent/local-folders",async(e,t)=>t.code(201).send({data:S.createLocalFolder(Fi.parse(e.body))})),F.delete("/api/node-agent/local-folders/:id",async e=>({data:{deleted:S.localFolders.delete(e.params.id)}})),F.get("/api/node-agent/models",async()=>({data:S.listModels()})),F.post("/api/node-agent/models",async(e,t)=>t.code(201).send({data:S.createModel(Qt.parse(e.body))})),F.put("/api/node-agent/models/:id/deploy",async e=>{const t=e.params.id,n=tn.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:S.deployModel(n)}}),F.patch("/api/node-agent/models/:id",async e=>({data:S.updateModel(e.params.id,en.parse(e.body))})),F.delete("/api/node-agent/models/:id",async e=>({data:{deleted:S.deleteModel(e.params.id)}})),F.get("/api/node-agent/instances",async()=>({data:S.listInstances()})),F.post("/api/node-agent/instances",async(e,t)=>{const n=S.createInstance(Vi.parse(e.body));return V.syncNow(),n.imageProvisioning&&X(n),t.code(201).send({data:n})}),F.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 i=_s();return e.controlledInstances.put(Dn.parse({...n,status:"provisioning",health:"unknown",imageProvisioning:{phase:"checking-image",requestedReference:n.imageSnapshot.requestedReference,generation:(n.imageProvisioning?.generation||0)+1,startedAt:i,updatedAt:i},updatedAt:i}))}(S,e.params.id);return V.syncNow(),X(t),{data:t}}),F.patch("/api/node-agent/instances/:id",async e=>{const t=e.params.id,n=S.requireInstance(t),i=Hi.parse(e.body),r=Dn.parse({...n,...i,...i.config?{config:{...n.config,...i.config}}:{},updatedAt:_s()}),s=S.controlledInstances.put(r);return V.syncNow(),{data:s}}),F.put("/api/node-agent/instances/:id/model-assignment",async e=>{const t=e.params.id,n=S.assignModels(t,nn.parse(e.body));return await Ps(C,S,t),{data:n}}),F.post("/api/node-agent/instances/:id/register",async(e,t)=>{const n=e.params.id,i=W(n,"register",e.body),r=S.registerInstance(n,Vn.parse(i),vs(e.headers));return V.syncNow(),G({instanceId:n,action:"register",protocolVersion:r.protocolVersion,build:r.build,targetStatus:r.targetStatus,targetStrategy:r.target.strategy},"node instance registered"),!L(r)||r.ready&&"matched"===r.runtimeVersion?.phase||H.schedule(n).catch(e=>F.log.error({instanceId:n,error:e},"runtime convergence after registration failed")),t.code(201).send({data:r})}),F.post("/api/node-agent/instances/:id/heartbeat",async e=>{const t=e.params.id,n=W(t,"heartbeat",e.body),i=S.heartbeatInstance(t,Hn.parse(n),vs(e.headers));return V.syncNow(),G({instanceId:t,action:"heartbeat",status:i.status,health:i.health,protocolVersion:i.protocolVersion,build:i.build,targetStatus:i.targetStatus,apps:i.apps.runningCount},"node instance heartbeat accepted"),!L(i)||i.ready&&"matched"===i.runtimeVersion?.phase||H.schedule(t).catch(e=>F.log.error({instanceId:t,error:e},"runtime convergence after heartbeat failed")),{data:i}}),F.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=V.addOutput(t);t.on("close",n),t.on("error",n)}),F.get("/api/node-agent/docker/images",async()=>({data:await ni(e.dockerCommandRunner)})),F.get("/api/node-agent/instances/:id/metrics",async e=>{const t=e.params.id,n=S.requireInstance(t);if("docker"!==S.requireRuntime(n.runtimeId).type){const e=new Error(`Runtime type ${S.requireRuntime(n.runtimeId).type} does not provide resource metrics.`);throw Object.assign(e,{statusCode:409,code:"INSTANCE_METRICS_UNSUPPORTED"}),e}return{data:await q.snapshot(t)}}),F.post("/api/node-agent/instances/:id/start",async e=>{const t=e.params.id;return gs.parse(e.body),{data:await Y(t,"request")}}),F.post("/api/node-agent/instances/:id/runtime/reconcile",async e=>{const t=e.params.id;gs.parse(e.body);const n=S.requireInstance(t);S.controlledInstances.put(Dn.parse({...n,ready:!1,runtimeVersion:ys(vr(n)),updatedAt:_s()}));const i=await H.schedule(t,{startRequested:!["created","stopped"].includes(n.status),resumeCancelled:!0});return V.syncNow(),{data:i}}),F.post("/api/node-agent/instances/:id/stop",async e=>{const t=e.params.id;await H.cancel(t);const n=S.requireInstance(t);G({instanceId:n.id,action:"stop",runtimeId:n.runtimeId,containerName:n.runtime.containerName},"node instance stop requested");const i=k.forRuntime(S.requireRuntime(n.runtimeId)),r=await i.stop(S.context(n)),s=Dn.parse({...n,...r,ready:!1,agentStatus:"offline",targetStatus:"unknown",uiAccessStatus:"unknown",updatedAt:_s()}),o=S.controlledInstances.put(s);return V.syncNow(),G({instanceId:n.id,action:"stop",status:o.status,connectionStatus:o.connectionStatus,containerName:o.runtime.containerName},"node instance stop completed"),{data:o}}),F.post("/api/node-agent/instances/:id/restart",async e=>{const t=e.params.id,n=S.requireInstance(t);if(gs.parse(e.body),L(n)&&(!n.ready||"matched"!==n.runtimeVersion?.phase)){const e=await H.schedule(t,{startRequested:!0});return V.syncNow(),{data:e}}G({instanceId:t,action:"restart",runtimeId:n.runtimeId,imageId:n.imageSelection?.imageId,containerName:n.runtime.containerName},"node instance restart requested");const i=k.forRuntime(S.requireRuntime(n.runtimeId)),r=await i.restart(S.context(n)),s=Dn.parse({...n,...r,target:r.target?{...n.target,...r.target}:n.target,updatedAt:_s()}),o=await Os(C,s),a=oo(n,S.requireInstance(t),{...r,target:r.target?{...r.target,status:o}:void 0,targetStatus:o,uiAccessStatus:o}),c=S.controlledInstances.put(a);return await Ds(C,c,"restart",J),V.syncNow(),G({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}}),F.post("/api/node-agent/instances/:id/delete",async e=>{const t=e.params.id,n=S.requireInstance(t);await H.cancel(t),G({instanceId:t,action:"delete",runtimeId:n.runtimeId,containerName:n.runtime.containerName},"node instance delete requested");const i=k.forRuntime(S.requireRuntime(n.runtimeId));await i.delete(S.context(n,{})),G({instanceId:t,action:"delete"},"node instance delete completed");const r=S.controlledInstances.delete(t);return S.modelAssignments.delete(t),S.modelEnvironments.delete(t),V.syncNow(),{data:{deleted:r}}}),F.post("/api/node-agent/instances/:id/proxy",async(e,t)=>{const n=e.params.id,i=$i.parse(e.body),r=js(S.requireInstance(n)),s=i.path.startsWith("/")?i.path:`/${i.path}`;"POST"===i.method&&"/api/apps/sessions"===s&&await Ps(C,S,n),G({instanceId:n,action:"proxy",method:i.method,path:s,instanceBase:r},"node instance proxy requested");const o=await C(`${r}${s}`,{method:i.method,headers:{...i.headers},body:ws(i)}),a=o.headers.get("content-type")||"application/octet-stream",c=await o.text();G({instanceId:n,action:"proxy",method:i.method,path:s,statusCode:o.status,contentType:a},"node instance proxy completed"),t.code(o.status).type(a).send(c)}),F.post("/api/node-agent/instances/:id/proxy/stream",{bodyLimit:zs},async(e,t)=>{const n=Date.now();U.requests+=1,U.active+=1;const i=new AbortController;let r=0,s=!1,o=!1;const a=e=>{o||(o=!0,U.active-=1,U.totalDurationMs+=Date.now()-n,U.responseBytes+=r,U[e]+=1)},d=()=>{i.abort(),s&&a("aborted")};e.raw.once("aborted",d),t.raw.once("close",d);try{const n=e.params.id,o=$i.parse(e.body),d=js(S.requireInstance(n)),l=o.path.startsWith("/")?o.path:`/${o.path}`;G({instanceId:n,action:"proxy.stream",method:o.method,path:l,instanceBase:d},"node instance streaming proxy requested");const u=await C(`${d}${l}`,{method:o.method,headers:{...o.headers},body:ws(o),signal:i.signal}),m=Number(u.headers.get("content-length"));if(Number.isFinite(m)&&m>U.maxResponseBytes)return U.limitRejected+=1,i.abort(),t.code(502).send({error:{code:"INSTANCE_PROXY_RESPONSE_TOO_LARGE",message:`Instance response exceeds ${U.maxResponseBytes} bytes.`}});t.code(u.status);for(const[e,n]of Object.entries(bs(u.headers)))t.header(e,n);if(!u.body||"HEAD"===o.method)return a("completed"),t.send();const p=new c.Transform({transform(e,t,n){if(r+=e.length,r>U.maxResponseBytes)return U.limitRejected+=1,i.abort(),void n(Object.assign(new Error("Instance proxy response limit exceeded."),{code:"INSTANCE_PROXY_RESPONSE_TOO_LARGE"}));n(null,e)}});return s=!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),s||a("completed")}}),F.post("/api/node-agent/instances/:id/proxy/raw",{bodyLimit:zs},async(e,t)=>{const n=e.params.id,i=$i.parse(e.body),r=js(S.requireInstance(n)),s=i.path.startsWith("/")?i.path:`/${i.path}`;G({instanceId:n,action:"proxy.raw",method:i.method,path:s,instanceBase:r},"node instance raw proxy requested");const o=await C(`${r}${s}`,{method:i.method,headers:{...i.headers},body:ws(i)}),a=Number(o.headers.get("content-length"));if(Number.isFinite(a)&&a>U.maxResponseBytes)return U.limitRejected+=1,t.code(502).send({error:{code:"INSTANCE_PROXY_RESPONSE_TOO_LARGE",message:`Instance response exceeds ${U.maxResponseBytes} bytes.`}});let c;try{c=await async function(e,t){if(!e.body)return Buffer.alloc(0);const n=[];let i=0;const r=e.body.getReader();for(;;){const{done:e,value:s}=await r.read();if(e)break;if(i+=s.byteLength,i>t)throw await r.cancel("Instance proxy response limit exceeded.").catch(()=>{}),Object.assign(new Error("Instance proxy response limit exceeded."),{code:"INSTANCE_PROXY_RESPONSE_TOO_LARGE"});n.push(Buffer.from(s))}return Buffer.concat(n,i)}(o,U.maxResponseBytes)}catch(e){if(!(e instanceof Error)||"INSTANCE_PROXY_RESPONSE_TOO_LARGE"!==e.code)throw e;return U.limitRejected+=1,t.code(502).send({error:{code:"INSTANCE_PROXY_RESPONSE_TOO_LARGE",message:`Instance response exceeds ${U.maxResponseBytes} bytes.`}})}return G({instanceId:n,action:"proxy.raw",method:i.method,path:s,statusCode:o.status,byteLength:c.length},"node instance raw proxy completed"),{data:{status:o.status,headers:bs(o.headers),bodyBase64:c.toString("base64")}}}),F.get("/api/node-agent/instances/:id/proxy/ws/*",{websocket:!0},(e,t)=>{const n=t.params.id,i=t.params["*"]||"",r=t.url.indexOf("?"),s=r>=0?t.url.slice(r):"";let o;try{const r=js(S.requireInstance(n)),a=new URL(`/${i}${s}`,`${r}/`);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);G({instanceId:n,action:"proxy.ws",path:`/${i}${s}`,upstreamUrl:a.toString(),protocols:c||[]},"node instance websocket proxy opening"),o=c?new u(a,c):new u(a),o.on("open",()=>{G({instanceId:n,action:"proxy.ws",path:`/${i}${s}`},"node instance websocket proxy opened"),e.on("message",(e,t)=>o?.readyState===u.OPEN&&o.send(function(e,t){return t?e:e.toString()}(e,t))),e.on("close",()=>o?.close()),e.on("error",()=>o?.close())}),o.on("message",(t,n)=>{e.readyState===u.OPEN&&e.send(n?t:t.toString())}),o.on("close",()=>{G({instanceId:n,action:"proxy.ws",path:`/${i}${s}`},"node instance websocket proxy closed"),e.close()}),o.on("error",t=>{G({instanceId:n,action:"proxy.ws",path:`/${i}${s}`,error:t instanceof Error?t.message:String(t)},"node instance websocket proxy failed"),e.close(1011,"Instance websocket proxy failed.")})}catch(t){G({instanceId:n,action:"proxy.ws",path:`/${i}${s}`,error:t instanceof Error?t.message:String(t)},"node instance websocket endpoint unavailable"),o?.close(),e.close(1011,"Instance websocket endpoint is not reachable.")}}),F}function uo(e){const t=new URL("/api/node-agent/tunnel",e);return t.protocol="https:"===t.protocol?"wss:":"ws:",t.toString()}function mo(e,t){const n=new URL(t.tunnelUrl);n.searchParams.set("nodeId",t.nodeId);const i=t.secret?ar({nodeId:t.nodeId,keyId:t.keyId,secret:t.secret,method:"GET",pathWithQuery:`${n.pathname}${n.search}`}):{},r=new u(n,{headers:i}),s=new Map,o=new Map;let a;const c=e=>{const n=e.startsWith("/")?e:`/${e}`,i="function"==typeof t.port?t.port():t.port,r=new URL(`/api/node-agent${n}`,`http://127.0.0.1:${i}`);return r.protocol="ws:",r},d=e=>t.secret?ar({nodeId:t.nodeId,keyId:t.keyId,secret:t.secret,method:"GET",pathWithQuery:`${e.pathname}${e.search}`}):{},l=(e,t=1e3,n="")=>{const i=s.get(e);s.delete(e),i?.upstream?.close(t,n),i?.tunnel?.close(t,n)},m=(e,t,n=!1)=>new Promise((i,r)=>{e.send(t,{binary:n},e=>e?r(e):i())});return r.on("open",()=>{r.send(JSON.stringify({type:"node-agent.identify",nodeId:t.nodeId,serverTime:(new Date).toISOString()})),a=e.nodeAgentEventForwarder?.addOutput(r)}),r.on("close",()=>{for(const e of s.keys())l(e,1001,"Reverse tunnel disconnected.");for(const[e,t]of o)o.delete(e),t.controller.abort(),t.tunnel.close(1001,"Reverse tunnel disconnected.");a?.(),a=void 0}),r.on("message",async i=>{let a;try{a=JSON.parse(String(i))}catch{return void r.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:"",i="string"==typeof p.route&&p.route.startsWith("/")?p.route:"/health",r=p.init&&"object"==typeof p.init?p.init:{},s=r.headers&&"object"==typeof r.headers?r.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 o.set(e,{tunnel:l,controller:a}),l.on("open",async()=>{try{const n=await fetch((e=>{const n=e.startsWith("/")?e:`/${e}`,i="function"==typeof t.port?t.port():t.port;return new URL(`/api/node-agent${n}`,`http://127.0.0.1:${i}`)})(i),{method:dr(r.method),headers:{...s,...t.token?{authorization:`Bearer ${t.token}`}:{}},body:"string"==typeof r.body?r.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{o.delete(e)}}),l.on("close",()=>{a.abort(),o.delete(e)}),void l.on("error",()=>a.abort())}if("control-plane.websocket.open"===p.type){const e="string"==typeof p.streamId?p.streamId:"",i="string"==typeof p.route?p.route:"",o=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=o?.length?new u(c(i),o,{headers:a}):new u(c(i),{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)});s.set(e,{upstream:l,tunnel:p,close:(e=1e3,t="")=>{l.close(e,t),p.close(e,t)}}),l.on("open",()=>{r.send(JSON.stringify({type:"node-agent.websocket.open",streamId:e,protocol:l.protocol}))}),function(e,t,n={}){const i=n.pendingFrameLimit??256;let r=!1,s=Bn(t);const o=[],a=[];let c;const d=()=>{c&&(clearTimeout(c),c=void 0)},l=(n,r)=>{if(n.length>=i)return Kn(e,1011,"WebSocket bridge pending frame limit exceeded."),void Kn(t,1011,"WebSocket bridge pending frame limit exceeded.");n.push(r)};n.upstreamOpenTimeoutMs&&!s&&(c=setTimeout(()=>{s||r||(Kn(e,1011,"Upstream websocket did not open."),Kn(t))},n.upstreamOpenTimeoutMs)),e.on("open",()=>Jn(e,a)),t.on("open",()=>{d(),s=!0,n.onUpstreamOpen?.(),Jn(t,o)}),e.on("message",(e,n=!1)=>{const i={data:e,isBinary:Boolean(n)};Bn(t)?Gn(t,i):l(o,i)}),t.on("message",(t,n=!1)=>{const i={data:t,isBinary:Boolean(n)};Bn(e)?Gn(e,i):l(a,i)}),t.on("close",(t,i)=>{d(),n.onUpstreamClose?.(t,i),(s||r||!n.onUpstreamCloseBeforeOpen?.())&&Kn(e,t,i)}),t.on("error",t=>{n.onUpstreamError?.(t),(s||r||!n.onUpstreamErrorBeforeOpen?.(t))&&Kn(e)}),e.on("close",(e,i)=>{d(),r=!0,n.onClientClose?.(e,i),Kn(t,e,i)}),e.on("error",e=>{d(),r=!0,n.onClientError?.(e),Kn(t,1011,"WebSocket bridge client failed.")})}(p,l,{pendingFrameLimit:256,upstreamOpenTimeoutMs:1e4,onClientClose:()=>{s.delete(e)},onClientError:t=>{s.delete(e),r.send(JSON.stringify({type:"node-agent.websocket.error",streamId:e,message:t instanceof Error?t.message:String(t)}))},onUpstreamClose:(t,n)=>{s.delete(e),r.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=>{s.delete(e),r.send(JSON.stringify({type:"node-agent.websocket.error",streamId:e,message:t instanceof Error?t.message:String(t)}))}})}catch(t){r.send(JSON.stringify({type:"node-agent.websocket.error",streamId:e,message:t instanceof Error?t.message:String(t)}))}return}if("control-plane.websocket.close"===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:"",i=p.init&&"object"==typeof p.init?p.init:{},s="string"==typeof p.route&&p.route.startsWith("/")?p.route:"/health",o=i.headers&&"object"==typeof i.headers?i.headers:{};try{const a=await e.inject({method:dr(i.method),url:`/api/node-agent${s}`,headers:{...o,...t.token?{authorization:`Bearer ${t.token}`}:{}},payload:"string"==typeof i.body?i.body:void 0});r.send(JSON.stringify({type:"node-agent.response",requestId:n,status:a.statusCode,headers:a.headers,body:a.body}))}catch(e){r.send(JSON.stringify({type:"node-agent.response",requestId:n,status:502,error:{code:"NODE_AGENT_REVERSE_INJECT_FAILED",message:e instanceof Error?e.message:String(e)}}))}}}),r}async function po(e){const s=Gi(e.dataDir),o=(a=e.host,c=e.port,En.parse({bindScope:"0.0.0.0"===a.trim()?"all-ipv4":"loopback",port:c}));var a,c;const d=t.existsSync(s.settingsPath),l=function(e,t){return new nr(e.settingsPath,()=>({version:1,externalListener:t}),{schema:ps,sanitize:ks})}(s,o),u=l.get().externalListener,m=function(e,r={}){return function(e,r={}){t.mkdirSync(n.dirname(e),{recursive:!0});const s={pid:process.pid,hostname:p.hostname(),component:r.component,command:process.argv.join(" "),acquiredAt:(new Date).toISOString(),token:i.randomUUID(),startIdentity:T(process.pid),dataDir:r.dataDir,host:r.host,port:r.port,instanceId:r.instanceId};for(let n=0;n<5;n+=1)try{return t.mkdirSync(e),t.writeFileSync(S(e),`${JSON.stringify({token:s.token,pid:s.pid,startIdentity:s.startIdentity,startedAt:(new Date).toISOString()})}\n`,{encoding:"utf8",mode:384,flag:"wx"}),R(e,s),{lockPath:e,owner:s,release(){const n=x(e);n?.token===s.token&&t.rmSync(e,{recursive:!0,force:!0})}}}catch(s){if("EEXIST"!==s.code)throw s;const o=x(e);if(O(o))throw new N(e,o,r.error);if(!o&&(P(e)||L(e)<(r.incompleteLockStaleMs??2e3))){if(n+1<5){M();continue}throw new N(e,void 0,r.error)}const a=i.randomUUID();if(!$(e,a)){if(n+1<5){M();continue}throw new N(e,x(e),r.error)}const c=x(e);if(O(c))throw j(E(e)),new N(e,c,r.error);if(o?.token&&c?.token!==o.token){j(E(e));continue}if(!U(e,a))continue;t.rmSync(e,{recursive:!0,force:!0})}const o=x(e);throw new N(e,o,r.error)}(e,{...r,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:s.dataDir,host:Ts(u.bindScope),port:u.port});try{const i={...e,port:u.port},o=await lo(i),a=function(e,t,n,i){const r=t.token||process.env.TASK_HANDOFF_NODE_AGENT_TOKEN,s=new rs(n),o=new Map,a=t=>{const n=t.url.replace(/\/$/,"");o.get(n)?.close(1e3,"Reverse tunnel reconnecting.");const s=mo(e,{tunnelUrl:uo(t.url),nodeId:i,port:()=>e.nodeAgentState.currentListenerPort,token:r,keyId:t.keyId,secret:t.secret});return o.set(n,s),s.on("close",()=>{o.get(n)===s&&o.delete(n)}),s};return{connect:a,connectConfigured:()=>{const 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 i=new URL("/api/node-agent/tunnel",n);return i.protocol="https:"===i.protocol?"wss:":"ws:",i.toString()}(t);if(n){const a=s.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),c=(process.env.TASK_HANDOFF_CONTROL_PLANE_URL||n).replace(/\/$/,"");o.get(c)?.close(1e3,"Reverse tunnel reconnecting.");const d=mo(e,{tunnelUrl:n,nodeId:i,port:()=>e.nodeAgentState.currentListenerPort,token:r,keyId:a?.keyId,secret:a?.secret});o.set(c,d)}for(const e of s.configuredRemoteControlPlanes())e.url&&!1!==e.active&&a({url:e.url,keyId:e.keyId,secret:e.secret})},closeAll:()=>{for(const e of o.values())e.close(1001,"Node agent shutting down.");o.clear()}}}(o,i,s,new rs(s).resolveNodeId(e.nodeId||process.env.TASK_HANDOFF_NODE_ID));o.decorate("nodeAgentReverseTunnels",a);const c=new ro({app:o,state:o.nodeAgentState,settings:l,config:u,source:d?"persisted":"bootstrap"});let p;o.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}}},i=()=>{n("SIGINT")},r=()=>{n("SIGTERM")};process.once("SIGINT",i),process.once("SIGTERM",r),e.addHook("onClose",async()=>{process.off("SIGINT",i),process.off("SIGTERM",r)})}(o),o.addHook("onClose",async()=>{p?.close(),m.release()});try{await o.ready();const i=e.ipcPath||process.env.TASK_HANDOFF_NODE_AGENT_IPC_PATH||ir(s.dataDir);p=await async function(e,i){!function(e,i=process.platform){if("win32"!==i){t.mkdirSync(n.dirname(e),{recursive:!0,mode:448});try{t.chmodSync(n.dirname(e),448)}catch{}try{t.unlinkSync(e)}catch(e){if("ENOENT"!==e.code)throw e}}}(i);const s=r.createServer((t,n)=>{e.server.emit("request",t,n)});return s.on("upgrade",(t,n,i)=>{e.server.emit("upgrade",t,n,i)}),await new Promise((e,t)=>{s.once("error",t),s.listen(i,()=>{s.off("error",t),e()})}),s}(o,i),await c.start(),a.connectConfigured(),await(o.nodeAgentRestoreLocalInstances?.())}catch(e){throw await o.close(),e}}catch(e){throw m.release(),e}}function go(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 ho(e){if("local-ipc"!==e&&"local-loopback"!==e)throw new Error("Connection mode must be local-ipc or local-loopback.");return e}function fo(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",go,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",ho).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 po({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",fo).option("--json","Print raw JSON output").action(async e=>{const n=t.opts(),i=e.ipcPath||n.ipcPath||process.env.TASK_HANDOFF_NODE_AGENT_IPC_PATH,s=e.dataDir||n.dataDir||process.env.TASK_HANDOFF_NODE_AGENT_DATA_DIR,o=e.endpoint?void 0:i||ir(s||Ki()),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}:{}}),i=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 i=n.method||"GET",s="string"==typeof n.body||n.body instanceof Buffer?n.body:void 0===n.body||null===n.body?void 0:String(n.body),o=new Headers(n.headers||{});return void 0===s||o.has("content-length")||o.set("content-length",String(Buffer.byteLength(s))),new Promise((a,d)=>{const l=r.request({socketPath:e,method:i,path:`/api/node-agent${t}`,headers:Object.fromEntries(o.entries())},e=>{const t=e.statusCode||500;a(new Response("HEAD"!==i&&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!==s&&l.write(s),l.end()})}(e.ipcPath,"/pairing/invites",{method:"POST",headers:t,body:n}),s=await i.json().catch(()=>({}));if(!i.ok)throw new Error(s.error?.message||`Node agent pairing invite failed with HTTP ${i.status}`);const o="string"==typeof s.data?.joinToken?s.data.joinToken:"";if(!o)throw new Error("Node agent pairing invite response did not include a join token.");return{nodeId:"string"==typeof s.data?.nodeId?s.data.nodeId:"",joinToken:o,expiresAt:"string"==typeof s.data?.expiresAt?s.data.expiresAt:""}}({endpoint:e.endpoint,ipcPath:o,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});