@task-handoff/node-agent 0.0.23 → 0.0.25-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -1 +1 @@
1
- "use strict";var e=require("commander"),t=require("node:fs"),n=require("node:path"),i=require("node:http"),r=require("node:url"),s=require("fastify"),o=require("@fastify/websocket"),a=require("zod"),c=require("node:os"),d=require("node:crypto"),l=require("node:child_process"),u=require("node-pty"),m=require("ws"),p=require("node:net"),h=require("node:stream"),g=require("node:fs/promises"),f=require("node:stream/promises"),y=require("tar"),I=require("write-file-atomic"),A=require("semver"),b="undefined"!=typeof document?document.currentScript:null;function w(e,n){try{const i=JSON.parse(t.readFileSync(e,"utf8"));if(n&&i.name!==n)return;return"string"==typeof i.version&&i.version.trim()?i.version.trim():void 0}catch{return}}function v(e){if(e)try{return n.dirname(t.realpathSync(e))}catch{return}}function E(e,t=process.env,i=e){const r=t.TASK_HANDOFF_VERSION?.trim();if(r)return r;const s=i.split("/").at(-1),o=process.argv[1]?n.resolve(process.argv[1]):void 0,a=o?n.dirname(o):void 0,c=[v(o),a,process.cwd()].filter(e=>Boolean(e));for(const t of new Set(c)){let i=t;for(;;){const t=w(n.join(i,"package.json"),e);if(t)return t;const r=n.dirname(i);if(r===i)break;i=r}}let d;for(const e of new Set(c)){let t=e;for(;;){if(s){const e=w(n.join(t,"packages",s,"package.json"),i);if(e)return e}d||=w(n.join(t,"package.json"));const e=n.dirname(t);if(e===t)break;t=e}}return d||"unknown"}class N extends Error{code;lockPath;owner;constructor(e,t,n={}){const i=t?.pid?` pid ${t.pid}`:"";super(`${n.label||"Process"} is already running${i}. Lock: ${e}`),this.name="ProcessSingletonError",this.code=n.code||"PROCESS_ALREADY_RUNNING",this.lockPath=e,this.owner=t}}function S(e){return n.join(e,"owner.json")}function z(e){return n.join(e,"initializing.json")}function T(e){return n.join(e,"recovering.json")}function _(e){return Number.isInteger(e)&&Number(e)>0}function C(e,n=process.platform){if(_(e)){if("linux"===n)try{const n=t.readFileSync(`/proc/${e}/stat`,"utf8"),i=n.lastIndexOf(")");if(i<0)return;const r=n.slice(i+2).trim().split(/\s+/)[19];return r?`linux:${r}`:void 0}catch{return}if(["darwin","freebsd","openbsd","aix","sunos"].includes(n)){const t=l.spawnSync("ps",["-o","lstart=","-p",String(e)],{encoding:"utf8",timeout:1e3}),i=0===t.status?t.stdout.trim().replace(/\s+/g," "):"";return i?`${n}:${i}`:void 0}if("win32"===n){const t=`(Get-Process -Id ${e} -ErrorAction Stop).StartTime.ToUniversalTime().Ticks`,n=l.spawnSync("powershell.exe",["-NoProfile","-NonInteractive","-Command",t],{encoding:"utf8",timeout:2e3}),i=0===n.status?n.stdout.trim():"";return/^\d+$/.test(i)?`win32:${i}`:void 0}}}function k(e){try{const n=JSON.parse(t.readFileSync(S(e),"utf8"));if(_(n.pid)&&"string"==typeof n.startTime){const e=n;return{pid:e.pid,hostname:"string"==typeof e.hostname&&e.hostname?e.hostname:c.hostname(),component:e.component||"server-update",command:"string"==typeof e.command?e.command:"",acquiredAt:"string"==typeof e.createdAt&&Number.isFinite(Date.parse(e.createdAt))?e.createdAt:new Date(0).toISOString(),token:"string"==typeof e.token&&e.token?e.token:`legacy:${e.pid}:${e.startTime}`,startIdentity:e.startTime.startsWith("linux:")?e.startTime:`linux:${e.startTime}`}}if(!(_(n.pid)&&"string"==typeof n.hostname&&n.hostname&&"string"==typeof n.command&&"string"==typeof n.acquiredAt&&Number.isFinite(Date.parse(n.acquiredAt))&&"string"==typeof n.token&&n.token))return;return n}catch{return}}const O=k;function R(e){if(!_(e))return!1;try{return process.kill(Number(e),0),!0}catch(e){return"EPERM"===e.code}}function x(e){if(!e||!R(e.pid))return!1;if(!e.startIdentity)return!0;const t=C(e.pid);return void 0===t||t===e.startIdentity}function D(e,i){const r=n.join(e,`.owner-${i.token}.tmp`);t.writeFileSync(r,`${JSON.stringify(i,null,2)}\n`,{encoding:"utf8",mode:384,flag:"wx"});const s=M(e);if(s?.token!==i.token)throw j(r),new Error(`Process lock initialization was superseded: ${e}`);t.renameSync(r,S(e)),j(z(e))}function P(e,i,r){const s=O(e);if(s?.token!==i.token)return!1;const o={...i};for(const[e,t]of Object.entries(r))void 0===t?delete o[e]:Object.assign(o,{[e]:t});const a=n.join(e,`.owner-update-${i.token}-${d.randomUUID()}.tmp`);try{if(t.writeFileSync(a,`${JSON.stringify(o,null,2)}\n`,{encoding:"utf8",mode:384,flag:"wx"}),O(e)?.token!==i.token)return!1;t.renameSync(a,S(e));for(const e of Object.keys(i))delete i[e];return Object.assign(i,o),!0}catch(e){if("ENOENT"===e.code)return!1;throw e}finally{j(a)}}function M(e){try{return JSON.parse(t.readFileSync(z(e),"utf8"))}catch{return}}function L(e){const t=M(e);return _(t?.pid)&&x({pid:t.pid,startIdentity:t.startIdentity})}function j(e){try{t.unlinkSync(e)}catch(e){if("ENOENT"!==e.code)throw e}}function $(){Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,20)}function F(e){try{const n=M(e),i=Date.parse(n?.startedAt||"");return Number.isFinite(i)?Math.max(0,Date.now()-i):Math.max(0,Date.now()-t.statSync(e).mtimeMs)}catch{return 0}}function U(e,i){try{return t.writeFileSync(T(e),`${JSON.stringify({token:i,pid:process.pid,startedAt:(new Date).toISOString()})}\n`,{encoding:"utf8",mode:384,flag:"wx"}),!0}catch(r){if("EEXIST"===r.code)return!!function(e){const i=T(e),r=V(i),s=Date.parse(r?.startedAt||"");if(R(r?.pid)||Number.isFinite(s)&&Date.now()-s<2e3)return!1;const o=n.join(e,`.recovering-${d.randomUUID()}.stale`);try{t.renameSync(i,o)}catch(e){if(["ENOENT","EEXIST"].includes(e.code||""))return!1;throw e}const a=V(o);if(a?.token===r?.token)return j(o),!0;try{t.linkSync(o,i)}catch(e){if("EEXIST"!==e.code)throw e}finally{j(o)}return!1}(e)&&U(e,i);if("ENOENT"===r.code)return!1;throw r}}function V(e){try{return JSON.parse(t.readFileSync(e,"utf8"))}catch{return}}function H(e,t){return V(T(e))?.token===t}const q=6048e5;function B(e,t){const i=n.resolve(e),r=n.resolve(i,t);if(n.dirname(r)!==i||n.basename(r)!==t)throw new Error(`Retention entry is not a direct child of its managed root: ${t}`);return r}function K(e){if(t.existsSync(e)){const n=t.lstatSync(e);if(!n.isDirectory()||n.isSymbolicLink())throw new Error(`Managed persistence path must be a real directory: ${e}`)}t.mkdirSync(e,{recursive:!0,mode:448}),t.chmodSync(e,448)}const G=41943040,J="ai.sessions",W=a.z.string().trim().min(1).max(80),Y=a.z.enum(["app-session","ai-session"]),X=a.z.enum(["running","waiting","idle","failed"]);a.z.object({instanceId:a.z.string().trim().min(1).max(160),sessionId:a.z.string().trim().min(1).max(120),unread:a.z.boolean(),sessionUpdatedAt:a.z.string().datetime(),updatedAt:a.z.string().datetime()}).strict();const Q=a.z.enum(["thinking","tool","editing","approval","responding","unknown"]),Z=a.z.object({id:a.z.string().trim().min(1).max(240).optional(),kind:a.z.string().trim().min(1).max(80).optional(),name:a.z.string().trim().min(1).max(120),inputPreview:a.z.string().trim().max(500).optional(),startedAt:a.z.string().datetime().optional()}).strict(),ee=a.z.enum(["running","completed","failed","waiting"]),te=a.z.object({id:a.z.string().trim().min(1).max(240),turnId:a.z.string().trim().min(1).max(240)}).strict(),ne=te.extend({type:a.z.literal("user-message"),text:a.z.string()}).strict(),ie=te.extend({type:a.z.literal("ai-message"),text:a.z.string()}).strict(),re=te.extend({type:a.z.literal("activity"),activityKind:a.z.string().trim().min(1).max(120),title:a.z.string().trim().min(1).max(240),status:ee.optional(),summary:a.z.string().max(4e3).optional(),input:a.z.string().max(1e5).optional(),output:a.z.string().max(1e6).optional(),paths:a.z.array(a.z.string().trim().min(1).max(4096)).max(500).optional(),exitCode:a.z.number().int().optional(),durationMs:a.z.number().int().nonnegative().optional()}).strict(),se=a.z.discriminatedUnion("type",[ne,ie,re]);a.z.object({sessionId:a.z.string().trim().min(1).max(120),providerSessionId:a.z.string().trim().min(1).max(240),items:a.z.array(se),generatedAt:a.z.string().datetime()}).strict(),a.z.object({sessionId:a.z.string().trim().min(1).max(120),turnId:a.z.string().trim().min(1).max(240),items:a.z.array(se),generatedAt:a.z.string().datetime()}).strict();const oe=a.z.enum(["pending-init","running","interrupted","completed","errored","shutdown","not-found"]),ae=a.z.enum(["started","interacted","interrupted"]),ce=a.z.object({threadId:a.z.string().trim().min(1).max(240),path:a.z.string().trim().max(4096).optional(),status:oe,activity:ae.optional(),message:a.z.string().trim().max(1e3).optional(),updatedAt:a.z.string().datetime()}).strict(),de=a.z.object({toolCalls:a.z.number().int().min(0).default(0),edits:a.z.number().int().min(0).default(0),approvals:a.z.number().int().min(0).default(0)}).strict().default({toolCalls:0,edits:0,approvals:0}),le=a.z.object({send:a.z.boolean().optional(),interrupt:a.z.boolean().optional(),approval:a.z.boolean().optional(),fork:a.z.boolean().optional(),openApp:a.z.boolean().optional(),close:a.z.boolean().optional()}).strict(),ue=a.z.object({kind:a.z.literal("fork"),parentProviderSessionId:a.z.string().trim().min(1).max(240),throughTurnId:a.z.string().trim().min(1).max(240).optional()}).strict(),me=a.z.enum(["image","file"]),pe=a.z.object({id:a.z.string().trim().min(1).max(120),kind:me,name:a.z.string().trim().min(1).max(240),mime:a.z.string().trim().min(1).max(120),size:a.z.number().int().min(0).max(Number.MAX_SAFE_INTEGER)}),he=a.z.union([pe.extend({source:a.z.object({type:a.z.literal("inline"),encoding:a.z.literal("base64"),data:a.z.string().min(1).max(31457280)}).strict()}).strict().superRefine((e,t)=>{const n="image"===e.kind?20971520:512e3;(e.size<=0||("file"===e.kind?e.size>=n:e.size>n))&&t.addIssue({code:a.z.ZodIssueCode.custom,path:["size"],message:`Inline ${e.kind} must be between 1 byte and ${n} bytes.`})}),pe.extend({source:a.z.object({type:a.z.literal("runtime-path"),path:a.z.string().trim().min(1).max(4096)}).strict()}).strict()]),ge=pe.extend({sourceType:a.z.enum(["inline","runtime-path"])}).strict(),fe=a.z.union([a.z.object({id:a.z.string().trim().min(1).max(120),kind:me.optional(),source:a.z.object({type:a.z.literal("upload-ref")}).strict().default({type:"upload-ref"})}).strict(),a.z.object({id:a.z.string().trim().min(1).max(120),kind:me,name:a.z.string().trim().min(1).max(240),mime:a.z.string().trim().min(1).max(120),size:a.z.number().int().min(0).max(Number.MAX_SAFE_INTEGER),source:a.z.object({type:a.z.literal("runtime-path"),path:a.z.string().trim().min(1).max(4096)}).strict()}).strict()]),ye=a.z.enum(["auto","queue","steer","immediate"]),Ie=a.z.enum(["ask","auto-review","full-access"]),Ae=a.z.enum(["review","rename","goal","compact"]);a.z.object({command:Ae,argument:a.z.string().trim().max(4e3).optional()}).strict().superRefine((e,t)=>{"rename"!==e.command||e.argument||t.addIssue({code:"custom",path:["argument"],message:"Rename requires a thread name."}),"review"!==e.command&&"compact"!==e.command||!e.argument||t.addIssue({code:"custom",path:["argument"],message:`${e.command} does not accept an argument.`})}),a.z.object({command:Ae,value:a.z.string().max(4e3).optional(),turnId:a.z.string().trim().min(1).max(240).optional()}).strict(),a.z.enum(["skill","app","plugin"]);const be=a.z.object({name:a.z.string().trim().min(1).max(240),path:a.z.string().trim().min(1).max(4096)}),we=a.z.discriminatedUnion("kind",[be.extend({kind:a.z.literal("skill"),path:a.z.string().trim().min(1).max(4096).refine(e=>e.startsWith("/"),"Skill paths must be absolute.")}).strict(),be.extend({kind:a.z.literal("app"),path:a.z.string().trim().min(7).max(4096).regex(/^app:\/\/[^\s/]+$/,"App paths must use app://<id>.")}).strict(),be.extend({kind:a.z.literal("plugin"),path:a.z.string().trim().min(10).max(4096).regex(/^plugin:\/\/[^\s/]+$/,"Plugin paths must use plugin://<id>.")}).strict()]),ve=a.z.array(we).max(20).default([]),Ee=a.z.enum(["plugin","skill","file","directory","app"]),Ne=a.z.object({kind:Ee,name:a.z.string().trim().min(1).max(240),description:a.z.string().trim().max(1e3).optional(),path:a.z.string().trim().min(1).max(4096),icon:a.z.string().trim().max(4096).optional()}).strict().superRefine((e,t)=>{"skill"!==e.kind||e.path.startsWith("/")||t.addIssue({code:"custom",path:["path"],message:"Skill paths must be absolute."}),"app"!==e.kind||/^app:\/\/[^\s/]+$/.test(e.path)||t.addIssue({code:"custom",path:["path"],message:"App paths must use app://<id>."}),"plugin"!==e.kind||/^plugin:\/\/[^\s/]+$/.test(e.path)||t.addIssue({code:"custom",path:["path"],message:"Plugin paths must use plugin://<id>."}),"file"!==e.kind&&"directory"!==e.kind||!e.path.startsWith("/")&&!e.path.split(/[\\/]+/).includes("..")||t.addIssue({code:"custom",path:["path"],message:"File and directory paths must be relative to the session cwd."})}),Se=a.z.object({category:a.z.enum(["skills","plugins","apps","files"]),code:a.z.string().trim().min(1).max(160),message:a.z.string().trim().min(1).max(2e3)}).strict();a.z.object({sessionId:a.z.string().trim().min(1).max(120),providerSessionId:a.z.string().trim().min(1).max(240),cwd:a.z.string().trim().min(1).max(4096),candidates:a.z.array(Ne).max(1e3).default([]),diagnostics:a.z.array(Se).max(20).default([])}).strict(),a.z.object({query:a.z.string().trim().max(240).default("")}).strict(),a.z.object({sessionId:a.z.string().trim().min(1).max(120),cwd:a.z.string().trim().min(1).max(4096),query:a.z.string().trim().max(240),requestId:a.z.string().trim().min(1).max(160),candidates:a.z.array(Ne.refine(e=>"file"===e.kind||"directory"===e.kind,"File search only returns files and directories.")).max(200).default([]),complete:a.z.boolean().default(!1)}).strict();const ze=a.z.object({message:a.z.string().trim().min(1).max(2e4),mode:ye.optional(),permissionMode:Ie.optional()}),Te=ze.extend({attachments:a.z.array(he).max(6).default([]),references:ve}).strict().superRefine((e,t)=>{e.attachments.reduce((e,t)=>e+("inline"===t.source.type?t.size:0),0)>G&&t.addIssue({code:a.z.ZodIssueCode.custom,path:["attachments"],message:"Inline attachments must be 41943040 bytes or less in total."})}),_e=ze.extend({attachments:a.z.array(fe).max(6).default([]),references:ve}).strict(),Ce=a.z.object({type:a.z.literal("runtime-path"),path:a.z.string().trim().min(1).max(4096).refine(e=>e.startsWith("/")||/^[A-Za-z]:[\\/]/.test(e),"Runtime paths must be absolute in the target controlled instance.")}).strict();Te.extend({agent:W,cwd:Ce,cwdFolderId:a.z.string().trim().min(1).max(120).optional(),clientRequestId:a.z.string().trim().min(1).max(160)}).strict();const ke=a.z.object({mode:a.z.enum(["current-folder","worktree"]),branch:a.z.string().trim().min(1).max(1024)}).strict();_e.extend({agent:W,cwdFolderId:a.z.string().trim().min(1).max(120).optional(),gitSelection:ke.optional(),clientRequestId:a.z.string().trim().min(1).max(160)}).strict(),a.z.object({disposition:a.z.enum(["created","already-created"]),aiSessionId:a.z.string().trim().min(1).max(120),providerSessionId:a.z.string().trim().min(1).max(240),creationSource:a.z.literal("ai-session")}).strict();const Oe=a.z.object({mode:a.z.enum(["current","managed-worktree"]).default("current")}).strict().default({mode:"current"});a.z.object({clientRequestId:a.z.string().trim().min(1).max(160),throughTurnId:a.z.string().trim().min(1).max(240).optional(),workspace:Oe.optional().default({mode:"current"})}).strict(),a.z.object({disposition:a.z.enum(["created","already-created"]),aiSessionId:a.z.string().trim().min(1).max(120),providerSessionId:a.z.string().trim().min(1).max(240),creationSource:a.z.literal("ai-session")}).strict(),a.z.object({clientRequestId:a.z.string().trim().min(1).max(160)}).strict(),a.z.object({disposition:a.z.enum(["opened","already-open"]),aiSessionId:a.z.string().trim().min(1).max(120),providerSessionId:a.z.string().trim().min(1).max(240),appSessionId:a.z.string().trim().min(1).max(120),creationSource:Y}).strict(),a.z.object({clientRequestId:a.z.string().trim().min(1).max(160)}).strict(),a.z.object({disposition:a.z.enum(["closed","already-closed"]),aiSessionId:a.z.string().trim().min(1).max(120),providerSessionId:a.z.string().trim().min(1).max(240),creationSource:Y}).strict(),a.z.object({code:a.z.enum(["invalid-request","not-found","unsupported","provider-unavailable","materialization-failed","open-app-failed","close-failed","conflict"]),message:a.z.string().trim().min(1).max(4e3),retryable:a.z.boolean().default(!1),aiSessionId:a.z.string().trim().min(1).max(120).optional(),providerSessionId:a.z.string().trim().min(1).max(240).optional()}).strict(),a.z.object({decision:a.z.enum(["allow","deny","skip"])}).strict(),a.z.object({expectedRevision:a.z.number().int().min(0),queueIds:a.z.array(a.z.string().trim().min(1).max(120)).max(100)}).strict(),a.z.object({expectedRevision:a.z.number().int().min(0),message:a.z.string().trim().min(1).max(2e4)}).strict(),a.z.object({code:a.z.string().trim().min(1).max(160),message:a.z.string(),instanceId:a.z.string().trim().min(1).max(160).optional(),nodeId:a.z.string().trim().min(1).max(160).optional(),route:a.z.string().trim().min(1).max(4096).optional()}).strict();const Re=a.z.object({id:a.z.string().trim().min(1).max(120),message:a.z.string().trim().min(1).max(2e4),attachments:a.z.array(ge).max(6).default([]),references:ve,permissionMode:Ie.optional(),status:a.z.enum(["queued","sending","failed"]).default("queued"),createdAt:a.z.string().datetime(),updatedAt:a.z.string().datetime(),error:a.z.string().trim().max(4e3).optional()}).strict(),xe=a.z.object({revision:a.z.number().int().min(0).default(0),pendingCount:a.z.number().int().min(0).default(0),items:a.z.array(Re).max(100).default([])}).strict().default({revision:0,pendingCount:0,items:[]}),De=a.z.enum(["control","realtime","adapter-snapshot","transcript-tail","transcript-scan","process-scan","app-session"]),Pe=a.z.object({id:a.z.string().trim().min(1).max(240),status:a.z.enum(["running","completed"]),startedAt:a.z.string().datetime().optional(),completedAt:a.z.string().datetime().optional()}).strict(),Me=a.z.object({id:a.z.string().trim().min(1).max(240),providerTurnId:a.z.string().trim().max(240).optional(),source:De.optional(),userPrompt:a.z.string().trim().optional(),status:a.z.enum(["queued","running","waiting","completed","failed"]).default("running"),phase:Q.optional(),summary:a.z.string().trim().max(1e3).optional(),lastMessage:a.z.string().trim().optional(),lastMessageItemId:a.z.string().trim().max(240).optional(),contextCompactions:a.z.array(Pe).max(20).optional(),revision:a.z.number().int().min(0).default(0),sourcePriority:a.z.number().int().min(0).max(100).optional(),snapshotVersion:a.z.number().int().min(0).optional(),observedAt:a.z.string().datetime().optional(),startedAt:a.z.string().datetime().optional(),updatedAt:a.z.string().datetime().optional(),completedAt:a.z.string().datetime().optional()}).strict(),Le=Me.pick({id:!0,providerTurnId:!0,userPrompt:!0,status:!0,phase:!0,summary:!0,lastMessage:!0,contextCompactions:!0,startedAt:!0,updatedAt:!0,completedAt:!0}).strict(),je=a.z.object({id:a.z.string().trim().min(1).max(120),agent:W,creationSource:Y.default("app-session"),appSessionId:a.z.string().trim().max(120).optional(),appId:a.z.string().trim().max(120).optional(),providerSessionId:a.z.string().trim().max(240).optional(),lineage:ue.optional(),providerMeta:a.z.record(a.z.string(),a.z.unknown()).optional(),appBindingKeys:a.z.array(a.z.string().trim().min(1).max(240)).max(20).optional(),actions:le.optional(),activeTurnId:a.z.string().trim().max(240).optional(),title:a.z.string().trim().max(240).optional(),cwd:a.z.string().trim().max(4096).optional(),cwdFolderId:a.z.string().trim().min(1).max(120).optional(),userPrompt:a.z.string().trim().optional(),turns:a.z.array(Me).max(50).optional(),status:X.default("running"),phase:Q.default("unknown"),summary:a.z.string().trim().max(1e3).optional(),lastMessage:a.z.string().trim().optional(),lastMessageItemId:a.z.string().trim().max(240).optional(),currentTool:Z.optional(),toolCallsSinceLastMessage:a.z.number().int().min(0).default(0),subAgents:a.z.array(ce).max(50).default([]),transcriptPath:a.z.string().trim().max(4096).optional(),transcriptSize:a.z.number().int().min(0).optional(),startedAt:a.z.string().datetime(),updatedAt:a.z.string().datetime(),completedAt:a.z.string().datetime().optional(),error:a.z.string().trim().max(4e3).optional(),counters:de,queue:xe}).strict();a.z.object({session:je,provider:a.z.string().trim().min(1).max(80),action:a.z.enum(["send","queue","steer","interrupt","approval"]),decision:a.z.enum(["allow","deny","skip"]).optional(),turnId:a.z.string().trim().min(1).max(240).optional(),providerTurnId:a.z.string().trim().min(1).max(240).optional(),queueId:a.z.string().trim().min(1).max(120).optional()}).strict();const $e=500,Fe=a.z.object({id:a.z.string().trim().min(1).max(120),agent:a.z.enum(["codex","claude"]),creationSource:Y,providerSessionId:a.z.string().trim().min(1).max(240),lineage:ue.optional(),title:a.z.string().trim().max(240).optional(),userPrompt:a.z.string().trim().optional(),lastMessage:a.z.string().trim().optional(),cwd:a.z.string().trim().min(1).max(4096),cwdFolderId:a.z.string().trim().min(1).max(120).optional(),lastActiveAt:a.z.string().datetime(),archivedAt:a.z.string().datetime()}).strict();a.z.object({schemaVersion:a.z.literal(1).default(1),items:a.z.array(Fe).max($e).default([])}).strict(),a.z.object({items:a.z.array(Fe).max($e).default([])}).strict(),a.z.object({item:Fe,turns:a.z.array(Le).max(50).default([])}).strict(),a.z.object({disposition:a.z.enum(["resumed","already-open"]),aiSessionId:a.z.string().trim().min(1).max(120),providerSessionId:a.z.string().trim().min(1).max(240),appSessionId:a.z.string().trim().min(1).max(120).optional(),creationSource:Y}).strict();const Ue=je.pick({id:!0,agent:!0,creationSource:!0,appSessionId:!0,appId:!0,providerSessionId:!0,lineage:!0,providerMeta:!0,appBindingKeys:!0,actions:!0,activeTurnId:!0,title:!0,cwd:!0,cwdFolderId:!0,userPrompt:!0,turns:!0,status:!0,phase:!0,summary:!0,lastMessage:!0,lastMessageItemId:!0,currentTool:!0,toolCallsSinceLastMessage:!0,subAgents:!0,queue:!0,startedAt:!0,updatedAt:!0,error:!0}),Ve=a.z.object({runningCount:a.z.number().int().min(0).default(0),waitingCount:a.z.number().int().min(0).default(0),staleCount:a.z.number().int().min(0).default(0),sessions:a.z.array(Ue).default([]),updatedAt:a.z.string().datetime()}).strict();a.z.object({streamId:a.z.string().trim().min(1).max(240),revision:a.z.number().int().min(0),lastEventAt:a.z.string().datetime(),snapshot:Ve}).strict(),Ve.pick({runningCount:!0,waitingCount:!0,staleCount:!0,updatedAt:!0}).extend({idleCount:a.z.number().int().min(0).default(0),problemCount:a.z.number().int().min(0).default(0),revision:a.z.number().int().min(0).optional()});const He=a.z.enum(["provider-event","app-session-created","app-session-updated","app-session-deleted","discovery-scan","control-action","heartbeat-sync","startup"]),qe=a.z.object({streamId:a.z.string().trim().min(1).max(240),instanceId:a.z.string().trim().min(1).max(160),nodeId:a.z.string().trim().min(1).max(160).optional(),revision:a.z.number().int().min(0),previousRevision:a.z.number().int().min(0).optional(),traceId:a.z.string().trim().min(1).max(160),generatedAt:a.z.string().datetime(),reason:He}).strict(),Be=a.z.object({meta:qe,snapshot:Ve}).strict(),Ke=a.z.object({meta:qe,upserted:a.z.array(Ue).default([]),removed:a.z.array(a.z.string().trim().min(1).max(120)).default([])}).strict(),Ge=a.z.object({meta:qe,sessionIds:a.z.array(a.z.string().trim().min(1).max(120)).default([]),expiresAt:a.z.string().datetime()}).strict();a.z.object({instanceId:a.z.string().trim().min(1).max(160),nodeId:a.z.string().trim().min(1).max(160).optional(),sessionId:a.z.string().trim().min(1).max(120),providerSessionId:a.z.string().trim().min(1).max(240),turnId:a.z.string().trim().min(1).max(240),itemId:a.z.string().trim().min(1).max(240),delta:a.z.string().min(1),generatedAt:a.z.string().datetime()}).strict(),a.z.object({instanceId:a.z.string().trim().min(1).max(160),nodeId:a.z.string().trim().min(1).max(160).optional(),sessionId:a.z.string().trim().min(1).max(120),providerSessionId:a.z.string().trim().min(1).max(240),item:se,generatedAt:a.z.string().datetime()}).strict(),a.z.object({streamId:a.z.string().trim().min(1).max(240),instanceId:a.z.string().trim().min(1).max(160),sinceRevision:a.z.number().int().min(0),latestRevision:a.z.number().int().min(0),earliestRetainedRevision:a.z.number().int().min(0),syncRequired:a.z.boolean().default(!1),events:a.z.array(a.z.discriminatedUnion("type",[a.z.object({type:a.z.literal("ai-session.snapshot"),payload:Be}).strict(),a.z.object({type:a.z.literal("ai-session.patch"),payload:Ke}).strict(),a.z.object({type:a.z.literal("ai-session.removed"),payload:Ge}).strict()])).default([])}).strict();const Je=a.z.object({source:De,sourcePriority:a.z.number().int().min(0).max(100).optional(),observedAt:a.z.string().datetime().optional(),snapshotVersion:a.z.number().int().min(0).optional()}).strict(),We=Je.extend({type:a.z.literal("snapshot"),agent:a.z.string().trim().min(1).max(80),creationSource:Y.optional(),appSessionId:a.z.string().trim().max(120).optional(),appId:a.z.string().trim().max(120).optional(),providerSessionId:a.z.string().trim().max(240).optional(),lineage:ue.optional(),providerMeta:a.z.record(a.z.string(),a.z.unknown()).optional(),appBindingKeys:a.z.array(a.z.string().trim().min(1).max(240)).max(20).optional(),actions:le.optional(),title:a.z.string().trim().max(240).optional(),cwd:a.z.string().trim().max(4096).optional(),cwdFolderId:a.z.string().trim().min(1).max(120).optional(),activeTurnId:a.z.string().trim().max(240).optional(),userPrompt:a.z.string().trim().optional(),turns:a.z.array(Me).max(50).optional(),status:X.optional(),phase:Q.optional(),summary:a.z.string().trim().max(1e3).optional(),lastMessage:a.z.string().trim().optional(),lastMessageItemId:a.z.string().trim().max(240).optional(),error:a.z.string().trim().max(4e3).optional(),currentTool:Z.optional(),toolCallsSinceLastMessage:a.z.number().int().min(0).optional(),subAgents:a.z.array(ce).max(50).optional(),transcriptPath:a.z.string().trim().max(4096).optional(),transcriptSize:a.z.number().int().min(0).optional(),replaceActivity:a.z.boolean().optional()}).strict(),Ye=Je.extend({type:a.z.literal("event"),sessionId:a.z.string().trim().min(1).max(120),kind:a.z.enum(["lifecycle","send-ack","turn-started","user-message","assistant-message","approval-requested","turn-completed","session-error","tool-activity","sub-agent-activity","context-compaction"]),activeTurnId:a.z.string().trim().max(240).optional(),providerTurnId:a.z.string().trim().max(240).optional(),userPrompt:a.z.string().trim().optional(),text:a.z.string().optional(),itemId:a.z.string().trim().max(240).optional(),status:X.optional(),phase:Q.optional(),summary:a.z.string().trim().max(1e3).optional(),error:a.z.string().trim().max(4e3).optional(),currentTool:Z.nullable().optional(),toolCallsSinceLastMessage:a.z.number().int().min(0).optional(),subAgents:a.z.array(ce).max(50).optional(),contextCompaction:Pe.optional(),counters:a.z.object({toolCalls:a.z.number().int().min(0).optional(),edits:a.z.number().int().min(0).optional(),approvals:a.z.number().int().min(0).optional()}).strict().optional()}).strict().superRefine((e,t)=>{if("session-error"!==e.kind||e.error||t.addIssue({code:"custom",path:["error"],message:"session-error events require error"}),"context-compaction"===e.kind?e.contextCompaction||t.addIssue({code:"custom",path:["contextCompaction"],message:"context-compaction events require contextCompaction"}):void 0!==e.contextCompaction&&t.addIssue({code:"custom",path:["contextCompaction"],message:"contextCompaction is only valid for context-compaction events"}),"sub-agent-activity"===e.kind?e.subAgents||t.addIssue({code:"custom",path:["subAgents"],message:"sub-agent-activity events require subAgents"}):void 0!==e.subAgents&&t.addIssue({code:"custom",path:["subAgents"],message:"subAgents is only valid for sub-agent-activity events"}),"tool-activity"!==e.kind)return void 0!==e.currentTool&&t.addIssue({code:"custom",path:["currentTool"],message:"currentTool is only valid for tool-activity events"}),void(void 0!==e.toolCallsSinceLastMessage&&t.addIssue({code:"custom",path:["toolCallsSinceLastMessage"],message:"toolCallsSinceLastMessage is only valid for tool-activity events"}));"currentTool"in e||t.addIssue({code:"custom",path:["currentTool"],message:"tool-activity events require currentTool"}),void 0===e.toolCallsSinceLastMessage&&t.addIssue({code:"custom",path:["toolCallsSinceLastMessage"],message:"tool-activity events require toolCallsSinceLastMessage"})});a.z.discriminatedUnion("type",[We,Ye]);const Xe=a.z.union([a.z.object({type:a.z.literal("schedule"),scheduleKind:a.z.literal("interval").default("interval"),intervalMs:a.z.number().int().min(1e3)}).strict(),a.z.object({type:a.z.literal("schedule"),scheduleKind:a.z.literal("daily"),timeOfDay:a.z.string().regex(/^([01]\d|2[0-3]):[0-5]\d$/),timezone:a.z.string().trim().min(1).max(120)}).strict(),a.z.object({type:a.z.literal("schedule"),scheduleKind:a.z.literal("weekly"),weekdays:a.z.array(a.z.number().int().min(0).max(6)).min(1).max(7),timeOfDay:a.z.string().regex(/^([01]\d|2[0-3]):[0-5]\d$/),timezone:a.z.string().trim().min(1).max(120)}).strict()]),Qe=a.z.union([Xe,a.z.object({type:a.z.literal("file-change"),roots:a.z.array(a.z.string().trim().min(1).max(4096)).min(1).max(50),globs:a.z.array(a.z.string().trim().min(1).max(500)).min(1).max(100),ignore:a.z.array(a.z.string().trim().min(1).max(500)).max(100).optional(),debounceMs:a.z.number().int().min(100).max(6e4).default(1500)}).strict(),a.z.object({type:a.z.literal("ai-session"),agent:a.z.string().trim().min(1).max(80).optional(),statuses:a.z.array(a.z.enum(["running","waiting","idle","failed"])).max(20).optional(),phases:a.z.array(a.z.enum(["thinking","tool","editing","approval","responding","unknown"])).max(20).optional()}).strict()]),Ze=a.z.object({promptTemplate:a.z.string().trim().min(1).max(2e4)}).strict(),et=a.z.object({cooldownMs:a.z.number().int().min(0).max(864e5).optional(),maxConcurrentRuns:a.z.number().int().min(1).max(20).default(1),whenBusy:a.z.enum(["skip","queue"]).default("skip")}).strict(),tt=a.z.object({configHash:a.z.string().trim().min(8).max(80),name:a.z.string().trim().min(1).max(160),description:a.z.string().trim().max(1e3).optional(),source:Qe,action:Ze,policy:et.default({maxConcurrentRuns:1,whenBusy:"skip"}),createdAt:a.z.string().datetime(),updatedAt:a.z.string().datetime()}).strict(),nt=a.z.object({type:a.z.literal("ai-session"),aiSessionId:a.z.string().trim().min(1).max(160)}).strict(),it=a.z.object({configHash:a.z.string().trim().min(8).max(80),deploymentId:a.z.string().trim().min(1).max(240).optional(),instanceId:a.z.string().trim().min(1).max(160),origin:a.z.enum(["control-plane","controlled-instance"]).default("controlled-instance"),enabled:a.z.boolean().default(!0),target:nt,localName:a.z.string().trim().min(1).max(160).optional(),createdAt:a.z.string().datetime(),updatedAt:a.z.string().datetime()}).strict(),rt=a.z.object({configHash:a.z.string().trim().min(8).max(80),deploymentId:a.z.string().trim().min(1).max(240).optional(),instanceId:a.z.string().trim().min(1).max(160),status:a.z.enum(["idle","running","disabled","error"]).default("idle"),lastTriggeredAt:a.z.string().datetime().optional(),lastCompletedAt:a.z.string().datetime().optional(),lastSkippedAt:a.z.string().datetime().optional(),lastError:a.z.string().trim().max(4e3).optional(),runCount:a.z.number().int().min(0).default(0),skippedCount:a.z.number().int().min(0).default(0)}).strict(),st=a.z.object({id:a.z.string().trim().min(1).max(160),configHash:a.z.string().trim().min(8).max(80),deploymentId:a.z.string().trim().min(1).max(240).optional(),instanceId:a.z.string().trim().min(1).max(160),eventType:a.z.enum(["manual","schedule","file-change","ai-session"]),status:a.z.enum(["started","completed","failed","skipped"]),target:nt,promptPreview:a.z.string().trim().max(500),eventSummary:a.z.string().trim().max(1e3).optional(),error:a.z.string().trim().max(4e3).optional(),startedAt:a.z.string().datetime(),completedAt:a.z.string().datetime().optional()}).strict();a.z.object({schemaVersion:a.z.literal(1).default(1),configs:a.z.array(tt).default([]),deployments:a.z.array(it).default([]),runtime:a.z.array(rt).default([]),recentRuns:a.z.array(st).default([])}).strict();const ot=a.z.object({instanceId:a.z.string().trim().min(1).max(160),instanceName:a.z.string().trim().min(1).max(160),deployment:it,runtime:rt.optional()}).strip(),at=st.extend({instanceName:a.z.string().trim().min(1).max(160).optional()}).strip(),ct=a.z.object({configHash:a.z.string().trim().min(8).max(80),config:tt,deploymentCount:a.z.number().int().min(0),enabledCount:a.z.number().int().min(0),runningCount:a.z.number().int().min(0),errorCount:a.z.number().int().min(0),ownedByControlPlane:a.z.boolean(),controlPlaneDeploymentCount:a.z.number().int().min(0),deployments:a.z.array(ot),recentRuns:a.z.array(at)}).strip();a.z.object({updatedAt:a.z.string().datetime(),triggers:a.z.array(ct)}).strip(),a.z.object({name:tt.shape.name,description:tt.shape.description,source:Qe,action:Ze,policy:et.partial().optional()}).strict();const dt=a.z.string().regex(/^\d{4}-\d{2}-\d{2}$/,"Proxy protocol version must use YYYY-MM-DD format."),lt=a.z.string().trim().min(1).max(160).regex(/^[a-zA-Z0-9][a-zA-Z0-9_.:-]*$/),ut=a.z.string().datetime(),mt=a.z.string().trim().min(32).max(4096),pt=a.z.string().trim().max(2048).transform((e,t)=>{try{return function(e){const t=new URL(e.trim());if("https:"!==t.protocol||t.username||t.password||"/"!==t.pathname||t.search||t.hash)throw new Error("Proxy origin must be an HTTPS origin without credentials, path, query, or fragment.");return t.origin}(e)}catch(e){return t.addIssue({code:"custom",message:e instanceof Error?e.message:String(e)}),a.z.NEVER}});a.z.string().trim().min(1).max(4096).transform((e,t)=>{try{return function(e){const t=e.trim();if(!t.startsWith("/")||t.startsWith("//")||t.includes("\\")||/%25/i.test(t))throw new Error("Proxy route must be a single-encoded node-agent relative route.");const n=t.split("?",1)[0];let i,r;try{i=n.split("/").map(e=>decodeURIComponent(e))}catch{throw new Error("Proxy route contains invalid percent encoding.")}if(i.some(e=>".."===e||"."===e))throw new Error("Proxy route cannot traverse outside the node-agent API.");try{r=new URL(t,"https://node-agent.invalid")}catch{throw new Error("Proxy route is invalid.")}if("https://node-agent.invalid"!==r.origin||r.username||r.password)throw new Error("Proxy route cannot select an absolute upstream URL.");return`${r.pathname}${r.search}`}(e)}catch(e){return t.addIssue({code:"custom",message:e instanceof Error?e.message:String(e)}),a.z.NEVER}});const ht=a.z.enum(Object.values({ProtocolUnsupported:"CONTROL_PLANE_PROXY_PROTOCOL_UNSUPPORTED",InviteInvalid:"CONTROL_PLANE_PROXY_INVITE_INVALID",InviteExpired:"CONTROL_PLANE_PROXY_INVITE_EXPIRED",InviteConsumed:"CONTROL_PLANE_PROXY_INVITE_CONSUMED",InviteRevoked:"CONTROL_PLANE_PROXY_INVITE_REVOKED",TargetUnavailable:"CONTROL_PLANE_PROXY_TARGET_UNAVAILABLE",TargetMismatch:"CONTROL_PLANE_PROXY_TARGET_MISMATCH",BindingUnknown:"CONTROL_PLANE_PROXY_BINDING_UNKNOWN",BindingRevoked:"CONTROL_PLANE_PROXY_BINDING_REVOKED",BindingIdentityConflict:"CONTROL_PLANE_PROXY_BINDING_IDENTITY_CONFLICT",AuthenticationFailed:"CONTROL_PLANE_PROXY_AUTHENTICATION_FAILED",RouteInvalid:"CONTROL_PLANE_PROXY_ROUTE_INVALID",HeaderInvalid:"CONTROL_PLANE_PROXY_HEADER_INVALID",ResourceLimit:"CONTROL_PLANE_PROXY_RESOURCE_LIMIT",SnapshotRequired:"CONTROL_PLANE_PROXY_SNAPSHOT_REQUIRED",Unavailable:"CONTROL_PLANE_PROXY_UNAVAILABLE",TransportFailed:"CONTROL_PLANE_PROXY_TRANSPORT_FAILED"})),gt=a.z.object({code:ht,message:a.z.string().trim().min(1).max(2048),retryable:a.z.boolean(),details:a.z.record(a.z.string(),a.z.unknown()).optional()}).strict(),ft=a.z.enum(["active","consumed","revoked","expired"]),yt=a.z.object({id:lt,targetNodeId:lt,tokenHash:a.z.string().trim().min(32).max(256),status:ft,createdBy:lt,expiresAt:ut,consumedByClaimId:lt.optional(),consumedAt:ut.optional(),revokedAt:ut.optional(),createdAt:ut,updatedAt:ut}).strict().omit({tokenHash:!0});a.z.object({targetNodeId:lt,expiresInSeconds:a.z.number().int().min(60).max(3600).default(600)}).strict(),a.z.object({invite:yt,token:a.z.string().trim().min(24).max(512),proxyOrigin:pt,protocolVersion:dt}).strict();const It=a.z.enum(["active","revoked"]),At=a.z.object({id:lt,claimId:lt,sourceControlPlaneId:lt,targetNodeId:lt,bindingKeyId:lt,credentialHash:a.z.string().trim().min(32).max(256),status:It,revision:a.z.number().int().positive(),lastError:gt.optional(),revokedAt:ut.optional(),createdAt:ut,updatedAt:ut}).strict().omit({credentialHash:!0});a.z.object({protocolVersion:dt,inviteToken:a.z.string().trim().min(24).max(512).optional(),claimId:lt,sourceControlPlaneId:lt,targetNodeId:lt.optional(),bindingKeyId:lt,credential:mt}).strict(),a.z.object({sourceControlPlaneId:lt,bindingKeyId:lt,credential:mt}).strict();const bt=a.z.object({id:lt,name:a.z.string().trim().min(1).max(160),status:a.z.enum(["unknown","online","offline","degraded"]),health:a.z.enum(["unknown","ok","degraded","failed"]),lastSeenAt:ut.optional(),capabilities:a.z.record(a.z.string(),a.z.unknown()).default({})}).strict(),wt=a.z.object({protocolVersion:dt,binding:At,streamId:lt,revision:a.z.number().int().nonnegative(),observedAt:ut,target:bt}).strict(),vt=a.z.object({type:a.z.literal("control-plane-proxy.event"),protocolVersion:dt,streamId:lt,bindingId:lt,sourceControlPlaneId:lt,targetNodeId:lt,revision:a.z.number().int().positive(),source:a.z.object({id:a.z.string().trim().min(1).max(512),seq:a.z.number().int().nonnegative()}).strict(),target:bt,event:a.z.object({type:a.z.string().trim().min(1).max(240),topic:a.z.string().trim().min(1).max(240),createdAt:ut}).strict()}).strict(),Et=a.z.object({type:a.z.literal("control-plane-proxy.events.ready"),protocolVersion:dt,streamId:lt,bindingId:lt,sourceControlPlaneId:lt,targetNodeId:lt,latestRevision:a.z.number().int().nonnegative(),earliestRetainedRevision:a.z.number().int().nonnegative()}).strict(),Nt=a.z.object({type:a.z.literal("control-plane-proxy.snapshot-required"),protocolVersion:dt,streamId:lt,bindingId:lt,sourceControlPlaneId:lt,targetNodeId:lt,sinceRevision:a.z.number().int().nonnegative(),latestRevision:a.z.number().int().nonnegative(),earliestRetainedRevision:a.z.number().int().nonnegative(),error:gt}).strict();a.z.discriminatedUnion("type",[vt,Et,Nt]),a.z.object({protocolVersion:dt,binding:At,target:wt.shape.target}).strict(),a.z.object({id:lt,claimId:lt,proxyOrigin:pt,requestedName:a.z.string().trim().min(1).max(160).optional(),sourceControlPlaneId:lt,targetNodeId:lt.optional(),bindingKeyId:lt,credential:mt,status:a.z.enum(["pending","compensation-required"]),createdAt:ut,updatedAt:ut,expiresAt:ut}).strict().omit({credential:!0}),a.z.object({id:lt,nodeId:lt,proxyOrigin:pt,proxyBindingId:lt,targetNodeId:lt,sourceControlPlaneId:lt,bindingKeyId:lt,credential:mt,createdAt:ut,updatedAt:ut}).strict();const St="2026-08-17",zt=new Set(["2026-08-01","2026-08-16",St]),Tt=a.z.string().regex(/^\d{4}-\d{2}-\d{2}$/,"Protocol version must use YYYY-MM-DD format."),_t=a.z.string().trim().min(1).max(120);function Ct(){return{features:{appRuntime:!1,tty:!1,gui:!1,browser:!1,screenshots:!1,logs:!1,aiSessionWorkspaceSelection:!1,aiSessionPersistenceSettings:!1,aiSessionTimeline:{sessionReadAgents:[],turnReadAgents:[],liveItemAgents:[]}}}}const kt=a.z.object({sessionReadAgents:a.z.array(_t).max(100).default([]),turnReadAgents:a.z.array(_t).max(100).default([]),liveItemAgents:a.z.array(_t).max(100).default([])}).passthrough(),Ot=a.z.object({appRuntime:a.z.boolean().default(!1),tty:a.z.boolean().default(!1),gui:a.z.boolean().default(!1),browser:a.z.boolean().default(!1),screenshots:a.z.boolean().default(!1),logs:a.z.boolean().default(!1),aiSessionWorkspaceSelection:a.z.boolean().default(!1),aiSessionPersistenceSettings:a.z.boolean().default(!1),aiSessionTimeline:kt.default(function(){return{sessionReadAgents:[],turnReadAgents:[],liveItemAgents:[]}})}).passthrough(),Rt=a.z.object({features:Ot.default(function(){return{appRuntime:!1,tty:!1,gui:!1,browser:!1,screenshots:!1,logs:!1,aiSessionWorkspaceSelection:!1,aiSessionPersistenceSettings:!1,aiSessionTimeline:{sessionReadAgents:[],turnReadAgents:[],liveItemAgents:[]}}})}).passthrough();function xt(e){const t={features:{appRuntime:!1,tty:!1,gui:!1,browser:!1,screenshots:!1,logs:!1,aiSessionWorkspaceSelection:!1,aiSessionPersistenceSettings:!1,aiSessionTimeline:{sessionReadAgents:[],turnReadAgents:[],liveItemAgents:[]}}};if(!e||"object"!=typeof e||Array.isArray(e))return t;const n=e,i=n.features;if(!i||"object"!=typeof i||Array.isArray(i))return t;const r=i,s={appRuntime:!1,tty:!1,gui:!1,browser:!1,screenshots:!1,logs:!1,aiSessionWorkspaceSelection:!1,aiSessionPersistenceSettings:!1,aiSessionTimeline:{sessionReadAgents:[],turnReadAgents:[],liveItemAgents:[]}};for(const e of["appRuntime","tty","gui","browser","screenshots","logs","aiSessionWorkspaceSelection","aiSessionPersistenceSettings"]){const t=a.z.boolean().safeParse(r[e]);t.success&&(s[e]=t.data)}const o=kt.safeParse(r.aiSessionTimeline);return o.success&&(s.aiSessionTimeline=o.data),Rt.parse({...n,features:{...r,...s}})}const Dt=a.z.string().trim().min(1).max(120).regex(/^[a-zA-Z0-9][a-zA-Z0-9_.:-]*$/),Pt=a.z.string().datetime(),Mt=a.z.record(a.z.string(),a.z.string()).default({}),Lt=a.z.record(a.z.string(),a.z.string()).default({}),jt=a.z.object({encoding:a.z.enum(["utf8","base64"]),data:a.z.string()}).strict().superRefine((e,t)=>{"base64"===e.encoding&&Buffer.from(e.data,"base64").toString("base64")!==e.data&&t.addIssue({code:"custom",path:["data"],message:"Node tunnel binary body must use canonical base64 encoding."})});function $t(e){if(null==e)return;const t=jt.parse(e);return"utf8"===t.encoding?t.data:Buffer.from(t.data,"base64")}const Ft=/^[A-Za-z0-9_][A-Za-z0-9_.-]{0,127}$/,Ut=/^sha256:([a-fA-F0-9]{64})$/,Vt=/^(?:localhost|[a-z0-9](?:[a-z0-9.-]*[a-z0-9])?)(?::[1-9][0-9]{0,4})?$/,Ht=/^[a-z0-9]+(?:(?:[._]|__|-+)[a-z0-9]+)*$/;function qt(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?Ut.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&&!Ft.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&&!Vt.test(u[0].toLowerCase()))throw new Error("Docker image registry host or port is invalid.");if(!p.length||p.some(e=>!Ht.test(e)))throw new Error("Docker image repository names must be lowercase and use valid separators.");const h=u.map((e,t)=>m&&0===t?e.toLowerCase():e).join("/"),g=s?`sha256:${s[1].toLowerCase()}`:void 0;return`${h}${d?`:${d}`:""}${g?`@${g}`:""}`}function Bt(e){const t=qt(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 Kt=a.z.string().trim().min(1).max(512).transform((e,t)=>{try{return qt(e)}catch(e){return t.addIssue({code:"custom",message:e instanceof Error?e.message:String(e)}),a.z.NEVER}}),Gt=a.z.string().trim().transform((e,t)=>{const n=Ut.exec(e);return n?`sha256:${n[1].toLowerCase()}`:(t.addIssue({code:"custom",message:"Docker image digest must use sha256 followed by 64 hexadecimal characters."}),a.z.NEVER)}),Jt=a.z.object({codexModelHash:Dt.nullable().optional(),claudeModelHash:Dt.nullable().optional()}).strict().default({}),Wt=a.z.object({imageId:Dt,tag:a.z.string().trim().min(1).max(128).regex(Ft).optional()}).strict(),Yt=a.z.discriminatedUnion("type",[a.z.object({type:a.z.literal("image"),imageSelection:Wt}).strict(),a.z.object({type:a.z.literal("template"),environmentTemplateId:Dt}).strict()]),Xt=a.z.enum(["creating","ready","failed","deleting"]),Qt=a.z.enum(["linux","darwin","win32","freebsd","openbsd","aix","sunos","unknown"]),Zt=a.z.enum(["x64","arm64","arm","ia32","ppc64","s390x","riscv64","unknown"]),en=a.z.object({code:a.z.string().trim().min(1).max(120),message:a.z.string().trim().min(1).max(2048),phase:a.z.enum(["validate","commit","inspect","security-check","persist","delete","recovery"]).optional()}).strict(),tn=a.z.object({templateId:Dt,nodeId:Dt,imageId:Gt,name:a.z.string().trim().min(1).max(160),platform:Qt,architecture:Zt}).strict(),nn=a.z.enum(["data","agent-home","workspace"]),rn=a.z.object({deleteVolumes:a.z.boolean()}).strict(),sn=a.z.object({role:nn,name:a.z.string().trim().min(1).max(255),mountPath:a.z.string().trim().startsWith("/").max(4096),status:a.z.enum(["deleted","retained","missing","failed"]),error:a.z.object({code:a.z.string().trim().min(1).max(120),message:a.z.string().trim().min(1).max(2048)}).strict().optional()}).strict(),on=a.z.object({instanceId:Dt,containerDeleted:a.z.boolean(),completed:a.z.boolean(),deletedVolumes:a.z.array(sn),retainedVolumes:a.z.array(sn),volumeResults:a.z.array(sn)}).strict(),an={img_default:"market_taskhandoff_browser",img_codex:"market_taskhandoff_codex",img_ai:"market_taskhandoff_ai"};function cn(e,t){if(e&&"object"==typeof e&&!Array.isArray(e)){const t=e;return{imageId:"string"==typeof t.imageId&&an[t.imageId]||t.imageId,..."string"==typeof t.tag?{tag:t.tag}:{}}}if("string"==typeof t)return{imageId:an[t]||t}}function dn(e){if(!e||"object"!=typeof e||Array.isArray(e))return e;const t=e,{defaultImageId:n,...i}=t;return{...i,defaultImageSelection:cn(t.defaultImageSelection,n)}}const ln=a.z.object({id:Dt,name:a.z.string().trim().min(1).max(120),kind:a.z.enum(["tty","gui","web"]),source:a.z.enum(["builtin","custom"]),availability:a.z.enum(["available","missing-dependency"]),capabilities:a.z.object({automation:a.z.enum(["cdp"]).optional(),supportsCwdSelection:a.z.boolean().default(!1)}).strict().default({supportsCwdSelection:!1}),diagnosticCode:a.z.enum(["APP_EXECUTABLE_NOT_FOUND"]).optional()}).strict(),un=a.z.object({code:a.z.enum(["APP_CATALOG_INVALID"]),message:a.z.string().trim().min(1).max(500)}).strict(),mn=a.z.object({items:a.z.array(ln).max(256),observedAt:Pt,issues:a.z.array(un).max(32).default([])}).strict(),pn=a.z.object({id:Dt,name:a.z.string().trim().min(1).max(160),sourceInstanceId:Dt,nodeId:Dt,imageId:Gt.optional(),internalTag:a.z.string().trim().min(1).max(512).optional(),platform:Qt.optional(),architecture:Zt.optional(),sizeBytes:a.z.number().int().nonnegative().optional(),status:Xt,error:en.optional(),createdAt:Pt,updatedAt:Pt}).strict().superRefine((e,t)=>{if("ready"===e.status)for(const n of["imageId","internalTag","platform","architecture","sizeBytes"])void 0===e[n]&&t.addIssue({code:"custom",path:[n],message:`Ready environment template requires ${n}.`});"failed"!==e.status||e.error||t.addIssue({code:"custom",path:["error"],message:"Failed environment template requires an error diagnostic."})}),hn=a.z.enum(["apt","dnf","brew","npm"]),gn=a.z.enum(["user","passwordless-sudo","root"]),fn=a.z.object({platform:Qt,arch:Zt,installers:a.z.array(hn).max(8),privilege:gn,installerAccess:a.z.object({npmGlobalWritable:a.z.boolean().optional()}).strict().optional()}).strict(),yn=a.z.enum(["installed","not-installed","broken","unsupported"]),In=a.z.enum(["recipe","bundled","external","none"]),An=a.z.object({code:a.z.enum(["BUNDLED","EXTERNALLY_MANAGED","ALREADY_INSTALLED","NOT_INSTALLED","UNSUPPORTED_PLATFORM","INSTALLER_UNAVAILABLE","INSTALLER_NOT_WRITABLE","INSUFFICIENT_PRIVILEGE","OPERATION_IN_PROGRESS"]),message:a.z.string().trim().min(1).max(500)}).strict(),bn=a.z.object({id:Dt,name:a.z.string().trim().min(1).max(120),kind:a.z.enum(["tty","gui","web"]),description:a.z.string().trim().max(500).optional(),state:yn,managementSource:In,version:a.z.string().trim().max(120).optional(),canInstall:a.z.boolean(),canUninstall:a.z.boolean(),installReason:An.optional(),uninstallReason:An.optional(),activeJobId:Dt.optional()}).strict(),wn=a.z.enum(["install","uninstall"]),vn=a.z.enum(["queued","running","succeeded","failed","cancelled","interrupted"]),En=a.z.object({current:a.z.number().finite().nonnegative().optional(),total:a.z.number().finite().positive().optional(),unit:a.z.string().trim().min(1).max(40).optional()}).strict().refine(e=>void 0===e.total||void 0===e.current||e.current<=e.total,{message:"Progress current must not exceed total.",path:["current"]}),Nn=a.z.object({executable:a.z.string().trim().min(1).max(4096),args:a.z.array(a.z.string().max(4096)).max(128)}).strict(),Sn=a.z.object({code:a.z.string().trim().min(1).max(120).regex(/^[a-z0-9][a-z0-9._-]*$/),message:a.z.string().trim().min(1).max(4096),retryable:a.z.boolean(),sessionIds:a.z.array(Dt).max(64).optional()}).strict(),zn=a.z.object({id:Dt,requestId:Dt.optional(),appId:Dt,operation:wn,state:vn,phase:a.z.string().trim().min(1).max(120).optional(),progress:En.optional(),command:Nn.optional(),logTail:a.z.string().max(32768).optional(),logTruncated:a.z.boolean().optional(),error:Sn.optional(),requestedAt:Pt,startedAt:Pt.optional(),finishedAt:Pt.optional(),updatedAt:Pt}).strict(),Tn=a.z.object({streamId:Dt,sequence:a.z.number().int().nonnegative(),capabilities:fn,apps:a.z.array(bn).max(256),activeJobs:a.z.array(zn).max(256),recentJobs:a.z.array(zn).max(256),observedAt:Pt}).strict();a.z.object({requestId:Dt.optional()}).strict(),a.z.object({job:zn}).strict(),a.z.object({type:a.z.literal("app-management"),streamId:Dt,sequence:a.z.number().int().nonnegative(),observedAt:Pt,job:zn.optional(),snapshot:Tn.optional()}).strict().refine(e=>void 0!==e.job||void 0!==e.snapshot,{message:"An app management event requires a job or snapshot."});const _n=a.z.object({component:a.z.enum(["control-plane","node-agent","controlled-instance"]),packageName:a.z.string().trim().max(160).optional(),packageVersion:a.z.string().trim().max(80).optional(),protocolVersion:Tt.optional(),buildId:a.z.string().trim().max(160).optional(),builtAt:a.z.string().trim().max(120).optional(),gitCommit:a.z.string().trim().max(120).optional(),imageRef:a.z.string().trim().max(512).optional(),imageDigest:a.z.string().trim().max(240).optional()}).strict();a.z.object({data:a.z.object({ok:a.z.literal(!0),role:a.z.literal("control-plane"),protocolVersion:Tt,build:_n.extend({component:a.z.literal("control-plane"),packageVersion:a.z.string().trim().min(1).max(80)}).loose(),dataDir:a.z.string().min(1),serverTime:Pt}).loose()}).loose();const Cn=a.z.enum(["stable","beta","alpha"]),kn=a.z.object({packageName:a.z.literal("@task-handoff/controlled-instance"),version:a.z.string().trim().min(1).max(80),platform:a.z.string().trim().min(1).max(40),arch:a.z.string().trim().min(1).max(40),formatVersion:a.z.number().int().positive(),launcherAbi:a.z.number().int().positive(),entrypoint:a.z.string().trim().min(1).max(512),sha256:a.z.string().regex(/^[a-f0-9]{64}$/)}).strict(),On=a.z.object({code:a.z.enum(["INSTANCE_RUNTIME_VERSION_MISMATCH","INSTANCE_RUNTIME_ARTIFACT_UNAVAILABLE","INSTANCE_RUNTIME_ARTIFACT_INVALID","INSTANCE_RUNTIME_INSTALL_FAILED","INSTANCE_RUNTIME_RESTART_FAILED","INSTANCE_RUNTIME_VERIFICATION_FAILED","INSTANCE_BASE_RUNTIME_INCOMPATIBLE","NODE_UPDATE_PREFLIGHT_FAILED","NODE_UPDATE_FAILED","LEGACY_INSTANCE_UPDATE_RETIRED"]),message:a.z.string().trim().min(1).max(4096),expectedVersion:a.z.string().trim().min(1).max(80).optional(),actualVersion:a.z.string().trim().min(1).max(80).optional(),retryable:a.z.boolean().default(!1)}).strict(),Rn=a.z.object({desiredVersion:a.z.string().trim().min(1).max(80),actualVersion:a.z.string().trim().min(1).max(80).optional(),phase:a.z.enum(["pending","draining","installing","restarting","verifying","matched","failed"]),attempt:a.z.number().int().nonnegative().default(0),lastAttemptAt:Pt.optional(),matchedAt:Pt.optional(),error:On.optional()}).strict(),xn=a.z.object({runningInstanceCount:a.z.number().int().nonnegative(),stoppedInstanceCount:a.z.number().int().nonnegative(),activeInstanceCount:a.z.number().int().nonnegative(),restartInstanceCount:a.z.number().int().nonnegative(),runningInstanceIds:a.z.array(Dt).max(1024).default([]),stoppedInstanceIds:a.z.array(Dt).max(1024).default([]),activeInstanceIds:a.z.array(Dt).max(1024).default([])}).strict(),Dn=a.z.object({phase:a.z.enum(["queued","updating-node","restarting-node","converging-instances","succeeded","degraded","failed"]),desiredVersion:a.z.string().trim().min(1).max(80),nodeVersion:a.z.string().trim().min(1).max(80).optional(),expectedInstanceIds:a.z.array(Dt).max(1024).default([]),expectedInstanceCount:a.z.number().int().nonnegative(),matchedInstanceCount:a.z.number().int().nonnegative(),pendingInstanceCount:a.z.number().int().nonnegative(),failedInstanceCount:a.z.number().int().nonnegative(),deferredInstanceCount:a.z.number().int().nonnegative().default(0)}).strict(),Pn=a.z.object({channel:Cn.default("stable")}).strict(),Mn=a.z.object({source:a.z.literal("npm"),channel:Cn,currentVersion:a.z.string().trim().max(240).optional(),availableVersion:a.z.string().trim().min(1).max(240),artifactRef:a.z.string().trim().min(1).max(512).optional(),runtimeArtifacts:a.z.array(kn).default([]),impact:xn,updateAvailable:a.z.boolean(),supported:a.z.boolean().default(!0),reason:a.z.string().trim().max(2048).optional(),checkedAt:Pt,preflightToken:a.z.string().trim().min(16).max(240).optional()}).strict(),Ln=a.z.object({id:Dt,nodeId:Dt,source:a.z.literal("npm"),channel:Cn,fromVersion:a.z.string().trim().max(240).optional(),toVersion:a.z.string().trim().min(1).max(240),artifactRef:a.z.string().trim().min(1).max(512).optional(),runtimeArtifacts:a.z.array(kn).default([]),impact:xn,rollout:Dn,status:a.z.enum(["queued","updating-node","restarting-node","converging-instances","succeeded","degraded","failed"]),error:On.optional(),startedAt:Pt.optional(),completedAt:Pt.optional(),createdAt:Pt,updatedAt:Pt}).strict(),jn=a.z.object({channel:Cn,targetVersion:a.z.string().trim().min(1).max(240),preflightToken:a.z.string().trim().min(16).max(240)}).strict(),$n=a.z.object({type:a.z.enum(["branch","tag","commit"]),name:a.z.string().trim().min(1).max(240).optional(),commit:a.z.string().trim().max(80).optional()}).strict(),Fn=a.z.object({type:a.z.enum(["none","ssh-key","https-token"]).default("none"),secretId:a.z.string().trim().min(1).max(120).optional()}).strict(),Un=a.z.object({depth:a.z.number().int().positive().max(1e5).optional(),submodules:a.z.boolean().default(!1),lfs:a.z.boolean().default(!1),subdirectory:a.z.string().trim().max(240).default("")}).strict();a.z.object({id:Dt,name:a.z.string().trim().min(1).max(160),url:a.z.string().trim().min(1).max(2048),provider:a.z.string().trim().max(80).optional(),ref:$n.default({type:"branch",name:"main"}),auth:Fn.default({type:"none"}),clone:Un.default({submodules:!1,lfs:!1,subdirectory:""}),defaultImageSelection:Wt.optional(),labels:Mt,createdAt:Pt,updatedAt:Pt}).strict();const Vn=a.z.object({id:Dt,nodeId:Dt,name:a.z.string().trim().min(1).max(160),path:a.z.string().trim().min(1).max(4096),defaultImageSelection:Wt.optional(),labels:Mt,createdAt:Pt,updatedAt:Pt}).strict(),Hn=a.z.discriminatedUnion("type",[a.z.object({type:a.z.literal("git-repository"),repositoryId:Dt.optional(),url:a.z.string().trim().min(1).max(2048),provider:a.z.string().trim().max(80).optional(),ref:$n.default({type:"branch",name:"main"}),auth:Fn.default({type:"none"}),clone:Un.default({submodules:!1,lfs:!1,subdirectory:""})}).strict(),a.z.object({type:a.z.literal("git-template"),url:a.z.string().trim().min(1).max(2048),templateId:a.z.string().trim().min(1).max(120).optional(),ref:$n.default({type:"branch",name:"main"}),auth:Fn.default({type:"none"}),clone:Un.default({submodules:!1,lfs:!1,subdirectory:""})}).strict(),a.z.object({type:a.z.literal("local-folder"),localFolderId:Dt.optional(),path:a.z.string().trim().min(1).max(4096),ownerNodeId:Dt.optional()}).strict()]),qn=a.z.object({mode:a.z.enum(["local-bind","git-clone","empty-volume","persistent-volume"]),path:a.z.string().trim().min(1).max(4096).default("/workspace"),volumeName:a.z.string().trim().max(240).optional(),readOnly:a.z.boolean().default(!1)}).strict(),Bn=a.z.enum(["codex","claude"]),Kn=a.z.object({id:Dt,name:a.z.string().trim().min(1).max(160),source:Hn,defaultImageSelection:Wt.optional(),defaultNodeId:Dt.optional(),defaultRuntimeId:Dt.optional(),workspacePolicy:qn,labels:Mt,createdAt:Pt,updatedAt:Pt}).strict(),Gn=a.z.object({id:Dt,name:a.z.string().trim().min(1).max(160),endpoint:a.z.string().trim().min(1).max(2048),key:a.z.string().trim().min(1).max(4096),model:a.z.string().trim().min(1).max(240),app:Bn,enabled:a.z.boolean().default(!0),order:a.z.number().int().min(0).max(1e6).default(0),labels:Mt,createdAt:Pt,updatedAt:Pt}).strict(),Jn=Gn,Wn=Gn.omit({key:!0}).extend({keyPreview:a.z.string().trim().min(1).max(160),keySet:a.z.boolean()}).strict(),Yn=Wn.extend({referenceCount:a.z.number().int().min(0)}).strict(),Xn=a.z.object({instanceId:Dt,codexModelHash:Dt.optional(),claudeModelHash:Dt.optional(),updatedAt:Pt}).strict(),Qn=a.z.discriminatedUnion("type",[a.z.object({type:a.z.literal("control-plane"),name:Gn.shape.name,enabled:Gn.shape.enabled,order:Gn.shape.order}).strict(),a.z.object({type:a.z.literal("node"),nodeId:Dt,name:Gn.shape.name,enabled:Gn.shape.enabled,order:Gn.shape.order,referenceCount:a.z.number().int().min(0)}).strict()]),Zn=a.z.object({id:Dt,model:Wn,locations:a.z.array(Qn).min(1),referenceCount:a.z.number().int().min(0).default(0)}).strict(),ei=a.z.object({nodeId:Dt,code:a.z.string().trim().min(1).max(120),message:a.z.string().trim().min(1).max(2e3)}).strict();a.z.object({models:a.z.array(Zn),nodeDiagnostics:a.z.array(ei).default([]),updatedAt:Pt}).strict();const ti=Gn.omit({id:!0,createdAt:!0,updatedAt:!0}).strict(),ni=ti.partial().strict(),ii=Gn,ri=a.z.object({modelSelection:Jt,codexModelHash:Dt.optional(),claudeModelHash:Dt.optional()}).strict();function si(e){const t={app:Bn.parse(e.app),endpoint:Gn.shape.endpoint.parse(e.endpoint),key:Gn.shape.key.parse(e.key),model:Gn.shape.model.parse(e.model)};return`mdl_${d.createHash("sha256").update(JSON.stringify(t)).digest("hex")}`}const oi=a.z.enum(["market","custom"]),ai=a.z.enum(["active","deprecated","yanked"]),ci=a.z.discriminatedUnion("kind",[a.z.object({kind:a.z.literal("builtin"),key:a.z.string().trim().min(1).max(120)}).strict(),a.z.object({kind:a.z.literal("remote"),url:a.z.string().trim().url().max(2048),mediaType:a.z.enum(["image/png","image/jpeg","image/webp"]).optional(),digest:Gt.optional()}).strict()]),di=a.z.array(a.z.string().trim().min(1).max(80)).default([]),li=a.z.array(a.z.string().trim().min(1).max(120)).default([]),ui=a.z.record(a.z.string().trim().min(2).max(35),a.z.string().trim().min(1).max(4096)),mi=a.z.object({os:a.z.string().trim().min(1).max(40),architecture:a.z.string().trim().min(1).max(40),digest:Gt.optional(),downloadSizeBytes:a.z.number().int().positive().optional(),unpackedSizeBytes:a.z.number().int().positive().optional()}).strict(),pi=a.z.object({name:a.z.string().trim().min(1).max(128).regex(Ft),version:a.z.string().trim().min(1).max(160).optional(),reference:Kt,manifestDigest:Gt.optional(),publishedAt:Pt.optional(),platforms:a.z.array(mi).default([]),status:ai.default("active")}).strict(),hi=a.z.object({id:Dt,publisher:a.z.string().trim().min(1).max(160),slug:a.z.string().trim().min(1).max(160),name:a.z.string().trim().min(1).max(160),description:a.z.string().trim().min(1).max(4096),localizedDescriptions:ui.optional(),cover:ci.optional(),repository:a.z.string().trim().min(1).max(512),defaultTag:a.z.string().trim().min(1).max(128).regex(Ft),tags:a.z.array(pi).min(1),capabilities:di,optionalApps:li,defaultEnv:Lt,labels:Mt,status:ai.default("active")}).strict().superRefine((e,t)=>{e.tags.some(t=>t.name===e.defaultTag)||t.addIssue({code:"custom",path:["defaultTag"],message:"Market defaultTag must identify one of the image tags."})});a.z.object({protocolVersion:Tt,catalogId:Dt,revision:a.z.string().trim().min(1).max(240),source:a.z.enum(["embedded","remote","cache"]),generatedAt:Pt,expiresAt:Pt.optional(),items:a.z.array(hi)}).strict(),a.z.object({source:a.z.enum(["embedded","remote","cache"]),state:a.z.enum(["ready","refreshing","stale","failed"]),revision:a.z.string().trim().min(1).max(240),updatedAt:Pt,error:a.z.string().trim().max(4096).optional()}).strict(),a.z.object({id:Dt,origin:a.z.literal("custom"),name:a.z.string().trim().min(1).max(160),description:a.z.string().trim().max(4096).optional(),localizedDescriptions:ui.optional(),cover:ci.optional(),reference:Kt,repository:a.z.string().trim().min(1).max(512),tag:a.z.string().trim().min(1).max(128).regex(Ft).optional(),pullPolicy:a.z.literal("if-not-present").default("if-not-present"),capabilities:di,optionalApps:li,defaultEnv:Lt,labels:Mt,createdAt:Pt,updatedAt:Pt}).strict();const gi=a.z.object({name:a.z.string().trim().min(1).max(128).regex(Ft),version:a.z.string().trim().min(1).max(160).optional(),reference:Kt,manifestDigest:Gt.optional(),status:ai}).strict(),fi=a.z.object({id:Dt,origin:oi,name:a.z.string().trim().min(1).max(160),description:a.z.string().trim().max(4096).optional(),localizedDescriptions:ui.optional(),cover:ci,repository:a.z.string().trim().min(1).max(512),tag:a.z.string().trim().min(1).max(128).regex(Ft).optional(),availableTags:a.z.array(gi),reference:Kt,digest:Gt.optional(),downloadSizeBytes:a.z.number().int().positive().optional(),unpackedSizeBytes:a.z.number().int().positive().optional(),capabilities:di,optionalApps:li,defaultEnv:Lt,labels:Mt,readOnly:a.z.boolean(),lifecycleStatus:ai.optional(),market:a.z.object({catalogId:Dt,catalogRevision:a.z.string().trim().min(1).max(240),publisher:a.z.string().trim().min(1).max(160),version:a.z.string().trim().min(1).max(160).optional()}).strict().optional()}).strict(),yi=a.z.object({id:Dt,origin:oi,name:a.z.string().trim().min(1).max(160),description:a.z.string().trim().max(4096).optional(),localizedDescriptions:ui.optional(),cover:ci.optional(),repository:a.z.string().trim().min(1).max(512),tag:a.z.string().trim().min(1).max(128).regex(Ft).optional(),requestedReference:Kt,resolvedDigest:Gt.optional(),resolvedReference:Kt.optional(),downloadSizeBytes:a.z.number().int().positive().optional(),pullPolicy:a.z.literal("if-not-present").default("if-not-present"),capabilities:di,optionalApps:li,defaultEnv:Lt,labels:Mt,market:a.z.object({catalogId:Dt,catalogRevision:a.z.string().trim().min(1).max(240),publisher:a.z.string().trim().min(1).max(160),version:a.z.string().trim().min(1).max(160).optional()}).strict().optional(),createdAt:Pt,updatedAt:Pt}).strict(),Ii=a.z.object({phase:a.z.enum(["checking-image","pulling-image","resolving-image","ready","failed"]),requestedReference:Kt,generation:a.z.number().int().nonnegative().default(0),error:a.z.string().trim().max(4096).optional(),startedAt:Pt,updatedAt:Pt}).strict(),Ai="image.pull.terminal.output",bi="image.pull.terminal.finished",wi=a.z.object({instanceId:Dt,generation:a.z.number().int().nonnegative(),requestedReference:Kt,sequence:a.z.number().int().nonnegative(),observedAt:Pt}).strict(),vi=wi.extend({data:a.z.string().min(1).max(65536),replay:a.z.boolean().optional()}).strict(),Ei=wi.extend({outcome:a.z.enum(["succeeded","failed"])}).strict();wi.extend({status:a.z.enum(["connecting","pulling","extracting","complete","failed"]),layers:a.z.object({total:a.z.number().int().nonnegative(),completed:a.z.number().int().nonnegative(),downloaded:a.z.number().int().nonnegative(),downloading:a.z.number().int().nonnegative(),extracting:a.z.number().int().nonnegative()}).strict(),bytes:a.z.object({current:a.z.number().finite().nonnegative(),total:a.z.number().finite().positive()}).strict().optional(),percent:a.z.number().finite().min(0).max(100).optional(),message:a.z.string().trim().min(1).max(500),terminalTail:a.z.string().max(262144).optional(),terminalTruncated:a.z.boolean().optional()}).strict();const Ni=a.z.discriminatedUnion("kind",[a.z.object({kind:a.z.literal("direct")}).strict(),a.z.object({kind:a.z.literal("control-plane-proxy"),proxyId:Dt,proxyBindingId:Dt,targetNodeId:Dt}).strict()]),Si=a.z.object({reachability:a.z.enum(["unknown","reachable","unreachable"]),bindingStatus:a.z.enum(["unknown","active","revoked"]),bindingRevision:a.z.number().int().positive().optional(),streamId:a.z.string().trim().min(1).max(160).optional(),revision:a.z.number().int().nonnegative().optional(),observedAt:Pt.optional(),target:bt.optional(),lastError:gt.optional(),updatedAt:Pt}).strict(),zi=a.z.object({id:Dt,name:a.z.string().trim().min(1).max(160),connectionMode:a.z.enum(["local-ipc","local-loopback","direct-http","reverse-wss","control-plane-proxy"]).default("direct-http"),connectionPath:Ni.default({kind:"direct"}),connectionEnabled:a.z.boolean().default(!0),auth:a.z.object({mode:a.z.enum(["local-static-key","paired-hmac","proxy-binding"]).default("local-static-key"),keyId:Dt.optional(),secret:a.z.string().trim().max(4096).optional(),pairedAt:Pt.optional(),pairing:a.z.object({status:a.z.enum(["pending","paired","expired"]).default("pending"),joinToken:a.z.string().trim().max(4096).optional(),expiresAt:Pt.optional()}).strict().optional()}).strict().default({mode:"local-static-key"}),endpoint:a.z.string().trim().max(2048).optional(),controlEndpoint:a.z.string().trim().max(2048).optional(),containerEndpoint:a.z.string().trim().max(2048).optional(),publicWebBase:a.z.string().trim().max(2048).optional(),status:a.z.enum(["unknown","online","offline","degraded"]).default("unknown"),health:a.z.enum(["unknown","ok","degraded","failed"]).default("unknown"),capabilities:a.z.record(a.z.string(),a.z.unknown()).default({}),proxyState:Si.optional(),appInventory:mn.optional(),labels:Mt,lastSeenAt:Pt.optional(),createdAt:Pt,updatedAt:Pt}).strict().superRefine((e,t)=>{"control-plane-proxy"===e.connectionPath.kind&&"control-plane-proxy"!==e.connectionMode&&t.addIssue({code:"custom",path:["connectionPath"],message:"Control-plane proxy paths require control-plane-proxy connection mode."}),"control-plane-proxy"===e.connectionMode&&"control-plane-proxy"!==e.connectionPath.kind&&t.addIssue({code:"custom",path:["connectionPath"],message:"Control-plane proxy nodes require a control-plane-proxy connection path."})}),Ti=a.z.object({id:Dt,nodeId:Dt,name:a.z.string().trim().min(1).max(160),type:a.z.enum(["docker","kubernetes","local"]),status:a.z.enum(["unknown","online","offline","degraded"]).default("unknown"),accessStrategy:a.z.enum(["node-proxy","direct-port","kubernetes-ingress","kubernetes-port-forward"]).default("node-proxy"),capabilities:a.z.record(a.z.string(),a.z.unknown()).default({}),labels:Mt,createdAt:Pt,updatedAt:Pt}).strict(),_i=a.z.object({instanceId:Dt,runtimeKind:a.z.literal("docker"),state:a.z.enum(["pending","available","stopped","unavailable"]),sampledAt:Pt,cpu:a.z.object({usagePercent:a.z.number().nonnegative()}).strict().optional(),memory:a.z.object({usageBytes:a.z.number().nonnegative(),limitBytes:a.z.number().nonnegative().optional(),usagePercent:a.z.number().nonnegative().optional()}).strict().optional(),network:a.z.object({rxBytes:a.z.number().nonnegative(),txBytes:a.z.number().nonnegative()}).strict().optional(),blockIo:a.z.object({readBytes:a.z.number().nonnegative(),writeBytes:a.z.number().nonnegative()}).strict().optional(),pids:a.z.number().int().nonnegative().optional(),error:a.z.string().trim().max(2048).optional()}).strict(),Ci=a.z.object({modelEndpointProbe:a.z.boolean().optional(),aiSessionHistoryLimit:a.z.boolean().optional()}).strip();a.z.object({ok:a.z.boolean().optional(),role:a.z.string().optional(),nodeId:Dt.optional(),platform:Qt.optional(),arch:Zt.optional(),protocolVersion:Tt.optional(),capabilities:Ci.optional(),build:_n.strip().optional(),process:a.z.object({pid:a.z.number().int().positive(),startIdentity:a.z.string().trim().min(1).optional()}).strip().optional(),listener:a.z.object({host:a.z.string().trim().min(1),port:a.z.number().int().min(1).max(65535)}).strip().optional(),instanceProxy:a.z.object({requests:a.z.number().int().nonnegative(),active:a.z.number().int().nonnegative(),completed:a.z.number().int().nonnegative(),aborted:a.z.number().int().nonnegative(),limitRejected:a.z.number().int().nonnegative(),responseBytes:a.z.number().nonnegative(),totalDurationMs:a.z.number().nonnegative(),maxResponseBytes:a.z.number().int().nonnegative()}).partial().strip().optional(),serverTime:Pt.optional()}).strip();const ki=a.z.object({bindScope:a.z.enum(["loopback","all-ipv4"]),port:a.z.number().int().min(1).max(65535)}).strict(),Oi=ki.extend({host:a.z.enum(["127.0.0.1","0.0.0.0"]),status:a.z.enum(["listening","error"]),source:a.z.enum(["bootstrap","persisted"]),error:a.z.string().trim().max(2048).optional()}).strict(),Ri=ki;a.z.object({nodeId:Dt,joinToken:a.z.string().trim().min(1),expiresAt:Pt}).passthrough(),a.z.object({nodeId:Dt,keyId:Dt,secret:a.z.string().regex(/^[A-Za-z0-9_-]{32,128}$/),pairedAt:Pt}).strict();const xi=a.z.object({id:Dt,keyId:Dt,name:a.z.string().trim().min(1).max(160).optional(),pairedAt:Pt,updatedAt:Pt,current:a.z.boolean()}).passthrough();a.z.object({keyId:Dt,revoked:a.z.literal(!0),revokedAt:Pt}).strict(),a.z.object({id:Dt,pairingKeyId:Dt,url:a.z.string().trim().min(1).max(2048),name:a.z.string().trim().min(1).max(160).optional(),enabled:a.z.boolean(),createdAt:Pt,updatedAt:Pt,status:a.z.enum(["disabled","connecting","connected","reconnecting","failed"]),lastConnectedAt:Pt.optional(),lastDisconnectedAt:Pt.optional(),error:a.z.string().optional()}).passthrough(),a.z.object({pairing:xi,connection:a.z.object({id:Dt,pairingKeyId:Dt,url:a.z.string().trim().min(1).max(2048),name:a.z.string().trim().min(1).max(160).optional(),enabled:a.z.boolean(),createdAt:Pt,updatedAt:Pt}).passthrough(),tunnel:a.z.object({status:a.z.enum(["disabled","saved","connecting","connected","failed"]),error:a.z.string().trim().max(2048).optional()}).passthrough()}).passthrough(),a.z.object({deleted:a.z.boolean().optional()}).passthrough();const Di=a.z.object({repository:a.z.string().trim().optional(),tag:a.z.string().trim().optional(),id:a.z.string().trim(),createdSince:a.z.string().trim().optional(),size:a.z.string().trim().optional(),sizeBytes:a.z.number().int().nonnegative().optional(),reference:a.z.string().trim().min(1),repoDigests:a.z.array(a.z.string().trim().min(1).max(512)).default([])}).passthrough();a.z.object({image:fi,status:a.z.enum(["available","pull-required","unknown"]),localImage:Di.optional(),localSizeBytes:a.z.number().int().nonnegative().optional(),downloadSizeBytes:a.z.number().int().positive().optional(),unpackedSizeBytes:a.z.number().int().positive().optional(),error:a.z.string().trim().max(2048).optional()}).strict();const Pi=a.z.lazy(()=>a.z.object({name:a.z.string().trim().min(1),path:a.z.string().trim().min(1).max(4096),children:a.z.array(Pi)}).passthrough());a.z.object({status:a.z.number().int().min(100).max(599).optional(),headers:a.z.record(a.z.string(),a.z.string()).optional(),bodyBase64:a.z.string().optional()}).passthrough();const Mi=a.z.object({strategy:a.z.enum(["node-proxy","direct-port","kubernetes-ingress","kubernetes-port-forward"]).default("node-proxy"),web:a.z.string().trim().max(2048).optional(),api:a.z.string().trim().max(2048).optional(),vnc:a.z.string().trim().max(2048).optional(),tty:a.z.string().trim().max(2048).optional(),logs:a.z.string().trim().max(2048).optional(),status:a.z.enum(["unknown","reachable","endpoint-unreachable"]).default("unknown")}).strict(),Li=a.z.object({strategy:a.z.enum(["control-plane-proxy","direct-port","node-proxy","kubernetes-ingress","kubernetes-port-forward"]).default("control-plane-proxy"),web:a.z.string().trim().max(2048).optional(),api:a.z.string().trim().max(2048).optional(),ws:a.z.string().trim().max(2048).optional(),status:a.z.enum(["unknown","reachable","endpoint-unreachable"]).default("unknown")}).strict().default({strategy:"control-plane-proxy",status:"unknown"}),ji=a.z.object({mode:a.z.enum(["local-bind","git-clone","empty-volume","persistent-volume"]).optional(),status:a.z.enum(["unknown","pending","ready","failed"]).default("unknown"),path:a.z.string().trim().max(4096).optional(),resolvedCommit:a.z.string().trim().max(120).optional(),error:a.z.string().trim().max(2048).optional()}).passthrough(),$i=a.z.object({id:Dt,name:a.z.string().trim().min(1).max(160),projectId:Dt.optional(),source:Hn,sourceSnapshot:a.z.record(a.z.string(),a.z.unknown()).default({}),modelSelection:Jt,nodeId:Dt,runtimeId:Dt,imageSelection:Wt.optional(),environmentSource:Yt.optional(),environmentTemplateOrigin:tn.optional(),imageSnapshot:yi.optional(),imageProvisioning:Ii.optional(),stateRevision:a.z.number().int().min(0).default(0),processIncarnationId:a.z.string().trim().min(1).max(120).optional(),status:a.z.enum(["created","provisioning","starting","registering","registered","running","stopping","stopped","deleting","failed","unhealthy"]).default("created"),health:a.z.enum(["unknown","ok","degraded","failed"]).default("unknown"),connectionStatus:a.z.enum(["unknown","online","offline","endpoint-unreachable"]).default("unknown"),agentStatus:a.z.enum(["unknown","online","offline"]).default("unknown"),targetStatus:a.z.enum(["unknown","reachable","endpoint-unreachable"]).default("unknown"),uiAccessStatus:a.z.enum(["unknown","reachable","endpoint-unreachable"]).default("unknown"),controlMode:a.z.enum(["standalone","controlled"]).default("controlled"),protocolVersion:Tt.optional(),instanceVersion:a.z.string().trim().max(80).optional(),build:_n.optional(),runtimeVersion:Rn.optional(),ready:a.z.boolean().default(!1),capabilities:Rt.default(Ct),appInventory:mn.optional(),config:a.z.object({autoImportAgentConfigs:a.z.boolean().default(!0),defaultCodexPermissionMode:Ie.default("ask"),aiSessionHistoryLimit:a.z.number().int().min(1).max($e).default(50)}).strict().default({autoImportAgentConfigs:!0,defaultCodexPermissionMode:"ask",aiSessionHistoryLimit:50}),workspace:ji.default({status:"unknown"}),target:Mi.default({strategy:"direct-port",status:"unknown"}),access:Li,apps:a.z.object({runningCount:a.z.number().int().min(0).default(0),problemCount:a.z.number().int().min(0).default(0),updatedAt:Pt.optional(),revision:a.z.number().int().min(0).optional()}).strict().default({runningCount:0,problemCount:0}),aiSessions:Ve.default(()=>({runningCount:0,waitingCount:0,staleCount:0,sessions:[],updatedAt:(new Date).toISOString()})),triggers:a.z.object({enabledCount:a.z.number().int().min(0).default(0),runningCount:a.z.number().int().min(0).default(0),errorCount:a.z.number().int().min(0).default(0),configs:a.z.array(a.z.object({configHash:a.z.string().trim().min(1),config:tt,deployments:a.z.array(it).default([]),runtime:a.z.array(rt).default([])}).strict()).default([]),recentRuns:a.z.array(st).default([])}).strict().optional(),runtime:a.z.object({kind:a.z.string().trim().max(80).optional(),containerName:a.z.string().trim().max(240).optional(),containerId:a.z.string().trim().max(240).optional(),workspacePath:a.z.string().trim().max(4096).optional(),pid:a.z.number().int().positive().optional(),port:a.z.number().int().positive().max(65535).optional(),labels:a.z.record(a.z.string(),a.z.string()).default({})}).strict().default({labels:{}}),registrationToken:a.z.string().trim().min(1).max(240).optional(),lastHeartbeatAt:Pt.optional(),createdAt:Pt,updatedAt:Pt}).strict(),Fi="instance.lifecycle.snapshot",Ui=a.z.object({instanceId:$i.shape.id,revision:a.z.number().int().min(0),updatedAt:Pt,status:$i.shape.status.unwrap(),health:$i.shape.health.unwrap(),connectionStatus:$i.shape.connectionStatus.unwrap(),accessStatus:a.z.enum(["reachable","endpoint-unreachable"]),imageProvisioning:Ii.optional(),workspace:ji,runtime:$i.shape.runtime.unwrap(),runtimeVersion:Rn.optional(),ready:a.z.boolean(),lastHeartbeatAt:Pt.optional()}).strict();function Vi(e,t){return $i.safeParse(Hi(e,t))}function Hi(e,t){if(!e||"object"!=typeof e||Array.isArray(e))return e;const n=e,i=new Set(Object.keys($i.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=xt(e)}else r.capabilities=xt(void 0);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=Ki(e,["id","name","kind","source","availability","diagnosticCode"]);return!i||"object"!=typeof i||Array.isArray(i)?i:{...i,capabilities:Ki(e.capabilities,["automation","supportsCwdSelection"])}}):i.items,issues:Array.isArray(i.issues)?i.issues.map(e=>Ki(e,["code","message"])):i.issues},s=mn.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=Hn.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=Ki(i,o);if("local-folder"!==r){const e=qi($n,Ki(i.ref,["type","name","commit"]),"source.ref",t,n),r=qi(Fn,Ki(i.auth,["type","secretId"]),"source.auth",t,n),s=qi(Un,Ki(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=qi(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=qi(_n,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=qi(Ue,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:Pt.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"}),Ve.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=qi(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=Ki(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=Ki(e,t)}return s.action=Ki(r.action,["promptTemplate"]),s.policy=Ki(r.policy,["cooldownMs","maxConcurrentRuns","whenBusy"]),qi(tt,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,it,`triggers.configs.${i}.deployments`),runtime:r(s.runtime,rt,`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,st,"triggers.recentRuns")}}(n.triggers,t,"string"==typeof n.id?n.id:void 0),r.apps=qi($i.shape.apps.unwrap(),Ki(n.apps,["runningCount","problemCount","updatedAt","revision"]),"apps",t,"string"==typeof n.id?n.id:void 0)||{runningCount:0,problemCount:0},r.config=qi($i.shape.config.unwrap(),Ki(n.config,["autoImportAgentConfigs","defaultCodexPermissionMode","aiSessionHistoryLimit"]),"config",t,"string"==typeof n.id?n.id:void 0)||{autoImportAgentConfigs:!0,defaultCodexPermissionMode:"ask",aiSessionHistoryLimit:50},r.modelSelection=qi(Jt.unwrap(),Ki(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=qt(s)}catch{if(!s.includes("@")&&s.lastIndexOf(":")<=s.lastIndexOf("/"))try{s=qt(`${s}:latest`)}catch{}}try{r=s?Bt(s):void 0}catch{}return{id:t.id,origin:"custom",name:t.name,description:t.description,localizedDescriptions:t.localizedDescriptions,cover:Ki(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?Bt(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?Ki(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=Ki(n.imageSelection,["imageId","tag"]);r.imageSelection=o||(s?{imageId:s,tag:r.imageSnapshot?.tag}:void 0),r.imageProvisioning=qi(Ii,Ki(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(Rn.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(On.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=Pt.safeParse(i.lastAttemptAt),m=Pt.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=qi(ji,n.workspace,"workspace",t,"string"==typeof n.id?n.id:void 0)||{status:"unknown"},r.environmentSource=qi(Yt,n.environmentSource,"environmentSource",t,"string"==typeof n.id?n.id:void 0),r.environmentTemplateOrigin=qi(tn,n.environmentTemplateOrigin,"environmentTemplateOrigin",t,"string"==typeof n.id?n.id:void 0),r.runtime=qi($i.shape.runtime.unwrap(),n.runtime,"runtime",t,"string"==typeof n.id?n.id:void 0)||{labels:{}},r.target=qi(Mi,Ki(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=qi(Li,Ki(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($i.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 qi(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=Bi(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=Bi(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 Bi(e,t){let n=e;for(const e of t){if(!n||"object"!=typeof n)return;n=n[e]}return n}function Ki(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 Gi=a.z.object({instanceId:Dt.optional(),projectId:Dt.optional(),source:Hn.optional(),nodeId:Dt.optional(),runtimeId:Dt.optional(),imageSelection:Wt.optional(),instanceVersion:a.z.string().trim().max(80).optional(),protocolVersion:Tt,build:_n.optional(),controlMode:a.z.enum(["standalone","controlled"]).default("controlled"),capabilities:Rt.default(Ct),appInventory:mn.optional(),target:Mi.default({strategy:"direct-port",status:"unknown"}),workspace:ji.default({status:"unknown"}),registrationToken:a.z.string().trim().max(240).optional(),processIncarnationId:a.z.string().trim().min(1).max(120).optional()}).strict().superRefine((e,t)=>{zt.has(e.protocolVersion)&&!e.appInventory&&t.addIssue({code:"custom",path:["appInventory"],message:"Current protocol register payload requires appInventory."})}),Ji=a.z.object({status:$i.shape.status.optional(),health:$i.shape.health.optional(),protocolVersion:Tt,build:_n.optional(),capabilities:$i.shape.capabilities.optional(),appInventory:mn.optional(),apps:$i.shape.apps.optional(),aiSessions:$i.shape.aiSessions.optional(),triggers:$i.shape.triggers.optional(),workspace:ji.optional(),target:Mi.partial().optional(),processIncarnationId:a.z.string().trim().min(1).max(120).optional()}).strict().superRefine((e,t)=>{zt.has(e.protocolVersion)&&!e.appInventory&&t.addIssue({code:"custom",path:["appInventory"],message:"Current protocol heartbeat payload requires appInventory."})}),Wi=a.z.enum(["web","telegram","wechat","dingding","lark"]);function Yi(e,t){let n=er(t);for(let t=0;t<100;t+=1){const t=e.safeParse(n);if(t.success)return t;const i=Xi(t.error.issues);let r=!1;for(const e of i){const t=Zi(n,e.path);if(t&&"object"==typeof t&&!Array.isArray(t))for(const n of e.keys)Object.prototype.hasOwnProperty.call(t,n)&&(delete t[n],r=!0)}if(!r)return t}return e.safeParse(n)}function Xi(e,t=[]){const n=[];for(const i of e){if("unrecognized_keys"===i.code){n.push({code:"unrecognized_keys",keys:i.keys,path:[...t,...i.path]});continue}if("invalid_union"!==i.code||!Array.isArray(i.errors))continue;const e=i.errors.filter(e=>Array.isArray(e));if(!e.length)continue;const r=e.reduce((e,t)=>Qi(t)<Qi(e)?t:e);n.push(...Xi(r,[...t,...i.path]))}return n}function Qi(e){return e.reduce((e,t)=>{if("unrecognized_keys"===t.code)return e;if("invalid_union"!==t.code||!Array.isArray(t.errors))return e+1;const n=t.errors.filter(e=>Array.isArray(e));return e+(n.length?Math.min(...n.map(Qi)):1)},0)}function Zi(e,t){let n=e;for(const e of t){if(!n||"object"!=typeof n)return;n=n[e]}return n}function er(e){return Array.isArray(e)?e.map(er):e&&"object"==typeof e?Object.getPrototypeOf(e)!==Object.prototype&&null!==Object.getPrototypeOf(e)?e:Object.fromEntries(Object.entries(e).map(([e,t])=>[e,er(t)])):e}function tr(e,t,n={}){return new Promise((i,r)=>{if(n.signal?.aborted)return void r(Object.assign(new Error(`${e} was aborted.`),{code:"RUNTIME_COMMAND_ABORTED"}));const s=l.spawn(e,t,{stdio:["ignore","pipe","pipe"]}),o=[],a=[];let c=!1;const d=n.timeoutMs?setTimeout(()=>{c=!0,s.kill("SIGKILL")},n.timeoutMs):void 0;let u=!1;const m=()=>{u=!0,s.kill("SIGKILL")},p=()=>{d&&clearTimeout(d),n.signal?.removeEventListener("abort",m)};n.signal?.addEventListener("abort",m,{once:!0}),d?.unref?.(),s.stdout.on("data",e=>o.push(Buffer.from(e))),s.stderr.on("data",e=>a.push(Buffer.from(e))),s.on("error",e=>{p(),r(e)}),s.on("close",t=>{p();const s={stdout:Buffer.concat(o).toString("utf8").trim(),stderr:Buffer.concat(a).toString("utf8").trim()};if(c){const t=new Error(`${e} timed out after ${n.timeoutMs}ms`);return Object.assign(t,{statusCode:504,code:"RUNTIME_COMMAND_TIMEOUT",details:s}),void r(t)}if(u)return void r(Object.assign(new Error(`${e} was aborted.`),{code:"RUNTIME_COMMAND_ABORTED",details:s}));if(0===t)return void i(s);const d=new Error(s.stderr||`${e} exited with code ${t}`);Object.assign(d,{statusCode:502,code:"RUNTIME_EXECUTOR_FAILED",details:s}),r(d)})})}a.z.object({id:Dt,channel:Wi,name:a.z.string().trim().min(1).max(160),enabled:a.z.boolean().default(!1),token:a.z.string().trim().max(4096).optional(),defaultChatId:a.z.string().trim().max(240).optional(),allowedUserIds:a.z.array(a.z.string().trim().min(1).max(240)).default([]),pollIntervalMs:a.z.number().int().positive().max(6e4).default(3e3),settings:a.z.record(a.z.string(),a.z.unknown()).default({}),createdAt:Pt,updatedAt:Pt}).strict(),a.z.object({id:Dt,channel:Wi,bridgeId:Dt.optional(),chatSessionId:a.z.string().trim().min(1).max(240),userId:a.z.string().trim().max(240).optional(),activeProjectId:Dt.optional(),activeInstanceId:Dt.optional(),activeAiSessionId:a.z.string().trim().min(1).max(120).optional(),lastUsedAt:Pt,createdAt:Pt,updatedAt:Pt}).strict(),a.z.object({source:a.z.object({type:a.z.literal("chat-gateway").default("chat-gateway"),channel:Wi,bridgeId:Dt.optional(),chatSessionId:a.z.string().trim().min(1).max(240),userId:a.z.string().trim().max(240).optional()}).strict(),message:a.z.object({text:a.z.string().trim().max(2e4).default(""),attachments:a.z.array(he).max(6).default([])}).strict().superRefine((e,t)=>{e.attachments.reduce((e,t)=>e+("inline"===t.source.type?t.size:0),0)>G&&t.addIssue({code:a.z.ZodIssueCode.custom,path:["attachments"],message:"Inline attachments must be 41943040 bytes or less in total."})}),target:a.z.object({instanceId:Dt,aiSessionId:a.z.string().trim().min(1).max(120)}).strict().optional()}).strict(),a.z.object({id:Dt,instanceId:Dt,projectId:Dt.optional(),aiSessionId:a.z.string().trim().min(1).max(120),providerSessionId:a.z.string().trim().max(240).optional(),result:a.z.string().default(""),timeoutMs:a.z.number().positive().optional(),source:a.z.string().trim().max(120).optional(),kind:a.z.enum(["task","approval"]).default("task"),status:a.z.enum(["pending","unreachable"]).default("pending"),error:a.z.string().trim().max(2048).optional(),lastSeenAt:Pt}).strict();const nr=(e,t,n={})=>new Promise((i,r)=>{if(n.signal?.aborted)return void r(Object.assign(new Error(`${e} was aborted.`),{code:"RUNTIME_COMMAND_ABORTED"}));const s=[];let o,a=!1,c=!1;try{o=u.spawn(e,t,{name:"xterm-256color",cols:n.cols||120,rows:n.rows||40,cwd:process.cwd(),env:process.env})}catch(e){return void r(e)}const d=n.timeoutMs?setTimeout(()=>{a=!0,o.kill("SIGKILL")},n.timeoutMs):void 0,l=()=>{c=!0;try{o.kill("SIGKILL")}catch{}};n.signal?.addEventListener("abort",l,{once:!0}),d?.unref?.(),o.onData(e=>{s.push(e),n.onData?.(e)}),o.onExit(({exitCode:t})=>{d&&clearTimeout(d),n.signal?.removeEventListener("abort",l);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})):c?r(Object.assign(new Error(`${e} was aborted.`),{code:"RUNTIME_COMMAND_ABORTED",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 ir{inFlight=new Map;runCommand;runTerminalCommand;constructor(e=tr,t){this.runCommand=e,this.runTerminalCommand=t||function(e){return e===tr?nr:async(t,n,i={})=>{const r=await e(t,n,{timeoutMs:i.timeoutMs,signal:i.signal});return r.stdout&&i.onData?.(r.stdout),r.stderr&&i.onData?.(r.stderr),r}}(e)}ensure(e,t,n,i){const r=qt(e),s=this.inFlight.get(r);if(s)return t&&(s.phaseListeners.add(t),s.phase&&t(s.phase)),n&&(s.terminalListeners.add(n),s.terminalTail&&n({sequence:s.terminalSequence,data:s.terminalTail,replay:!0})),this.bindAbort(s,i),s.promise;const o=new Set,a=new Set;t&&o.add(t),n&&a.add(n);const c={promise:Promise.resolve(void 0),controller:new AbortController,abortDisposers:new Set,phaseListeners:o,terminalListeners:a,terminalSequence:0,terminalTail:""};return this.bindAbort(c,i),c.promise=this.ensureOnce(r,e=>{c.phase=e,o.forEach(t=>t(e))},e=>{c.terminalSequence+=1,c.terminalTail=`${c.terminalTail}${e}`.slice(-262144);const t={sequence:c.terminalSequence,data:e};a.forEach(e=>e(t))},c.controller.signal).finally(()=>{this.inFlight.delete(r);for(const e of c.abortDisposers)e();c.abortDisposers.clear()}),this.inFlight.set(r,c),c.promise}bindAbort(e,t){if(!t)return;if(t.aborted)return void e.controller.abort();const n=()=>e.controller.abort();t.addEventListener("abort",n,{once:!0}),e.abortDisposers.add(()=>t.removeEventListener("abort",n))}async ensureOnce(e,t,n,i){t("checking-image");let r=await this.inspect(e,i).catch(e=>{if(i.aborted)throw e}),s=!1;r||(t("pulling-image"),await this.runTerminalCommand("docker",["pull",e],{cols:120,rows:40,signal:i,onData:n}),s=!0,r=await this.inspect(e,i)),t("resolving-image");const o=(a=r,Array.isArray(a.RepoDigests)?a.RepoDigests.filter(e=>"string"==typeof e):[]).find(e=>/@sha256:[a-fA-F0-9]{64}$/.test(e));var a;const c=o?.split("@").at(-1)?.toLowerCase();return{requestedReference:e,...c?{resolvedDigest:c}:{},resolvedReference:o||e,pulled:s}}async inspect(e,t){const n=await this.runCommand("docker",["image","inspect",e,"--format","{{json .}}"],{signal:t});return JSON.parse(n.stdout.trim()||"{}")}}function rr(e){if(!e)return;const t=/^([0-9]+(?:\.[0-9]+)?)\s*(B|kB|MB|GB|TB)$/i.exec(e.trim());if(!t)return;const n=Number(t[1])*{b:1,kb:1e3,mb:1e6,gb:1e9,tb:1e12}[t[2].toLowerCase()];return Number.isSafeInteger(Math.round(n))?Math.round(n):void 0}const sr="/run/task-handoff/bootstrap",or=`${sr}/entrypoint.sh`,ar="/bin/bash",cr=`${sr}/runtime-installer.mjs`,dr="/opt/task-handoff/instance-runtime";function lr(e,t){return{role:"runtime",name:`${Tr(e)}-runtime`,mountPath:dr,labels:{"task-handoff.owner":"task-handoff","task-handoff.instance-id":e,"task-handoff.node-id":t,"task-handoff.volume-role":"runtime"}}}function ur(e){return function(e,t,n){const i=Tr(e);return[{role:"data",suffix:"data",mountPath:"/data"},{role:"agent-home",suffix:"agent-home",mountPath:"/home/agent"},..."local-folder"===n.type?[]:[{role:"workspace",suffix:"workspace",mountPath:"/workspace"}]].map(({role:n,suffix:r,mountPath:s})=>({role:n,name:`${i}-${r}`,mountPath:s,labels:{"task-handoff.owner":"task-handoff","task-handoff.instance-id":e,"task-handoff.node-id":t,"task-handoff.volume-role":n}}))}(e.instance.id,e.node?.id||"node_unset",e.project.source)}const mr=new Set(["TASK_HANDOFF_REGISTRATION_TOKEN","OPENAI_API_KEY","OPENAI_BASE_URL","CODEX_MODEL","TASK_HANDOFF_CODEX_BASE_URL","TASK_HANDOFF_CODEX_MODEL","TASK_HANDOFF_CODEX_MODEL_ID","ANTHROPIC_API_KEY","ANTHROPIC_BASE_URL","CLAUDE_MODEL","TASK_HANDOFF_CLAUDE_MODEL","TASK_HANDOFF_CLAUDE_MODEL_ID"]);function pr(e,t=[]){const n=e&&"object"==typeof e&&!Array.isArray(e)?e:{},i=n.Config&&"object"==typeof n.Config&&!Array.isArray(n.Config)?n.Config:n,r=new Set;for(const e of Array.isArray(i.Env)?i.Env:[]){if("string"!=typeof e)continue;const n=e.indexOf("="),i=-1===n?e:e.slice(0,n),s=-1===n?"":e.slice(n+1);mr.has(i)&&r.add(`Config.Env.${i}`),t.some(e=>e&&s.includes(e))&&r.add(`Config.Env.${i||"unknown"}`)}if(i.Labels&&"object"==typeof i.Labels&&!Array.isArray(i.Labels))for(const[e,n]of Object.entries(i.Labels))(mr.has(e)||"string"==typeof n&&t.some(e=>e&&n.includes(e)))&&r.add(`Config.Labels.${e}`);if(r.size)throw Object.assign(new Error(`Docker configuration contains instance-private values in ${[...r].sort().join(", ")}.`),{statusCode:409,code:"ENVIRONMENT_TEMPLATE_SECRET_IN_DOCKER_CONFIG",findings:[...r].sort()})}class hr{runCommand;publishHost;images;launcherAssetsDir;portResolutionRetryDelaysMs;constructor(e=tr,t={}){this.runCommand=e,this.images=t.imageService||new ir(e),this.publishHost=t.publishHost||"127.0.0.1",this.launcherAssetsDir=t.launcherAssetsDir||br(),this.portResolutionRetryDelaysMs=t.portResolutionRetryDelaysMs?.length?t.portResolutionRetryDelaysMs:[0,100,250,500,1e3]}async start(e){kr(e);const t=e.instance.runtime.containerName||Tr(e.instance.id),i=await this.inspectContainerForStart(t);if(i){Sr(t,i.id,e.instance.runtime.containerId,"before start","RUNTIME_EXECUTOR_FAILED");const r=i.labels["task-handoff.instance-id"];if(r!==e.instance.id)throw vr("RUNTIME_EXECUTOR_FAILED",`Docker container ${t} belongs to ${r||"an unknown instance"}, not ${e.instance.id}.`);const s=i.mounts.find(e=>"bind"===e.type&&e.destination===sr);if("1"!==i.labels["task-handoff.bootstrap-abi"]||i.entrypoint[0]!==ar||i.command[0]!==or||!s?.source||n.resolve(s.source)!==n.resolve(this.launcherAssetsDir)){const n=new Set(ur(e).flatMap(e=>i.mounts.some(t=>"volume"===t.type&&t.name===e.name&&t.destination===e.mountPath)?[e.name]:[]));return await this.createPersistentVolumes(e,n),this.recreateWithAuthoritativeBootstrap(e,t,i)}await this.createRuntimeVolume(e),await this.validatePersistentVolumes(e,i.mounts);try{await this.runCommand("docker",["start",t])}catch(e){throw vr("RUNTIME_EXECUTOR_FAILED",`Could not start Docker container ${t}.`,e)}return this.resumedContainerResult(e,t,i.id)}if(e.instance.environmentTemplateOrigin){const t=await this.inspectEnvironmentTemplateImage(e.instance.environmentTemplateOrigin.imageId);if(t.imageId!==e.instance.environmentTemplateOrigin.imageId||t.platform!==e.instance.environmentTemplateOrigin.platform||t.architecture!==e.instance.environmentTemplateOrigin.architecture)throw Object.assign(new Error(`Environment template image identity or platform changed for instance ${e.instance.id}.`),{statusCode:409,code:"ENVIRONMENT_TEMPLATE_IMAGE_IDENTITY_MISMATCH"})}else await this.images.ensure(e.image.resolvedReference||e.image.requestedReference);let r;await this.createPersistentVolumes(e);try{r=await this.runCommand("docker",Cr(e,t,{publishHost:this.publishHost,launcherAssetsDir:this.launcherAssetsDir}))}catch(e){throw vr("RUNTIME_EXECUTOR_FAILED",`Could not create Docker container ${t}.`,e)}return this.bootstrapResult(e,t,r.stdout||void 0)}async recreateWithAuthoritativeBootstrap(e,t,n){const i=`${t}-pre-bootstrap-${n.id.slice(0,12)}`;n.running&&await this.runCommand("docker",["stop",t]);try{await this.runCommand("docker",["rename",t,i])}catch(e){throw n.running&&await this.runCommand("docker",["start",t]).catch(()=>({stdout:"",stderr:""})),vr("RUNTIME_EXECUTOR_FAILED",`Could not preserve Docker container ${t} before bootstrap migration.`,e)}try{const r=await this.runCommand("docker",Cr(e,t,{publishHost:this.publishHost,launcherAssetsDir:this.launcherAssetsDir,imageReference:n.image}));return this.bootstrapResult(e,t,r.stdout||void 0,i)}catch(e){throw await this.runCommand("docker",["rm","-f",t]).catch(()=>({stdout:"",stderr:""})),await this.runCommand("docker",["rename",i,t]).catch(()=>({stdout:"",stderr:""})),n.running&&await this.runCommand("docker",["start",t]).catch(()=>({stdout:"",stderr:""})),vr("RUNTIME_EXECUTOR_FAILED",`Could not recreate Docker container ${t} with the node-agent bootstrap.`,e)}}async inspectContainerConfigSecurity(e,t){pr(await this.runCommand("docker",["inspect","--format","{{json .}}",e]).then(e=>JSON.parse(e.stdout||"{}")).catch(t=>{throw vr("ENVIRONMENT_TEMPLATE_CONTAINER_INSPECT_FAILED",`Could not inspect Docker container ${e}.`,t)}),t)}async inspectImageConfigSecurity(e,t){pr(await this.runCommand("docker",["image","inspect","--format","{{json .}}",e]).then(e=>JSON.parse(e.stdout||"{}")).catch(e=>{throw vr("ENVIRONMENT_TEMPLATE_IMAGE_INSPECT_FAILED","Could not inspect Docker image configuration.",e)}),t)}async commitEnvironmentTemplate(e,t,n){const i=await this.inspectContainerId(e);if(!i)throw vr("ENVIRONMENT_TEMPLATE_CONTAINER_NOT_FOUND",`Docker container ${e} does not exist.`);Sr(e,i,t,"before environment template commit","ENVIRONMENT_TEMPLATE_CONTAINER_IDENTITY_MISMATCH");try{const t=(await this.runCommand("docker",["commit",e,n])).stdout.trim();if(!t)throw new Error("Docker commit did not return an image id.");return t}catch(t){throw vr("ENVIRONMENT_TEMPLATE_COMMIT_FAILED",`Could not save Docker container ${e} as an environment template.`,t)}}async inspectEnvironmentTemplateImage(e){try{const t=await this.runCommand("docker",["image","inspect","--format","{{json .}}",e]),n=JSON.parse(t.stdout||"{}"),i="string"==typeof n.Id?n.Id:"",r=Ir(n.Os),s=Ar(n.Architecture),o="number"==typeof n.Size?n.Size:Number.NaN;if(!/^sha256:[a-f0-9]{64}$/.test(i)||!r||!s||!Number.isSafeInteger(o)||o<0)throw new Error("Docker image inspection did not return a valid immutable identity.");return{imageId:i,platform:r,architecture:s,sizeBytes:o}}catch(e){throw vr("ENVIRONMENT_TEMPLATE_IMAGE_INSPECT_FAILED","Could not inspect the committed environment template image.",e)}}async untagEnvironmentTemplate(e,t){try{const n=t||(await this.inspectEnvironmentTemplateImage(e)).imageId;return await this.runCommand("docker",["tag",n,wr(n)]),await this.runCommand("docker",["image","rm",e]),n}catch(e){const t=Er(e)?.toLowerCase()||"";if(t.includes("no such image")||t.includes("no such object"))return;throw vr("ENVIRONMENT_TEMPLATE_UNTAG_FAILED","Could not remove the environment template tag.",e)}}async garbageCollectEnvironmentTemplateImage(e){try{try{await this.runCommand("docker",["image","rm",wr(e)])}catch(e){const t=Er(e)?.toLowerCase()||"";if(t.includes("being used by")||t.includes("is referenced")||t.includes("conflict"))return!1;if(!t.includes("no such image")&&!t.includes("no such object"))throw e}return await this.runCommand("docker",["image","rm",e]),!0}catch(e){const t=Er(e)?.toLowerCase()||"";if(t.includes("being used by")||t.includes("is referenced")||t.includes("conflict"))return!1;if(t.includes("no such image")||t.includes("no such object"))return!0;throw vr("ENVIRONMENT_TEMPLATE_GC_FAILED","Could not garbage collect the environment template image.",e)}}async createPersistentVolumes(e,t=new Set){const n=lr(e.instance.id,e.node?.id||"node_unset");for(const i of[...ur(e),n])await this.createVolume(i),await this.validateOwnedVolume(e.instance.id,i,t.has(i.name))}async createRuntimeVolume(e){await this.createVolume(lr(e.instance.id,e.node?.id||"node_unset"))}async createVolume(e){const t=["volume","create"];for(const[n,i]of Object.entries(e.labels).sort(([e],[t])=>e.localeCompare(t)))t.push("--label",`${n}=${i}`);t.push(e.name);try{await this.runCommand("docker",t)}catch(t){throw vr("INSTANCE_VOLUME_CREATE_FAILED",`Could not create managed volume ${e.name}.`,t)}}async validatePersistentVolumes(e,t){for(const n of ur(e)){await this.validateOwnedVolume(e.instance.id,n);const i=t.find(e=>"volume"===e.type&&e.destination===n.mountPath);if(!i||i.name!==n.name)throw Object.assign(new Error(`Docker container mount for ${n.role} does not match managed volume ${n.name}.`),{statusCode:409,code:"INSTANCE_VOLUME_MOUNT_IDENTITY_MISMATCH"})}const i=lr(e.instance.id,e.node?.id||"node_unset");await this.validateOwnedVolume(e.instance.id,i);const r=t.find(e=>"volume"===e.type&&e.destination===i.mountPath);if(!r||r.name!==i.name)throw Object.assign(new Error(`Docker container runtime mount does not match ${i.name}.`),{statusCode:409,code:"INSTANCE_VOLUME_MOUNT_IDENTITY_MISMATCH"});if("local-folder"===e.project.source.type){const i=t.find(t=>t.destination===(e.project.workspacePolicy.path||"/workspace"));if(!i||"bind"!==i.type||n.resolve(i.source||"")!==n.resolve(e.project.source.path))throw Object.assign(new Error(`Docker container workspace bind does not match local folder ${e.project.source.path}.`),{statusCode:409,code:"INSTANCE_WORKSPACE_MOUNT_IDENTITY_MISMATCH"})}}async validateOwnedVolume(e,t,n=!1){let i;try{i=await this.runCommand("docker",["volume","inspect","--format","{{json .}}",t.name])}catch(e){throw vr("INSTANCE_VOLUME_INSPECT_FAILED",`Could not inspect managed volume ${t.name}.`,e)}try{const r=JSON.parse(i.stdout||"{}"),s=r.Labels&&"object"==typeof r.Labels&&!Array.isArray(r.Labels)?r.Labels:{},o=r.Name===t.name&&"task-handoff"===s["task-handoff.owner"]&&s["task-handoff.instance-id"]===e&&s["task-handoff.volume-role"]===t.role,a=n&&r.Name===t.name&&0===Object.keys(s).length;if(!o&&!a)throw new Error("volume name or ownership labels do not match")}catch(n){throw Object.assign(new Error(`Managed volume ${t.name} identity does not match instance ${e}.`,{cause:n}),{statusCode:409,code:"INSTANCE_VOLUME_IDENTITY_MISMATCH"})}}async runningResult(e,t,n){const i=await this.publishedEndpoint(t),r=e.node?.id||"node_unset",s=e.runtime?.id||"runtime_local_docker";return{status:"registering",health:"unknown",connectionStatus:"online",agentStatus:"unknown",targetStatus:"unknown",uiAccessStatus:"unknown",target:{strategy:"direct-port",status:"reachable",...i},workspace:{mode:e.project.workspacePolicy.mode,status:"pending",path:e.project.workspacePolicy.path},runtime:{...e.instance.runtime,kind:"docker",containerName:t,...n?{containerId:n}:{},labels:{...e.instance.runtime.labels,"task-handoff.instance-id":e.instance.id,"task-handoff.project-id":e.project.id,"task-handoff.node-id":r,"task-handoff.runtime-id":s,"task-handoff.image-id":e.image.id}}}}async resumedContainerResult(e,t,n){const i=this.bootstrapResult(e,t,n);return{...i,target:{...i.target,...await this.publishedEndpoint(t)}}}async publishedEndpoint(e){const t=`http://127.0.0.1:${await this.containerPort(e,"8080/tcp")}`;return{web:t,api:`${t}/api`}}bootstrapResult(e,t,n,i){return{status:"starting",health:"unknown",connectionStatus:"unknown",agentStatus:"unknown",targetStatus:"unknown",uiAccessStatus:"unknown",target:{strategy:"direct-port",status:"unknown"},workspace:{mode:e.project.workspacePolicy.mode,status:"pending",path:e.project.workspacePolicy.path},runtime:{...e.instance.runtime,kind:"docker",containerName:t,...n?{containerId:n}:{},labels:{...e.instance.runtime.labels,"task-handoff.bootstrap-abi":"1",...i?{"task-handoff.bootstrap-backup":i}:{}}}}}async stop(e){const t=e.instance.runtime.containerName||Tr(e.instance.id);try{await this.runCommand("docker",["stop",t])}catch(e){if(!Nr(e))throw vr("RUNTIME_EXECUTOR_FAILED",`Could not stop Docker container ${t}.`,e)}return{status:"stopped",health:"unknown",connectionStatus:"offline",target:{...e.instance.target,status:"unknown"},runtime:e.instance.runtime}}async restart(e,t){kr(e);const n=e.instance.runtime.containerName||Tr(e.instance.id),i=await this.inspectContainerId(n);if(!i)throw vr("INSTANCE_RUNTIME_RESTART_FAILED",`Docker container ${n} does not exist.`);Sr(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 vr("INSTANCE_RUNTIME_RESTART_FAILED",`Docker container identity changed while restarting ${n}.`);return Sr(n,r,t,"after restart","INSTANCE_RUNTIME_RESTART_FAILED"),this.runningResult(e,n,r)}async delete(e,t){const n=e.instance.runtime.containerName||Tr(e.instance.id),i=await this.inspectContainerForStart(n),r=new Set;if(i){Sr(n,i.id,e.instance.runtime.containerId,"before delete","RUNTIME_EXECUTOR_FAILED");const t=i.labels["task-handoff.instance-id"];if(t!==e.instance.id)throw vr("RUNTIME_EXECUTOR_FAILED",`Docker container ${n} belongs to ${t||"an unknown instance"}, not ${e.instance.id}.`);for(const t of ur(e))i.mounts.some(e=>"volume"===e.type&&e.name===t.name&&e.destination===t.mountPath)&&r.add(t.name);try{await this.runCommand("docker",["rm","-f",i.id])}catch(e){if(!Nr(e))throw vr("RUNTIME_EXECUTOR_FAILED",`Could not delete Docker container ${n}.`,e)}}const s=[];for(const n of ur(e))if(t.deleteVolumes)try{const t=await this.inspectVolumeForDelete(n.name);if(!t){s.push({role:n.role,name:n.name,mountPath:n.mountPath,status:"missing"});continue}const i=t.name===n.name&&"task-handoff"===t.labels["task-handoff.owner"]&&t.labels["task-handoff.instance-id"]===e.instance.id&&t.labels["task-handoff.volume-role"]===n.role,o=r.has(n.name)&&t.name===n.name&&0===Object.keys(t.labels).length;if(!i&&!o)throw Object.assign(new Error(`Managed volume ${n.name} ownership does not match instance ${e.instance.id}.`),{code:"INSTANCE_VOLUME_IDENTITY_MISMATCH"});await this.runCommand("docker",["volume","rm",n.name]),s.push({role:n.role,name:n.name,mountPath:n.mountPath,status:"deleted"})}catch(e){s.push({role:n.role,name:n.name,mountPath:n.mountPath,status:"failed",error:{code:"object"==typeof e&&e&&"code"in e&&"string"==typeof e.code?e.code:"INSTANCE_VOLUME_DELETE_FAILED",message:e instanceof Error?e.message:String(e)}})}else s.push({role:n.role,name:n.name,mountPath:n.mountPath,status:"retained"});return await this.deleteRuntimeVolume(e),on.parse({instanceId:e.instance.id,containerDeleted:!0,completed:s.every(e=>"failed"!==e.status),deletedVolumes:s.filter(e=>"deleted"===e.status||"missing"===e.status),retainedVolumes:s.filter(e=>"retained"===e.status),volumeResults:s})}async deleteRuntimeVolume(e){const t=lr(e.instance.id,e.node?.id||"node_unset"),n=await this.inspectVolumeForDelete(t.name);if(n){if(n.name!==t.name||"task-handoff"!==n.labels["task-handoff.owner"]||n.labels["task-handoff.instance-id"]!==e.instance.id||"runtime"!==n.labels["task-handoff.volume-role"])throw vr("INSTANCE_VOLUME_IDENTITY_MISMATCH",`Runtime volume ${t.name} ownership does not match instance ${e.instance.id}.`);try{await this.runCommand("docker",["volume","rm",t.name])}catch(e){throw vr("INSTANCE_VOLUME_DELETE_FAILED",`Could not delete runtime volume ${t.name}.`,e)}}}async inspectVolumeForDelete(e){try{const t=await this.runCommand("docker",["volume","inspect","--format","{{json .}}",e]),n=JSON.parse(t.stdout||"{}");return{name:"string"==typeof n.Name?n.Name:"",labels:n.Labels&&"object"==typeof n.Labels&&!Array.isArray(n.Labels)?Object.fromEntries(Object.entries(n.Labels).filter(e=>"string"==typeof e[1])):{}}}catch(t){if(function(e){const t=Er(e)?.toLowerCase()||"";return t.includes("no such volume")||t.includes("no such object")}(t))return;throw vr("INSTANCE_VOLUME_INSPECT_FAILED",`Could not inspect managed volume ${e}.`,t)}}async installRuntime(e){const t=await this.installRuntimeRelease(e);Sr(e.containerName,t,e.expectedContainerId,"before runtime restart","INSTANCE_RUNTIME_RESTART_FAILED");try{await this.runCommand("docker",["restart",t])}catch(t){throw vr("INSTANCE_RUNTIME_RESTART_FAILED",`Could not restart Docker container ${e.containerName}.`,t)}const n=await this.inspectContainerId(e.containerName);if(!n||n!==t)throw vr("INSTANCE_RUNTIME_RESTART_FAILED",`Docker container identity changed while updating ${e.containerName}.`);return Sr(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 vr("INSTANCE_RUNTIME_INSTALL_FAILED",`Docker container ${e.containerName} does not exist.`);Sr(e.containerName,t,e.expectedContainerId,"before runtime install","INSTANCE_RUNTIME_INSTALL_FAILED");const n=`/opt/task-handoff/instance-runtime/incoming/task-handoff-runtime-${i=e.identity.version,i.replace(/[^0-9A-Za-z.+_-]/g,"-")}-${e.identity.sha256.slice(0,12)}.tar.gz`;var i;await this.runCommand("docker",["exec","--user","0",t,"install","-d","-o","root","-g","root","-m","0755","/opt/task-handoff/instance-runtime/incoming"]),await this.runCommand("docker",["cp",e.artifactPath,`${t}:${n}`]);try{await this.runCommand("docker",["exec","--user","0",t,"node",cr,"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 vr("INSTANCE_RUNTIME_INSTALL_FAILED",`Could not install controlled-instance ${e.identity.version} in ${e.containerName}.`,t)}finally{await this.runCommand("docker",["exec","--user","0",t,"rm","-f",n]).catch(()=>({stdout:"",stderr:""}))}const r=await this.inspectContainerId(e.containerName);if(!r||r!==t)throw vr("INSTANCE_RUNTIME_INSTALL_FAILED",`Docker container identity changed while installing ${e.containerName}.`);return Sr(e.containerName,r,e.expectedContainerId,"after runtime install","INSTANCE_RUNTIME_INSTALL_FAILED"),t}async inspectRuntimeVersion(e){const t=await this.inspectContainerId(e);if(!t)return{};const n=await this.runCommand("docker",["exec","--user","agent",e,"node",cr,"verify-active"]).catch(()=>{});if(!n?.stdout)return{containerId:t};try{const e=Yi(kn,JSON.parse(n.stdout));return e.success?{containerId:t,...e.data}:{containerId:t}}catch{return{containerId:t}}}async removeBootstrapBackup(e,t){const n=await this.inspectContainerForStart(e);if(n){if(n.labels["task-handoff.instance-id"]!==t)throw vr("RUNTIME_EXECUTOR_FAILED",`Docker bootstrap backup ${e} does not belong to ${t}.`);await this.runCommand("docker",["rm","-f",e])}}async inspectRuntimeTarget(e){let t,n;if(e){const i=await this.runCommand("docker",["inspect","--format","{{json .}}",e]).then(e=>JSON.parse(e.stdout.trim()||"{}")).catch(()=>{});if(t=i?.Platform,"string"==typeof i?.Image&&i.Image){const e=await this.runCommand("docker",["image","inspect","--format","{{json .}}",i.Image]).then(e=>JSON.parse(e.stdout.trim()||"{}")).catch(()=>{});t=e?.Os||t,n=e?.Architecture}}if(!t||!n){const e=await this.runCommand("docker",["info","--format","{{json .}}"]).then(e=>JSON.parse(e.stdout.trim()||"{}")).catch(e=>{throw vr("INSTANCE_BASE_RUNTIME_INCOMPATIBLE","Could not inspect the Docker runtime target.",e)});t||=e.OSType,n||=e.Architecture}const i=Ir(t),r=Ar(n);if(!i||!r)throw vr("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Docker reported an unsupported runtime target ${String(t||"unknown")}/${String(n||"unknown")}.`);return{platform:i,arch:r,launcherAbi:1}}async installRuntimeReleaseWithRecovery(e){const t=e.containerName,i=await this.inspectContainerForStart(t);if(!i)throw vr("INSTANCE_RUNTIME_INSTALL_FAILED",`Docker container ${t} does not exist.`);if(Sr(t,i.id,e.expectedContainerId,"before runtime install recovery","INSTANCE_RUNTIME_INSTALL_FAILED"),i.running)return await this.installRuntimeLauncher(t,i.id),void await this.installRuntimeRelease({...e,expectedContainerId:i.id});if(!i.image)throw vr("INSTANCE_RUNTIME_INSTALL_FAILED",`Docker container ${t} does not expose its immutable image identity.`);const r="/run/task-handoff/runtime-rescue-artifact.tar.gz",s=[`test -r ${or}`,`test -r ${sr}/instance-launcher.sh`,`test -r ${cr}`,`install -d -o root -g root -m 0755 ${dr} ${dr}/releases ${dr}/staging ${dr}/incoming`,`chown -R root:root ${dr}`,`chmod -R go-w ${dr}`,`node ${cr} install --artifact "$1" --version "$2" --sha256 "$3" --platform "$4" --arch "$5" --launcher-abi "$6"`].join("; ");try{await this.runCommand("docker",["run","--rm","--user","0:0","--volumes-from",i.id,"--mount",`type=bind,source=${n.resolve(e.artifactPath)},target=${r},readonly`,"--entrypoint",ar,i.image,"-ceu",s,"task-handoff-runtime-rescue",r,e.identity.version,e.identity.sha256,e.identity.platform,e.identity.arch,String(e.identity.launcherAbi)])}catch(n){throw vr("INSTANCE_RUNTIME_INSTALL_FAILED",`Could not rescue controlled-instance ${e.identity.version} in stopped container ${t}.`,n)}const o=await this.inspectContainerForStart(t);if(!o)throw vr("INSTANCE_RUNTIME_INSTALL_FAILED",`Docker container ${t} disappeared during runtime install recovery.`);if(Sr(t,o.id,i.id,"after runtime install recovery","INSTANCE_RUNTIME_INSTALL_FAILED"),o.running)throw vr("INSTANCE_RUNTIME_INSTALL_FAILED",`Stopped Docker container ${t} changed lifecycle state during runtime install recovery.`)}async installRuntimeLauncher(e,t){const n=await this.inspectContainerId(e);if(!n)throw vr("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Docker container ${e} does not exist.`);Sr(e,n,t,"before runtime launcher install","INSTANCE_BASE_RUNTIME_INCOMPATIBLE");try{await this.runCommand("docker",["exec","--user","0",n,"bash","-ceu",`test -r ${or}; test -r ${sr}/instance-launcher.sh; test -r ${cr}; install -d -o root -g root -m 0755 /opt/task-handoff/instance-runtime /opt/task-handoff/instance-runtime/releases /opt/task-handoff/instance-runtime/staging /opt/task-handoff/instance-runtime/incoming; chown -R root:root /opt/task-handoff/instance-runtime; chmod -R go-w /opt/task-handoff/instance-runtime`])}catch(t){throw vr("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Could not install the runtime launcher in ${e}.`,t)}const i=await this.inspectContainerId(e);if(i!==n)throw vr("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Docker container identity changed while installing the runtime launcher in ${e}.`);Sr(e,i,t,"after runtime launcher install","INSTANCE_BASE_RUNTIME_INCOMPATIBLE")}async inspectContainerId(e){try{return(await this.runCommand("docker",["inspect","--format","{{.Id}}",e])).stdout.trim()||void 0}catch(t){if(Nr(t))return;throw vr("RUNTIME_EXECUTOR_FAILED",`Could not inspect Docker container ${e}.`,t)}}async inspectContainerForStart(e){let t;try{t=await this.runCommand("docker",["inspect","--format","{{json .}}",e])}catch(t){if(Nr(t))return;throw vr("RUNTIME_EXECUTOR_FAILED",`Could not inspect Docker container ${e}.`,t)}try{const e=JSON.parse(t.stdout||"{}");if("string"!=typeof e.Id||!e.Id)throw new Error("Docker inspect did not return a container id.");const n=e.Config?.Labels&&"object"==typeof e.Config.Labels&&!Array.isArray(e.Config.Labels)?Object.fromEntries(Object.entries(e.Config.Labels).filter(e=>"string"==typeof e[1])):{},i=Array.isArray(e.Mounts)?e.Mounts.flatMap(e=>{if(!e||"object"!=typeof e||Array.isArray(e))return[];const t=e,n="volume"===t.Type||"bind"===t.Type?t.Type:void 0,i="string"==typeof t.Destination?t.Destination:void 0;return n&&i?[{type:n,destination:i,name:"string"==typeof t.Name?t.Name:void 0,source:"string"==typeof t.Source?t.Source:void 0}]:[]}):[],r=Array.isArray(e.Config?.Entrypoint)?e.Config.Entrypoint.filter(e=>"string"==typeof e):"string"==typeof e.Config?.Entrypoint?[e.Config.Entrypoint]:[],s=Array.isArray(e.Config?.Cmd)?e.Config.Cmd.filter(e=>"string"==typeof e):"string"==typeof e.Config?.Cmd?[e.Config.Cmd]:[];return{id:e.Id,image:"string"==typeof e.Image?e.Image:void 0,running:!0===e.State?.Running,entrypoint:r,command:s,labels:n,mounts:i}}catch(t){throw vr("RUNTIME_EXECUTOR_FAILED",`Docker returned invalid inspection data for ${e}.`,t)}}async containerPort(e,t){let n,i=!1;for(const r of this.portResolutionRetryDelaysMs){r>0&&await yr(r);try{const n=gr((await this.runCommand("docker",["port",e,t])).stdout);if(n)return n}catch(e){n=e}try{const n=fr((await this.runCommand("docker",["inspect","--format","{{json .NetworkSettings.Ports}}",e])).stdout,t);if(i=!0,n)return n}catch(e){n=e}}if(i)throw vr("RUNTIME_EXECUTOR_FAILED",`Docker container ${e} does not publish ${t}.`);throw vr("RUNTIME_EXECUTOR_FAILED",`Could not resolve the published port for Docker container ${e}.`,n)}}function gr(e){const t=e.split(/\r?\n/).find(Boolean);return t?.match(/:(\d+)$/)?.[1]}function fr(e,t){const n=JSON.parse(e||"null");if(!n||"object"!=typeof n||Array.isArray(n))return;const i=n[t];if(Array.isArray(i))for(const e of i){if(!e||"object"!=typeof e||Array.isArray(e))continue;const t=e.HostPort;if("string"==typeof t&&/^\d+$/.test(t))return t}}function yr(e){return new Promise(t=>setTimeout(t,e))}function Ir(e){return"linux"===e||"darwin"===e?e:"windows"===e||"win32"===e?"win32":void 0}function Ar(e){return"amd64"===e||"x86_64"===e||"x64"===e?"x64":"arm64"===e||"aarch64"===e?"arm64":void 0}function br(){const e=("undefined"==typeof document?require("url").pathToFileURL(__filename).href:b&&"SCRIPT"===b.tagName.toUpperCase()&&b.src||new URL("cli.js",document.baseURI).href)?n.dirname(r.fileURLToPath("undefined"==typeof document?require("url").pathToFileURL(__filename).href:b&&"SCRIPT"===b.tagName.toUpperCase()&&b.src||new URL("cli.js",document.baseURI).href)):__dirname,i=[n.resolve(e,"../../../../../docker"),n.resolve(e,"../docker"),n.resolve(e,"../../docker")];return i.find(e=>t.existsSync(n.join(e,"runtime-installer.mjs")))||i[0]}function wr(e){return`task-handoff/environment-image:${e.replace(/^sha256:/,"")}`}function vr(e,t,n){const i=Er(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 Er(e){if(!e||"object"!=typeof e)return void 0===e?void 0:String(e);const t=e,n=t.details?.stderr||t.details?.stdout;return"string"==typeof n&&n.trim()?n.trim():"string"==typeof t.message&&t.message.trim()?t.message.trim():void 0}function Nr(e){const t=Er(e)?.toLowerCase()||"";return t.includes("no such container")||t.includes("no such object")}function Sr(e,t,n,i,r){if(n&&t!==n)throw vr(r,`Docker container ${e} identity mismatch ${i}: expected ${n}, got ${t}.`)}async function zr(e=tr){return async function(e=tr){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:rr(t.Size),reference:s,repoDigests:o}}).filter(e=>Boolean(e.reference))}(e)}function Tr(e){return`task-handoff-${e.replace(/[^a-zA-Z0-9_.-]/g,"-")}`}function _r(e,t,n){e.push("-e",`${t}=${n}`)}function Cr(e,t,i={}){const r=i.publishHost||"127.0.0.1",s=n.resolve(i.launcherAssetsDir||br()),o=e.node?.id||"node_unset",a=e.runtime?.id||"runtime_local_docker",c=["run","-d","--name",t,"--user","0:0","--label",`task-handoff.instance-id=${e.instance.id}`,"--label",`task-handoff.project-id=${e.project.id}`,"--label",`task-handoff.node-id=${o}`,"--label",`task-handoff.runtime-id=${a}`,"--label",`task-handoff.image-id=${e.image.id}`,"--label","task-handoff.bootstrap-abi=1","--shm-size","1gb","--security-opt","seccomp=unconfined","--network","bridge","--no-healthcheck","--add-host","host.docker.internal:host-gateway","--tmpfs","/tmp:rw,mode=1777","-p",`${r}::8080`];if(!e.privateConfigPath)throw Object.assign(new Error(`Instance ${e.instance.id} private config was not materialized.`),{statusCode:409,code:"INSTANCE_PRIVATE_CONFIG_MISSING"});c.push("--mount",`type=bind,src=${e.privateConfigPath},dst=/run/task-handoff/instance-private-config.json,readonly`,"--mount",`type=bind,src=${s},dst=${sr},readonly`,"--entrypoint",ar);for(const t of ur(e))c.push("--mount",`type=volume,src=${t.name},dst=${t.mountPath}`);const d=lr(e.instance.id,e.node?.id||"node_unset");c.push("--mount",`type=volume,src=${d.name},dst=${d.mountPath}`);const l={TASK_HANDOFF_CONTROL_MODE:"controlled",TASK_HANDOFF_NODE_AGENT_URL:e.nodeAgentUrl||e.node?.endpoint||"",TASK_HANDOFF_INSTANCE_ID:e.instance.id,TASK_HANDOFF_INSTANCE_NAME:e.instance.name,TASK_HANDOFF_PROJECT_ID:e.project.id,TASK_HANDOFF_NODE_ID:o,TASK_HANDOFF_RUNTIME_ID:a,TASK_HANDOFF_IMAGE_ID:e.image.id,TASK_HANDOFF_INSTANCE_LAUNCHER:`${sr}/instance-launcher.sh`,...e.image.tag?{TASK_HANDOFF_IMAGE_TAG:e.image.tag}:{},TASK_HANDOFF_CHAT_BRIDGES:"none",TASK_HANDOFF_WORKSPACE:e.project.workspacePolicy.path||"/workspace",TASK_HANDOFF_WORKSPACE_MODE:e.project.workspacePolicy.mode};for(const[e,t]of Object.entries(l))_r(c,e,t);"local-folder"===e.project.source.type?c.push("-v",`${e.project.source.path}:${e.project.workspacePolicy.path||"/workspace"}:${e.project.workspacePolicy.readOnly?"ro":"rw"}`):(_r(c,"TASK_HANDOFF_PROJECT_SOURCE",JSON.stringify(e.project.source)),_r(c,"TASK_HANDOFF_WORKSPACE_POLICY",JSON.stringify(e.project.workspacePolicy)),_r(c,"TASK_HANDOFF_GIT_URL",e.project.source.url),e.project.source.ref?.commit?_r(c,"TASK_HANDOFF_GIT_COMMIT",e.project.source.ref.commit):e.project.source.ref?.name&&_r(c,"TASK_HANDOFF_GIT_REF",e.project.source.ref.name),e.project.source.clone?.depth&&_r(c,"TASK_HANDOFF_GIT_DEPTH",String(e.project.source.clone.depth)),_r(c,"TASK_HANDOFF_GIT_SUBMODULES",e.project.source.clone?.submodules?"true":"false"),_r(c,"TASK_HANDOFF_GIT_LFS",e.project.source.clone?.lfs?"true":"false"),e.project.source.clone?.subdirectory&&_r(c,"TASK_HANDOFF_WORKSPACE_SUBDIRECTORY",e.project.source.clone.subdirectory));for(const[t,n]of Object.entries(e.image.defaultEnv))_r(c,t,n);return c.push(i.imageReference||e.instance.environmentTemplateOrigin?.imageId||e.image.resolvedReference||e.image.requestedReference,or,"task-handoff","web"),c}function kr(e){if("local-folder"===e.project.source.type&&e.project.source.ownerNodeId&&e.project.source.ownerNodeId!==e.node.id){const e=new Error("Local folder projects can only start on the node that owns the folder.");throw Object.assign(e,{statusCode:400,code:"LOCAL_FOLDER_REQUIRES_OWNER_NODE"}),e}if(!e.image.requestedReference?.trim()){const e=new Error("Image profile must reference a registered image.");throw Object.assign(e,{statusCode:400,code:"IMAGE_PROFILE_INVALID"}),e}}a.z.object({type:a.z.literal("snapshot"),data:a.z.string(),pendingEscape:a.z.string(),cols:a.z.number().int().positive(),rows:a.z.number().int().positive()}).passthrough();const Or=a.z.enum(["created","starting","running","stopping","stopped","exited","failed","closed","terminated","unknown"]),Rr=a.z.enum(["tty","vnc","web"]);a.z.object({mode:Rr,url:a.z.string().trim().min(1).max(4096),token:a.z.string().trim().min(1).max(512),expiresAt:a.z.string().datetime()}).strict(),a.z.object({revoked:a.z.boolean()}).strict();const xr=a.z.object({type:a.z.enum(["app-session","provider-session","adapter-key"]),id:a.z.string().trim().min(1).max(240),agent:a.z.string().trim().min(1).max(80).optional(),adapter:a.z.string().trim().min(1).max(80).optional(),key:a.z.string().trim().min(1).max(240).optional()}).strict(),Dr=a.z.record(a.z.string(),a.z.unknown()).and(a.z.object({id:a.z.string().trim().min(1).max(160),appId:a.z.string().trim().min(1).max(160).optional(),title:a.z.string().trim().max(240).optional(),kind:a.z.string().trim().max(80).optional(),status:Or.default("unknown"),bindings:a.z.array(xr).max(40).default([]),workspace:a.z.object({cwd:a.z.string().trim().max(4096).optional()}).strict().optional(),createdAt:a.z.string().datetime().optional(),updatedAt:a.z.string().datetime().optional()})),Pr=a.z.object({runningCount:a.z.number().int().min(0).default(0),problemCount:a.z.number().int().min(0).default(0),sessions:a.z.array(Dr).default([]),updatedAt:a.z.string().datetime()}).strict();a.z.object({streamId:a.z.string().trim().min(1).max(240),revision:a.z.number().int().min(0),lastEventAt:a.z.string().datetime(),snapshot:Pr}).strict(),Pr.pick({runningCount:!0,problemCount:!0,updatedAt:!0}).extend({revision:a.z.number().int().min(0).optional()});const Mr=a.z.enum(["app-session-created","app-session-updated","app-session-deleted","app-session-recovered","control-action","heartbeat-sync","startup"]),Lr=a.z.object({streamId:a.z.string().trim().min(1).max(240),instanceId:a.z.string().trim().min(1).max(160),nodeId:a.z.string().trim().min(1).max(160).optional(),revision:a.z.number().int().min(0),previousRevision:a.z.number().int().min(0).optional(),traceId:a.z.string().trim().min(1).max(160),generatedAt:a.z.string().datetime(),reason:Mr}).strict(),jr=a.z.object({meta:Lr,snapshot:Pr}).strict(),$r=a.z.object({meta:Lr,session:Dr}).strict(),Fr=a.z.object({meta:Lr,sessionId:a.z.string().trim().min(1).max(160),tombstone:Dr.optional(),expiresAt:a.z.string().datetime().optional()}).strict();function Ur(e){return e.startsWith("ai-session.")||e.startsWith("ai.session.")?"ai.sessions":e.startsWith("app-session.")?"app.sessions":e.startsWith("app.management")?"apps":e.startsWith("trigger.")?"triggers":e.startsWith("instance.")?"instances":e.startsWith("node.")?"nodes":e.startsWith("project.")?"projects":e.startsWith("model.")?"models":e.startsWith("image.")?"images":e.startsWith("market.")?"market":"system"}a.z.object({streamId:a.z.string().trim().min(1).max(240),instanceId:a.z.string().trim().min(1).max(160),sinceRevision:a.z.number().int().min(0),latestRevision:a.z.number().int().min(0),earliestRetainedRevision:a.z.number().int().min(0),syncRequired:a.z.boolean().default(!1),events:a.z.array(a.z.discriminatedUnion("type",[a.z.object({type:a.z.literal("app-session.snapshot"),payload:jr}).strict(),a.z.object({type:a.z.literal("app-session.patch"),payload:$r}).strict(),a.z.object({type:a.z.literal("app-session.removed"),payload:Fr}).strict()])).default([])}).strict();const Vr=a.z.enum(["ai.sessions","app.sessions"]),Hr=a.z.object({topic:Vr,instanceId:a.z.string().trim().min(1).max(160),streamId:a.z.string().trim().min(1).max(240),latestRevision:a.z.number().int().min(0),earliestRetainedRevision:a.z.number().int().min(0)}).strict(),qr=a.z.object({protocolVersion:a.z.literal(1),streams:a.z.array(Hr)}).strict();class Br{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 Kr(e,t=6e4){const n=[];for(let i=0;i<e.length;i+=t)n.push(e.slice(i,i+t));return n}class Gr{sockets=new Map;socketUrls=new Map;retries=new Map;outputs=new Set;imagePullTerminalByInstance=new Map;state;token;logger;safetyIntervalMs;lastAiSessionEventByInstance=new Map;lastAppSessionEventByInstance=new Map;timer;reconnectAttempts=0;safetyReconciliations=0;localSequence=0;createSocket;setIntervalFn;clearIntervalFn;constructor(e,t,n={}){var i;this.state=e,this.token=t,this.logger=n.logger,this.safetyIntervalMs=(i=n.safetyIntervalMs,Math.min(6e4,Math.max(3e4,i??45e3))),this.createSocket=n.createSocket||((e,t)=>new m(e,t)),this.setIntervalFn=n.setIntervalFn||setInterval,this.clearIntervalFn=n.clearIntervalFn||clearInterval}start(){this.sync(),this.timer=this.setIntervalFn(()=>{this.safetyReconciliations+=1,this.sync()},this.safetyIntervalMs)}stop(){this.timer&&(this.clearIntervalFn(this.timer),this.timer=void 0);for(const e of this.sockets.values())e.close();this.sockets.clear(),this.socketUrls.clear();for(const e of this.retries.values())e.timer.cancel();this.retries.clear(),this.outputs.clear()}addOutput(e){this.outputs.add(e),e.on("close",()=>this.outputs.delete(e)),e.on("error",()=>this.outputs.delete(e));for(const t of this.state.listInstances()){const n=Jr(t);n?this.sendForwarded(e,this.createEvent(Fi,n,{instanceId:t.id})):this.logger?.warn?.({instanceId:t.id},"instance.lifecycle.snapshot.invalid")}for(const[t,n]of this.imagePullTerminalByInstance)Kr(n.tail).forEach((i,r)=>this.sendForwarded(e,this.createEvent(Ai,{...n.output,sequence:n.output.sequence+r,data:i,...0===r?{replay:!0}:{}},{instanceId:t}))),n.finished&&this.sendForwarded(e,this.createEvent(bi,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===Ai){const e=Yi(vi,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===bi){const e=Yi(Ei,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(Fi,function(e){return Ui.parse(Wr(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:Ur(e),createdAt:(new Date).toISOString(),payload:t,scope:n}}sendForwarded(e,t){const n=JSON.stringify({type:"node-agent.event.forwarded",event:t});e.readyState===m.OPEN&&e.send(n)}syncNow(){this.sync()}diagnostics(){return{reconnectAttempts:this.reconnectAttempts,safetyReconciliations:this.safetyReconciliations,activeConnections:this.sockets.size,pendingRetries:[...this.retries.values()].filter(e=>e.timer.pending).length,safetyIntervalMs:this.safetyIntervalMs}}sync(){const e=new Set(this.state.listInstances().map(e=>e.id));for(const t of this.imagePullTerminalByInstance.keys())e.has(t)||this.imagePullTerminalByInstance.delete(t);if(!this.outputs.size){for(const e of this.sockets.values())e.close();this.sockets.clear(),this.socketUrls.clear();for(const e of this.retries.values())e.timer.cancel();return void this.retries.clear()}const t=new Set;for(const e of this.state.listInstances()){const n=Xr(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 Br,url:t}),i.readyState===m.OPEN&&(i.send(JSON.stringify({v:1,type:"subscribe",topics:[J,"app.sessions","apps","instances"]})),this.logger?.info?.({instanceId:e,url:t},"ai-session.event.forward.connect"),this.logger?.info?.({instanceId:e,url:t},"app-session.event.forward.connect"))}),i.on("message",t=>{const n=function(e,t){try{const n=JSON.parse(String(e));if(!n||"object"!=typeof n||Array.isArray(n))return;const i=n,r="string"==typeof i.type?i.type:"";if(!r||"events.connected"===r)return;const 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:Ur(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(qr,n.payload);if(!t.success)return this.logger?.warn?.({instanceId:e,issues:t.error.issues},"session-stream.handshake.invalid"),void i.close(1002,"Incompatible session stream handshake.");const r=JSON.stringify({type:"node-agent.streams.hello",instanceId:e,payload:t.data});for(const e of this.outputs)e.readyState===m.OPEN&&e.send(r);return}this.recordAiSessionEvent(e,n),this.recordAppSessionEvent(e,n);const r=JSON.stringify({type:"node-agent.event.forwarded",event:n});for(const e of this.outputs)e.readyState===m.OPEN&&e.send(r)}),i.on("close",()=>{this.sockets.get(e)===i&&(this.sockets.delete(e),this.socketUrls.delete(e),this.scheduleReconnect(e))}),i.on("error",()=>{this.logger?.warn?.({instanceId:e,url:t},"ai-session.event.forward.error"),this.logger?.warn?.({instanceId:e,url:t},"app-session.event.forward.error"),i.close()})}scheduleReconnect(e){const t=this.state.listInstances().find(t=>t.id===e),n=t&&Xr(t);if(!n||!this.outputs.size)return;const i=this.retries.get(e)??{timer:new Br};if(i.timer.pending)return;i.url=n;const r=i.timer.schedule(()=>{this.sockets.has(e)||this.connect(e,n)});r&&(this.reconnectAttempts+=1,this.logger?.info?.({instanceId:e,url:n,attempt:r.attempt,delay:r.delay,reconnectAttempts:this.reconnectAttempts},"session-stream.connection.reconnect-scheduled")),this.retries.set(e,i)}recordAiSessionEvent(e,t){if(t.topic!==J)return;if("ai-session.message-delta"===t.type)return;const n=Yr(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=Yr(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 Jr(e){const t=Ui.safeParse(Wr(e));return t.success?t.data:void 0}function Wr(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 Yr(e){const t=e&&"object"==typeof e&&!Array.isArray(e)?e:{},n=t.meta&&"object"==typeof t.meta&&!Array.isArray(t.meta)?t.meta:{};return{streamId:"string"==typeof n.streamId?n.streamId:void 0,revision:"number"==typeof n.revision?n.revision:void 0,traceId:"string"==typeof n.traceId?n.traceId:void 0}}function Xr(e){if(!function(e){return!1!==e.ready&&(!e.runtimeVersion||["matched","failed"].includes(e.runtimeVersion.phase))}(e))return;const t=e.target?.api||e.target?.web;if(t)try{const e=new URL("/api/events",t);return e.protocol="https:"===e.protocol?"wss:":"ws:",e.toString()}catch{return}}const Qr=new Set(["provisioning","starting","registering","registered","running","unhealthy"]),Zr=JSON.stringify({id:"{{.ID}}",name:"{{.Name}}",cpu:"{{.CPUPerc}}",memory:"{{.MemUsage}}",memoryPercent:"{{.MemPerc}}",network:"{{.NetIO}}",blockIo:"{{.BlockIO}}",pids:"{{.PIDs}}"});class es{snapshots=new Map;runCommand;targets;publish;intervalMs;timer;inFlight;pendingTargets=new Map;collectingTargets=new Map;constructor(e,t,n,i=3e3){this.runCommand=e,this.targets=t,this.publish=n,this.intervalMs=i}start(){this.collect().catch(()=>{}),this.timer=setInterval(()=>{this.collect().catch(()=>{})},this.intervalMs)}stop(){this.timer&&clearInterval(this.timer),this.timer=void 0}async snapshot(e){const t=this.targets().find(t=>t.id===e);if(!t)return;if(!Qr.has(t.status))return os(t.id);const n=this.snapshots.get(e);return n&&Date.now()-Date.parse(n.sampledAt)<=this.intervalMs?n:(await this.collect([t]),this.snapshots.get(e))}async collect(e){const t=e||this.targets();if(!e){const e=new Set(t.map(e=>e.id));for(const t of this.snapshots.keys())e.has(t)||this.snapshots.delete(t)}for(const e of t){const t=ts(e);this.collectingTargets.get(e.id)!==t&&this.pendingTargets.set(e.id,e)}this.inFlight||(this.inFlight=this.drain().finally(()=>{this.inFlight=void 0})),await this.inFlight}async drain(){for(;this.pendingTargets.size;){const e=[...this.pendingTargets.values()];this.pendingTargets.clear();for(const t of e)this.collectingTargets.set(t.id,ts(t));try{await this.collectOnce(e)}finally{for(const t of e)this.collectingTargets.delete(t.id)}}}async collectOnce(e){const t=e.filter(e=>Qr.has(e.status)&&(e.runtime.containerId||e.runtime.containerName));for(const t of e.filter(e=>Qr.has(e.status)&&!e.runtime.containerId&&!e.runtime.containerName))this.update(as(t.id));for(const t of e.filter(e=>!Qr.has(e.status)))this.update(os(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",Zr,...n],{timeoutMs:5e3});this.applyDockerOutput(t,e.stdout,i)}catch(e){if(1===t.length)return void this.update(cs(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",Zr,t],{timeoutMs:5e3});this.applyDockerOutput([e],n.stdout,i)}catch(t){this.update(cs(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=ss(e.id),s=ss(e.name),o=r||s;if(!o)continue;const a=ns(ss(e.memory)),c=ns(ss(e.network)),d=ns(ss(e.blockIo)),l=_i.parse({instanceId:o,runtimeKind:"docker",state:"available",sampledAt:t,cpu:is(e.cpu,"usagePercent"),memory:a?{usageBytes:a[0],...void 0!==a[1]?{limitBytes:a[1]}:{},...is(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:rs(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}:cs(t.id,n,"Container metrics were not returned by Docker."))}}update(e){const t=_i.parse(e);this.snapshots.set(t.instanceId,t),this.publish?.(t)}}function ts(e){return[e.status,e.runtime.containerId||"",e.runtime.containerName||""].join("\0")}function ns(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 is(e,t){const n=Number(ss(e).replace(/%$/,""));return Number.isFinite(n)&&n>=0?{[t]:n}:void 0}function rs(e){const t=Number(ss(e));return Number.isFinite(t)&&t>=0?t:void 0}function ss(e){return"string"==typeof e||"number"==typeof e?String(e).trim():""}function os(e){return{instanceId:e,runtimeKind:"docker",state:"stopped",sampledAt:(new Date).toISOString()}}function as(e){return{instanceId:e,runtimeKind:"docker",state:"pending",sampledAt:(new Date).toISOString()}}function cs(e,t,n){return{instanceId:e,runtimeKind:"docker",state:"unavailable",sampledAt:t,error:n.slice(0,2048)}}function ds(e){try{return t.statSync(e).isDirectory()}catch{return!1}}function ls(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()&&ds(n.join(s,e.name))).sort((e,t)=>e.name.localeCompare(t.name)).slice(0,80).flatMap(e=>{const t=ls(n.join(s,e.name),i-1);return t?[t]:[]}):[];return{name:o,path:s,children:c}}function us(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(ds)}()).flatMap(t=>{const n=ls(t,e.depth);return n?[n]:[]})}function ms(){return process.env.TASK_HANDOFF_NODE_AGENT_DATA_DIR||n.join(c.homedir(),".config","task-handoff","node-agent")}function ps(e=ms()){const t=n.resolve(e);return{dataDir:t,identityPath:n.join(t,"identity.json"),settingsPath:n.join(t,"runtime-settings.json"),localFoldersDir:n.join(t,"local-folders"),nodeRuntimesDir:n.join(t,"node-runtimes"),controlledInstancesDir:n.join(t,"controlled-instances"),environmentTemplatesDir:n.join(t,"environment-templates"),instancePrivateConfigsDir:n.join(t,"instance-private-configs"),nodeModelsDir:n.join(t,"models"),modelAssignmentsDir:n.join(t,"model-assignments"),modelEnvironmentsDir:n.join(t,"model-environments"),updatesDir:n.join(t,"updates"),logsDir:n.join(t,"logs")}}function hs(e,t){const i=n.extname(e);return`${i?e.slice(0,-i.length):e}.${t}${i}`}function gs(e,n=10485760,i=2){if(!t.existsSync(e))return!1;const r=t.lstatSync(e);if(!r.isFile()||r.isSymbolicLink()||r.size<=n)return!1;if(i>0){!function(e,n){if(!(n<=0)){t.rmSync(hs(e,n),{force:!0});for(let i=n-1;i>=1;i-=1){const n=hs(e,i);t.existsSync(n)&&t.renameSync(n,hs(e,i+1))}}}(e,i);const r=function(e,n){const i=t.statSync(e),r=Math.min(i.size,n),s=Buffer.allocUnsafe(r),o=t.openSync(e,"r");let a=0;try{for(;a<r;){const e=t.readSync(o,s,a,r-a,i.size-r+a);if(0===e)break;a+=e}}finally{t.closeSync(o)}return a===r?s:s.subarray(0,a)}(e,n);t.writeFileSync(hs(e,1),r,{mode:384})}return t.truncateSync(e,0),t.chmodSync(e,384),!0}class fs{localInstancesRoot;localInstancesTrashRoot;options;constructor(e,t={}){this.options=t,this.localInstancesRoot=n.join(e.dataDir,"local-instances"),this.localInstancesTrashRoot=n.join(e.dataDir,"local-instances-trash")}run(e){const n=new Set(e);if(t.existsSync(this.localInstancesRoot)){K(this.localInstancesRoot);for(const e of t.readdirSync(this.localInstancesRoot,{withFileTypes:!0}))e.isDirectory()&&!e.isSymbolicLink()&&(n.has(e.name)?this.capControlledInstanceLogs(e.name):this.retire(e.name))}return function(e){if(!t.existsSync(e.trashRoot))return[];const n=e.nowMs??Date.now(),i=e.retentionMs??q,r=[];for(const s of t.readdirSync(e.trashRoot,{withFileTypes:!0})){const o=B(e.trashRoot,s.name);try{const e=Number(s.name.split("-",1)[0]);if(!Number.isFinite(e)||e+i>n)continue;const a=t.lstatSync(o);a.isSymbolicLink()?t.unlinkSync(o):a.isDirectory()?t.rmSync(o,{recursive:!0,force:!0}):t.unlinkSync(o),r.push(o)}catch(t){e.logger?.("retired persistence entry cleanup failed",{path:o,error:t instanceof Error?t.message:String(t)})}}return r}({trashRoot:this.localInstancesTrashRoot,retentionMs:this.options.retentionMs??q,nowMs:this.now(),logger:this.options.logger})}capActiveInstanceLogs(e){for(const t of e)this.capControlledInstanceLogs(t)}capControlledInstanceLogs(e){const t=n.resolve(this.localInstancesRoot,e);if(n.dirname(t)!==n.resolve(this.localInstancesRoot))return[];const i=n.join(t,"logs"),r=[];for(const t of["controlled-instance.out.log","controlled-instance.err.log"]){const s=n.join(i,t);try{gs(s)&&r.push(s)}catch(t){this.options.logger?.("controlled instance log rotation failed",{instanceId:e,filePath:s,error:t instanceof Error?t.message:String(t)})}}return r}retire(e){try{return function(e){const n=B(e.sourceRoot,e.entryName);if(!t.existsSync(n))return;const i=t.lstatSync(n);if(!i.isDirectory()||i.isSymbolicLink())throw new Error(`Retention source must be a real directory: ${n}`);K(e.trashRoot);const r=e.nowMs??Date.now();let s=0,o=`${r}-${e.entryName}`;for(;t.existsSync(B(e.trashRoot,o));)s+=1,o=`${r}-${s}-${e.entryName}`;const a=B(e.trashRoot,o);return t.renameSync(n,a),a}({sourceRoot:this.localInstancesRoot,entryName:e,trashRoot:this.localInstancesTrashRoot,nowMs:this.now()})}catch(t){return void this.options.logger?.("local instance persistence retirement failed",{instanceId:e,error:t instanceof Error?t.message:String(t)})}}now(){return this.options.now?.()??Date.now()}}function ys(e,t=process.platform){const i=n.resolve(e),r=d.createHash("sha256").update(i).digest("hex").slice(0,16);return"win32"===t?`\\\\.\\pipe\\task-handoff-node-agent-${r}`:n.join("/tmp",`task-handoff-node-agent-${process.getuid?.()??"user"}`,`${r}.sock`)}const Is="runtime-manifest.json";class As 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 bs(e,t=""){const i=[],r=await g.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===Is)continue;const o=n.join(e,...r.split("/"));if(s.isDirectory()){i.push(...await bs(e,r));continue}if(s.isSymbolicLink()){const t=await g.readlink(o);if(n.isAbsolute(t))throw new As("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 As("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload symlink escapes the artifact: ${r}`);if(!await g.lstat(s).catch(()=>{}))throw new As("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 As("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload contains unsupported entry: ${r}`);const a=await g.lstat(o);i.push({absolutePath:o,relativePath:r,kind:"file",size:a.size})}return i}async function ws(e){const n=(await bs(e)).sort((e,t)=>function(e,t){return Buffer.compare(Buffer.from(e,"utf8"),Buffer.from(t,"utf8"))}(e.relativePath,t.relativePath)),i=d.createHash("sha256");for(const e of n){if(i.update("file"===e.kind?"F":"L","ascii"),i.update(Buffer.from(e.relativePath,"utf8")),i.update(Buffer.from([0])),i.update(Buffer.from(String(e.size),"ascii")),i.update(Buffer.from([0])),"file"===e.kind)for await(const n of t.createReadStream(e.absolutePath))i.update(n);else i.update(Buffer.from(e.target,"utf8"));i.update(Buffer.from([0]))}return i.digest("hex")}function vs(e){for(const[t,n]of[["version",e.version],["platform",e.platform],["arch",e.arch]])if(!/^[0-9A-Za-z._-]+$/.test(n))throw new As("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Invalid runtime artifact ${t}: ${n}`);return`${e.version}-${e.platform}-${e.arch}`}function Es(e,t){return`${vs(e)}-${e.sha256}-${t}`}async function Ns(e){const n=d.createHash("sha256");for await(const i of t.createReadStream(e))n.update(i);return n.digest("hex")}class Ss{#e;#t;#n=new Map;constructor(e){this.#e=e.cacheDir,this.#t=e.fetchImpl??fetch}resolve(e,t){const n=kn.parse(e);if(!/^[a-f0-9]{64}$/.test(t.archiveSha256))throw new As("INSTANCE_RUNTIME_ARTIFACT_INVALID","Runtime archive SHA-256 is invalid.");if((t.archiveUrl?1:0)+(t.archivePath?1:0)!=1)throw new As("INSTANCE_RUNTIME_ARTIFACT_INVALID","Runtime artifact source must specify exactly one archive location.");const i=Es(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,i){if(!/^[a-f0-9]{64}$/.test(i.archiveSha256))throw new As("INSTANCE_RUNTIME_ARTIFACT_INVALID","Runtime archive SHA-256 is invalid.");const r=Es(e,i.archiveSha256),s=n.join(this.#e,"archives"),o=n.join(s,`${r}.tar.gz`);if(await g.mkdir(s,{recursive:!0}),await this.#r(o,e,i.archiveSha256))return{identity:e,archivePath:o,cacheHit:!0};await g.rm(o,{force:!0});const a=n.join(s,`.${r}.${d.randomUUID()}.part`);try{const n=await g.open(a,"wx");if(i.archivePath)await f.pipeline(t.createReadStream(i.archivePath),n.createWriteStream());else{const e=await this.#t(i.archiveUrl);if(!e.ok||!e.body)throw await n.close(),new As("INSTANCE_RUNTIME_ARTIFACT_UNAVAILABLE",`Runtime artifact download failed with HTTP ${e.status}.`,{retryable:e.status>=500});await f.pipeline(e.body,n.createWriteStream())}if(await Ns(a)!==i.archiveSha256)throw new As("INSTANCE_RUNTIME_ARTIFACT_INVALID","Downloaded runtime archive SHA-256 does not match release metadata.");return await this.#s(a,e),await g.rename(a,o),{identity:e,archivePath:o,cacheHit:!1}}catch(e){if(e instanceof As)throw e;throw new As("INSTANCE_RUNTIME_ARTIFACT_UNAVAILABLE","Could not download runtime artifact.",{cause:e,retryable:!0})}finally{await g.rm(a,{force:!0})}}async#r(e,t,n){try{return await Ns(e)===n&&(await this.#s(e,t),!0)}catch{return!1}}async#s(e,t){const i=n.join(this.#e,"validation",`${vs(t)}-${d.randomUUID()}`);try{await async function(e,t){await g.mkdir(t,{recursive:!0});try{await y.extract({file:e,cwd:t,strict:!0,preservePaths:!1,filter:(e,t)=>{const i=n.posix.normalize(e.replace(/^\.\//,""));if(!i||".."===i||i.startsWith("../")||n.posix.isAbsolute(i))throw new As("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 As("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime archive contains unsupported entry type ${r??"unknown"}: ${e}`);return!0}})}catch(e){throw new As("INSTANCE_RUNTIME_ARTIFACT_INVALID","Could not extract runtime artifact safely.",{cause:e})}}(e,i),await async function(e,t,i){const r=await async function(e){let t;try{t=JSON.parse(await g.readFile(n.join(e,Is),"utf8"))}catch(e){throw new As("INSTANCE_RUNTIME_ARTIFACT_INVALID","Runtime artifact manifest is missing or invalid JSON.",{cause:e})}const i=Yi(kn,t);if(!i.success)throw new As("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 As("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 As("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Unsupported runtime artifact format ${r.formatVersion}.`);if(i?.platform&&"universal"!==r.platform&&r.platform!==i.platform)throw new As("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 As("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 As("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 As("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 As("INSTANCE_RUNTIME_ARTIFACT_INVALID",`${t} escapes the runtime root.`);return i}(r.entrypoint,"Runtime entrypoint"),o=await g.lstat(n.join(e,...s.split("/"))).catch(()=>{});if(!o?.isFile())throw new As("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime entrypoint is missing: ${s}`);const a=await ws(e);if(a!==r.sha256)throw new As("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload SHA-256 mismatch: expected ${r.sha256}, got ${a}.`);return r}(i,t,{platform:t.platform,arch:t.arch})}finally{await g.rm(i,{recursive:!0,force:!0})}}}async function zs(e,t,i,r=fetch){if("linux"!==t||!["x64","arm64"].includes(i))throw new As("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([g.readFile(n.join(i,`${t}.manifest.json`),"utf8"),g.readFile(n.join(i,`${t}.tar.gz.sha256`),"utf8")]),o=Yi(kn,JSON.parse(r));if(!o.success||o.data.version!==e||"linux"!==o.data.platform||"universal"!==o.data.arch)throw new As("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 As("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 As)throw t;throw new As("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 As("INSTANCE_RUNTIME_ARTIFACT_UNAVAILABLE",`Could not read release metadata for controlled-instance ${e}.`,{cause:t,retryable:!0})});if(!u.ok||!m.ok)throw new As("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 As("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Release manifest for controlled-instance ${e} is not valid JSON.`,{cause:t})}const h=Yi(kn,p);if(!h.success)throw new As("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Release manifest for controlled-instance ${e} is invalid: ${h.error.message}`);if(h.data.version!==e||"linux"!==h.data.platform||"universal"!==h.data.arch)throw new As("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Release identity mismatch: requested ${e}-linux-universal, received ${h.data.version}-${h.data.platform}-${h.data.arch}.`);const f=(await m.text()).trim().split(/\s+/)[0]?.toLowerCase();if(!f||!/^[a-f0-9]{64}$/.test(f))throw new As("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Release checksum for controlled-instance ${e} is invalid.`);return{identity:h.data,source:{archiveUrl:d,archiveSha256:f}}}class Ts{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=Ps(i.retryBaseDelayMs??1e3,"retryBaseDelayMs"),this.retryMaxDelayMs=Ps(i.retryMaxDelayMs??3e4,"retryMaxDelayMs")}schedule(e,t={}){const n=this.requests.get(e)||{startRequested:!1,resumeCancelled:!1};n.startRequested||=!0===t.startRequested,n.resumeCancelled||=!0===t.resumeCancelled||!0===t.startRequested,n.resumeCancelled&&this.cancelled.delete(e),this.requests.set(e,n);const i=this.inFlight.get(e);if(i)return i;const r=Promise.resolve().then(()=>this.reconcile(e,n)).finally(()=>{this.inFlight.delete(e),this.requests.delete(e)});return this.inFlight.set(e,r),r}isRunning(e){return this.inFlight.has(e)}cancel(e){return this.cancelled.add(e),this.inFlight.get(e)}async reconcile(e,t){let n=this.requireInstance(e);const i=this.desiredVersion();if(this.cancelled.has(e)&&!t.resumeCancelled)return this.storePhase(n,"pending");const r=n.runtimeVersion?.desiredVersion!==i||t.startRequested||ks(n)?0:this.remainingRetryDelayMs(n.runtimeVersion);if(r>0&&(await this.delay(r),n=this.requireInstance(e),this.cancelled.has(e)))return this.storePhase(n,"pending");const s=_s(n),o=s===i&&(await(this.hooks.isInstalled?.(n,i))??!0);if(this.cancelled.has(e))return this.storePhase(this.requireInstance(e),"pending");if(s===i&&o)return this.storeState(n,{desiredVersion:i,actualVersion:s,phase:"matched",attempt:n.runtimeVersion?.attempt||0,matchedAt:this.timestamp()},!ks(n)&&"failed"!==n.health);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?Os(t,n):Rs("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,s,o)),ks(n)&&!t.startRequested)return n;let a=!1,c=0;try{for(;c<this.maxAttempts;){if(this.cancelled.has(e))return this.storePhase(this.requireInstance(e),"pending");let r;try{if(n=this.storePhase(n,"draining"),await(this.hooks.beginDrain?.(n)),a=!0,n=this.requireInstance(e),Cs(n)){const t=await this.waitUntil(e,this.drainTimeoutMs,e=>!Cs(e));if(n=this.requireInstance(e),!t){if(this.cancelled.has(e))return this.storePhase(n,"pending");await(this.hooks.onForcedDrain?.(n))}}if(n=this.storePhase(this.requireInstance(e),"installing",!0),c+=1,await this.hooks.install(n,i),this.cancelled.has(e)||ks(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=>_s(e)===i);if(this.cancelled.has(e))return this.storePhase(this.requireInstance(e),"pending");if(!r)throw Rs("INSTANCE_RUNTIME_VERIFICATION_FAILED",`Instance ${e} did not register controlled-instance ${i} after restart.`,i,_s(this.requireInstance(e)),!0);const s=this.requireInstance(e);if(this.hooks.isInstalled&&!await this.hooks.isInstalled(s,i))throw Rs("INSTANCE_RUNTIME_VERIFICATION_FAILED",`Instance ${e} reported controlled-instance ${i}, but its active runtime release is missing.`,i,_s(s),!0);return this.storeState(s,{desiredVersion:i,actualVersion:i,phase:"matched",attempt:s.runtimeVersion?.attempt||1,matchedAt:this.timestamp()},!ks(s)&&"failed"!==s.health)}catch(t){if(this.cancelled.has(e))return this.storePhase(this.requireInstance(e),"pending");r=xs(t,i,_s(this.store.get(e)))}n=this.requireInstance(e);const s=n.runtimeVersion?.attempt||1;if(!r.retryable||c>=this.maxAttempts)return this.storeBatchFailure(n,i,s>=this.maxAttempts&&r.retryable?Ds(i,_s(n),this.maxAttempts,r):r);n=this.storeState(n,{desiredVersion:i,..._s(n)?{actualVersion:_s(n)}:{},phase:"pending",attempt:s,lastAttemptAt:this.timestamp(),error:r}),await this.delay(this.retryDelayMs(s))}return this.storeBatchFailure(n,i,Ds(i,_s(n),this.maxAttempts,n.runtimeVersion?.error))}finally{a&&await(this.hooks.endDrain?.(this.requireInstance(e)))}}storeBatchFailure(e,t,n){const i=_s(e);return this.storeState(e,{desiredVersion:t,...i?{actualVersion:i}:{},phase:"pending",attempt:e.runtimeVersion?.attempt||0,lastAttemptAt:this.timestamp(),error:n})}retryDelayMs(e){return Math.min(this.retryMaxDelayMs,this.retryBaseDelayMs*2**Math.max(0,e-1))}remainingRetryDelayMs(e){if(!e?.error||!e.lastAttemptAt)return 0;const t=Date.parse(e.lastAttemptAt);return Number.isFinite(t)?Math.max(0,t+this.retryDelayMs(e.attempt||1)-this.now().getTime()):0}storePhase(e,t,n=!1){const i=this.desiredVersion(),r=_s(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:Os(i,r)}:{}},"restarting"!==t&&void 0)}storeState(e,t,n){const i=this.store.get(e.id)||e;return this.store.put($i.parse({...i,runtimeVersion:t,...void 0===n?{}:{ready:n},updatedAt:this.timestamp()}))}async waitUntil(e,t,n){const i=this.now().getTime()+t;for(;;){const t=this.store.get(e);if(t&&n(t))return!0;if(this.cancelled.has(e))return!1;if(this.now().getTime()>=i)return!1;await this.delay(Math.min(this.pollIntervalMs,Math.max(0,i-this.now().getTime())))}}requireInstance(e){const t=this.store.get(e);if(!t)throw new Error(`Instance ${e} was removed during runtime reconciliation.`);return t}timestamp(){return this.now().toISOString()}}function _s(e){return e?.build?.packageVersion||e?.instanceVersion}function Cs(e){return e.apps.runningCount>0||e.aiSessions.runningCount>0}function ks(e){return["created","stopped","failed"].includes(e.status)}function Os(e,t){return Rs("INSTANCE_RUNTIME_VERSION_MISMATCH",`Expected controlled-instance ${e}, received ${t||"an unknown version"}.`,e,t,!0)}function Rs(e,t,n,i,r){return{code:e,message:t,expectedVersion:n,...i?{actualVersion:i}:{},retryable:r}}function xs(e,t,n){if(e&&"object"==typeof e&&"code"in e&&"message"in e){const i=e,r=On.shape.code.safeParse(i.code);if(r.success&&"string"==typeof i.message)return Rs(r.data,i.message,t,n,"boolean"!=typeof i.retryable||i.retryable)}return Rs("INSTANCE_RUNTIME_INSTALL_FAILED",e instanceof Error?e.message:String(e),t,n,!0)}function Ds(e,t,n,i){const r=i?.message?` Last error: ${i.message}`:"";return Rs(i?.code||"INSTANCE_RUNTIME_INSTALL_FAILED",`Runtime convergence paused after ${n} attempts and will retry.${r}`,e,t,!0)}function Ps(e,t){if(!Number.isFinite(e)||e<0)throw new TypeError(`${t} must be a nonnegative finite number.`);return e}function Ms(e,n=448){t.mkdirSync(e,{recursive:!0,mode:n}),t.chmodSync(e,n)}function Ls(e,i,r={}){const s=r.directoryMode??448,o=r.fileMode??384;Ms(n.dirname(e),s),I.sync(e,`${JSON.stringify(i,null,2)}\n`,{encoding:"utf8",mode:o}),t.chmodSync(e,o)}function js(e,t){console.warn(JSON.stringify({message:e,...t}))}function $s(e){return e&&"object"==typeof e&&"issues"in e?{issues:e.issues}:{error:e instanceof Error?e.message:String(e)}}function Fs(e,n){const i=n.logger||js;let r;try{r=JSON.parse(t.readFileSync(e,"utf8"))}catch(t){return void i("stored JSON could not be read",{filePath:e,...$s(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 Us(e){return`${e}_${d.randomUUID().replace(/-/g,"").slice(0,20)}`}function Vs(){return d.randomBytes(24).toString("base64url")}class Hs{directory;options;permissionsInitialized=!1;constructor(e,t={}){this.directory=e,this.options=t}init(){if(this.permissionsInitialized&&t.existsSync(this.directory))return;Ms(this.directory,this.options.directoryMode??448);const e=this.options.fileMode??384;for(const i of t.readdirSync(this.directory).filter(e=>e.endsWith(".json")))t.chmodSync(n.join(this.directory,i),e);this.permissionsInitialized=!0}filePath(e){return n.join(this.directory,`${e}.json`)}list(){return this.init(),t.readdirSync(this.directory).filter(e=>e.endsWith(".json")).sort().flatMap(e=>{const t=Fs(n.join(this.directory,e),this.options);return t?[t]:[]})}get(e){this.init();const n=this.filePath(e);return t.existsSync(n)?Fs(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 Ls(this.filePath(n.id),n,this.options),n}patch(e,t){const n=this.get(e);if(!n)return;const i={...n,...t,id:n.id,createdAt:n.createdAt,updatedAt:(new Date).toISOString()};return this.put(i)}delete(e){const n=this.filePath(e);return!!t.existsSync(n)&&(t.unlinkSync(n),!0)}}class qs{filePathValue;defaults;options;constructor(e,t,n={}){this.filePathValue=e,this.defaults=t,this.options=n}init(){Ms(n.dirname(this.filePathValue),this.options.directoryMode??448),t.existsSync(this.filePathValue)?t.chmodSync(this.filePathValue,this.options.fileMode??384):this.put(this.defaults())}get(){return this.init(),t.existsSync(this.filePathValue)?Fs(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 Ls(this.filePathValue,n,this.options),n}}const Bs=a.z.record(a.z.string(),a.z.string()),Ks=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 Gs{directory;constructor(e){this.directory=e}get(e){try{return Bs.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=Bs.parse(n);t.mkdirSync(this.directory,{recursive:!0,mode:448});const r=this.filePath(e);return I.sync(r,`${JSON.stringify(i,null,2)}\n`,{encoding:"utf8",mode:384}),t.chmodSync(r,384),i}delete(e){t.rmSync(this.filePath(e),{force:!0})}filePath(e){return n.join(this.directory,`${e}.json`)}}class Js{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=Jn.parse(e);this.init();const i=this.filePath(n.id);return I.sync(i,`${JSON.stringify(n,null,2)}\n`,{encoding:"utf8",mode:384}),t.chmodSync(i,384),n}delete(e){const n=this.filePath(e);return!!t.existsSync(n)&&(t.unlinkSync(n),!0)}read(e){try{const i=JSON.parse(t.readFileSync(e,"utf8")),r=n.basename(e,".json"),s=Jn.safeParse(i);if(s.success&&s.data.id===r&&si(s.data)===s.data.id)return s.data;const o=Jn.strip().safeParse(i);return o.success&&o.data.id===r&&si(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 Ws{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=Xn.safeParse(i);if(r.success)return r.data;const s=Xn.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=Xn.parse(e);this.init();const i=this.filePath(n.instanceId);return I.sync(i,`${JSON.stringify(n,null,2)}\n`,{encoding:"utf8",mode:384}),t.chmodSync(i,384),n}delete(e){t.rmSync(this.filePath(e),{force:!0})}filePath(e){return n.join(this.directory,`${e}.json`)}}function Ys(){return(new Date).toISOString()}class Xs{models;assignments;legacyEnvironments;nodeId;instances;constructor(e,t,n){this.nodeId=t,this.instances=n,this.models=new Js(e.nodeModelsDir,t),this.assignments=new Ws(e.modelAssignmentsDir),this.legacyEnvironments=new Gs(e.modelEnvironmentsDir)}init(){this.models.init(),this.assignments.init(),this.migrateLegacyEnvironments()}list(){const e=new Map;for(const t of this.instances.list()){const n=this.assignments.get(t.id);for(const t of[n?.codexModelHash,n?.claudeModelHash])t&&e.set(t,(e.get(t)||0)+1)}return this.models.list().map(t=>this.toPublic(t,e.get(t.id)||0))}create(e){const t=Ys(),n=si(e),i=this.models.get(n),r=Jn.parse({...e,id:n,enabled:e.enabled??!0,order:e.order??this.nextOrder(),labels:e.labels||{},createdAt:i?.createdAt||t,updatedAt:t});return this.toPublic(this.models.put(r),this.referenceIds(n).length)}deploy(e){const t=si(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(Jn.parse(e));return this.toPublic(n,this.referenceIds(n.id).length)}update(e,t){const n=this.requireModel(e),i=Jn.parse({...n,...t,key:t.key?.trim()?t.key:n.key,createdAt:n.createdAt,updatedAt:Ys()}),r=si(i),s=this.models.put(Jn.parse({...i,id:r}));return this.toPublic(s,this.referenceIds(r).length)}delete(e){this.requireModel(e);const t=this.referenceIds(e);if(t.length)throw Object.assign(new Error(`Model ${e} is assigned to ${t.length} instance${1===t.length?"":"s"}.`),{statusCode:409,code:"NODE_MODEL_IN_USE",instanceIds:t});return this.models.delete(e)}resolveProbeKey(e,t){const n=t?.trim()||(e?this.requireModel(e).key:"");if(!n)throw Object.assign(new Error("An API key is required to contact the model endpoint."),{statusCode:400,code:"MODEL_API_KEY_REQUIRED"});return n}assign(e,t){const n=this.instances.require(e);if(this.validateRef("codex",t.codexModelHash),this.validateRef("claude",t.claudeModelHash),void 0!==t.modelSelection.codexModelHash&&(t.modelSelection.codexModelHash??void 0)!==t.codexModelHash)throw Object.assign(new Error("Codex model selection does not match its node assignment."),{statusCode:400,code:"NODE_MODEL_SELECTION_MISMATCH"});if(void 0!==t.modelSelection.claudeModelHash&&(t.modelSelection.claudeModelHash??void 0)!==t.claudeModelHash)throw Object.assign(new Error("Claude model selection does not match its node assignment."),{statusCode:400,code:"NODE_MODEL_SELECTION_MISMATCH"});const i=this.assignments.get(e),r=Xn.parse({instanceId:e,codexModelHash:t.codexModelHash,claudeModelHash:t.claudeModelHash,updatedAt:Ys()});this.assignments.put(r);try{return{assignment:r,instance:this.instances.put($i.parse({...n,modelSelection:t.modelSelection,updatedAt:Ys()}))}}catch(t){throw i?this.assignments.put(i):this.assignments.delete(e),t}}resolvedEnvironment(e){const t=this.assignments.get(e);if(!t){if(this.legacyEnvironments.has(e))throw Object.assign(new Error(`Legacy model environment for instance ${e} requires manual migration.`),{statusCode:409,code:"NODE_MODEL_MIGRATION_REQUIRED"});return{}}return{...this.environmentForRef("codex",t.codexModelHash),...this.environmentForRef("claude",t.claudeModelHash)}}deleteInstanceMetadata(e){this.assignments.delete(e),this.legacyEnvironments.delete(e)}validateRef(e,t){if(!t)return;const n=this.requireModel(t);if(n.app!==e)throw Object.assign(new Error(`Model ${n.id} belongs to ${n.app}, not ${e}.`),{statusCode:400,code:"NODE_MODEL_APP_MISMATCH"});if(!n.enabled)throw Object.assign(new Error(`Model ${n.id} is disabled.`),{statusCode:409,code:"NODE_MODEL_DISABLED"})}environmentForRef(e,t){if(!t)return{};this.validateRef(e,t);const n=this.requireModel(t);return"codex"===e?{OPENAI_API_KEY:n.key,OPENAI_BASE_URL:n.endpoint,TASK_HANDOFF_CODEX_BASE_URL:n.endpoint,TASK_HANDOFF_CODEX_MODEL:n.model}:{ANTHROPIC_API_KEY:n.key,ANTHROPIC_BASE_URL:n.endpoint,TASK_HANDOFF_CLAUDE_MODEL:n.model}}requireModel(e){const t=this.models.get(e);if(!t)throw Object.assign(new Error(`Model ${e} was not found on node ${this.nodeId}.`),{statusCode:404,code:"NODE_MODEL_NOT_FOUND"});if(si(t)!==t.id)throw Object.assign(new Error(`Stored model ${e} does not match its content hash.`),{statusCode:409,code:"NODE_MODEL_HASH_INVALID"});return t}referenceIds(e){return this.instances.list().filter(t=>{const n=this.assignments.get(t.id);return n?.codexModelHash===e||n?.claudeModelHash===e}).map(e=>e.id)}toPublic(e,t){const{key:n,...i}=e;return Yn.parse({...i,keyPreview:n.length<=8?"set":`${n.slice(0,4)}...${n.slice(-4)}`,keySet:!0,referenceCount:t})}nextOrder(){return this.models.list().reduce((e,t)=>Math.max(e,t.order),0)+100}migrateLegacyEnvironments(){for(const e of this.legacyEnvironments.listInstanceIds()){if(!this.instances.has(e)){this.warnMigration(e,"instance-not-found");continue}if(this.assignments.get(e)){try{this.resolvedEnvironment(e),this.legacyEnvironments.delete(e)}catch{this.warnMigration(e,"existing-assignment-invalid")}continue}let t;try{t=this.legacyEnvironments.get(e)}catch{this.warnMigration(e,"sidecar-invalid");continue}if(!Object.keys(t).length){this.legacyEnvironments.delete(e);continue}if(Object.keys(t).some(e=>!Ks.has(e))){this.warnMigration(e,"unknown-fields");continue}const n=[];try{const i=this.migrateApp(t,"codex",n),r=this.migrateApp(t,"claude",n);if(!i&&!r)throw new Error("no complete model configuration");const s={...i?{codexModelHash:i}:{},...r?{claudeModelHash:r}:{}};this.assign(e,{modelSelection:s,codexModelHash:i,claudeModelHash:r}),this.resolvedEnvironment(e),this.legacyEnvironments.delete(e)}catch{this.assignments.delete(e);for(const e of n)this.models.delete(e);this.warnMigration(e,"mapping-failed")}}}migrateApp(e,t,n){const i=e["codex"===t?"OPENAI_API_KEY":"ANTHROPIC_API_KEY"],r="codex"===t?e.TASK_HANDOFF_CODEX_BASE_URL||e.OPENAI_BASE_URL:e.ANTHROPIC_BASE_URL,s="codex"===t?e.TASK_HANDOFF_CODEX_MODEL||e.CODEX_MODEL:e.TASK_HANDOFF_CLAUDE_MODEL||e.CLAUDE_MODEL;if(!i&&!r&&!s)return;if(!i||!r||!s)throw new Error("model configuration incomplete");const o=si({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=Ys();return this.models.put(Jn.parse({id:o,name:`Migrated ${"codex"===t?"Codex":"Claude"} model`,endpoint:r,key:i,model:s,app:t,enabled:!0,order:this.nextOrder(),labels:{migratedFrom:"instance-model-environment"},createdAt:c,updatedAt:c})),n.push(o),o}warnMigration(e,t){console.warn(JSON.stringify({message:"legacy model environment was preserved because it could not be migrated",nodeId:this.nodeId,instanceId:e,reason:t}))}}function Qs(){return(new Date).toISOString()}function Zs(e,t){if(!e)return!0;const n=A.valid(e),i=A.valid(t);return n&&i?A.gt(i,n):e!==t}function eo(){return process.env.TASK_HANDOFF_NPM_COMMAND||"npm"}function to(e,i){const r=n.join(e,...i.split("/"),"package.json");try{const e=JSON.parse(t.readFileSync(r,"utf8"));if(e.name!==i||"string"!=typeof e.version||!e.version.trim())throw new Error(`Installed package manifest is invalid: ${r}`);return{name:i,version:e.version.trim()}}catch(e){if("ENOENT"===e.code)return;throw e}}async function no(e){const t=(await e(eo(),["root","--global"])).stdout.trim();if(!t)throw new Error("npm did not return its global module root.");const n=to(t,"@task-handoff/server"),i=to(t,"@task-handoff/node-agent");return n?{packageName:"@task-handoff/server",currentVersion:n.version,relatedCurrentVersions:i?[i.version]:[]}:{packageName:"@task-handoff/node-agent",currentVersion:i?.version,relatedCurrentVersions:[]}}function io(e){if(!e||"object"!=typeof e||Array.isArray(e))return e;const t=e,n="string"==typeof t.updatedAt?t.updatedAt:Qs(),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=xn.strip().safeParse(t.impact).success?xn.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}:On.strip().safeParse(t.error).success?On.strip().parse(t.error):t.error&&"object"==typeof t.error?{code:"NODE_UPDATE_FAILED",message:"string"==typeof t.error.message?t.error.message:"Stored update job contained an unknown error.",retryable:!1}:void 0:{code:"NODE_UPDATE_FAILED",message:`Stored update job used an unknown status: ${a}.`,retryable:!1},{target:m,error:p,...h}=t,g={phase:"succeeded"===c?"succeeded":"failed"===c?"failed":c||"queued",desiredVersion:d,expectedInstanceIds:[],expectedInstanceCount:0,matchedInstanceCount:0,pendingInstanceCount:0,failedInstanceCount:r||"failed"===c?1:0,deferredInstanceCount:0},f=Dn.strip().safeParse(t.rollout);return{...h,source:"npm",status:c,impact:l,runtimeArtifacts:Array.isArray(t.runtimeArtifacts)?t.runtimeArtifacts.flatMap(e=>{const t=kn.strip().safeParse(e);return t.success?[t.data]:[]}):[],rollout:f.success?f.data:g,...u?{error:u}:{},...r?{completedAt:t.completedAt||n}:{}}}class ro{records;constructor(e){this.records=new Hs(e.updatesDir,{schema:Ln,sanitize:io})}init(){this.records.init()}list(){return this.records.list().sort((e,t)=>t.createdAt.localeCompare(e.createdAt))}create(e,t){const n=Qs();return this.records.put(Ln.parse({id:Us("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(Ln.parse({...n,...t,id:e,createdAt:n.createdAt,updatedAt:Qs()}))}reconcileRollouts(e,t,n={}){const i=new Map(e.map(e=>[e.id,e]));for(const e of this.list().filter(e=>["updating-node","restarting-node","converging-instances"].includes(e.status))){if(n.processStarted&&"restarting-node"===e.status&&t!==e.toVersion){this.patch(e.id,{status:"failed",rollout:{...e.rollout,phase:"failed",nodeVersion:t},error:{code:"NODE_UPDATE_FAILED",message:`Node agent restarted with version ${t}, expected ${e.toVersion}.`,retryable:!1},completedAt:Qs()});continue}const r="converging-instances"!==e.status&&t===e.toVersion?this.patch(e.id,{status:"converging-instances",rollout:{...e.rollout,phase:"converging-instances",nodeVersion:t}}):e;if("converging-instances"!==r.status)continue;const s=r.rollout.expectedInstanceIds,o=s.map(e=>i.get(e)),a=o.filter(e=>e?.ready&&"matched"===e.runtimeVersion?.phase&&e.runtimeVersion.actualVersion===r.toVersion).length,c=o.filter(e=>e&&["created","stopped","failed"].includes(e.status||"")&&"failed"!==e.runtimeVersion?.phase).length,d=o.filter(e=>!e||"failed"===e.runtimeVersion?.phase).length,l=Math.max(0,s.length-a-d-c),u=d>0?"degraded":0===l?"succeeded":"converging-instances";this.patch(r.id,{status:u,rollout:{...r.rollout,phase:u,nodeVersion:t,expectedInstanceCount:s.length,matchedInstanceCount:a,pendingInstanceCount:l,failedInstanceCount:d,deferredInstanceCount:r.impact.stoppedInstanceCount+c},..."succeeded"===u||"degraded"===u?{completedAt:Qs()}:{}})}}run(e,t){(async()=>{this.patch(e.id,{status:"updating-node",rollout:{...e.rollout,phase:"updating-node"},startedAt:Qs(),error:void 0});try{await t(e),this.patch(e.id,{status:"succeeded",completedAt:Qs()})}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:Qs()})}})()}}function so(){return(new Date).toISOString()}class oo{records;constructor(e){this.records=new Hs(e.environmentTemplatesDir,{schema:pn,sanitize:e=>function(e,t){if(!e||"object"!=typeof e||Array.isArray(e))return e;const n=e,i=new Set(["id","name","sourceInstanceId","nodeId","imageId","internalTag","platform","architecture","sizeBytes","status","error","createdAt","updatedAt"]),r="string"==typeof n.id?n.id:void 0;for(const e of Object.keys(n))i.has(e)||t?.({templateId:r,field:e});const s=Ki(n,[...i]);if(n.error&&"object"==typeof n.error&&!Array.isArray(n.error)){const e=n.error;for(const n of Object.keys(e))["code","message","phase"].includes(n)||t?.({templateId:r,field:`error.${n}`});s.error=Ki(e,["code","message","phase"])}return s}(e,e=>{console.warn(JSON.stringify({message:"unknown stored environment template field was ignored",...e}))})})}init(){this.records.init();for(const e of this.records.list())"creating"===e.status&&this.records.put(pn.parse({...e,status:"failed",error:{code:"ENVIRONMENT_TEMPLATE_CREATION_INTERRUPTED",message:"Environment template creation was interrupted by a node-agent restart.",phase:"recovery"},updatedAt:so()}))}list(){return this.records.list()}get(e){return this.records.get(e)}put(e){return this.records.put(pn.parse(e))}patch(e,t){return this.records.patch(e,t)}delete(e){return this.records.delete(e)}}const ao=a.z.record(a.z.string().regex(/^[A-Za-z_][A-Za-z0-9_]*$/),a.z.string()),co=a.z.object({version:a.z.literal(1),instanceId:a.z.string().trim().min(1).max(120),instanceCredential:a.z.string().trim().min(1).max(240),environment:ao,updatedAt:a.z.string().datetime()}).strict();class lo{directory;constructor(e){this.directory=e.instancePrivateConfigsDir}init(){t.mkdirSync(this.directory,{recursive:!0,mode:448}),t.chmodSync(this.directory,448);for(const e of t.readdirSync(this.directory).filter(e=>e.endsWith(".json")))t.chmodSync(n.join(this.directory,e),384)}filePath(e){return n.join(this.directory,`${e}.json`)}get(e){const n=this.filePath(e);if(!t.existsSync(n))return;const i=JSON.parse(t.readFileSync(n,"utf8")),r=i&&"object"==typeof i&&!Array.isArray(i)?i:{},s=co.parse({version:r.version,instanceId:r.instanceId,instanceCredential:r.instanceCredential??r.registrationToken,environment:r.environment,updatedAt:r.updatedAt});if(s.instanceId!==e)throw Object.assign(new Error(`Private config identity mismatch for instance ${e}.`),{statusCode:409,code:"INSTANCE_PRIVATE_CONFIG_IDENTITY_MISMATCH"});return void 0===r.instanceCredential&&void 0!==r.registrationToken&&this.put(s),s}put(e){const n=co.parse(e);this.init();const i=this.filePath(n.instanceId);return I.sync(i,`${JSON.stringify(n,null,2)}\n`,{encoding:"utf8",mode:384}),t.chmodSync(i,384),n}materialize(e,t,n){if(!t)throw Object.assign(new Error(`Instance ${e} does not have a long-lived credential.`),{statusCode:409,code:"INSTANCE_PRIVATE_CONFIG_CREDENTIAL_MISSING"});return this.put({version:1,instanceId:e,instanceCredential:t,environment:n,updatedAt:(new Date).toISOString()})}delete(e){t.rmSync(this.filePath(e),{force:!0})}}const uo=function(e,t=process.env,n=e){let i;return()=>{const r=t.TASK_HANDOFF_VERSION?.trim();return r||(i||=E(e,t,n),i)}}("@task-handoff/node-agent",process.env,"@task-handoff/control-plane");function mo(){return uo()}function po(e,t){return{code:"INSTANCE_RUNTIME_VERSION_MISMATCH",message:`Expected controlled-instance ${e}, received ${t||"an unknown version"}.`,expectedVersion:e,...t?{actualVersion:t}:{},retryable:!0}}function ho(e){const t=mo();return e===t?{desiredVersion:t,actualVersion:e,phase:"matched",attempt:0,matchedAt:(new Date).toISOString()}:{desiredVersion:t,...e?{actualVersion:e}:{},phase:"pending",attempt:0,error:po(t,e)}}function go(e,t,n=!0){if(!n)return ho(t);const i=mo(),r=e.runtimeVersion;if(!r||r.desiredVersion!==i)return ho(t);const s="INSTANCE_RUNTIME_VERSION_MISMATCH"!==r.error?.code?r.error:t===i?void 0:po(i,t);return Rn.parse({...r,desiredVersion:i,...t?{actualVersion:t}:{actualVersion:void 0},..."pending"===r.phase?{error:s||(t!==i?po(i,t):void 0)}:{}})}const fo="runtime_local_host",yo="task-handoff.node-agent.builtin";function Io(){return(new Date).toISOString()}function Ao(e){const t={...e};return delete t[yo],t}function bo(e){return"local-folder"===e.type?qn.parse({mode:"local-bind",path:"/workspace",readOnly:!1}):qn.parse({mode:"git-clone",path:"/workspace",readOnly:!1})}function wo(e){const t=Hn.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 Kn.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:bo(t),labels:{},createdAt:e.createdAt,updatedAt:e.updatedAt})}function vo(e,t){throw Object.assign(new Error(t),{statusCode:403,code:e})}function Eo(e,t){e!==St&&console.warn(JSON.stringify({message:"protocol version mismatch",peer:t,expectedProtocolVersion:St,actualProtocolVersion:e||"missing",errorCode:"PROTOCOL_VERSION_MISMATCH"}))}function No(e){return"none"!==e.capabilities.artifactKind}function So(e={}){return{...e,requiresImage:!1,supportsControlledInstanceApi:!0,supportsContainerLifecycle:!1,supportsAppSessions:!0,supportsHostSessions:!0,artifactKind:"none",isolation:"none"}}class zo extends Hs{onStored;privateConfigs;constructor(e,t,n){super(e,t),this.privateConfigs=n}setOnStored(e){this.onStored=e}put(e){const t=super.get(e.id)?.stateRevision||0,n=this.privateConfigs.get(e.id),i=e.registrationToken||n?.instanceCredential;i&&this.privateConfigs.materialize(e.id,i,n?.environment||{});const{registrationToken:r,...s}=e,o=super.put($i.parse({...s,stateRevision:Math.max(e.stateRevision||0,t)+1})),a=this.hydrate(o);return this.onStored?.(a),a}get(e){const t=super.get(e);return t?this.hydrate(t):void 0}list(){return super.list().map(e=>this.hydrate(e))}hydrate(e){const t=this.privateConfigs.get(e.id)?.instanceCredential||e.registrationToken;return $i.parse({...e,registrationToken:t})}}class To{nodeId;paths;localFolders;nodeRuntimes;controlledInstances;environmentTemplates;instancePrivateConfigs;modelRegistry;updateJobs;node;listenerPort;containerUrlOverride;platform;constructor(e,t,n,i,r,s){this.paths=e,this.nodeId=t,this.localFolders=new Hs(e.localFoldersDir,{schema:Vn,sanitize:dn}),this.nodeRuntimes=new Hs(e.nodeRuntimesDir,{schema:Ti}),this.instancePrivateConfigs=new lo(e),this.controlledInstances=new zo(e.controlledInstancesDir,{schema:$i,sanitize:e=>Hi(e,e=>{console.warn(JSON.stringify({message:"legacy controlled instance field was ignored",...e}))})},this.instancePrivateConfigs),this.environmentTemplates=new oo(e),this.modelRegistry=new Xs(e,t,{has:e=>Boolean(this.controlledInstances.get(e)),list:()=>this.listInstances(),require:e=>this.requireInstance(e),put:e=>this.controlledInstances.put(e)}),this.updateJobs=new ro(e),this.listenerPort=r,this.platform=s,this.containerUrlOverride=i;const o=Io();this.node=zi.parse({id:t,name:t,connectionMode:"direct-http",endpoint:n,controlEndpoint:n,containerEndpoint:this.containerUrl,publicWebBase:n?n.replace(/:\d+$/,""):void 0,status:"online",health:"ok",capabilities:{},labels:{},createdAt:o,updatedAt:o})}init(){this.localFolders.init();for(const e of this.localFolders.list())this.localFolders.put(e);if(this.nodeRuntimes.init(),this.instancePrivateConfigs.init(),this.controlledInstances.init(),this.environmentTemplates.init(),this.modelRegistry.init(),this.updateJobs.init(),this.updateJobs.reconcileRollouts(this.controlledInstances.list(),mo(),{processStarted:!0}),!this.nodeRuntimes.get("runtime_local_docker")){const e=Io();this.nodeRuntimes.put(Ti.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(fo),t=Io();this.nodeRuntimes.put(Ti.parse({id:fo,nodeId:this.nodeId,name:"Local Runtime",type:"local",status:e?.status||"unknown",accessStrategy:"node-proxy",capabilities:So(e?.capabilities),labels:{...e?.labels,[yo]:"true"},createdAt:e?.createdAt||t,updatedAt:e?.updatedAt||t}))}for(const e of this.nodeRuntimes.list())e.nodeId!==this.nodeId&&this.nodeRuntimes.put(Ti.parse({...e,nodeId:this.nodeId,updatedAt:Io()}));for(const e of this.localFolders.list())e.nodeId!==this.nodeId&&this.localFolders.put(Vn.parse({...e,nodeId:this.nodeId,updatedAt:Io()}));this.normalizeInstanceRuntimeVersions()}normalizeInstanceRuntimeVersions(){for(const e of this.controlledInstances.list()){const t=ho(e.build?.packageVersion||e.instanceVersion),n=No(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}:{...t,phase:"pending",attempt:r?.attempt||0,lastAttemptAt:r?.lastAttemptAt,error:r?.error||t.error}:t;this.controlledInstances.put($i.parse({...e,ready:!1,runtimeVersion:s,updatedAt:Io()}))}}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=Io()}runningInstanceCount(){const e=new Set(["created","stopped","failed"]);return this.listInstances().filter(t=>!e.has(t.status)).length}createLocalFolder(e){const t=Io(),n=Vn.parse({...e,id:e.id||Us("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=Io(),n=Ti.parse({...e,id:e.id||Us("runtime"),nodeId:this.nodeId,accessStrategy:e.accessStrategy||(i=e.type,"docker"===i?"direct-port":"node-proxy"),capabilities:e.capabilities||{},labels:Ao(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[yo]){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=Ti.parse({...n,...t,id:n.id,nodeId:this.nodeId,accessStrategy:t.accessStrategy||n.accessStrategy,capabilities:t.capabilities||n.capabilities,labels:t.labels?Ao(t.labels):n.labels,createdAt:n.createdAt,updatedAt:Io()});return this.nodeRuntimes.put(i)}deleteRuntime(e){if("true"===this.requireRuntime(e).labels[yo]){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=Ti.parse({...n,...e,id:n.id,nodeId:this.nodeId,createdAt:n.createdAt,updatedAt:Io()});return this.nodeRuntimes.put(t)}):this.nodeRuntimes.put(Ti.parse({...n,status:"unknown",updatedAt:Io()}))}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=Vi(t);if(!n.success)throw function(e,t){const n=t.map(e=>`${e.path.join(".")||"body"}: ${e.message}`).join("; ");return Object.assign(new Error(`Stored instance ${e} is not compatible with protocol ${St}: ${n}`),{statusCode:409,code:"NODE_INSTANCE_PAYLOAD_INVALID"})}(e,n.error.issues);return n.data}applyInstanceLifecycle(e,t){return this.controlledInstances.put(function(e,t,n=(new Date).toISOString()){switch(t.type){case"start-requested":return $i.parse({...e,status:"starting",ready:!1,updatedAt:n});case"stop-requested":return $i.parse({...e,status:"stopping",ready:!1,updatedAt:n});case"stop-failed":return"stopping"!==e.status?e:$i.parse({...e,status:t.baseline.status,health:t.baseline.health,connectionStatus:t.baseline.connectionStatus,agentStatus:t.baseline.agentStatus,targetStatus:t.baseline.targetStatus,uiAccessStatus:t.baseline.uiAccessStatus,ready:t.baseline.ready,target:{...e.target,status:t.baseline.target.status},updatedAt:n});case"convergence-restart-requested":return $i.parse({...e,build:void 0,instanceVersion:void 0,ready:!1,updatedAt:n});case"runtime-lifecycle-completed":return function(e,t,n,i){if(t.stateRevision>e.stateRevision&&["failed","stopping","stopped","deleting"].includes(t.status))return t;const r=t.stateRevision>e.stateRevision&&t.lastHeartbeatAt!==e.lastHeartbeatAt&&"online"===t.agentStatus;return $i.parse({...t,...n,...r?{status:t.status,health:t.health,connectionStatus:t.connectionStatus,agentStatus:t.agentStatus,targetStatus:t.targetStatus,uiAccessStatus:t.uiAccessStatus}:{},ready:!!r&&t.ready,target:n.target?r?{...n.target,...t.target}:{...t.target,...n.target}:t.target,workspace:n.workspace?r?{...n.workspace,...t.workspace}:{...t.workspace,...n.workspace}:t.workspace,runtime:n.runtime?{...t.runtime,...n.runtime}:t.runtime,updatedAt:i})}(t.baseline,e,t.observation,n);case"stop-completed":return $i.parse({...e,status:"stopped",health:"unknown",connectionStatus:"offline",ready:!1,agentStatus:"offline",targetStatus:"unknown",uiAccessStatus:"unknown",target:{...e.target,status:"unknown"},updatedAt:n});case"runtime-exited":case"start-failed":return $i.parse({...e,status:"failed",ready:!1,health:"failed",connectionStatus:"offline",agentStatus:"offline",targetStatus:"unknown",uiAccessStatus:"unknown",workspace:{...e.workspace,error:(i=t.error,i instanceof Error?i.message:String(i))},updatedAt:n})}var i}(this.requireInstance(e),t))}listInstances(){return this.controlledInstances.list().flatMap(e=>{const t=Vi(e);return t.success?[t.data]:[]})}resolvedAssignedModelEnvironment(e){return this.modelRegistry.resolvedEnvironment(e)}createInstance(e){const t=this.requireRuntime(e.runtimeId),i=Io(),r=e.id||Us("inst"),s=Hn.parse(e.source),o=e.environmentSource||(e.imageSelection?{type:"image",imageSelection:e.imageSelection}:void 0);if("template"===o?.type&&"docker"!==t.type){const e=new Error(`Runtime ${t.name} does not support environment templates.`);throw Object.assign(e,{statusCode:409,code:"ENVIRONMENT_TEMPLATE_RUNTIME_UNSUPPORTED"}),e}const a="template"===o?.type?this.environmentTemplates.get(o.environmentTemplateId):void 0;if("template"===o?.type&&(!a||"ready"!==a.status)){const e=new Error(`Environment template ${o.environmentTemplateId} is not ready on node ${this.nodeId}.`);throw Object.assign(e,{statusCode:a?409:404,code:a?"ENVIRONMENT_TEMPLATE_NOT_READY":"ENVIRONMENT_TEMPLATE_NOT_FOUND"}),e}if(a&&a.nodeId!==this.nodeId){const e=new Error(`Environment template ${a.id} belongs to node ${a.nodeId}, not ${this.nodeId}.`);throw Object.assign(e,{statusCode:409,code:"ENVIRONMENT_TEMPLATE_NODE_MISMATCH"}),e}if(function(e){return"boolean"==typeof e.capabilities.requiresImage?e.capabilities.requiresImage:"local"!==e.type}(t)&&(!o||"image"===o.type&&!e.image)){const e=new Error(`Runtime ${t.name} requires an image.`);throw Object.assign(e,{statusCode:400,code:"NODE_RUNTIME_IMAGE_REQUIRED"}),e}if("local"===t.type&&"local-folder"!==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 c=a?yi.parse({id:a.id,origin:"custom",name:a.name,repository:"task-handoff/environment-template",tag:a.id.toLowerCase().replace(/[^a-z0-9_.-]/g,"-"),requestedReference:a.internalTag,resolvedDigest:a.imageId,resolvedReference:a.internalTag,downloadSizeBytes:a.sizeBytes||void 0,pullPolicy:"if-not-present",capabilities:[],optionalApps:[],defaultEnv:{},labels:{},createdAt:a.createdAt,updatedAt:a.updatedAt}):e.image?yi.parse(e.image):void 0,d="local"===t.type&&"local-folder"===s.type?n.resolve(s.path):void 0,l=$i.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:"image"===o?.type?o.imageSelection:void 0,environmentSource:o,environmentTemplateOrigin:a?{templateId:a.id,nodeId:a.nodeId,imageId:a.imageId,name:a.name,platform:a.platform,architecture:a.architecture}:void 0,imageSnapshot:c,imageProvisioning:c&&"docker"===t.type&&"template"!==o?.type?{phase:"checking-image",requestedReference:c.requestedReference,generation:0,startedAt:i,updatedAt:i}:void 0,status:c&&"docker"===t.type&&"template"!==o?.type?"provisioning":"created",health:"unknown",connectionStatus:"unknown",agentStatus:"unknown",targetStatus:"unknown",uiAccessStatus:"unknown",controlMode:"controlled",ready:!1,runtimeVersion:ho(),capabilities:{},config:{autoImportAgentConfigs:e.config?.autoImportAgentConfigs??!0,defaultCodexPermissionMode:e.config?.defaultCodexPermissionMode??("docker"===t.type?"full-access":"ask"),aiSessionHistoryLimit:e.config?.aiSessionHistoryLimit??50},workspace:"local"===t.type?{mode:"local-bind",status:"unknown",path:d}:{status:"unknown"},target:{strategy:"node-proxy",status:"unknown"},runtime:"local"===t.type?{kind:"local",workspacePath:d,labels:{"task-handoff.runtime-kind":"local"}}:{labels:{}},registrationToken:Vs(),createdAt:i,updatedAt:i}),u=this.controlledInstances.put(l);return this.instancePrivateConfigs.materialize(u.id,u.registrationToken,this.resolvedAssignedModelEnvironment(u.id)),u}registerInstance(e,t,n){const i=Gi.parse(t),r=Io(),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}if(this.validateInstanceReport(s,i,n),i.processIncarnationId&&i.processIncarnationId===s.processIncarnationId)return s;Eo(i.protocolVersion,`Instance ${e}`);const o=i.build?.packageVersion||i.instanceVersion,a=No(this.requireRuntime(s.runtimeId)),c=go(s,o,a),d=$i.parse({...s,status:"registered",health:o===mo()?"ok":"degraded",ready:!a&&o===mo(),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,processIncarnationId:i.processIncarnationId||s.processIncarnationId,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=Ji.parse(t);i.processIncarnationId&&r.processIncarnationId&&r.processIncarnationId!==i.processIncarnationId&&function(e,t){throw Object.assign(new Error(t),{statusCode:409,code:"INSTANCE_PROCESS_INCARNATION_MISMATCH"})}(0,`Instance ${e} report belongs to an obsolete controlled-instance process.`),Eo(r.protocolVersion,`Instance ${e}`);const s=Io(),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=go(i,r.build?.packageVersion||i.build?.packageVersion||i.instanceVersion,No(this.requireRuntime(i.runtimeId))),l=r.health||i.health,u="running"===(r.status||i.status)&&"failed"!==l,m=$i.parse({...i,...r,target:a,ready:u,health:l,runtimeVersion:d,processIncarnationId:r.processIncarnationId||i.processIncarnationId,agentStatus:"online",targetStatus:c,uiAccessStatus:c,connectionStatus:"online",build:r.build||i.build,lastHeartbeatAt:s,updatedAt:s});return this.controlledInstances.put(m)}validateInstanceReport(e,t,n){this.validateInstanceToken(e,n||t.registrationToken),t.instanceId&&t.instanceId!==e.id&&vo("INSTANCE_ID_MISMATCH",`Instance ${t.instanceId} cannot register as ${e.id}.`),t.nodeId&&t.nodeId!==this.nodeId&&vo("INSTANCE_NODE_MISMATCH",`Instance ${e.id} belongs to node ${this.nodeId}.`),t.runtimeId&&t.runtimeId!==e.runtimeId&&vo("INSTANCE_RUNTIME_MISMATCH",`Instance ${e.id} belongs to runtime ${e.runtimeId}.`),t.imageSelection&&t.imageSelection.imageId!==e.imageSelection?.imageId&&vo("INSTANCE_IMAGE_MISMATCH",`Instance ${e.id} belongs to image ${e.imageSelection?.imageId}.`)}validateInstanceToken(e,t){e.registrationToken&&t===e.registrationToken||vo("INSTANCE_REGISTRATION_TOKEN_INVALID",`Invalid registration token for instance ${e.id}.`)}context(e,t=this.resolvedAssignedModelEnvironment(e.id)){const n=e.imageSnapshot||yi.parse({id:"img_localhost",origin:"custom",name:"Localhost",repository:"localhost",tag:"local",requestedReference:"localhost:local",pullPolicy:"if-not-present",capabilities:[],optionalApps:[],defaultEnv:{},labels:{},createdAt:e.createdAt,updatedAt:e.updatedAt}),i=this.instancePrivateConfigs.materialize(e.id,e.registrationToken,t);return{project:wo(e),image:n,node:this.node,runtime:this.requireRuntime(e.runtimeId),instance:e,nodeAgentUrl:this.containerUrl,modelEnv:t,privateConfigPath:this.instancePrivateConfigs.filePath(i.instanceId)}}}async function _o(e,t){const n=function(e){const t=Oo(e),n=[],i=t.pathname.split("/").filter(Boolean).at(-1)||"";return Mo(n,ko(t.toString(),/^v\d+$/.test(i)?"models":"v1/models")),Mo(n,new URL("/v1/models",t.origin).toString()),Mo(n,new URL("/models",t.origin).toString()),n}(t.endpoint),i=Date.now();let r;for(const s of n){const n=await Ro(e,s,{method:"GET",headers:{accept:"application/json",authorization:`Bearer ${t.key}`}});if(404===n.status||405===n.status){r=n.status;continue}if(!n.ok)throw Do("MODEL_DISCOVERY_FAILED",n.status);const o=await xo(n,"MODEL_DISCOVERY_RESPONSE_INVALID"),a=Array.isArray(o.data)?o.data:void 0;if(!a)throw Po("MODEL_DISCOVERY_RESPONSE_INVALID","The model endpoint returned an invalid model list.",502);return{models:Lo(a.flatMap(e=>{if(!e||"object"!=typeof e||Array.isArray(e))return[];const t=e,n="string"==typeof t.id?t.id.trim():"";if(!n)return[];const i="string"==typeof t.owned_by?t.owned_by.trim():"";return[{id:n,...i?{ownedBy:i}:{}}]}).sort((e,t)=>e.id.localeCompare(t.id))),latencyMs:Date.now()-i}}throw Po("MODEL_DISCOVERY_UNSUPPORTED","No compatible model-list endpoint was found for this endpoint.",502,r)}async function Co(e,t){const n=Date.now(),i="codex"===t.app?await Ro(e,ko(t.endpoint,"responses"),{method:"POST",headers:{accept:"application/json",authorization:`Bearer ${t.key}`,"content-type":"application/json"},body:JSON.stringify({model:t.model,input:"Reply with OK.",max_output_tokens:32,stream:!1})}):await Ro(e,function(e){const t=Oo(e),n=t.pathname.split("/").filter(Boolean).at(-1)||"";return ko(t.toString(),/^v\d+$/.test(n)?"messages":"v1/messages")}(t.endpoint),{method:"POST",headers:{accept:"application/json","anthropic-version":"2023-06-01","content-type":"application/json","x-api-key":t.key},body:JSON.stringify({model:t.model,max_tokens:8,messages:[{role:"user",content:"Reply with OK."}]})});if(!i.ok)throw Do("MODEL_TEST_FAILED",i.status);if((await xo(i,"MODEL_TEST_RESPONSE_INVALID")).error)throw Po("MODEL_TEST_RESPONSE_INVALID","The model endpoint returned an error payload.",502);return{success:!0,latencyMs:Date.now()-n}}function ko(e,t){const n=Oo(e);return n.pathname=`${n.pathname.replace(/\/+$/,"")}/${t.replace(/^\/+/,"")}`,n.search="",n.hash="",n.toString()}function Oo(e){let t;try{t=new URL(e.trim())}catch{throw Po("MODEL_ENDPOINT_INVALID","The model endpoint must be a valid HTTP or HTTPS URL.",400)}if("http:"!==t.protocol&&"https:"!==t.protocol||t.username||t.password)throw Po("MODEL_ENDPOINT_INVALID","The model endpoint must be an HTTP or HTTPS URL without embedded credentials.",400);return t}async function Ro(e,t,n){try{return await e(t,{...n,redirect:"error",signal:AbortSignal.timeout(15e3)})}catch(e){const t=e&&"object"==typeof e&&"name"in e&&"TimeoutError"===e.name;throw Po(t?"MODEL_ENDPOINT_TIMEOUT":"MODEL_ENDPOINT_UNREACHABLE",t?"The model endpoint timed out.":"The model endpoint could not be reached.",t?504:502)}}async function xo(e,t){const n=await e.text();if(n.length>1e6)throw Po(t,"The model endpoint response was too large.",502);try{const e=JSON.parse(n);if(!e||"object"!=typeof e||Array.isArray(e))throw new Error("not an object");return e}catch{throw Po(t,"The model endpoint returned invalid JSON.",502)}}function Do(e,t){return Po(e,401===t||403===t?"The model endpoint rejected the API key.":"The model endpoint rejected the request.",502,t)}function Po(e,t,n,i){return Object.assign(new Error(t),{code:e,statusCode:n,...i?{details:{upstreamStatus:i}}:{}})}function Mo(e,t){e.includes(t)||e.push(t)}function Lo(e){const t=new Set;return e.filter(e=>!t.has(e.id)&&(t.add(e.id),!0))}const jo=a.z.object({endpoint:a.z.string().trim().url().max(2048),key:a.z.string().trim().min(1).max(4096).optional(),existingModelId:a.z.string().trim().min(1).max(120).optional()}).strict(),$o=jo.extend({model:a.z.string().trim().min(1).max(240),app:a.z.enum(["codex","claude"])}).strict(),Fo=a.z.object({path:a.z.string().trim().min(1).max(2048),method:a.z.string().trim().min(1).max(20).default("GET"),headers:a.z.record(a.z.string(),a.z.string()).default({}),body:a.z.string().optional(),bodyBase64:a.z.string().optional()}).strict(),Uo=a.z.object({id:a.z.string().trim().min(1).max(120).optional(),name:a.z.string().trim().min(1).max(160),path:a.z.string().trim().min(1).max(4096),defaultImageSelection:Wt.optional(),labels:a.z.record(a.z.string(),a.z.string()).default({})}).strict(),Vo=a.z.object({path:a.z.string().trim().min(1).max(4096).optional(),depth:a.z.coerce.number().int().min(0).max(1).default(0)}).strict(),Ho=a.z.object({id:a.z.string().trim().min(1).max(120).optional(),name:a.z.string().trim().min(1).max(160).optional(),runtimeId:a.z.string().trim().min(1).max(120),imageSelection:Wt.optional(),environmentSource:Yt.optional(),projectId:a.z.string().trim().min(1).max(120).optional(),image:yi.optional(),source:Hn,sourceSnapshot:a.z.record(a.z.string(),a.z.unknown()).default({}),config:a.z.object({autoImportAgentConfigs:a.z.boolean().optional(),defaultCodexPermissionMode:Ie.optional(),aiSessionHistoryLimit:a.z.number().int().min(1).max($e).optional()}).strict().optional(),modelSelection:$i.shape.modelSelection}).strict().superRefine((e,t)=>{e.environmentSource&&e.imageSelection&&t.addIssue({code:"custom",path:["environmentSource"],message:"environmentSource and imageSelection are mutually exclusive."}),"template"===e.environmentSource?.type&&e.image&&t.addIssue({code:"custom",path:["image"],message:"Template environment source is resolved by the node-agent and cannot include an image snapshot."})}),qo=a.z.object({name:a.z.string().trim().min(1).max(160).optional(),config:a.z.object({autoImportAgentConfigs:a.z.boolean().optional(),defaultCodexPermissionMode:Ie.optional(),aiSessionHistoryLimit:a.z.number().int().min(1).max($e).optional()}).strict().optional(),modelSelection:$i.shape.modelSelection.optional()}).strict(),Bo=a.z.object({id:a.z.string().trim().min(1).max(120).optional(),name:a.z.string().trim().min(1).max(160),type:a.z.enum(["docker","kubernetes","local"]),status:a.z.enum(["unknown","online","offline","degraded"]).default("unknown"),accessStrategy:a.z.enum(["node-proxy","direct-port","kubernetes-ingress","kubernetes-port-forward"]).optional(),capabilities:a.z.record(a.z.string(),a.z.unknown()).default({}),labels:a.z.record(a.z.string(),a.z.string()).default({})}).strict(),Ko=Bo.omit({id:!0}).partial().strict();function Go(e){const t=e.authorization;return"string"==typeof t&&t.startsWith("Bearer ")?t.slice(7).trim():void 0}class Jo{operations=new Map;intents=new Map;intent(e){const t=this.intents.get(e);if(t)return t;const n={};return this.intents.set(e,n),n}invalidate(e){const t={};return this.intents.set(e,t),t}isIntentCurrent(e,t){return this.intents.get(e)===t}clearIntent(e){this.intents.delete(e)}async run(e,t){const n=this.operations.get(e)||Promise.resolve();let i;const r=new Promise(e=>{i=e});this.operations.set(e,r),await n;try{return await t()}finally{i(),this.operations.get(e)===r&&this.operations.delete(e)}}}const Wo=a.z.object({}).strict().default({});function Yo(){return(new Date).toISOString()}function Xo(){return(new Date).toISOString()}class Qo{state;images;options;inFlight=new Map;abortController=new AbortController;stopped=!1;constructor(e,t,n){this.state=e,this.images=t,this.options=n}retry(e){const t=this.state.requireInstance(e);if("docker"!==this.state.requireRuntime(t.runtimeId).type||!t.imageSnapshot)throw Object.assign(new Error(`Instance ${e} does not use a Docker image.`),{statusCode:400,code:"INSTANCE_IMAGE_PROVISIONING_UNSUPPORTED"});if("failed"!==t.status||"failed"!==t.imageProvisioning?.phase)throw Object.assign(new Error(`Instance ${e} does not have failed image provisioning to retry.`),{statusCode:409,code:"INSTANCE_IMAGE_PROVISIONING_NOT_FAILED"});const n=Xo();return this.state.controlledInstances.put($i.parse({...t,status:"provisioning",health:"unknown",imageProvisioning:{phase:"checking-image",requestedReference:t.imageSnapshot.requestedReference,generation:(t.imageProvisioning?.generation||0)+1,startedAt:n,updatedAt:n},updatedAt:n}))}provision(e,t){if(this.stopped)return Promise.resolve();const n=e.imageProvisioning?.generation;if(void 0===n)return Promise.resolve();const i=`${e.id}:${n}`,r=this.inFlight.get(i);if(r)return r;const s=this.provisionGeneration(e,n,t).finally(()=>{this.inFlight.get(i)===s&&this.inFlight.delete(i)});return this.inFlight.set(i,s),s}async stop(){this.stopped=!0,this.abortController.abort(),await Promise.allSettled([...this.inFlight.values()])}async provisionGeneration(e,t,n){const i=this.currentGeneration(e.id,t,!0,e.createdAt);if(!i)return;let r,s=0,o=!1,a=Promise.resolve();try{const c=await this.images.ensure(i.imageSnapshot.requestedReference,n=>{a=a.then(async()=>{if(!r)try{await this.updatePhase(e.id,t,n,e.createdAt)}catch(e){r={error:e}}})},n=>{this.stopped||(o=!0,s=n.sequence,this.publishTerminalOutput(e,t,n))},this.abortController.signal);if(await a,r)throw r.error;if(this.stopped)return;o&&this.publishFinished(e,t,s+1,"succeeded");const d=async()=>{if(this.stopped)return;const i=this.currentGeneration(e.id,t,!0,e.createdAt);if(!i)return;const r=this.state.controlledInstances.put($i.parse({...i,status:"provisioning"===i.status?"created":i.status,health:"unknown",imageSnapshot:{...i.imageSnapshot,requestedReference:c.requestedReference,resolvedDigest:c.resolvedDigest,resolvedReference:c.resolvedReference},imageProvisioning:{...i.imageProvisioning,phase:"ready",error:void 0,updatedAt:Xo()},updatedAt:Xo()}));this.options.sync(),this.options.diagnostic({instanceId:e.id,action:"image.provision",reference:c.requestedReference,digest:c.resolvedDigest,pulled:c.pulled},"node instance image provisioning completed"),"starting"===r.status&&await(n?.())};await(this.options.runInstanceOperation?.(e.id,d)??d())}catch(n){if(await a,r&&(n=r.error),this.stopped)return;o&&this.publishFinished(e,t,s+1,"failed");const i=n instanceof Error?n.message:String(n),c=async()=>{if(this.stopped)return;const n=this.currentGeneration(e.id,t,!1,e.createdAt);n?.imageProvisioning&&["provisioning","starting"].includes(n.status)&&(this.state.controlledInstances.put($i.parse({...n,status:"failed",health:"failed",imageProvisioning:{...n.imageProvisioning,phase:"failed",error:i,updatedAt:Xo()},updatedAt:Xo()})),this.options.sync(),this.options.warn({instanceId:e.id,action:"image.provision",reference:n.imageProvisioning.requestedReference,error:i},"node instance image provisioning failed"))};await(this.options.runInstanceOperation?.(e.id,c)??c())}}currentGeneration(e,t,n=!0,i){const r=this.state.controlledInstances.get(e);if(!(!r||i&&r.createdAt!==i||r.imageProvisioning?.generation!==t||n&&!r.imageSnapshot))return r}async updatePhase(e,t,n,i){if(this.stopped)return;const r=async()=>{if(this.stopped)return;const r=this.currentGeneration(e,t,!0,i);r&&["provisioning","starting"].includes(r.status)&&(this.state.controlledInstances.put($i.parse({...r,status:"starting"===r.status?"starting":"provisioning",imageProvisioning:{...r.imageProvisioning,phase:n,error:void 0,updatedAt:Xo()},updatedAt:Xo()})),this.options.sync())};await(this.options.runInstanceOperation?.(e,r)??r())}eventBase(e,t){return{instanceId:e.id,generation:t,requestedReference:e.imageProvisioning.requestedReference,observedAt:Xo()}}publishTerminalOutput(e,t,n){for(const[i,r]of function(e,t=6e4){const n=[];for(let i=0;i<e.length;i+=t)n.push(e.slice(i,i+t));return n}(n.data).entries())this.options.publish(Ai,{...this.eventBase(e,t),sequence:1e3*n.sequence+i,data:r,...n.replay?{replay:!0}:{}},e.id)}publishFinished(e,t,n,i){this.options.publish(bi,{...this.eventBase(e,t),sequence:1e3*n,outcome:i},e.id)}}const Zo=a.z.object({name:a.z.string().trim().min(1).max(160)}).strict();function ea(){return(new Date).toISOString()}function ta(e,t,n){return{code:"object"==typeof e&&e&&"code"in e&&"string"==typeof e.code?e.code:t,message:e instanceof Error?e.message:String(e),phase:n}}class na{templateOperations=new Jo;store;privateConfigs;docker;requireInstanceValue;requireRuntimeValue;runInstanceOperationValue;isImageReferencedValue;constructor(e,t,n,i,r,s,o=()=>!1){this.store=e,this.privateConfigs=t,this.docker=n,this.requireInstanceValue=i,this.requireRuntimeValue=r,this.runInstanceOperationValue=s,this.isImageReferencedValue=o}list(){return this.store.list()}require(e){const t=this.store.get(e);if(!t)throw Object.assign(new Error(`Environment template ${e} was not found.`),{statusCode:404,code:"ENVIRONMENT_TEMPLATE_NOT_FOUND"});return t}runTemplateOperation(e,t){return this.templateOperations.run(e,async()=>t())}async create(e,t){const n=Zo.parse(t),i=this.requireInstanceValue(e),r=this.requireRuntimeValue(i.runtimeId);if("docker"!==r.type)throw Object.assign(new Error(`Runtime ${r.name} does not support environment templates.`),{statusCode:409,code:"ENVIRONMENT_TEMPLATE_RUNTIME_UNSUPPORTED"});if(!i.runtime.containerName)throw Object.assign(new Error(`Instance ${i.id} does not have a Docker container.`),{statusCode:409,code:"ENVIRONMENT_TEMPLATE_CONTAINER_NOT_FOUND"});const s=ea(),o=Us("envtpl"),a=`task-handoff/environment-template:${o.toLowerCase().replace(/[^a-z0-9_.-]/g,"-")}`;return this.store.put(pn.parse({id:o,name:n.name,sourceInstanceId:i.id,nodeId:i.nodeId,internalTag:a,status:"creating",createdAt:s,updatedAt:s})),this.runInstanceOperationValue(i.id,async()=>{let e,t=!1;try{const n=this.requireInstanceValue(i.id);if("docker"!==this.requireRuntimeValue(n.runtimeId).type||!n.runtime.containerName)throw Object.assign(new Error(`Instance ${i.id} is no longer a valid Docker template source.`),{code:"ENVIRONMENT_TEMPLATE_SOURCE_CHANGED"});const r=this.privateConfigs.get(i.id);if(!r)throw Object.assign(new Error(`Instance ${i.id} private configuration is missing.`),{code:"INSTANCE_PRIVATE_CONFIG_MISSING"});const s=[r.instanceCredential,...Object.values(r.environment)];await this.docker.inspectContainerConfigSecurity(n.runtime.containerName,s),e=await this.docker.commitEnvironmentTemplate(n.runtime.containerName,n.runtime.containerId,a),t=!0;const c=await this.docker.inspectEnvironmentTemplateImage(a);return await this.docker.inspectImageConfigSecurity(a,s),this.store.put(pn.parse({...this.require(o),...c,status:"ready",error:void 0,updatedAt:ea()}))}catch(n){return t&&(await this.docker.untagEnvironmentTemplate(a,e).catch(()=>!1),e&&await this.docker.garbageCollectEnvironmentTemplateImage(e).catch(()=>!1)),this.store.put(pn.parse({...this.require(o),status:"failed",error:ta(n,"ENVIRONMENT_TEMPLATE_CREATE_FAILED","commit"),updatedAt:ea()}))}})}async delete(e){return this.runTemplateOperation(e,async()=>{const t=this.require(e);this.store.put(pn.parse({...t,status:"deleting",error:void 0,updatedAt:ea()}));try{const n=t.internalTag?await this.docker.untagEnvironmentTemplate(t.internalTag,t.imageId):void 0,i=t.imageId||n;return i&&!this.isImageReferencedValue(i)&&await this.docker.garbageCollectEnvironmentTemplateImage(i),this.store.delete(e),{deleted:!0,templateId:e}}catch(e){throw this.store.put(pn.parse({...t,status:"failed",error:ta(e,"ENVIRONMENT_TEMPLATE_DELETE_FAILED","delete"),updatedAt:ea()})),e}})}async releaseUnusedImage(e){return!this.store.list().some(t=>t.imageId===e)&&!this.isImageReferencedValue(e)&&this.docker.garbageCollectEnvironmentTemplateImage(e)}}const ia=new Set(["DELETE","GET","HEAD","PATCH","POST","PUT","OPTIONS"]);function ra(e){return"string"==typeof e&&ia.has(e.toUpperCase())?e.toUpperCase():"GET"}const sa=new Set(["content-encoding","content-length","transfer-encoding"]),oa=67108864;function aa(e){return Object.fromEntries([...e.entries()].filter(([e])=>!sa.has(e.toLowerCase())))}function ca(e){return e.bodyBase64?Buffer.from(e.bodyBase64,"base64"):e.body}function da(){const e=Number(process.env.TASK_HANDOFF_INSTANCE_PROXY_MAX_RESPONSE_BYTES);return Number.isSafeInteger(e)&&e>0?e:67108864}function la(e){return e.startsWith("/")?e:`/${e}`}function ua(e,t){return e.code(502).send({error:{code:"INSTANCE_PROXY_RESPONSE_TOO_LARGE",message:`Instance response exceeds ${t} bytes.`}})}const ma=a.z.object({version:a.z.literal(1),externalListener:ki}).strict();function pa(e){return"all-ipv4"===e?"0.0.0.0":"127.0.0.1"}function ha(e){if(!e||"object"!=typeof e||Array.isArray(e))return e;const t=e,n=t.externalListener&&"object"==typeof t.externalListener&&!Array.isArray(t.externalListener)?t.externalListener:{},i=Object.keys(t).filter(e=>"version"!==e&&"externalListener"!==e),r=Object.keys(n).filter(e=>"bindScope"!==e&&"port"!==e);return(i.length||r.length)&&console.warn(JSON.stringify({message:"unknown stored node agent runtime setting fields were ignored",filePath:"runtime-settings.json",fields:[...i,...r.map(e=>`externalListener.${e}`)]})),{version:t.version,externalListener:{bindScope:n.bindScope,port:n.port}}}async function ga(e){const t=pa(e.bindScope);return!await new Promise(t=>{const n=p.createConnection({host:"127.0.0.1",port:e.port}),i=e=>{n.removeAllListeners(),n.destroy(),t(e)};n.once("connect",()=>i(!0)),n.once("error",()=>i(!1)),n.setTimeout(250,()=>i(!1))})&&new Promise(n=>{const i=p.createServer();i.once("error",()=>n(!1)),i.listen({host:t,port:e.port,exclusive:!0},()=>i.close(()=>n(!0)))})}class fa{app;state;settings;sockets=new Set;config;source;status="error";error;onActiveListener;updateQueue=Promise.resolve();constructor(e){this.app=e.app,this.state=e.state,this.settings=e.settings,this.config=e.config,this.source=e.source,this.onActiveListener=e.onActiveListener,this.app.server.on("connection",e=>{this.sockets.add(e),e.once("close",()=>this.sockets.delete(e))})}current(){return Oi.parse({...this.config,host:pa(this.config.bindScope),status:this.status,source:this.source,...this.error?{error:this.error}:{}})}async start(){try{await this.listen(this.config),this.status="listening",this.error=void 0,this.state.setListenerPort(this.config.port)}catch(e){throw this.status="error",this.error=e instanceof Error?e.message:String(e),this.app.log.error({host:pa(this.config.bindScope),port:this.config.port,error:this.error},"node agent TCP listener failed to start"),Object.assign(new Error(`Failed to bind node agent TCP listener at ${pa(this.config.bindScope)}:${this.config.port}: ${this.error}`),{statusCode:409,code:"NODE_AGENT_LISTENER_BIND_FAILED"})}const e=this.current();return this.onActiveListener?.(e),e}update(e){const t=this.updateQueue.then(()=>this.updateOnce(e));return this.updateQueue=t.then(()=>{},()=>{}),t}async updateOnce(e){const t=Ri.parse(e);if(t.bindScope===this.config.bindScope&&t.port===this.config.port)return this.current();if(t.port!==this.config.port){const e=this.state.runningInstanceCount();if(e>0)throw Object.assign(new Error(`Cannot change the node agent port while ${e} controlled instance(s) are running.`),{statusCode:409,code:"NODE_AGENT_LISTENER_PORT_IN_USE_BY_INSTANCES",blockingInstanceCount:e})}const n=this.snapshot();await this.stop();try{await this.listen(t)}catch(e){throw await this.restore(n),Object.assign(new Error(`Failed to bind node agent TCP listener at ${pa(t.bindScope)}:${t.port}: ${e instanceof Error?e.message:String(e)}`),{statusCode:409,code:"NODE_AGENT_LISTENER_BIND_FAILED"})}try{this.settings.put({version:1,externalListener:t})}catch(e){throw await this.stop(),await this.restore(n),Object.assign(new Error(`Failed to persist node agent TCP listener: ${e instanceof Error?e.message:String(e)}`),{statusCode:500,code:"NODE_AGENT_LISTENER_PERSIST_FAILED"})}this.config=t,this.source="persisted",this.status="listening",this.error=void 0,this.state.setListenerPort(t.port);const i=this.current();return this.onActiveListener?.(i),i}async shutdown(){await this.updateQueue,await this.stop()}snapshot(){return{config:this.config,source:this.source,status:this.status,error:this.error}}async restore(e){if(this.config=e.config,this.source=e.source,this.status=e.status,this.error=e.error,"listening"===e.status)try{await this.listen(e.config)}catch(e){this.status="error",this.error=`Failed to restore previous listener: ${e instanceof Error?e.message:String(e)}`,this.app.log.error({error:this.error},"node agent TCP listener rollback failed")}this.state.setListenerPort(e.config.port),"listening"===this.status&&this.onActiveListener?.(this.current())}async listen(e){await new Promise((t,n)=>{const i=e=>{this.app.server.off("listening",r),n(e)},r=()=>{this.app.server.off("error",i),t()};this.app.server.once("error",i),this.app.server.once("listening",r),this.app.server.listen({host:pa(e.bindScope),port:e.port})})}async stop(){this.app.server.listening&&await new Promise((e,t)=>{this.app.server.close(n=>n?t(n):e());for(const e of this.sockets)e.destroy()})}}const ya="TASK_HANDOFF_NODE_AGENT_V1",Ia="/api/node-tunnel";function Aa(e=""){return d.createHash("sha256").update(e).digest("hex")}function ba(e,t){return d.createHmac("sha256",e).update(function(e){return[ya,e.keyId,e.method.toUpperCase(),e.pathWithQuery,e.timestamp,e.nonce,e.bodySha256].join("\n")}(t)).digest("hex")}function wa(e){const t=e.timestamp||(new Date).toISOString(),n=e.nonce||d.randomBytes(18).toString("base64url"),i=Aa(e.body||""),r=ba(e.secret,{keyId:e.keyId,method:e.method,pathWithQuery:e.pathWithQuery,timestamp:t,nonce:n,bodySha256:i});return{"x-taskhandoff-node-id":e.nodeId,"x-taskhandoff-key-id":e.keyId,"x-taskhandoff-timestamp":t,"x-taskhandoff-nonce":n,"x-taskhandoff-body-sha256":i,"x-taskhandoff-signature":r}}class va{usedNonces=new Map;identity;nodeId;overrideSecret;overrideKeyId;nowMs;constructor(e,t,n,i,r=Date.now){this.identity=e,this.nodeId=t,this.overrideSecret=n,this.overrideKeyId=i,this.nowMs=r}hasRemoteSecrets(){return this.identity.remoteSecrets(this.overrideSecret,this.overrideKeyId).length>0}verify(e){const t=function(e){const t=new Map;for(const[n,i]of Object.entries(e)){const e=Array.isArray(i)?i.join(","):"string"==typeof i?i:void 0===i?"":String(i);t.set(n.toLowerCase(),e)}return{nodeId:t.get("x-taskhandoff-node-id")||"",keyId:t.get("x-taskhandoff-key-id")||"",timestamp:t.get("x-taskhandoff-timestamp")||"",nonce:t.get("x-taskhandoff-nonce")||"",bodySha256:t.get("x-taskhandoff-body-sha256")||"",signature:t.get("x-taskhandoff-signature")||""}}(e.headers);if(!t.nodeId&&!t.signature)return!1;const n="DELETE"===e.method&&"/api/node-agent/pairing/current"===e.url.split("?")[0],i=this.identity.remoteSecrets(this.overrideSecret,this.overrideKeyId,n);if(!i.length)return!1;if(t.nodeId!==this.nodeId)throw Object.assign(new Error("Invalid node agent HMAC node id."),{statusCode:401,code:"NODE_AGENT_HMAC_NODE_MISMATCH"});if(!t.keyId)throw Object.assign(new Error("Node agent HMAC key id is missing."),{statusCode:401,code:"NODE_AGENT_HMAC_KEY_MISSING"});const r=i.filter(e=>t.keyId===e.keyId);if(!r.length)throw Object.assign(new Error("Invalid node agent HMAC key id."),{statusCode:401,code:"NODE_AGENT_HMAC_KEY_INVALID"});const 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=Aa(null==(c=e.body)?"":"string"==typeof c||Buffer.isBuffer(c)?c:JSON.stringify(c));var c;if(t.bodySha256!==a)throw Object.assign(new Error("Node agent HMAC body hash mismatch."),{statusCode:401,code:"NODE_AGENT_HMAC_BODY_HASH_INVALID"});if(!r.some(n=>function(e,t){const n=Buffer.from(e,"hex"),i=Buffer.from(t,"hex");return n.length===i.length&&d.timingSafeEqual(n,i)}(t.signature,ba(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 Ea=a.z.string().trim().min(1).max(160),Na=a.z.string().datetime(),Sa=a.z.string().min(1).max(4096),za=a.z.string().trim().url().max(2048),Ta=a.z.object({id:Ea,keyId:Ea,name:a.z.string().trim().min(1).max(160).optional(),secret:Sa,pairedAt:Na,revokedAt:Na.optional(),updatedAt:Na}).strip(),_a=a.z.object({id:Ea,pairingKeyId:Ea,name:a.z.string().trim().min(1).max(160).optional(),url:za,enabled:a.z.boolean().default(!0),createdAt:Na,updatedAt:Na}).strip(),Ca=a.z.object({controlPlaneName:a.z.string().trim().min(1).max(160).optional(),controlPlaneUrl:a.z.string().trim().max(2048).optional(),expiresInMs:a.z.number().int().positive().max(36e5).optional()}).strict(),ka=a.z.object({joinToken:a.z.string().trim().min(1).max(4096),controlPlaneId:a.z.string().trim().min(1).max(160).optional(),controlPlaneName:a.z.string().trim().min(1).max(160).optional()}).strict(),Oa=a.z.object({controlPlaneUrl:a.z.string().trim().url().max(2048),joinToken:a.z.string().trim().min(1).max(4096),controlPlaneName:a.z.string().trim().min(1).max(160).optional(),activate:a.z.boolean().optional()}).strict();function Ra(){return(new Date).toISOString()}const xa=new Set(["nodeId","createdAt","updatedAt","pairingInvites","controlPlanePairings","controlPlaneConnections","remoteControlPlanes"]),Da=new Set(["id","keyId","name","secret","pairedAt","revokedAt","updatedAt"]),Pa=new Set(["id","pairingKeyId","name","url","enabled","createdAt","updatedAt"]),Ma=new Set(["id","keyId","name","url","secret","pairedAt","updatedAt","active"]);function La(e,t){console.warn(JSON.stringify({message:e,...t}))}function ja(e,t){return Object.assign(new Error(e,void 0===t?void 0:{cause:t}),{code:"NODE_AGENT_IDENTITY_INVALID"})}function $a(e,t){return Object.keys(e).filter(e=>!t.has(e))}function Fa(e,t,n){const i=Na.safeParse(e);return i.success?i.data:(n("invalid node agent identity timestamp was replaced",{field:t}),Ra())}function Ua(e,t){if(!e||"object"!=typeof e||Array.isArray(e))throw ja("Node agent identity must be a JSON object.");const n=e,i=Ea.safeParse(n.nodeId);if(!i.success)throw ja("Node agent identity has an invalid nodeId.",i.error);const r=i.data,s=$a(n,xa);s.length&&t("unknown node agent identity fields were ignored",{fields:s}),Array.isArray(n.pairingInvites)&&n.pairingInvites.length&&t("persisted node agent pairing invites were discarded",{count:n.pairingInvites.length});const o=Array.isArray(n.remoteControlPlanes)?n.remoteControlPlanes.flatMap(e=>{if(!e||"object"!=typeof e||Array.isArray(e))return[];const n=e,i=$a(n,Ma);i.length&&t("unknown legacy node agent remote control-plane fields were ignored",{fields:i});const r=Ta.safeParse(n);if(!r.success)return t("invalid legacy node agent control-plane pairing was ignored",{issues:r.error.issues}),[];const s=n.url?_a.safeParse({id:`connection_${r.data.keyId}`,pairingKeyId:r.data.keyId,name:n.name,url:n.url,enabled:!1!==n.active,createdAt:r.data.pairedAt,updatedAt:r.data.updatedAt}):void 0;return[{pairing:r.data,...s?.success?{connection:s.data}:{}}]}):[],a=(e,n,i,r)=>Array.isArray(e)?e.flatMap(e=>{if(!e||"object"!=typeof e||Array.isArray(e))return t(`invalid node agent ${r} was ignored`,{}),[];const s=$a(e,n);s.length&&t(`unknown node agent ${r} fields were ignored`,{fields:s});const o=i.safeParse(e);return o.success?[o.data]:(t(`invalid node agent ${r} was ignored`,{issues:o.error.issues}),[])}):[];return{nodeId:r,createdAt:Fa(n.createdAt,"createdAt",t),updatedAt:Fa(n.updatedAt,"updatedAt",t),controlPlanePairings:n.controlPlanePairings?a(n.controlPlanePairings,Da,Ta,"control-plane pairing"):o.map(e=>e.pairing),controlPlaneConnections:n.controlPlaneConnections?a(n.controlPlaneConnections,Pa,_a,"control-plane connection"):o.flatMap(e=>e.connection?[e.connection]:[])}}class Va{paths;logger;constructor(e,t={}){this.paths=e,this.logger=t.logger||La}read(){let e,n;try{e=t.readFileSync(this.paths.identityPath,"utf8")}catch(e){if("ENOENT"===e.code)return;throw Object.assign(new Error(`Node agent identity could not be read: ${this.paths.identityPath}`,{cause:e}),{code:"NODE_AGENT_IDENTITY_READ_FAILED"})}try{n=JSON.parse(e)}catch(e){throw ja(`Node agent identity contains invalid JSON: ${this.paths.identityPath}`,e)}return Ua(n,this.logger)}init(){const e=this.read();if(!e)return;const n=JSON.parse(t.readFileSync(this.paths.identityPath,"utf8"));("pairingInvites"in n||"remoteControlPlanes"in n)&&this.write(e)}write(e){t.mkdirSync(n.dirname(this.paths.identityPath),{recursive:!0});const i=Ua({...e,updatedAt:Ra()},this.logger);I.sync(this.paths.identityPath,`${JSON.stringify(i,null,2)}\n`,{encoding:"utf8",mode:384})}}class Ha{values=new Map;put(e,t){this.prune(),this.values.set(e,t)}take(e){this.prune();const t=this.values.get(e);return t&&this.values.delete(e),t}prune(e=Date.now()){for(const[t,n]of this.values)Date.parse(n.expiresAt)<=e&&this.values.delete(t)}}function qa(){return(new Date).toISOString()}class Ba{store;pairingInvites=new Ha;controlPlaneConnectionOperations=new Map;constructor(e){this.store=new Va(e),this.store.init()}async runControlPlaneConnectionOperation(e,t){const n=e.replace(/\/$/,""),i=this.controlPlaneConnectionOperations.get(n)||Promise.resolve();let r;const s=new Promise(e=>{r=e});this.controlPlaneConnectionOperations.set(n,s),await i;try{return await t()}finally{r(),this.controlPlaneConnectionOperations.get(n)===s&&this.controlPlaneConnectionOperations.delete(n)}}resolveNodeId(e){if(e?.trim())return this.writeNodeId(e.trim()),e.trim();const t=this.store.read();if(t?.nodeId)return t.nodeId;const n=Us("node");return this.writeNodeId(n),n}createPairingInvite(e){const t=qa(),n=new Date(Date.now()+(e.expiresInMs||6e5)).toISOString(),i=Vs(),r={tokenHash:Aa(i),createdAt:t,expiresAt:n,...e.controlPlaneName?{controlPlaneName:e.controlPlaneName}:{}};return this.pairingInvites.put(r.tokenHash,r),{...r,token:i}}completePairingInvite(e){const t=this.store.read()||this.newIdentity(),n=Aa(e.joinToken),i=this.pairingInvites.take(n);if(!i){const e=new Error("Node agent pairing invite is invalid or expired.");throw Object.assign(e,{statusCode:401,code:"NODE_AGENT_PAIRING_INVITE_INVALID"}),e}const r=qa(),s={id:e.controlPlaneId||Us("cp"),keyId:Us("key"),...e.controlPlaneName||i.controlPlaneName?{name:e.controlPlaneName||i.controlPlaneName}:{},secret:Vs(),pairedAt:r,updatedAt:r};return this.store.write({...t,controlPlanePairings:[...(t.controlPlanePairings||[]).filter(e=>e.id!==s.id),s]}),s}stageControlPlaneConnection(e){const{pairing:t,connection:n}=this.createControlPlaneConnection(e),i=this.store.read()||this.newIdentity(),r=n.url.replace(/\/$/,""),s=(i.controlPlaneConnections||[]).filter(e=>e.id===n.id||e.url.replace(/\/$/,"")===r);return this.store.write({...i,controlPlanePairings:[...(i.controlPlanePairings||[]).filter(e=>e.keyId!==t.keyId),t],controlPlaneConnections:[...(i.controlPlaneConnections||[]).filter(e=>e.id!==n.id&&e.url.replace(/\/$/,"")!==r),n]}),{pairing:t,connection:n,replacedConnections:s}}commitControlPlaneConnection(e,t={}){const n=this.store.read()||this.newIdentity(),i={...e.pairing,...t.name?{name:t.name}:{}},r={...e.connection,...t.name?{name:t.name}:{}},s=new Set((n.controlPlaneConnections||[]).map(e=>e.pairingKeyId)),o=new Set(e.replacedConnections.map(e=>e.pairingKeyId));return this.store.write({...n,controlPlanePairings:[...(n.controlPlanePairings||[]).filter(e=>e.keyId!==i.keyId&&(!o.has(e.keyId)||s.has(e.keyId))),i],controlPlaneConnections:[...(n.controlPlaneConnections||[]).filter(e=>e.id!==r.id),r]}),{pairing:i,connection:r}}rollbackControlPlaneConnection(e){const t=this.store.read();if(!t)return;const n=new Set(e.replacedConnections.map(e=>e.id));this.store.write({...t,controlPlanePairings:(t.controlPlanePairings||[]).filter(t=>t.keyId!==e.pairing.keyId),controlPlaneConnections:[...(t.controlPlaneConnections||[]).filter(t=>t.id!==e.connection.id&&!n.has(t.id)),...e.replacedConnections]})}createControlPlaneConnection(e){const t=qa(),n={id:Us("cp"),keyId:Us("key"),...e.name?{name:e.name}:{},secret:Vs(),pairedAt:t,updatedAt:t};return{pairing:n,connection:{id:Us("connection"),pairingKeyId:n.keyId,...e.name?{name:e.name}:{},url:e.url,enabled:!1!==e.enabled,createdAt:t,updatedAt:t}}}resolvedControlPlaneAccess(){const e=this.store.read(),t=new Map((e?.controlPlanePairings||[]).filter(e=>!e.revokedAt).map(e=>[e.keyId,e])),n=e?.controlPlaneConnections||[];return{hasPersistedAccess:n.length>0||t.size>0,connections:n.map(e=>({connection:e,pairing:t.get(e.pairingKeyId)}))}}listControlPlanePairings(e=""){return(this.store.read()?.controlPlanePairings||[]).filter(e=>!e.revokedAt).map(({secret:t,...n})=>({...n,current:Boolean(e&&n.keyId===e)})).sort((e,t)=>Number(t.current)-Number(e.current)||t.updatedAt.localeCompare(e.updatedAt))}listControlPlaneConnections(){return[...this.store.read()?.controlPlaneConnections||[]].sort((e,t)=>t.updatedAt.localeCompare(e.updatedAt))}deleteControlPlanePairing(e,t=""){if(t&&e===t){const e=new Error("Cannot delete the pairing used to authenticate the current request.");throw Object.assign(e,{statusCode:409,code:"NODE_AGENT_PAIRING_CURRENT_REQUEST"}),e}const n=this.store.read();if(!n)return!1;if((n.controlPlaneConnections||[]).some(t=>t.pairingKeyId===e))throw Object.assign(new Error("Cannot delete a pairing used by a configured control-plane connection."),{statusCode:409,code:"NODE_AGENT_PAIRING_IN_USE"});const i=(n.controlPlanePairings||[]).filter(t=>t.keyId!==e);return i.length!==(n.controlPlanePairings||[]).length&&(this.store.write({...n,controlPlanePairings:i}),!0)}revokeCurrentControlPlanePairing(e){if(!e)throw Object.assign(new Error("Current paired-HMAC authentication is required to revoke this pairing."),{statusCode:403,code:"NODE_AGENT_PAIRING_SELF_REVOKE_HMAC_REQUIRED"});const t=this.store.read(),n=t?.controlPlanePairings?.find(t=>t.keyId===e);if(!t||!n)throw Object.assign(new Error("The current control-plane pairing no longer exists."),{statusCode:404,code:"NODE_AGENT_PAIRING_NOT_FOUND"});if(n.revokedAt)return{keyId:e,revoked:!0,revokedAt:n.revokedAt};if((t.controlPlaneConnections||[]).some(t=>t.pairingKeyId===e))throw Object.assign(new Error("Cannot revoke a pairing used by a configured control-plane connection."),{statusCode:409,code:"NODE_AGENT_PAIRING_IN_USE"});const i=qa();return this.store.write({...t,controlPlanePairings:t.controlPlanePairings.map(t=>t.keyId===e?{...t,revokedAt:i,updatedAt:i}:t)}),{keyId:e,revoked:!0,revokedAt:i}}deleteControlPlaneConnection(e){const t=this.store.read();if(!t)return!1;const n=(t.controlPlaneConnections||[]).filter(t=>t.id!==e);return n.length!==(t.controlPlaneConnections||[]).length&&(this.store.write({...t,controlPlaneConnections:n}),!0)}remoteSecrets(e,t,n=!1){return[...(this.store.read()?.controlPlanePairings||[]).filter(e=>n||!e.revokedAt).map(e=>({keyId:e.keyId,secret:e.secret})),...e&&t?[{keyId:t,secret:e}]:[]]}isRevokedPairing(e){return Boolean(this.store.read()?.controlPlanePairings?.some(t=>t.keyId===e&&t.revokedAt))}reverseTunnelSecret(e,t,n){if(t&&n)return{keyId:n,secret:t};const i=this.store.read(),r=(i?.controlPlanePairings||[]).filter(e=>!e.revokedAt);if(!r.length)return;if(e){const t=e.replace(/\/$/,""),n=(i?.controlPlaneConnections||[]).find(e=>e.url.replace(/\/$/,"")===t),s=n&&r.find(e=>e.keyId===n.pairingKeyId);if(s)return{keyId:s.keyId,secret:s.secret}}const s=[...r].sort((e,t)=>t.updatedAt.localeCompare(e.updatedAt))[0];return s?{keyId:s.keyId,secret:s.secret}:void 0}newIdentity(){return{nodeId:this.resolveNodeId(),createdAt:qa(),updatedAt:qa(),controlPlanePairings:[],controlPlaneConnections:[]}}writeNodeId(e){const t=this.store.read();this.store.write({...t||{createdAt:qa()},nodeId:e,updatedAt:qa(),controlPlanePairings:t?.controlPlanePairings||[],controlPlaneConnections:t?.controlPlaneConnections||[]})}}const Ka=a.z.string().trim().min(1).max(160);const Ga=jn.strict();function Ja(e){const t=e.filter(e=>!["created","stopped","failed"].includes(e.status)),n=new Set(t.map(e=>e.id)),i=t.filter(e=>e.apps.runningCount>0||e.aiSessions.runningCount>0);return{runningInstanceCount:t.length,stoppedInstanceCount:e.length-t.length,activeInstanceCount:i.length,restartInstanceCount:t.length,runningInstanceIds:t.map(e=>e.id).sort(),stoppedInstanceIds:e.filter(e=>!n.has(e.id)).map(e=>e.id).sort(),activeInstanceIds:i.map(e=>e.id).sort()}}class Wa{preflights=new Map;options;constructor(e){this.options=e}async check(e){const t=Pn.parse(e),n=Ja(this.options.listInstances()),i=await no(this.options.runCommand),r=this.options.currentRuntimeVersion(),s="@task-handoff/server"===i.packageName?[...new Set([...i.relatedCurrentVersions,r])]:i.relatedCurrentVersions,o=await async function(e){const t=e.packageName||"@task-handoff/node-agent",n=await async function(e,t,n){const i=function(e){return"stable"===e?"latest":e}(n),r=await e(eo(),["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,t,e.channel);if(!n)return function(e){return Mn.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:Qs()})}({channel:e.channel,currentVersion:e.currentVersion,impact:e.impact});const i=Zs(e.currentVersion,n)||(e.relatedCurrentVersions||[]).some(e=>Zs(e,n)),r=i?await async function(e,t,n){const i=await e(eo(),["view",`${t}@${n}`,"dist.integrity","--json"]),r=JSON.parse(i.stdout);if("string"!=typeof r||!/^sha(?:256|384|512)-[A-Za-z0-9+/=]+$/.test(r))throw Object.assign(new Error(`npm did not return immutable integrity metadata for ${t}@${n}.`),{statusCode:502,code:"NODE_UPDATE_PREFLIGHT_FAILED",retryable:!0});return r}(e.runCommand,t,n):void 0;return Mn.parse({source:"npm",channel:e.channel,currentVersion:e.currentVersion,availableVersion:n,...r?{artifactRef:`npm:${t}@${n}#${r}`}:{},runtimeArtifacts:e.runtimeArtifacts||[],impact:e.impact||{runningInstanceCount:0,stoppedInstanceCount:0,activeInstanceCount:0,restartInstanceCount:0,runningInstanceIds:[],stoppedInstanceIds:[],activeInstanceIds:[]},updateAvailable:i,checkedAt:Qs()})}({channel:t.channel,currentVersion:i.currentVersion||r,runCommand:this.options.runCommand,packageName:i.packageName,relatedCurrentVersions:s,impact:n});if(!o.updateAvailable)return o;const a={...o,runtimeArtifacts:await this.options.resolveRuntimeArtifacts(o.availableVersion),preflightToken:Vs()};return this.preflights.set(a.preflightToken,{result:a,expiresAt:Date.now()+6e5}),a}async apply(e){const i=Ga.parse(e),r=await this.consumePreflight(i);if(!r.supported)throw Object.assign(new Error(r.reason||"The requested update is not supported."),{statusCode:400,code:"UPDATE_UNSUPPORTED"});if(!r.updateAvailable)throw Object.assign(new Error(r.reason||"No update is available for the selected channel."),{statusCode:409,code:"UPDATE_NOT_AVAILABLE"});const s=this.options.jobs.create(this.options.nodeId,r),{worker:o,packaged:a,expectedWorker:c}=function(e,i=t.existsSync){const r=[n.resolve(e,"..","bin","task-handoff-node-update-worker"),n.resolve(e,"..","..","bin","task-handoff-node-update-worker")],s=r.find(i),o=n.resolve(e,"..","..","..","..","scripts","node-update-worker.cts");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]}}(this.options.moduleDir);if(!o)throw this.options.jobs.patch(s.id,{status:"failed",rollout:{...s.rollout,phase:"failed"},error:{code:"NODE_UPDATE_FAILED",message:`Update worker was not found: ${c}`,retryable:!1},completedAt:(new Date).toISOString()}),Object.assign(new Error(`Node agent update worker was not found: ${c}`),{statusCode:500,code:"UPDATE_WORKER_NOT_FOUND"});const d=process.env.TASK_HANDOFF_CONTROL_PLANE_HEALTH_URL?.trim();try{await this.options.runCommand("systemd-run",["--unit",`task-handoff-update-${s.id}`,"--collect","--property=Type=exec",...a?[o]:[process.execPath,o],"--job-file",this.options.jobs.records.filePath(s.id),"--target-version",s.toVersion,"--npm-command",eo(),...d?["--control-plane-health-url",d]:[]])}catch(e){const t=e instanceof Error?e.message:String(e);throw this.options.jobs.patch(s.id,{status:"failed",rollout:{...s.rollout,phase:"failed"},error:{code:"NODE_UPDATE_FAILED",message:`Failed to launch the node update worker: ${t}`,retryable:!0},completedAt:(new Date).toISOString()}),Object.assign(new Error(`Failed to launch the node update worker: ${t}`),{statusCode:500,code:"NODE_UPDATE_WORKER_LAUNCH_FAILED",cause:e})}return s}async consumePreflight(e){const t=this.preflights.get(e.preflightToken);if(this.preflights.delete(e.preflightToken),!t||t.expiresAt<=Date.now())throw Object.assign(new Error("The update preflight is missing or expired. Check for updates again."),{statusCode:409,code:"UPDATE_PREFLIGHT_EXPIRED"});const n=t.result,i=await no(this.options.runCommand);n.channel===e.channel&&n.availableVersion===e.targetVersion&&n.currentVersion===(i.currentVersion||this.options.currentRuntimeVersion())&&!0===n.artifactRef?.startsWith(`npm:${i.packageName}@`)&&JSON.stringify(n.impact)===JSON.stringify(Ja(this.options.listInstances()))||this.throwStale();const r=await this.options.resolveRuntimeArtifacts(n.availableVersion);return JSON.stringify(n.runtimeArtifacts)!==JSON.stringify(r)&&this.throwStale(),n}throwStale(){throw Object.assign(new Error("The update target or affected instances changed after preflight. Check for updates again."),{statusCode:409,code:"UPDATE_PREFLIGHT_STALE"})}}const Ya=new Set(["provisioning","starting","registering","registered","running"]);function Xa(e){return $i.parse({...e,health:"unknown",connectionStatus:"offline",agentStatus:"offline",targetStatus:"unknown",uiAccessStatus:"unknown",target:{...e.target,status:"unknown"},updatedAt:(new Date).toISOString()})}class Qa{options;restoredInstances=new Set;restoreErrors=new Map;unexpectedExitRetries=new Map;suppressedInstances=new Set;pendingUnexpectedExits=new Map;activeRestores=new Map;timer;activeCycle;cycleRequested=!1;cycleRequestDelayMs;started=!1;stopped=!1;constructor(e){this.options=e}markRestored(e){const t=this.options.state.requireInstance(e).status;return!["failed","stopping","stopped"].includes(t)&&(this.restoredInstances.add(e),this.restoreErrors.delete(e),!0)}allowRecovery(e){this.suppressedInstances.delete(e);const t=this.pendingUnexpectedExits.get(e);void 0!==t&&(this.pendingUnexpectedExits.delete(e),this.applyUnexpectedLocalExit(e,t))}completeSuppressedOperation(e){this.pendingUnexpectedExits.delete(e),this.restoredInstances.delete(e),this.restoreErrors.delete(e),this.unexpectedExitRetries.delete(e)}forgetInstance(e){this.restoredInstances.delete(e),this.restoreErrors.delete(e),this.unexpectedExitRetries.delete(e),this.suppressedInstances.delete(e),this.activeRestores.delete(e),this.pendingUnexpectedExits.delete(e)}async suppressRecovery(e){this.suppressedInstances.add(e),await(this.activeRestores.get(e)?.catch(()=>{}))}handleUnexpectedLocalExit(e,t){this.stopped||(this.suppressedInstances.has(e)?this.pendingUnexpectedExits.set(e,t):this.applyUnexpectedLocalExit(e,t))}applyUnexpectedLocalExit(e,t){const n=this.options.state.requireInstance(e);if("local"!==this.options.state.requireRuntime(n.runtimeId).type)return;this.restoredInstances.delete(e);const i=this.options.nowMs?.()??Date.now(),r=this.unexpectedExitRetries.get(e),s=this.options.crashStableWindowMs??3e4,o=r&&i-r.lastExitAt<s?r.attempt+1:1;this.unexpectedExitRetries.set(e,{attempt:o,lastExitAt:i});const a=this.options.retryBaseDelayMs??1e3,c=1===o?0:Math.min(this.options.retryMaxDelayMs??3e4,a*2**Math.min(o-2,10)),d=t instanceof Error?t.message:String(t);this.restoreErrors.set(e,{message:d,attempt:o,nextAttemptAt:i+c}),this.options.state.applyInstanceLifecycle(e,{type:"runtime-exited",error:t}),this.requestCycle(c)}async restoreManagedInstances(){if(this.stopped)return;const{state:e}=this.options;for(const t of e.listInstances()){if(this.stopped)return;"docker"===e.requireRuntime(t.runtimeId).type&&["provisioning","starting"].includes(t.status)&&"ready"!==t.imageProvisioning?.phase&&this.options.provisionImage(t)}const t=e.listInstances().filter(t=>{if(this.restoredInstances.has(t.id))return!1;if(this.suppressedInstances.has(t.id))return!1;const n=e.requireRuntime(t.runtimeId);if("local"===n.type){const e=this.restoreErrors.get(t.id);return(Ya.has(t.status)||"failed"===t.status)&&(!e||e.nextAttemptAt<=(this.options.nowMs?.()??Date.now()))}return"docker"===n.type&&(Ya.has(t.status)||"provisioning"===t.status&&"ready"===t.imageProvisioning?.phase)});await Promise.all(t.map(async t=>{if(this.stopped)return;const n=async()=>{if(this.stopped)return;const n=e.listInstances().find(e=>e.id===t.id);if(!n)return;if(!this.isRestoreCandidate(n))return;const i=this.restoreErrors.get(n.id);try{const t=this.options.restoreInstance(n.id);this.activeRestores.set(n.id,t);try{await t}finally{this.activeRestores.get(n.id)===t&&this.activeRestores.delete(n.id)}if(this.stopped||this.suppressedInstances.has(n.id))return;if(await this.options.autoImport(e.requireInstance(n.id)),this.stopped||this.suppressedInstances.has(n.id))return;if(this.restoreErrors.get(n.id)!==i)return;if(!this.markRestored(n.id))throw new Error(`Restored instance ${n.id} did not reach a recoverable running state.`)}catch(t){if(this.stopped||this.suppressedInstances.has(n.id))return;"local"===e.requireRuntime(n.runtimeId).type&&e.applyInstanceLifecycle(n.id,{type:"start-failed",error:t});const i=t instanceof Error?t.message:String(t),r=this.restoreErrors.get(n.id),s=(r?.attempt??0)+1,o=this.options.retryBaseDelayMs??1e3,a=Math.min(this.options.retryMaxDelayMs??3e4,o*2**Math.min(s-1,10)),c=(this.options.nowMs?.()??Date.now())+a;this.restoreErrors.set(n.id,{message:i,attempt:s,nextAttemptAt:c}),r?.message===i&&r.attempt===s||this.options.warn({instanceId:n.id,action:"restore",runtimeId:n.runtimeId,error:i,attempt:s,nextAttemptAt:new Date(c).toISOString()},"node instance restore failed; recovery will retry")}};await(this.options.runInstanceOperation?.(t.id,n)??n())}))}isRestoreCandidate(e){if(this.restoredInstances.has(e.id)||this.suppressedInstances.has(e.id))return!1;const t=this.options.state.requireRuntime(e.runtimeId);if("local"===t.type){const t=this.restoreErrors.get(e.id);return(Ya.has(e.status)||"failed"===e.status)&&(!t||t.nextAttemptAt<=(this.options.nowMs?.()??Date.now()))}return"docker"===t.type&&(Ya.has(e.status)||"provisioning"===e.status&&"ready"===e.imageProvisioning?.phase)}async recoverManagedInstances(){if(this.stopped)return;const{state:e,convergence:t}=this.options,n=e.listInstances().filter(e=>this.options.usesManagedArtifact(e)&&!t.isRunning(e.id)&&(this.restoredInstances.has(e.id)||"unknown"!==e.target.status)&&(!e.ready||"matched"!==e.runtimeVersion?.phase)&&!["created","stopped","failed","provisioning","stopping"].includes(e.status));await Promise.all(n.map(async e=>{if(!this.stopped)try{await t.schedule(e.id)}catch(t){this.options.error({instanceId:e.id,error:t},"runtime convergence recovery failed")}}))}start(){this.started||this.stopped||(this.started=!0,this.runAndContinue())}async stop(){this.stopped=!0,this.timer&&clearTimeout(this.timer),this.timer=void 0;const e=this.options.stopImageProvisioning(),t=this.options.state.listInstances().map(e=>this.options.convergence.cancel(e.id));await Promise.all(t),await this.activeCycle,await e,await this.options.runtimeAdapters.stopAll();for(const e of this.options.state.listInstances())"local"===this.options.state.requireRuntime(e.runtimeId).type&&this.options.state.controlledInstances.put(Xa(e))}async runCycle(){await this.restoreManagedInstances(),this.stopped||await this.recoverManagedInstances()}runAndContinue(){if(this.stopped)return;const e=this.runCycle().catch(e=>this.options.error({error:e},"node agent startup recovery cycle failed"));this.activeCycle=e,e.finally(()=>{this.activeCycle===e&&(this.activeCycle=void 0),this.cycleRequested?(this.cycleRequested=!1,this.cycleRequestDelayMs=void 0,this.scheduleNext()):this.scheduleNext()})}scheduleNext(){if(this.stopped)return;const e=this.options.nowMs?.()??Date.now(),t=new Map(this.options.state.listInstances().map(e=>[e.id,e])),n=[...this.restoreErrors.entries()].reduce((e,[n,i])=>{const r=t.get(n);return!r||this.restoredInstances.has(n)||this.suppressedInstances.has(n)||"local"!==this.options.state.requireRuntime(r.runtimeId).type?e:Ya.has(r.status)||"failed"===r.status?Math.min(e,i.nextAttemptAt):e},Number.POSITIVE_INFINITY),i=Math.min(this.options.intervalMs??1e4,Math.max(0,n-e));this.timer=setTimeout(()=>{this.timer=void 0,this.runAndContinue()},i),this.timer.unref?.()}requestCycle(e=0){if(this.started&&!this.stopped){if(this.activeCycle)return this.cycleRequested=!0,void(this.cycleRequestDelayMs=void 0===this.cycleRequestDelayMs?e:Math.min(this.cycleRequestDelayMs,e));this.timer&&clearTimeout(this.timer),this.timer=setTimeout(()=>{this.timer=void 0,this.runAndContinue()},e),this.timer.unref?.()}}}function Za(e){return e.readyState===(e.OPEN??1)}function ec(e){const t=Buffer.isBuffer(e)?e.toString("utf8"):"string"==typeof e?e:"";if(Buffer.byteLength(t,"utf8")<=123)return t;let n="";for(const e of t){const t=`${n}${e}`;if(Buffer.byteLength(t,"utf8")>123)break;n=t}return n}function tc(e){if("number"==typeof e&&Number.isInteger(e))return e>=3e3&&e<=4999||e>=1e3&&e<=1014&&1004!==e&&1005!==e&&1006!==e?e:void 0}function nc(e,t,n){e.close(tc(t),ec(n)||void 0)}function ic(e,t,n,i){if(Za(e))for(const e of t.splice(0))if(i(e),!n(e))return}function rc(e,t){const n=new URL(t.tunnelUrl);n.searchParams.set("nodeId",t.nodeId);const i=t.secret?wa({nodeId:t.nodeId,keyId:t.keyId,secret:t.secret,method:"GET",pathWithQuery:`${n.pathname}${n.search}`}):{},r=new m(n,{headers:i}),s=new Map,o=new Map,a=new Map;let c;r.on("error",i=>{e.log.warn({nodeId:t.nodeId,tunnelUrl:`${n.origin}${n.pathname}`,error:i instanceof Error?i.message:String(i)},"node agent reverse tunnel connection failed")});const d=e=>{const n=e.startsWith("/")?e:`/${e}`,i="function"==typeof t.port?t.port():t.port,r=new URL(`/api/node-agent${n}`,`http://127.0.0.1:${i}`);return r.protocol="ws:",r},l=(e,n,i,r={})=>{const s=e.startsWith("/")?e:`/${e}`;return{...r,...t.secret&&t.keyId?wa({nodeId:t.nodeId,keyId:t.keyId,secret:t.secret,method:n,pathWithQuery:`/api/node-agent${s}`,body:i}):t.token?{authorization:`Bearer ${t.token}`}:{}}},u=e=>t.secret?wa({nodeId:t.nodeId,keyId:t.keyId,secret:t.secret,method:"GET",pathWithQuery:`${e.pathname}${e.search}`}):{},p=(e,t,n)=>{const i=s.get(e);s.delete(e),i?.upstream&&nc(i.upstream,t,n),i?.tunnel&&nc(i.tunnel,t,n)},h=(e,t,n=!1)=>new Promise((i,r)=>{e.send(t,{binary:n},e=>e?r(e):i())});r.on("open",()=>{r.send(JSON.stringify({type:"node-agent.identify",nodeId:t.nodeId,serverTime:(new Date).toISOString()})),c=e.nodeAgentEventForwarder?.addOutput(r)}),r.on("close",()=>{for(const e of s.keys())p(e,1001,"Reverse tunnel disconnected.");for(const[e,t]of o)o.delete(e),t.controller.abort(),nc(t.tunnel,1001,"Reverse tunnel disconnected.");for(const[e,t]of a)a.delete(e),t.abort();c?.(),c=void 0});return r.on("message",i=>{(async i=>{let c;try{c=JSON.parse(String(i))}catch{return void r.send(JSON.stringify({type:"node-agent.error",code:"INVALID_JSON"}))}const g=c&&"object"==typeof c?c:{};if("control-plane.http.open"===g.type){const i="string"==typeof g.streamId?g.streamId:"",s="string"==typeof g.route&&g.route.startsWith("/")?g.route:"/health",a=g.init&&"object"==typeof g.init?g.init:{},c=a.headers&&"object"==typeof a.headers?a.headers:{},d=ra(a.method);let p;try{p=$t(a.body)}catch(n){return e.log.warn({nodeId:t.nodeId,messageType:g.type,streamId:i,error:n instanceof Error?n.message:String(n)},"node agent reverse tunnel request body rejected"),void r.send(JSON.stringify({type:"node-agent.error",code:"NODE_TUNNEL_REQUEST_BODY_INVALID",streamId:i}))}const f=new AbortController,y=(e=>{const t=new URL(n);return t.pathname=`${t.pathname.replace(/\/$/,"")}/http-streams/${encodeURIComponent(e)}`,t})(i),I=new m(y,{headers:u(y)});return o.set(i,{tunnel:I,controller:f}),I.on("open",async()=>{try{const e=await fetch((e=>{const n=e.startsWith("/")?e:`/${e}`,i="function"==typeof t.port?t.port():t.port;return new URL(`/api/node-agent${n}`,`http://127.0.0.1:${i}`)})(s),{method:d,headers:l(s,d,p,c),body:Buffer.isBuffer(p)?new Uint8Array(p):p,signal:f.signal});if(await h(I,JSON.stringify({type:"node-agent.http.head",streamId:i,status:e.status,headers:Object.fromEntries(e.headers.entries())})),e.body){const t=e.body.getReader();for(;;){const{done:e,value:n}=await t.read();if(e)break;await h(I,Buffer.from(n),!0)}}await h(I,JSON.stringify({type:"node-agent.http.end",streamId:i})),I.close(1e3,"HTTP stream completed.")}catch(e){I.readyState===m.OPEN&&(await h(I,JSON.stringify({type:"node-agent.http.error",streamId:i,message:e instanceof Error?e.message:String(e)})).catch(()=>{}),I.close(1011,"HTTP stream failed."))}finally{o.delete(i)}}),I.on("close",()=>{f.abort(),o.delete(i)}),void I.on("error",()=>f.abort())}if("control-plane.http.cancel"===g.type){const e="string"==typeof g.streamId?g.streamId:"",t=o.get(e);if(!t)return;return o.delete(e),t.controller.abort(),void nc(t.tunnel,1e3,"string"==typeof g.reason?g.reason:"HTTP stream canceled.")}if("control-plane.websocket.open"===g.type){const e="string"==typeof g.streamId?g.streamId:"",t="string"==typeof g.route?g.route:"",i=Array.isArray(g.protocols)?g.protocols.filter(e=>"string"==typeof e):void 0;try{const o=l(t,"GET",void 0),a=i?.length?new m(d(t),i,{headers:o}):new m(d(t),{headers:o}),c=(e=>{const t=new URL(n);return t.pathname=`${t.pathname.replace(/\/$/,"")}/streams/${encodeURIComponent(e)}`,t})(e),p=new m(c,{headers:u(c)});s.set(e,{upstream:a,tunnel:p,close:(e=1e3,t="")=>{nc(a,e,t),nc(p,e,t)}}),a.on("open",()=>{r.send(JSON.stringify({type:"node-agent.websocket.open",streamId:e,protocol:a.protocol}))}),function(e,t,n={}){const i=n.pendingFrameLimit??256,r=n.maxFrameBytes??8388608,s=n.maxTotalBytes??1073741824,o=n.maxBufferedBytes??16777216;let a=!1,c=Za(t);const d=[],l=[];let u,m=0,p=0,h=0;const g=e=>Buffer.isBuffer(e)||e instanceof ArrayBuffer||ArrayBuffer.isView(e)?e.byteLength:Buffer.byteLength("string"==typeof e?e:String(e),"utf8"),f=(i,o)=>{const a=g(o);return h+=a,n.onFrame?.(i,a),!(a>r||h>s)||(nc(e,1009,"WebSocket bridge traffic limit exceeded."),nc(t,1009,"WebSocket bridge traffic limit exceeded."),!1)},y=()=>{u&&(clearTimeout(u),u=void 0)},I=(n,i)=>{const r=i.bytes;if((n.bufferedAmount??0)+r>o)return nc(e,1013,"WebSocket bridge consumer is too slow."),nc(t,1013,"WebSocket bridge consumer is too slow."),!1;try{return function(e,t){e.send(t.data,{binary:t.isBinary})}(n,i),!0}catch{return nc(e,1011,"WebSocket bridge send failed."),nc(t,1011,"WebSocket bridge send failed."),!1}},A=(n,r,s)=>{if(r.length>=i)return nc(e,1011,"WebSocket bridge pending frame limit exceeded."),void nc(t,1011,"WebSocket bridge pending frame limit exceeded.");const a="upstream"===n?m:p;if((("upstream"===n?t:e).bufferedAmount??0)+a+s.bytes>o)return nc(e,1013,"WebSocket bridge consumer is too slow."),void nc(t,1013,"WebSocket bridge consumer is too slow.");r.push(s),"upstream"===n?m+=s.bytes:p+=s.bytes};n.upstreamOpenTimeoutMs&&!c&&(u=setTimeout(()=>{c||a||(nc(e,1011,"Upstream websocket did not open."),nc(t))},n.upstreamOpenTimeoutMs)),e.on("open",()=>ic(e,l,t=>I(e,t),e=>{p-=e.bytes})),t.on("open",()=>{y(),c=!0,n.onUpstreamOpen?.(),ic(t,d,e=>I(t,e),e=>{m-=e.bytes})}),e.on("message",(e,n=!1)=>{if(!f("client-to-upstream",e))return;const i={data:e,isBinary:Boolean(n),bytes:g(e)};Za(t)?I(t,i):A("upstream",d,i)}),t.on("message",(t,n=!1)=>{if(!f("upstream-to-client",t))return;const i={data:t,isBinary:Boolean(n),bytes:g(t)};Za(e)?I(e,i):A("client",l,i)}),t.on("close",(t,i)=>{y(),n.onUpstreamClose?.(t,i),(c||a||!n.onUpstreamCloseBeforeOpen?.())&&nc(e,t,i)}),t.on("error",t=>{n.onUpstreamError?.(t),(c||a||!n.onUpstreamErrorBeforeOpen?.(t))&&nc(e)}),e.on("close",(e,i)=>{y(),a=!0,n.onClientClose?.(e,i),nc(t,e,i)}),e.on("error",e=>{y(),a=!0,n.onClientError?.(e),nc(t,1011,"WebSocket bridge client failed.")})}(p,a,{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);const i=tc(t),o=ec(n);r.send(JSON.stringify({type:"node-agent.websocket.close",streamId:e,...void 0===i?{}:{code:i},...o?{reason:o}:{}}))},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"===g.type){const e="string"==typeof g.streamId?g.streamId:"";return void p(e,"number"==typeof g.code?g.code:1e3,"string"==typeof g.reason?g.reason:"")}if("control-plane.request.cancel"===g.type){const e="string"==typeof g.requestId?g.requestId:"";return a.get(e)?.abort(),void a.delete(e)}if("control-plane.request"===g.type){const n="string"==typeof g.requestId?g.requestId:"",i=g.init&&"object"==typeof g.init?g.init:{},s="string"==typeof g.route&&g.route.startsWith("/")?g.route:"/health",o=i.headers&&"object"==typeof i.headers?i.headers:{},c=ra(i.method);let d;try{d=$t(i.body)}catch(i){return e.log.warn({nodeId:t.nodeId,messageType:g.type,requestId:n,error:i instanceof Error?i.message:String(i)},"node agent reverse tunnel request body rejected"),void r.send(JSON.stringify({type:"node-agent.response",requestId:n,status:400,error:{code:"NODE_TUNNEL_REQUEST_BODY_INVALID",message:"Reverse tunnel request body does not match the negotiated protocol."}}))}const u=new AbortController;a.set(n,u);try{const t=await e.inject({method:c,url:`/api/node-agent${s}`,headers:l(s,c,d,o),payload:d,signal:u.signal});if(u.signal.aborted)return;r.send(JSON.stringify({type:"node-agent.response",requestId:n,status:t.statusCode,headers:t.headers,body:t.body}))}catch(e){if(u.signal.aborted)return;r.send(JSON.stringify({type:"node-agent.response",requestId:n,status:502,error:{code:"NODE_AGENT_REVERSE_INJECT_FAILED",message:e instanceof Error?e.message:String(e)}}))}finally{a.delete(n)}}})(i).catch(n=>{e.log.warn({nodeId:t.nodeId,error:n instanceof Error?n.message:String(n)},"node agent reverse tunnel message rejected");try{r.send(JSON.stringify({type:"node-agent.error",code:"INVALID_TUNNEL_MESSAGE"}))}catch{}})}),r}function sc(e,t){return Number.isFinite(e)&&Number(e)>0?Number(e):t}function oc(e){return e.unref?.(),e}class ac{connectTimeoutMs;handshakeTimeoutMs;heartbeatIntervalMs;heartbeatTimeoutMs;stableThresholdMs;now;setTimeoutFn;clearTimeoutFn;ping;onTimeout;onStable;onPhase;connectTimer;handshakeTimer;heartbeatTimer;stableTimer;awaitingPongSince;stable=!1;stopped=!1;currentPhase="connecting";lastActivityAt;lastPongAt;constructor(e){this.connectTimeoutMs=sc(e.connectTimeoutMs,1e4),this.handshakeTimeoutMs=sc(e.handshakeTimeoutMs,1e4),this.heartbeatIntervalMs=sc(e.heartbeatIntervalMs,25e3),this.heartbeatTimeoutMs=sc(e.heartbeatTimeoutMs,1e4),this.stableThresholdMs=sc(e.stableThresholdMs,6e4),this.now=e.now||Date.now,this.setTimeoutFn=e.setTimeoutFn||setTimeout,this.clearTimeoutFn=e.clearTimeoutFn||clearTimeout,this.ping=e.ping,this.onTimeout=e.onTimeout,this.onStable=e.onStable,this.onPhase=e.onPhase}get phase(){return this.currentPhase}start(){this.stopped=!1,this.setPhase("connecting"),this.clearTimer("connectTimer"),this.connectTimer=oc(this.setTimeoutFn(()=>this.timeout("connect"),this.connectTimeoutMs))}opened(){this.stopped||(this.clearTimer("connectTimer"),this.setPhase("handshaking"),this.handshakeTimer=oc(this.setTimeoutFn(()=>this.timeout("handshake"),this.handshakeTimeoutMs)),this.scheduleHeartbeat(this.heartbeatIntervalMs))}healthy(){this.stopped||(this.clearTimer("handshakeTimer"),this.activity(),this.setPhase("healthy"),this.stable||this.stableTimer||(this.stableTimer=oc(this.setTimeoutFn(()=>{this.stableTimer=void 0,this.stopped||"healthy"!==this.currentPhase||(this.stable=!0,this.onStable?.())},this.stableThresholdMs))))}activity(){this.stopped||(this.lastActivityAt=this.now())}pong(){if(this.stopped)return;const e=this.now();this.awaitingPongSince=void 0,this.lastPongAt=e,this.lastActivityAt=e,this.scheduleHeartbeat(this.heartbeatIntervalMs)}close(){this.stopped||(this.stopped=!0,this.clearTimers(),this.awaitingPongSince=void 0,this.setPhase("closed"))}diagnostics(){return{phase:this.currentPhase,stable:this.stable,...void 0===this.lastActivityAt?{}:{lastActivityAt:new Date(this.lastActivityAt).toISOString()},...void 0===this.lastPongAt?{}:{lastPongAt:new Date(this.lastPongAt).toISOString()}}}scheduleHeartbeat(e){this.stopped||(this.clearTimer("heartbeatTimer"),this.heartbeatTimer=oc(this.setTimeoutFn(()=>{if(this.heartbeatTimer=void 0,!this.stopped){if(void 0!==this.awaitingPongSince){const e=Math.max(0,this.now()-this.awaitingPongSince);return e>=this.heartbeatTimeoutMs?void this.timeout("heartbeat"):void this.scheduleHeartbeat(this.heartbeatTimeoutMs-e)}this.awaitingPongSince=this.now();try{this.ping()}catch{return void this.timeout("heartbeat")}this.scheduleHeartbeat(this.heartbeatTimeoutMs)}},e)))}timeout(e){this.stopped||(this.clearTimers(),this.setPhase("failed"),this.onTimeout(e))}setPhase(e){this.currentPhase!==e&&(this.currentPhase=e,this.onPhase?.(e))}clearTimers(){this.clearTimer("connectTimer"),this.clearTimer("handshakeTimer"),this.clearTimer("heartbeatTimer"),this.clearTimer("stableTimer")}clearTimer(e){const t=this[e];t&&this.clearTimeoutFn(t),this[e]=void 0}}function cc(e){const t=new URL(Ia,e);return t.protocol="https:"===t.protocol?"wss:":"ws:",t.toString()}const dc=new Set(["linux","darwin","win32","freebsd","openbsd","aix","sunos"]);function lc(e){return dc.has(e)?e:"unknown"}function uc(e){return!0===e.managedArtifacts}class mc{managedArtifacts=!0;executor;runCommand;platform;arch;constructor(e,t,n,i){this.executor=e,this.runCommand=t,this.platform=n,this.arch=i}artifactTarget(e){return this.executor.inspectRuntimeTarget(e?.instance.runtime.containerName)}async installRuntime(e,t){const n=e.instance.runtime.containerName;if(!n)throw Object.assign(new Error(`Instance ${e.instance.id} does not have a Docker container.`),{code:"INSTANCE_RUNTIME_INSTALL_FAILED"});await this.executor.installRuntimeReleaseWithRecovery({containerName:n,expectedContainerId:e.instance.runtime.containerId,artifactPath:t.archivePath,identity:t.identity})}async inspectRuntime(e,t){const n=e.instance.runtime.containerName;if(!n)return!1;const i=function(e,t){return e.packageName===t.packageName&&e.version===t.version&&e.platform===t.platform&&e.arch===t.arch&&e.formatVersion===t.formatVersion&&e.launcherAbi===t.launcherAbi&&e.entrypoint===t.entrypoint&&e.sha256===t.sha256}(await this.executor.inspectRuntimeVersion(n),t),r=e.instance.runtime.labels["task-handoff.bootstrap-backup"];return i&&r&&await this.executor.removeBootstrapBackup(r,e.instance.id),i}start(e){return this.executor.start(e)}stop(e){return this.executor.stop(e)}restart(e){return this.executor.restart(e,e.instance.runtime.containerId)}delete(e,t){return this.executor.delete(e,t)}async check(e){try{const t=(await this.runCommand("docker",["version","--format","{{.Server.Version}}"],{timeoutMs:5e3})).stdout.trim();return{status:"online",capabilities:{...e.capabilities,daemon:{status:"online",hostPlatform:lc(this.platform),...t?{serverVersion:t}:{}}}}}catch(t){return{status:"offline",capabilities:{...e.capabilities,daemon:{status:"offline",hostPlatform:lc(this.platform),error:t instanceof Error?t.message:String(t)}}}}}}class pc{docker;local;constructor(e,t){this.docker=e,this.local=t}forRuntime(e){if("docker"===e.type)return this.docker;if("local"===e.type)return this.local;throw Object.assign(new Error(`Runtime type ${e.type} is not supported by this node agent.`),{statusCode:400,code:"NODE_RUNTIME_TYPE_UNSUPPORTED"})}managedAdapters(){return[this.docker,this.local].filter(uc)}async stopAll(){await(this.local.stopAll?.())}}const hc="task-handoff.local-process-nonce",gc=1e3,fc=1e4,yc=2e3;function Ic(e,t){try{e?.(t)}catch{}}function Ac(e){return e.runtime.port?`http://127.0.0.1:${e.runtime.port}`:e.target.web}async function bc(e,t){try{const n=await fetch(`${e}/api/internal/node-agent/process-identity`,{headers:{authorization:`Bearer ${t}`},signal:AbortSignal.timeout(gc)});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 wc(e,t){if(C(e)!==t)return!1;try{process.kill(e,"SIGTERM")}catch{return!0}const n=Date.now()+fc;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()+yc;for(;Date.now()<i;){try{process.kill(e,0)}catch{return!0}await new Promise(e=>setTimeout(e,50))}return!1}function vc(e,t){return Object.assign(new Error(t),{statusCode:503,code:"LOCAL_INSTANCE_STOP_UNCONFIRMED",instanceId:e.id})}async function Ec(e){return!await function(e){return new Promise(t=>{const n=p.createConnection({host:"127.0.0.1",port:e}),i=e=>{n.removeAllListeners(),n.destroy(),t(e)};n.once("connect",()=>i(!0)),n.once("error",()=>i(!1)),n.setTimeout(250,()=>i(!1))})}(e)&&new Promise(t=>{const n=p.createServer();n.once("error",()=>t(!1)),n.listen({host:"127.0.0.1",port:e,exclusive:!0},()=>n.close(()=>t(!0)))})}const Nc=Ec;function Sc(e,t){return null!==e.exitCode||null!==e.signalCode?Promise.resolve(!0):new Promise(n=>{const i=setTimeout(()=>{e.off("exit",r),n(null!==e.exitCode||null!==e.signalCode)},t);i.unref();const r=()=>{clearTimeout(i),n(!0)};e.once("exit",r)})}async function zc(e,t=1e4,n=2e3,i){if(await Sc(e,t))return;Ic(i,{stage:"graceful-timeout",pid:e.pid,timeoutMs:t});let r=!1;if(null===e.exitCode&&null===e.signalCode&&(e.kill("SIGKILL"),r=!0,Ic(i,{stage:"force-signal-sent",pid:e.pid,signal:"SIGKILL"})),!await Sc(e,n))throw Ic(i,{stage:"force-exit-unconfirmed",pid:e.pid,signal:"SIGKILL",timeoutMs:n}),Object.assign(new Error(`Controlled instance process pid=${e.pid??"unknown"} did not exit after SIGKILL.`),{statusCode:503,code:"LOCAL_INSTANCE_PROCESS_EXIT_UNCONFIRMED",pid:e.pid});r&&Ic(i,{stage:"force-exit-confirmed",pid:e.pid,signal:"SIGKILL"})}class Tc{children=new Map;readyChildren=new WeakSet;expectedExits=new WeakSet;lifecycleReporters=new WeakMap;lockPath;onUnexpectedExit;onUnexpectedExitError;constructor(e,t,n){this.lockPath=e,this.onUnexpectedExit=t,this.onUnexpectedExitError=n}track(e,t,n){this.children.set(e,t),n&&this.lifecycleReporters.set(t,n),t.once("exit",(n,i)=>{if(this.release(e,t),this.readyChildren.has(t)&&!this.expectedExits.has(t)){const r={instanceId:e,pid:t.pid,code:n,signal:i},s=e=>{try{this.onUnexpectedExitError?.(e,r)}catch{}};try{Promise.resolve(this.onUnexpectedExit?.(r)).catch(s)}catch(e){s(e)}}})}markReady(e,t){return this.children.get(e)===t&&null===t.exitCode&&null===t.signalCode&&(this.readyChildren.add(t),!0)}release(e,t){this.children.get(e)===t&&this.children.delete(e)}async stop(e){const t=this.children.get(e.id);if(t){this.expectedExits.add(t);const n=this.lifecycleReporters.get(t);return t.killed||(t.kill("SIGTERM"),Ic(n,{stage:"graceful-signal-sent",pid:t.pid,signal:"SIGTERM"})),this.children.delete(e.id),void await zc(t,fc,yc,n)}const i=await async function(e){const t=Ac(e),n=e.runtime.labels?.[hc];if(!t||!n||!e.registrationToken)return;const i=await bc(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(gc)})).ok?i:void 0}catch{return}}(e);if(i){const t=Ac(e),n=Date.now()+fc;for(;t&&Date.now()<n;){if(!await bc(t,e.registrationToken))return;await new Promise(e=>setTimeout(e,50))}const r=t?await bc(t,e.registrationToken):void 0;if(r&&r.instanceId===i.instanceId&&r.pid===i.pid&&r.processNonce===i.processNonce&&r.startIdentity===i.startIdentity&&r.startIdentity&&await wc(r.pid,r.startIdentity))return;throw vc(e,`Controlled instance ${e.id} accepted shutdown but its exit could not be confirmed.`)}const r=function(e=function(){const e="win32"===process.platform?c.tmpdir():"/tmp";return n.join(e,`task-handoff-local-controlled-instance-${function(){const e=process.getuid?.();return void 0!==e?String(e):c.userInfo().username.replace(/[^a-zA-Z0-9_.-]/g,"_")}()}.lock`)}()){return k(e)}(this.lockPath),s=await async function(e){const t=Ac(e);if(t)try{const[n,i]=await Promise.all([fetch(`${t}/api/instance/status`,{signal:AbortSignal.timeout(gc)}),fetch(`${t}/api/diagnostics`,{signal:AbortSignal.timeout(gc)})]);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=C(o);return a?{pid:o,startIdentity:a}:void 0}catch{return}}(e);if(s){if(await wc(s.pid,s.startIdentity))return;throw vc(e,`Legacy controlled instance ${e.id} did not exit after termination.`)}if(r?.instanceId===e.id&&x(r))throw vc(e,`Local controlled instance ${e.id} is still owned by pid ${r.pid}, but its process identity could not be verified.`)}async waitUntilHealthy(e,t,n,i,r=function(e=process.env.TASK_HANDOFF_LOCAL_PROCESS_READY_TIMEOUT_MS){const t=Number(e);return Number.isFinite(t)&&t>0?t:3e4}()){const s=Date.now()+r;for(;Date.now()<s;){if(null!==n.exitCode||null!==n.signalCode)return!1;const r=await bc(e,i);if(r&&r.instanceId===t.instanceId&&r.pid===t.pid&&r.processNonce===t.processNonce&&r.startIdentity===t.startIdentity)return!0;await new Promise(e=>setTimeout(e,100))}return!1}async stopAll(){const e=Array.from(this.children.values());for(const t of e){this.expectedExits.add(t);const e=this.lifecycleReporters.get(t);t.killed||(t.kill("SIGTERM"),Ic(e,{stage:"graceful-signal-sent",pid:t.pid,signal:"SIGTERM"}))}this.children.clear(),await Promise.all(e.map(e=>zc(e,fc,yc,this.lifecycleReporters.get(e))))}}async function _c(e,t){try{const n=await e(t,["--version"]);return{available:!0,command:t,version:(n.stdout||n.stderr).split(/\r?\n/)[0]?.trim()||void 0}}catch{return{available:!1}}}class Cc{runCommand;paths;nodeAgentUrl;processSupervisor;commandOverride;lockPath;constructor(e,t,n,i,r,s,o){this.runCommand=e,this.paths=t,this.nodeAgentUrl=n,this.commandOverride=i,this.lockPath=r,this.processSupervisor=new Tc(r,s,o)}async start(e){await this.processSupervisor.stop(e.instance);const i=function(e){if("local-folder"!==e.source.type){const e=new Error("Localhost runtime currently supports local folder sources only.");throw Object.assign(e,{statusCode:400,code:"LOCAL_RUNTIME_REQUIRES_LOCAL_FOLDER"}),e}return n.resolve(e.source.path)}(e.instance),r=e.instance.runtime.port,s=!!r&&await Ec(r),o="allocate"===process.env.TASK_HANDOFF_LOCAL_INSTANCE_PORT_CONFLICT;if(r&&!s&&!o)throw Object.assign(new Error(`Local controlled instance port 127.0.0.1:${r} is already in use.`),{statusCode:409,code:"LOCAL_INSTANCE_PORT_IN_USE"});const a=r&&s?r:await async function(){const e=Number(process.env.TASK_HANDOFF_LOCAL_INSTANCE_PORT_START||19e3),t=Number.isInteger(e)&&e>0?e:19e3;for(let e=t;e<t+1e3&&e<=65535;e+=1)if(await Nc(e))return e;throw Object.assign(new Error(`No free localhost port found in range ${t}-${Math.min(t+999,65535)}.`),{statusCode:503,code:"LOCAL_INSTANCE_PORT_UNAVAILABLE"})}(),c=n.join(this.paths.dataDir,"local-instances",e.instance.id),u=n.join(c,"logs");t.mkdirSync(u,{recursive:!0,mode:448}),t.chmodSync(c,448),t.chmodSync(u,448);const[m,...p]=function(e){if(e)return e;const i=n.resolve(process.cwd(),"bin","task-handoff.js");if(t.existsSync(i))return[process.execPath,i,"web"];throw Object.assign(new Error("The bundled controlled-instance command is unavailable."),{statusCode:500,code:"LOCAL_CONTROLLED_COMMAND_MISSING"})}(this.commandOverride),h=[...p,"--host","127.0.0.1","--port",String(a)],g=d.randomUUID(),f=n.join(u,"controlled-instance.out.log"),y=n.join(u,"controlled-instance.err.log");gs(f),gs(y);const I=t.openSync(f,"a",384),A=t.openSync(y,"a",384),b=l.spawn(m,h,{cwd:i,detached:!1,stdio:["ignore",I,A],env:{...process.env,TASK_HANDOFF_CONTROL_MODE:"controlled",TASK_HANDOFF_RUNTIME_KIND:"local",TASK_HANDOFF_CONTROLLED_INSTANCE_VERSION:mo(),...this.lockPath?{TASK_HANDOFF_LOCAL_CONTROLLED_INSTANCE_LOCK_PATH:this.lockPath}:{},TASK_HANDOFF_NODE_AGENT_URL:this.nodeAgentUrl(),TASK_HANDOFF_INSTANCE_ID:e.instance.id,TASK_HANDOFF_INSTANCE_NAME:e.instance.name,TASK_HANDOFF_REGISTRATION_TOKEN:e.instance.registrationToken||"",TASK_HANDOFF_PROJECT_ID:e.project.id,TASK_HANDOFF_NODE_ID:e.node.id,TASK_HANDOFF_RUNTIME_ID:e.runtime.id,TASK_HANDOFF_LOCAL_PROCESS_NONCE:g,TASK_HANDOFF_WORKSPACE:i,TASK_HANDOFF_WORKSPACE_MODE:"local-bind",TASK_HANDOFF_DATA_DIR:c,TASK_HANDOFF_LOG_DIR:u,TASK_HANDOFF_APP_SESSION_PERSIST:"1",TASK_HANDOFF_CODEX_APP_SERVER:process.env.TASK_HANDOFF_CODEX_APP_SERVER||"1",TASK_HANDOFF_WEB_PORT:String(a),TASK_HANDOFF_WEB_HOST:"127.0.0.1",...e.modelEnv||{}}});t.closeSync(I),t.closeSync(A);try{await function(e){return new Promise((t,n)=>{const i=()=>{e.off("error",r),t()},r=t=>{e.off("spawn",i),n(t)};e.once("spawn",i),e.once("error",r)})}(b)}catch(e){const r=e instanceof Error?e.message:String(e);try{t.appendFileSync(n.join(u,"controlled-instance.lifecycle.log"),`[${(new Date).toISOString()}] spawn failed command=${m} cwd=${i} error=${r}\n`)}catch{}throw Object.assign(new Error(`Controlled instance process could not start with command ${m} in ${i}: ${r}`),{statusCode:500,code:"LOCAL_INSTANCE_PROCESS_SPAWN_FAILED"})}const w=n.join(u,"controlled-instance.lifecycle.log");this.processSupervisor.track(e.instance.id,b,e=>{t.appendFileSync(w,`[${(new Date).toISOString()}] shutdown stage=${e.stage} pid=${e.pid??""} signal=${e.signal??""} timeoutMs=${e.timeoutMs??""}\n`)}),b.on("error",e=>{try{t.appendFileSync(w,`[${(new Date).toISOString()}] process error pid=${b.pid??""} error=${e.message}\n`)}catch{}}),b.once("exit",(e,n)=>{try{t.appendFileSync(w,`[${(new Date).toISOString()}] exited pid=${b.pid??""} code=${e??""} signal=${n??""}\n`)}catch{}});const v=`http://127.0.0.1:${a}`,E=b.pid?C(b.pid):void 0;if(!(b.pid&&e.instance.registrationToken&&await this.processSupervisor.waitUntilHealthy(v,{instanceId:e.instance.id,pid:b.pid,processNonce:g,startIdentity:E},b,e.instance.registrationToken)&&this.processSupervisor.markReady(e.instance.id,b)))throw this.processSupervisor.release(e.instance.id,b),null===b.exitCode&&null===b.signalCode&&b.kill("SIGTERM"),await zc(b),Object.assign(new Error(`Controlled instance process did not become ready for instance ${e.instance.id} on ${v}.`),{statusCode:503,code:"LOCAL_INSTANCE_PROCESS_NOT_READY"});return{status:"registering",health:"unknown",connectionStatus:"online",agentStatus:"unknown",targetStatus:"unknown",uiAccessStatus:"unknown",target:{strategy:"direct-port",status:"unknown",web:v,api:`${v}/api`},workspace:{mode:"local-bind",status:"pending",path:i},runtime:{kind:"local",workspacePath:i,pid:b.pid,port:a,labels:{...e.instance.runtime.labels,"task-handoff.runtime-kind":"local",[hc]:g}}}}async stop(e){return await this.processSupervisor.stop(e.instance),{status:"stopped",health:"unknown",connectionStatus:"offline",agentStatus:"offline",targetStatus:"unknown",uiAccessStatus:"unknown",target:{...e.instance.target,status:"unknown"},runtime:e.instance.runtime}}async restart(e){return this.start(e)}async delete(e,t){return await this.stop(e),on.parse({instanceId:e.instance.id,containerDeleted:!0,completed:!0,deletedVolumes:[],retainedVolumes:[],volumeResults:[]})}async check(e){const[t,n]=await Promise.all([_c(this.runCommand,"codex"),_c(this.runCommand,"claude")]);return{status:"online",capabilities:So({...e.capabilities,apps:{terminal:!0,codex:t,claude:n}})}}async stopAll(){await this.processSupervisor.stopAll()}}const kc=["codex","claude"],Oc=5e3,Rc=C(process.pid);function xc(e){const t=process.env[e]?.trim();return t||void 0}function Dc(e){const t=e.authorization;return"string"==typeof t&&t.startsWith("Bearer ")?t.slice(7).trim():void 0}function Pc(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 Mc(e){return!e.ip&&!e.socket.remoteAddress&&!e.socket.remoteFamily}function Lc(){return(new Date).toISOString()}async function jc(e,t){if(!t.target.web)return"unknown";const n=new AbortController,i=setTimeout(()=>n.abort(),2e3);try{return(await e(`${Vc(t)}/api/health`,{signal:n.signal})).ok?"reachable":"endpoint-unreachable"}catch{return"endpoint-unreachable"}finally{clearTimeout(i)}}async function $c(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 Fc(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=Vc(t),s=Number(process.env.TASK_HANDOFF_CONFIG_AUTO_IMPORT_TIMEOUT_MS||Oc);for(const o of kc)try{const a=await $c(e,`${r}/api/config-sync/import/${encodeURIComponent(o)}`,{method:"POST"},Number.isFinite(s)&&s>0?s:Oc);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 Uc(e,t,n,i){const r=t.requireInstance(n);if(t.instancePrivateConfigs.materialize(r.id,r.registrationToken,t.resolvedAssignedModelEnvironment(n)),"reachable"!==r.targetStatus||!r.target.web)return!1;let s;try{s=await $c(e,`${Vc(r)}/api/internal/model-environment`,{method:"PUT",headers:{"content-type":"application/json",authorization:`Bearer ${r.registrationToken}`},body:JSON.stringify(t.resolvedAssignedModelEnvironment(n))},Oc)}catch(e){return i?.({instanceId:n,targetWeb:r.target.web,error:e instanceof Error?e.message:String(e)},"node instance model environment live sync deferred"),!1}return!!s.ok||(i?.({instanceId:n,targetWeb:r.target.web,statusCode:s.status},"node instance model environment live sync deferred"),!1)}function Vc(e){const t=e.target.web;if(!t){const t=new Error(`Instance ${e.id} does not have a web endpoint.`);throw Object.assign(t,{statusCode:409,code:"NODE_INSTANCE_WEB_ENDPOINT_MISSING"}),t}if("direct-port"!==e.target.strategy)return t.replace(/\/$/,"");try{const e=new URL(t);return e.port?(e.hostname=process.env.TASK_HANDOFF_NODE_AGENT_PROXY_HOST||"127.0.0.1",e.toString().replace(/\/$/,"")):t.replace(/\/$/,"")}catch{return t.replace(/\/$/,"")}}async function Hc(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($i.parse({...o,status:"starting",updatedAt:Lc()}));r.diagnostic({instanceId:i,action:"start",reason:s,runtimeId:o.runtimeId,imageId:o.imageSelection?.imageId},"node instance start requested");const a=e.applyInstanceLifecycle(i,{type:"start-requested"}),c=t.forRuntime(e.requireRuntime(a.runtimeId)),d=await c.start(e.context(a)),l=await jc(n,$i.parse({...a,...d,target:d.target?{...a.target,...d.target}:a.target,workspace:d.workspace?{...a.workspace,error:void 0,...d.workspace}:a.workspace,runtime:d.runtime?{...a.runtime,...d.runtime}:a.runtime,updatedAt:Lc()})),u=e.applyInstanceLifecycle(i,{type:"runtime-lifecycle-completed",baseline:a,observation:{...d,target:d.target?{...d.target,status:l}:void 0,workspace:d.workspace?{error:void 0,...d.workspace}:void 0,targetStatus:l,uiAccessStatus:l}});return r.diagnostic({instanceId:i,action:"start",reason:s,status:u.status,connectionStatus:u.connectionStatus,targetStatus:u.targetStatus,targetWeb:u.target.web,containerName:u.runtime.containerName},"node instance start completed"),u}async function qc(e={}){const t=e.token||process.env.TASK_HANDOFF_NODE_AGENT_TOKEN,i=Number(e.port||process.env.TASK_HANDOFF_NODE_AGENT_PORT||"8091"),c=`http://127.0.0.1:${i}`,d=e.containerUrl||process.env.TASK_HANDOFF_NODE_AGENT_CONTAINER_URL,l=ps(e.dataDir),u=e.remoteSecret||process.env.TASK_HANDOFF_NODE_AGENT_REMOTE_SECRET,p=e.remoteKeyId||process.env.TASK_HANDOFF_NODE_AGENT_REMOTE_KEY_ID,g=new Ba(l),f=g.resolveNodeId(e.nodeId||process.env.TASK_HANDOFF_NODE_ID),y=e.connectionMode||("local-ipc"===process.env.TASK_HANDOFF_NODE_AGENT_CONNECTION_MODE?"local-ipc":"local-loopback"),I=e.ipcPath||process.env.TASK_HANDOFF_NODE_AGENT_IPC_PATH||ys(l.dataDir),A="local-ipc"===y?`ipc://${encodeURIComponent(I)}`:c,w=e.platform||process.platform,v=e.arch||process.arch,E=new To(l,f,c,d,i,w);E.node.connectionMode=y,E.node.controlEndpoint=A,E.node.endpoint=A,E.init();const N=e.dockerCommandRunner||tr,S=new ir(N,e.dockerTerminalCommandRunner),z=new hr(N,{publishHost:"127.0.0.1",imageService:S});let T;const _=new pc(new mc(z,N,w,v),new Cc(e.dockerCommandRunner||tr,l,()=>E.localNodeAgentUrl,function(){const e=process.env.TASK_HANDOFF_LOCAL_CONTROLLED_COMMAND_ARGV?.trim();if(!e){const e=process.env.TASK_HANDOFF_LOCAL_CONTROLLED_COMMAND?.trim();return e?e.split(/\s+/):void 0}let t;try{t=JSON.parse(e)}catch{throw Object.assign(new Error("TASK_HANDOFF_LOCAL_CONTROLLED_COMMAND_ARGV must be valid JSON."),{code:"LOCAL_CONTROLLED_COMMAND_INVALID"})}if(!Array.isArray(t)||!t.length||t.some(e=>"string"!=typeof e||!e))throw Object.assign(new Error("TASK_HANDOFF_LOCAL_CONTROLLED_COMMAND_ARGV must be a non-empty string array."),{code:"LOCAL_CONTROLLED_COMMAND_INVALID"});return t}(),e.localControlledInstanceLockPath||process.env.TASK_HANDOFF_LOCAL_CONTROLLED_INSTANCE_LOCK_PATH,e=>T.handleUnexpectedLocalExit(e.instanceId,new Error(`Local controlled instance exited unexpectedly (pid=${e.pid??"unknown"}, code=${e.code??"none"}, signal=${e.signal??"none"}).`)),(e,t)=>U.log.error({error:e,instanceId:t.instanceId,pid:t.pid},"local controlled instance exit recovery failed"))),C=e.updateCommandRunner||e.dockerCommandRunner||tr,k=e.fetchImpl||fetch,O=new Map,R=async e=>{const t=E.requireInstance(e);if(!(xt(t.capabilities).features.aiSessionPersistenceSettings&&"reachable"===t.targetStatus&&t.target.web&&t.registrationToken))return!1;const n=`${t.processIncarnationId||"unknown"}:${t.config.aiSessionHistoryLimit}`;if(O.get(e)===n)return!0;let i;try{i=await $c(k,`${Vc(t)}/api/internal/ai-session-persistence-settings`,{method:"PUT",headers:{"content-type":"application/json",authorization:`Bearer ${t.registrationToken}`},body:JSON.stringify({historyLimit:t.config.aiSessionHistoryLimit})},Oc)}catch(t){return ee.warn({instanceId:e,error:t instanceof Error?t.message:String(t)},"node instance AI session persistence settings live sync deferred"),!1}return i.ok?(O.set(e,n),!0):(ee.warn({instanceId:e,statusCode:i.status},"node instance AI session persistence settings live sync deferred"),!1)},x=new Ss({cacheDir:n.join(l.dataDir,"runtime-artifacts"),fetchImpl:k}),D=e.resolveRuntimeArtifactRelease||((e,t,n)=>zs(e,t,n,k)),P=async(t,n,i)=>{const r=await n.artifactTarget(i);if(e.resolveRuntimeArtifact)return e.resolveRuntimeArtifact(t,r.platform,r.arch);const s=await D(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 x.resolve(s.identity,s.source)},M=e=>_.forRuntime(E.requireRuntime(e.runtimeId)),L=e=>{const t=M(e);return uc(t)?t:void 0},j=e=>{const t=L(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})},$=e=>Boolean(L(e)),F=(e,t)=>{const n=E.context(e);return P(t,j(e),n)},U=s({logger:e.logger??!0}),V=new fs(l,{logger:(e,t)=>U.log.warn(t,e)}),H=()=>E.listInstances().map(e=>e.id),q=()=>{try{V.run(H())}catch(e){U.log.warn({error:e},"node-agent persistence maintenance failed")}};q();const B=setInterval(()=>{q()},216e5);B.unref();const K=setInterval(()=>{(()=>{try{V.capActiveInstanceLogs(H())}catch(e){U.log.warn({error:e},"node-agent active log maintenance failed")}})()},6e4);K.unref();const G={requests:0,active:0,completed:0,aborted:0,limitRejected:0,responseBytes:0,totalDurationMs:0,maxResponseBytes:da()};U.decorate("nodeAgentState",E),await U.register(o);const J=new Gr(E,t,{logger:U.log,safetyIntervalMs:Number(process.env.TASK_HANDOFF_EVENT_CONNECTION_SAFETY_INTERVAL_MS)||void 0}),W=new Ts(E.controlledInstances,mo,{isInstalled:async(e,t)=>{const n=await F(e,t),i=await j(e).inspectRuntime(E.context(e),n.identity);if(i&&e.runtime.labels["task-handoff.bootstrap-backup"]){const t=E.requireInstance(e.id),n={...t.runtime.labels};delete n["task-handoff.bootstrap-backup"],E.controlledInstances.put($i.parse({...t,runtime:{...t.runtime,labels:n},updatedAt:Lc()}))}return i},beginDrain:async e=>{try{const t=await async function(e,t){const n=Vc(t);if(t.registrationToken&&(await $c(e,`${n}/api/internal/node-agent/drain`,{method:"POST",headers:{authorization:`Bearer ${t.registrationToken}`}},1e4)).ok)return{requested:t.apps.runningCount,failures:[]};const i=await $c(e,`${n}/api/apps/sessions`,{method:"GET",headers:{"cache-control":"no-cache"}},5e3);if(!i.ok)throw new Error(`Could not list app sessions for runtime drain (HTTP ${i.status}).`);const r=function(e){if(!e||"object"!=typeof e||Array.isArray(e))return[];const t=e.data;if(Array.isArray(t))return t;if(!t||"object"!=typeof t||Array.isArray(t))return[];const n=t.snapshot,i=(n&&"object"==typeof n&&!Array.isArray(n)?n:t).sessions;return Array.isArray(i)?i:[]}(await i.json()).flatMap(e=>{if(!e||"object"!=typeof e||Array.isArray(e))return[];const t=e;return"running"===t.status&&"string"==typeof t.id&&t.id?[t.id]:[]}),s=await Promise.all(r.map(async t=>{try{const i=await $c(e,`${n}/api/apps/sessions/${encodeURIComponent(t)}/stop`,{method:"POST"},5e3);return i.ok?void 0:{sessionId:t,error:`HTTP ${i.status}`}}catch(e){return{sessionId:t,error:e instanceof Error?e.message:String(e)}}}));return{requested:r.length,failures:s.filter(e=>Boolean(e))}}(k,e);t.failures.length?U.log.warn({instanceId:e.id,requested:t.requested,failures:t.failures},"runtime convergence could not stop every app session"):U.log.info({instanceId:e.id,requested:t.requested},"runtime convergence requested app session drain")}catch(t){U.log.warn({instanceId:e.id,error:t instanceof Error?t.message:String(t)},"runtime convergence could not request app session drain")}},endDrain:async e=>{try{await async function(e,t){return!!t.registrationToken&&(await $c(e,`${Vc(t)}/api/internal/node-agent/resume`,{method:"POST",headers:{authorization:`Bearer ${t.registrationToken}`}},5e3)).ok}(k,e)&&U.log.info({instanceId:e.id},"runtime convergence released app session drain")}catch(t){U.log.warn({instanceId:e.id,error:t instanceof Error?t.message:String(t)},"runtime convergence could not release app session drain")}},install:async(e,t)=>{const n=j(e);await n.installRuntime(E.context(e),await F(e,t))},restart:async e=>{const t=M(e),n=E.applyInstanceLifecycle(e.id,{type:"convergence-restart-requested"}),i=await t.restart(E.context(n));E.applyInstanceLifecycle(e.id,{type:"runtime-lifecycle-completed",baseline:n,observation:i})},onForcedDrain:e=>U.log.warn({instanceId:e.id},"runtime convergence drain deadline reached; restarting instance")},{drainTimeoutMs:Number(process.env.TASK_HANDOFF_RUNTIME_DRAIN_TIMEOUT_MS)||void 0,verificationTimeoutMs:Number(process.env.TASK_HANDOFF_RUNTIME_VERIFY_TIMEOUT_MS)||void 0,maxAttempts:Number(process.env.TASK_HANDOFF_RUNTIME_MAX_ATTEMPTS)||void 0});E.controlledInstances.setOnStored(e=>{J.publishInstanceLifecycle(e),E.updateJobs.reconcileRollouts(E.listInstances(),mo())}),J.start(),U.decorate("nodeAgentEventForwarder",J);const Y=new es(N,()=>E.listInstances().filter(e=>"docker"===E.requireRuntime(e.runtimeId).type),e=>J.publish("instance.metrics.snapshot",e,{instanceId:e.instanceId}));Y.start(),U.decorate("nodeAgentRuntimeMetrics",Y);const X=(oe=process.env.TASK_HANDOFF_DIAGNOSTIC_LOGS,["1","true","yes","on"].includes(String(oe||"").trim().toLowerCase())),Q=new va(g,f,u,p),Z=(e,t)=>{X&&U.log.info(e,t)},ee={diagnostic:Z,warn:(e,t)=>U.log.warn(e,t)},te=new Jo,ne=new na(E.environmentTemplates,E.instancePrivateConfigs,z,e=>E.requireInstance(e),e=>E.requireRuntime(e),(e,t)=>te.run(e,t),e=>E.listInstances().some(t=>t.environmentTemplateOrigin?.imageId===e)),ie=async(e,t,n=()=>!0)=>{try{if(!n())return E.requireInstance(e);let i=E.requireInstance(e);"failed"===i.runtimeVersion?.phase&&$(i)&&(i=E.controlledInstances.put($i.parse({...i,ready:!1,runtimeVersion:ho(_s(i)),updatedAt:Lc()})));const r=E.requireRuntime(i.runtimeId);await Hc(E,_,k,e,ee);const s=E.requireInstance(e);if("docker"===r.type&&s.imageProvisioning&&"ready"!==s.imageProvisioning.phase)return J.syncNow(),s;if(!n())return E.requireInstance(e);T.markRestored(e);let o=E.requireInstance(e);if($(o)){try{o=await W.schedule(e,{startRequested:!0})}catch(n){o=E.requireInstance(e),ee.warn({instanceId:e,action:"runtime.converge",reason:t,error:n instanceof Error?n.message:String(n)},"node instance runtime convergence failed after start")}"matched"!==o.runtimeVersion?.phase&&o.runtimeVersion?.error&&ee.warn({instanceId:e,action:"runtime.converge",reason:t,error:o.runtimeVersion.error},"node instance started with pending runtime convergence")}return n()?(await Fc(k,o,"start",ee),J.syncNow(),o):E.requireInstance(e)}catch(n){throw E.applyInstanceLifecycle(e,{type:"start-failed",error:n}),J.syncNow(),ee.warn({instanceId:e,action:"start",reason:t,error:n instanceof Error?n.message:String(n)},"node instance start failed"),n}},re=new Qo(E,S,{sync:()=>J.syncNow(),diagnostic:ee.diagnostic,warn:ee.warn,publish:(e,t,n)=>J.publish(e,t,{instanceId:n}),runInstanceOperation:(e,t)=>te.run(e,t)}),se=e=>{const t=te.intent(e.id);re.provision(e,async()=>{await ie(e.id,"image-ready",()=>te.isIntentCurrent(e.id,t)).catch(()=>{})})};var oe;T=new Qa({state:E,runtimeAdapters:_,convergence:W,restoreInstance:e=>Hc(E,_,k,e,ee,"restore"),autoImport:e=>Fc(k,e,"start",ee),provisionImage:se,stopImageProvisioning:()=>re.stop(),usesManagedArtifact:$,warn:ee.warn,error:(e,t)=>U.log.error(e,t),runInstanceOperation:(e,t)=>te.run(e,t)});const ae=new Wa({nodeId:f,jobs:E.updateJobs,runCommand:C,currentRuntimeVersion:mo,listInstances:()=>E.listInstances(),resolveRuntimeArtifacts:async e=>(await(async e=>{const t=new Map;for(const e of _.managedAdapters()){const n=await e.artifactTarget();t.set(`${n.platform}-${n.arch}`,{adapter:e})}for(const e of E.listInstances()){const n=L(e);if(!n)continue;const i=E.context(e),r=await n.artifactTarget(i);t.set(`${r.platform}-${r.arch}`,{adapter:n,context:i})}return(await Promise.all([...t.values()].map(({adapter:t,context:n})=>P(e,t,n)))).sort((e,t)=>`${e.identity.platform}/${e.identity.arch}`.localeCompare(`${t.identity.platform}/${t.identity.arch}`))})(e)).map(e=>e.identity),moduleDir:("undefined"==typeof document?require("url").pathToFileURL(__filename).href:b&&"SCRIPT"===b.tagName.toUpperCase()&&b.src||new URL("cli.js",document.baseURI).href)?n.dirname(r.fileURLToPath("undefined"==typeof document?require("url").pathToFileURL(__filename).href:b&&"SCRIPT"===b.tagName.toUpperCase()&&b.src||new URL("cli.js",document.baseURI).href)):__dirname});return U.setErrorHandler((e,t,n)=>{const i=function(e){if(e instanceof a.z.ZodError)return{statusCode:400,code:"VALIDATION_ERROR",message:e.issues.map(e=>`${e.path.join(".")||"body"}: ${e.message}`).join("; "),details:{issues:e.issues.map(e=>({path:e.path.map(String),code:e.code,message:e.message}))}};const t=e&&"object"==typeof e?e:{};return{statusCode:"number"==typeof t.statusCode?t.statusCode:500,code:"string"==typeof t.code?t.code:"NODE_AGENT_ERROR",message:e instanceof Error?e.message:String(e),...t.details&&"object"==typeof t.details&&!Array.isArray(t.details)?{details:t.details}:{},..."boolean"==typeof t.retryable?{retryable:t.retryable}:{}}}(e);(X||i.statusCode>=500)&&(i.statusCode>=500?U.log.error.bind(U.log):U.log.warn.bind(U.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}:{}}})}),U.addHook("preHandler",async e=>{const n=Q.verify(e);if(n){if(g.isRevokedPairing(n)&&"/api/node-agent/pairing/current"!==e.url.split("?")[0]){const e=new Error("The node agent pairing used for this request has been revoked.");throw Object.assign(e,{statusCode:401,code:"NODE_AGENT_HMAC_KEY_REVOKED"}),e}e.nodeAgentAuthKeyId=n}else if(Mc(e)){if(t&&Dc(e.headers)!==t){const e=new Error("Invalid node agent token.");throw Object.assign(e,{statusCode:401,code:"NODE_AGENT_UNAUTHORIZED"}),e}}else if("/api/node-agent/pairing/complete"!==e.url.split("?")[0]&&!function(e){const t=e.split("?")[0];return/^\/api\/node-agent\/instances\/[^/]+\/(register|heartbeat)$/.test(t)}(e.url)){if(Q.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 Pc(e.ip)||Pc(e.socket.remoteAddress)||!e.ip&&!e.socket.remoteAddress&&!e.socket.remoteFamily}(e)){const e=new Error("Local node agent access is only accepted from loopback or local IPC connections.");throw Object.assign(e,{statusCode:401,code:"NODE_AGENT_LOCAL_TOKEN_REQUIRES_LOOPBACK"}),e}if(t&&Dc(e.headers)!==t){const e=new Error("Invalid node agent token.");throw Object.assign(e,{statusCode:401,code:"NODE_AGENT_UNAUTHORIZED"}),e}}}),U.addHook("onClose",async()=>{clearInterval(B),clearInterval(K),Y.stop(),J.stop(),await T.stop()}),U.decorate("nodeAgentRestoreManagedInstances",()=>T.restoreManagedInstances()),U.decorate("nodeAgentRecoverManagedInstances",()=>T.recoverManagedInstances()),U.decorate("nodeAgentStartRecoverySupervisor",()=>T.start()),U.get("/api/node-agent/health",async()=>{return{data:{ok:!0,role:"node-agent",process:{pid:process.pid,...Rc?{startIdentity:Rc}:{}},listener:{host:"127.0.0.1",port:E.currentListenerPort},nodeId:f,platform:lc(w),arch:process.arch,protocolVersion:St,capabilities:{modelEndpointProbe:!0,aiSessionHistoryLimit:!0},build:(e="node-agent",{component:e,packageName:"@task-handoff/node-agent",packageVersion:mo(),protocolVersion:St,buildId:xc("TASK_HANDOFF_BUILD_ID"),builtAt:xc("TASK_HANDOFF_BUILT_AT"),gitCommit:xc("TASK_HANDOFF_GIT_COMMIT"),imageRef:xc("TASK_HANDOFF_IMAGE_REF"),imageDigest:xc("TASK_HANDOFF_IMAGE_DIGEST")}),instanceProxy:{...G},serverTime:(new Date).toISOString()}};var e}),function(e,t){e.get("/api/node-agent/settings/external-listener",async e=>({data:t(e).current()})),e.patch("/api/node-agent/settings/external-listener",async e=>({data:await t(e).update(e.body)}))}(U,e=>{if(!Mc(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(!U.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 U.nodeAgentListenerManager}),function(e,t,n){e.get("/api/node-agent/updates/jobs",async()=>({data:n.list()})),e.post("/api/node-agent/updates/check",async e=>({data:await t.check(e.body)})),e.post("/api/node-agent/updates/apply",async(e,n)=>n.code(202).send({data:await t.apply(e.body)}))}(U,ae,E.updateJobs),function(e,t){const{identity:n,nodeId:i,fetchImpl:r}=t;e.post("/api/node-agent/pairing/invites",async(e,t)=>{const r=n.createPairingInvite(Ca.parse(e.body||{}));return t.code(201).send({data:{nodeId:i,joinToken:r.token,expiresAt:r.expiresAt}})}),e.post("/api/node-agent/pairing/complete",async(e,t)=>{const r=n.completePairingInvite(ka.parse(e.body));return t.code(201).send({data:{nodeId:i,keyId:r.keyId,secret:r.secret,pairedAt:r.pairedAt}})}),e.get("/api/node-agent/control-plane-pairings",async e=>({data:n.listControlPlanePairings(e.nodeAgentAuthKeyId)})),e.delete("/api/node-agent/control-plane-pairings/:keyId",async e=>{const t=Ka.parse(e.params.keyId);return{data:{deleted:n.deleteControlPlanePairing(t,e.nodeAgentAuthKeyId)}}}),e.delete("/api/node-agent/pairing/current",async e=>({data:n.revokeCurrentControlPlanePairing(e.nodeAgentAuthKeyId||"")})),e.get("/api/node-agent/control-plane-connections",async()=>({data:n.listControlPlaneConnections().map(e=>({...e,...t.reverseTunnels()?.state(e.id)||{status:e.enabled?"connecting":"disabled"}}))})),e.delete("/api/node-agent/control-plane-connections/:connectionId",async e=>{const i=Ka.parse(e.params.connectionId),r=n.deleteControlPlaneConnection(i);return r&&t.reverseTunnels()?.connectConfigured(),{data:{deleted:r}}}),e.post("/api/node-agent/control-plane-connections",async(e,s)=>{const o=Oa.parse(e.body),a=function(e){const t=new URL(e);if("http:"!==t.protocol&&"https:"!==t.protocol){const e=new Error("Control-plane URL must use http or https.");throw Object.assign(e,{statusCode:400,code:"NODE_AGENT_REMOTE_CONTROL_PLANE_URL_INVALID"}),e}return t.toString().replace(/\/$/,"")}(o.controlPlaneUrl);return n.runControlPlaneConnectionOperation(a,async()=>{const e=n.stageControlPlaneConnection({url:a,...o.controlPlaneName?{name:o.controlPlaneName}:{},enabled:!1!==o.activate});let c;try{c=await async function(e,t,n){const i=await e(new URL("/api/node-join/complete",t).toString(),{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(n)}),r=await i.json().catch(()=>({}));if(!i.ok){const e=new Error(r.error?.message||`Control-plane node join failed with HTTP ${i.status}.`);throw Object.assign(e,{statusCode:i.status,code:r.error?.code||"NODE_AGENT_REMOTE_JOIN_FAILED"}),e}return r.data||{}}(r,a,{joinToken:o.joinToken,nodeId:i,nodeName:t.nodeName(),keyId:e.pairing.keyId,secret:e.pairing.secret,pairedAt:e.pairing.pairedAt})}catch(t){throw n.rollbackControlPlaneConnection(e),t}const d=n.commitControlPlaneConnection(e,{name:o.controlPlaneName||("string"==typeof c.name&&c.name?c.name:void 0)});let l,u=d.connection.enabled?"saved":"disabled";const m=t.reverseTunnels();if(m)try{m.connectConfigured(),d.connection.enabled&&(u="connecting")}catch(e){u="failed",l=e instanceof Error?e.message:String(e)}return s.code(201).send({data:{pairing:n.listControlPlanePairings().find(e=>e.keyId===d.pairing.keyId),connection:d.connection,tunnel:{status:u,...l?{error:l}:{}}}})})})}(U,{identity:g,nodeId:f,nodeName:()=>E.node.name,fetchImpl:k,reverseTunnels:()=>U.nodeAgentReverseTunnels}),function(e,t){e.get("/api/node-agent/runtimes",async()=>({data:t.listRuntimes()})),e.post("/api/node-agent/runtimes",async(e,n)=>n.code(201).send({data:t.createRuntime(Bo.parse(e.body))})),e.patch("/api/node-agent/runtimes/:id",async e=>({data:t.updateRuntime(e.params.id,Ko.parse(e.body))})),e.delete("/api/node-agent/runtimes/:id",async e=>({data:{deleted:t.deleteRuntime(e.params.id)}})),e.post("/api/node-agent/runtimes/:id/check",async e=>({data:await t.checkRuntime(e.params.id)})),e.get("/api/node-agent/local-folders",async()=>({data:t.listLocalFolders()})),e.get("/api/node-agent/folders/tree",async e=>({data:t.listFolderTree(Vo.parse(e.query))})),e.post("/api/node-agent/local-folders",async(e,n)=>n.code(201).send({data:t.createLocalFolder(Uo.parse(e.body))})),e.delete("/api/node-agent/local-folders/:id",async e=>({data:{deleted:t.deleteLocalFolder(e.params.id)}}))}(U,{listRuntimes:()=>E.nodeRuntimes.list(),createRuntime:e=>E.createRuntime(e),updateRuntime:(e,t)=>E.updateRuntime(e,t),deleteRuntime:e=>E.deleteRuntime(e),checkRuntime:async e=>{const t=E.requireRuntime(e);return E.checkRuntime(e,_.forRuntime(t))},listLocalFolders:()=>E.localFolders.list(),listFolderTree:us,createLocalFolder:e=>E.createLocalFolder(e),deleteLocalFolder:e=>E.localFolders.delete(e)}),function(e,t,n,i){e.get("/api/node-agent/models",async()=>({data:t.list()})),e.post("/api/node-agent/models",async(e,n)=>n.code(201).send({data:t.create(ti.parse(e.body))})),e.post("/api/node-agent/models/discover",async e=>{const n=jo.parse(e.body);return{data:await _o(i,{...n,key:t.resolveProbeKey(n.existingModelId,n.key)})}}),e.post("/api/node-agent/models/test",async e=>{const n=$o.parse(e.body);return{data:await Co(i,{...n,key:t.resolveProbeKey(n.existingModelId,n.key)})}}),e.put("/api/node-agent/models/:id/deploy",async e=>{const n=e.params.id,i=ii.parse(e.body);if(i.id!==n)throw Object.assign(new Error(`Model payload id ${i.id} does not match route id ${n}.`),{statusCode:400,code:"NODE_MODEL_ID_MISMATCH"});return{data:t.deploy(i)}}),e.patch("/api/node-agent/models/:id",async e=>({data:t.update(e.params.id,ni.parse(e.body))})),e.delete("/api/node-agent/models/:id",async e=>({data:{deleted:t.delete(e.params.id)}})),e.put("/api/node-agent/instances/:id/model-assignment",async e=>{const i=e.params.id,r=t.assign(i,ri.parse(e.body));return await n(i),{data:r}})}(U,E.modelRegistry,e=>Uc(k,E,e,ee.warn),k),function(e,t){e.get("/api/node-agent/environment-templates",async()=>({data:t.list()})),e.get("/api/node-agent/environment-templates/:id",async e=>({data:pn.parse(t.require(e.params.id))})),e.post("/api/node-agent/instances/:id/environment-templates",async(e,n)=>{const i=await t.create(e.params.id,e.body);return n.code(201).send({data:i})}),e.delete("/api/node-agent/environment-templates/:id",async e=>({data:await t.delete(e.params.id)}))}(U,ne),function(e,t){e.get("/api/node-agent/instances",async()=>({data:t.list()})),e.post("/api/node-agent/instances",async(e,n)=>{const i=await t.create(Ho.parse(e.body));return t.afterCreate(i),n.code(201).send({data:i})}),e.post("/api/node-agent/instances/:id/image-provisioning/retry",async e=>{const n=t.retryImageProvisioning(e.params.id);return t.afterImageRetry(n),{data:n}}),e.patch("/api/node-agent/instances/:id",async e=>{const n=t.update(e.params.id,qo.parse(e.body));return await t.afterUpdate(n),{data:n}}),e.post("/api/node-agent/instances/:id/register",async(e,n)=>{const i=e.params.id,r=t.sanitizeReport(i,"register",e.body),s=t.register(i,Gi.parse(r),Go(e.headers));return t.afterReport(s,"register"),n.code(201).send({data:s})}),e.post("/api/node-agent/instances/:id/heartbeat",async e=>{const n=e.params.id,i=t.sanitizeReport(n,"heartbeat",e.body),r=t.heartbeat(n,Ji.parse(i),Go(e.headers));return t.afterReport(r,"heartbeat"),{data:r}})}(U,{list:()=>E.listInstances(),create:e=>"template"===e.environmentSource?.type?ne.runTemplateOperation(e.environmentSource.environmentTemplateId,()=>E.createInstance(e)):E.createInstance(e),retryImageProvisioning:e=>re.retry(e),update:(e,t)=>{const n=E.requireInstance(e);return E.controlledInstances.put($i.parse({...n,...t,...t.config?{config:{...n.config,...t.config}}:{},updatedAt:Lc()}))},register:(e,t,n)=>E.registerInstance(e,t,n),heartbeat:(e,t,n)=>E.heartbeatInstance(e,t,n),sanitizeReport:(e,t,n)=>{const i=n&&"object"==typeof n&&!Array.isArray(n)?n.protocolVersion:void 0;if("string"!=typeof i||i===St)return n;const r=({field:n,action:r})=>U.log.warn({instanceId:e,report:t,protocolVersion:i,expectedProtocolVersion:St,field:n,action:r},"cross-version controlled instance report sanitized");return"register"===t?function(e,t){if(!e||"object"!=typeof e||Array.isArray(e))return e;const n=e,i=["instanceId","projectId","source","nodeId","runtimeId","imageSelection","instanceVersion","protocolVersion","build","controlMode","capabilities","appInventory","target","workspace","registrationToken","processIncarnationId"],r=new Set([...i,"imageId"]);for(const e of Object.keys(n))r.has(e)||t?.({field:e,action:"ignored"});return Object.prototype.hasOwnProperty.call(n,"imageId")&&t?.({field:"imageId",action:"migrated"}),{...Ki(n,i),imageSelection:cn(n.imageSelection,n.imageId)}}(n,r):function(e,t){if(!e||"object"!=typeof e||Array.isArray(e))return e;const n=["status","health","protocolVersion","build","capabilities","appInventory","apps","aiSessions","triggers","workspace","target","processIncarnationId"],i=new Set(n);for(const n of Object.keys(e))i.has(n)||t?.({field:n,action:"ignored"});return Ki(e,n)}(n,r)},afterCreate:e=>{J.syncNow(),e.imageProvisioning&&se(e)},afterImageRetry:e=>{J.syncNow(),se(e)},afterUpdate:async e=>{J.syncNow(),await R(e.id)},afterReport:(e,t)=>{J.syncNow(),R(e.id),"register"===t?Z({instanceId:e.id,action:t,protocolVersion:e.protocolVersion,build:e.build,targetStatus:e.targetStatus,targetStrategy:e.target.strategy},"node instance registered"):Z({instanceId:e.id,action:t,status:e.status,health:e.health,protocolVersion:e.protocolVersion,build:e.build,targetStatus:e.targetStatus,apps:e.apps.runningCount},"node instance heartbeat accepted"),!$(e)||e.ready&&"matched"===e.runtimeVersion?.phase||W.schedule(e.id).catch(n=>U.log.error({instanceId:e.id,error:n},`runtime convergence after ${t} failed`))}}),U.get("/api/node-agent/events",{websocket:!0},e=>{const t=e;t.send(JSON.stringify({type:"node-agent.events.connected",nodeId:f,serverTime:(new Date).toISOString()}));const n=J.addOutput(t);t.on("close",n),t.on("error",n)}),U.get("/api/node-agent/docker/images",async()=>({data:await zr(e.dockerCommandRunner)})),U.get("/api/node-agent/instances/:id/metrics",async e=>{const t=e.params.id,n=E.requireInstance(t);if("docker"!==E.requireRuntime(n.runtimeId).type){const e=new Error(`Runtime type ${E.requireRuntime(n.runtimeId).type} does not provide resource metrics.`);throw Object.assign(e,{statusCode:409,code:"INSTANCE_METRICS_UNSUPPORTED"}),e}return{data:await Y.snapshot(t)}}),function(e,t,n,i,r,s=new Jo){const o=e=>s.intent(e),a=e=>Promise.resolve(i.cancel(e)).then(()=>({ok:!0}),e=>({ok:!1,error:e})),c=(e,t)=>{if(!s.isIntentCurrent(e,t))throw Object.assign(new Error(`Instance operation for ${e} was superseded by stop or delete.`),{statusCode:409,code:"INSTANCE_OPERATION_SUPERSEDED"})};e.post("/api/node-agent/instances/:id/start",async e=>{Wo.parse(e.body);const t=e.params.id,n=o(t);return s.run(t,async()=>(c(t,n),r.allowRecovery(t),{data:await r.start(t,()=>s.isIntentCurrent(t,n))}))}),e.post("/api/node-agent/instances/:id/runtime/reconcile",async e=>{const n=e.params.id;Wo.parse(e.body);const a=o(n);return s.run(n,async()=>{c(n,a);const e=t.requireInstance(n);t.putInstance($i.parse({...e,ready:!1,runtimeVersion:ho(_s(e)),updatedAt:Yo()})),c(n,a);const s=await i.schedule(n,{startRequested:!["created","stopped"].includes(e.status),resumeCancelled:!0});return c(n,a),r.sync(),{data:s}})}),e.post("/api/node-agent/instances/:id/stop",async e=>{const i=e.params.id;t.requireInstance(i),s.invalidate(i);const o=a(i);return s.run(i,async()=>{const e=t.requireInstance(i);t.applyLifecycle(i,{type:"stop-requested"});try{await r.suppressRecovery(i);const e=await o;if("error"in e)throw e.error;const s=t.requireInstance(i);r.diagnostic({instanceId:i,action:"stop",runtimeId:s.runtimeId,containerName:s.runtime.containerName},"node instance stop requested"),await n.forRuntime(t.requireRuntime(s.runtimeId)).stop(t.context(s))}catch(n){try{t.applyLifecycle(i,{type:"stop-failed",baseline:e}),r.sync()}finally{r.allowRecovery(i)}throw n}const s=t.applyLifecycle(i,{type:"stop-completed"});return r.completeSuppressedRecovery(i),r.sync(),r.diagnostic({instanceId:i,action:"stop",status:s.status,connectionStatus:s.connectionStatus,containerName:s.runtime.containerName},"node instance stop completed"),{data:s}})}),e.post("/api/node-agent/instances/:id/restart",async e=>{const a=e.params.id;Wo.parse(e.body);const d=o(a);return s.run(a,async()=>{c(a,d),r.allowRecovery(a);let e=t.requireInstance(a);if(r.isManaged(e)&&(!e.ready||"matched"!==e.runtimeVersion?.phase)){"failed"===e.runtimeVersion?.phase&&(e=t.putInstance($i.parse({...e,runtimeVersion:ho(_s(e)),updatedAt:Yo()}))),c(a,d);const n=await i.schedule(a,{startRequested:!0});return c(a,d),r.sync(),{data:n}}r.diagnostic({instanceId:a,action:"restart",runtimeId:e.runtimeId,imageId:e.imageSelection?.imageId,containerName:e.runtime.containerName},"node instance restart requested");const s=await n.forRuntime(t.requireRuntime(e.runtimeId)).restart(t.context(e));let o=t.applyLifecycle(a,{type:"runtime-lifecycle-completed",baseline:e,observation:{...s,target:s.target?{...e.target,...s.target}:void 0}});r.markRestarted(a),c(a,d);const l=$i.parse({...o,updatedAt:Yo()}),u=await r.probe(l);return c(a,d),o=t.applyLifecycle(a,{type:"runtime-lifecycle-completed",baseline:o,observation:{target:{...o.target,status:u},targetStatus:u,uiAccessStatus:u}}),await r.autoImport(o),r.sync(),r.diagnostic({instanceId:a,action:"restart",status:o.status,connectionStatus:o.connectionStatus,targetStatus:o.targetStatus,targetWeb:o.target.web,containerName:o.runtime.containerName},"node instance restart completed"),{data:o}})}),e.post("/api/node-agent/instances/:id/delete",async e=>{const i=e.params.id,o=rn.parse(e.body);t.requireInstance(i),s.invalidate(i);const c=a(i);return s.run(i,async()=>{const e=t.requireInstance(i);"deleting"!==e.status&&t.applyLifecycle(i,{type:"stop-requested"});try{await r.suppressRecovery(i);const e=await c;if("error"in e)throw e.error;const a=t.requireInstance(i);t.putInstance($i.parse({...a,status:"deleting",ready:!1,updatedAt:Yo()})),r.diagnostic({instanceId:i,action:"delete",runtimeId:a.runtimeId,containerName:a.runtime.containerName},"node instance delete requested");const d=await n.forRuntime(t.requireRuntime(a.runtimeId)).delete(t.context(a,{}),o);if(!d.completed)return r.diagnostic({instanceId:i,action:"delete",volumeResults:d.volumeResults},"node instance delete requires retry"),r.sync(),{data:d};r.diagnostic({instanceId:i,action:"delete"},"node instance delete completed");const l=t.deleteInstance(i);return l&&(r.forgetRecovery(i),s.clearIntent(i)),r.deleteMetadata(i),l&&r.retireInstanceData(i),l&&a.environmentTemplateOrigin?.imageId&&r.releaseEnvironmentImage&&await r.releaseEnvironmentImage(a.environmentTemplateOrigin.imageId).catch(e=>{r.diagnostic({instanceId:i,action:"release-environment-image",error:e instanceof Error?e.message:String(e)},"environment image cleanup deferred after instance deletion")}),r.sync(),{data:d}}catch(n){try{t.putInstance($i.parse({...e,updatedAt:Yo()})),r.sync()}finally{r.allowRecovery(i)}throw n}})})}(U,{requireInstance:e=>E.requireInstance(e),requireRuntime:e=>E.requireRuntime(e),putInstance:e=>E.controlledInstances.put(e),deleteInstance:e=>E.controlledInstances.delete(e),applyLifecycle:(e,t)=>E.applyInstanceLifecycle(e,t),context:(e,t)=>E.context(e,t)},_,W,{start:(e,t)=>ie(e,"request",t),sync:()=>J.syncNow(),isManaged:$,probe:e=>jc(k,e),autoImport:e=>Fc(k,e,"restart",ee),markRestarted:e=>T.markRestored(e),allowRecovery:e=>T.allowRecovery(e),suppressRecovery:e=>T.suppressRecovery(e),forgetRecovery:e=>T.forgetInstance(e),completeSuppressedRecovery:e=>T.completeSuppressedOperation(e),deleteMetadata:e=>{O.delete(e),E.modelRegistry.deleteInstanceMetadata(e),E.instancePrivateConfigs.delete(e)},retireInstanceData:e=>{V.retire(e)},releaseEnvironmentImage:e=>ne.releaseUnusedImage(e),diagnostic:Z},te),function(e,t){const{fetchImpl:n,metrics:i,diagnostic:r}=t;e.post("/api/node-agent/instances/:id/proxy",async(e,i)=>{const s=e.params.id,o=Fo.parse(e.body),a=t.instanceBase(s),c=la(o.path);"POST"===o.method&&"/api/apps/sessions"===c&&await t.syncModelEnvironment(s),r({instanceId:s,action:"proxy",method:o.method,path:c,instanceBase:a},"node instance proxy requested");const d=await n(`${a}${c}`,{method:o.method,headers:{...o.headers},body:ca(o)}),l=d.headers.get("content-type")||"application/octet-stream",u=await d.text();r({instanceId:s,action:"proxy",method:o.method,path:c,statusCode:d.status,contentType:l},"node instance proxy completed"),i.code(d.status).type(l).send(u)}),e.post("/api/node-agent/instances/:id/proxy/stream",{bodyLimit:oa},async(e,s)=>{const o=Date.now();i.requests+=1,i.active+=1;const a=new AbortController;let c=0,d=!1,l=!1;const u=e=>{l||(l=!0,i.active-=1,i.totalDurationMs+=Date.now()-o,i.responseBytes+=c,i[e]+=1)},m=()=>{a.abort(),d&&u("aborted")};e.raw.once("aborted",m),s.raw.once("close",m);try{const o=e.params.id,l=Fo.parse(e.body),m=t.instanceBase(o),p=la(l.path);r({instanceId:o,action:"proxy.stream",method:l.method,path:p,instanceBase:m},"node instance streaming proxy requested");const g=await n(`${m}${p}`,{method:l.method,headers:{...l.headers},body:ca(l),signal:a.signal}),f=Number(g.headers.get("content-length"));if(Number.isFinite(f)&&f>i.maxResponseBytes)return i.limitRejected+=1,a.abort(),ua(s,i.maxResponseBytes);s.code(g.status);for(const[e,t]of Object.entries(aa(g.headers)))s.header(e,t);if(!g.body||"HEAD"===l.method)return u("completed"),s.send();const y=new h.Transform({transform(e,t,n){if(c+=e.length,c>i.maxResponseBytes)return i.limitRejected+=1,a.abort(),void n(Object.assign(new Error("Instance proxy response limit exceeded."),{code:"INSTANCE_PROXY_RESPONSE_TOO_LARGE"}));n(null,e)}});return d=!0,y.once("end",()=>u("completed")),y.once("error",()=>u("aborted")),s.send(h.Readable.fromWeb(g.body).pipe(y))}catch(e){throw u("aborted"),e}finally{e.raw.off("aborted",m),d||u("completed")}}),e.post("/api/node-agent/instances/:id/proxy/raw",{bodyLimit:oa},async(e,s)=>{const o=e.params.id,a=Fo.parse(e.body),c=t.instanceBase(o),d=la(a.path);r({instanceId:o,action:"proxy.raw",method:a.method,path:d,instanceBase:c},"node instance raw proxy requested");const l=await n(`${c}${d}`,{method:a.method,headers:{...a.headers},body:ca(a)}),u=Number(l.headers.get("content-length"));if(Number.isFinite(u)&&u>i.maxResponseBytes)return i.limitRejected+=1,await(l.body?.cancel("Instance proxy response limit exceeded.").catch(()=>{})),ua(s,i.maxResponseBytes);let m;try{m=await async function(e,t){if(!e.body)return Buffer.alloc(0);const n=[];let i=0;const r=e.body.getReader();for(;;){const{done:e,value: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)}(l,i.maxResponseBytes)}catch(e){if(!(e instanceof Error)||"INSTANCE_PROXY_RESPONSE_TOO_LARGE"!==e.code)throw e;return i.limitRejected+=1,ua(s,i.maxResponseBytes)}return r({instanceId:o,action:"proxy.raw",method:a.method,path:d,statusCode:l.status,byteLength:m.length},"node instance raw proxy completed"),{data:{status:l.status,headers:aa(l.headers),bodyBase64:m.toString("base64")}}}),e.get("/api/node-agent/instances/:id/proxy/ws/*",{websocket:!0},(e,n)=>{const i=n.params.id,s=n.params["*"]||"",o=n.url.indexOf("?"),a=o>=0?n.url.slice(o):"";let c;try{const o=t.instanceBase(i),d=new URL(`/${s}${a}`,`${o}/`);d.protocol="https:"===d.protocol?"wss:":"ws:";const l=function(e){const t=e["sec-websocket-protocol"],n=(Array.isArray(t)?t.join(","):"string"==typeof t?t:"").split(",").map(e=>e.trim()).filter(Boolean);return n.length?n:void 0}(n.headers);r({instanceId:i,action:"proxy.ws",path:`/${s}${a}`,upstreamUrl:d.toString(),protocols:l||[]},"node instance websocket proxy opening"),c=l?new m(d,l):new m(d),c.on("open",()=>{r({instanceId:i,action:"proxy.ws",path:`/${s}${a}`},"node instance websocket proxy opened"),e.on("message",(e,t)=>c?.readyState===m.OPEN&&c.send(function(e,t){return t?e:e.toString()}(e,t))),e.on("close",()=>c?.close()),e.on("error",()=>c?.close())}),c.on("message",(t,n)=>e.readyState===m.OPEN&&e.send(n?t:t.toString())),c.on("close",()=>{r({instanceId:i,action:"proxy.ws",path:`/${s}${a}`},"node instance websocket proxy closed"),e.close()}),c.on("error",t=>{r({instanceId:i,action:"proxy.ws",path:`/${s}${a}`,error:t instanceof Error?t.message:String(t)},"node instance websocket proxy failed"),e.close(1011,"Instance websocket proxy failed.")})}catch(t){r({instanceId:i,action:"proxy.ws",path:`/${s}${a}`,error:t instanceof Error?t.message:String(t)},"node instance websocket endpoint unavailable"),c?.close(),e.close(1011,"Instance websocket endpoint is not reachable.")}})}(U,{fetchImpl:k,metrics:G,instanceBase:e=>Vc(E.requireInstance(e)),syncModelEnvironment:e=>Uc(k,E,e,ee.warn),diagnostic:Z}),U}async function Bc(e){const r=ps(e.dataDir),s=function(e,i={}){return function(e,i={}){t.mkdirSync(n.dirname(e),{recursive:!0});const r=C(process.pid),s={pid:process.pid,hostname:c.hostname(),command:process.argv.join(" "),acquiredAt:(new Date).toISOString(),token:d.randomUUID(),...void 0!==i.component?{component:i.component}:{},...r?{startIdentity:r}:{},...void 0!==i.dataDir?{dataDir:i.dataDir}:{},...void 0!==i.host?{host:i.host}:{},...void 0!==i.port?{port:i.port}:{},...void 0!==i.instanceId?{instanceId:i.instanceId}:{}};for(let n=0;n<5;n+=1)try{return t.mkdirSync(e),t.writeFileSync(z(e),`${JSON.stringify({token:s.token,pid:s.pid,startIdentity:s.startIdentity,startedAt:(new Date).toISOString()})}\n`,{encoding:"utf8",mode:384,flag:"wx"}),D(e,s),{lockPath:e,owner:s,updateDetails:t=>P(e,s,t),release(){const n=O(e);n?.token===s.token&&t.rmSync(e,{recursive:!0,force:!0})}}}catch(r){if("EEXIST"!==r.code)throw r;const s=O(e);if(x(s))throw new N(e,s,i.error);if(!s&&(L(e)||F(e)<(i.incompleteLockStaleMs??2e3))){if(n+1<5){$();continue}throw new N(e,void 0,i.error)}const o=d.randomUUID();if(!U(e,o)){if(n+1<5){$();continue}throw new N(e,O(e),i.error)}const a=O(e);if(x(a))throw j(T(e)),new N(e,a,i.error);if(s?.token&&a?.token!==s.token){j(T(e));continue}if(!H(e,o))continue;t.rmSync(e,{recursive:!0,force:!0})}const o=O(e);throw new N(e,o,i.error)}(e,{...i,component:"node-agent",error:{label:"Node agent",code:"NODE_AGENT_ALREADY_RUNNING"}})}(function(){const e=process.env.TASK_HANDOFF_NODE_AGENT_LOCK_PATH?.trim();return e?n.resolve(e):n.join(c.tmpdir(),`task-handoff-node-agent-${process.getuid?.()??"user"}.lock`)}(),{dataDir:r.dataDir});try{const c=(o=e.host,a=e.port,ki.parse({bindScope:"0.0.0.0"===o.trim()?"all-ipv4":"loopback",port:a})),d=t.existsSync(r.settingsPath),l=function(e,t){return new qs(e.settingsPath,()=>({version:1,externalListener:t}),{schema:ma,sanitize:ha})}(r,c);let u=l.get().externalListener;if("allocate"===process.env.TASK_HANDOFF_NODE_AGENT_PORT_CONFLICT){const e=await async function(e,t=20){for(let n=0;n<t&&e.port+n<=65535;n+=1){const t={...e,port:e.port+n};if(await ga(t))return t}throw Object.assign(new Error(`No available node-agent port found starting at ${e.port}.`),{statusCode:503,code:"NODE_AGENT_LISTENER_PORT_UNAVAILABLE"})}(u);e.port!==u.port&&(l.put({version:1,externalListener:e}),u=e)}const m=e=>{if(!s.updateDetails({dataDir:r.dataDir,host:e.host,port:e.port,instanceId:void 0}))throw new Error("Node agent singleton ownership changed while publishing listener state.")},p={...e,port:u.port},h=await qc(p),g=h.nodeAgentState;if(!g)throw new Error("Node agent state was not initialized.");const f=new Ba(r).resolveNodeId(e.nodeId||process.env.TASK_HANDOFF_NODE_ID),y=function(e,t,n,i){const r=t.token||process.env.TASK_HANDOFF_NODE_AGENT_TOKEN,s=new Ba(n),o=new Map;let a=!1;const c=(t,n)=>{if(a||n.retry.pending||o.get(t)!==n)return;const r=n.retry.schedule(()=>{a||o.get(t)!==n||n.socket||d(t,n)});r&&(n.status="reconnecting",n.nextRetryAt=new Date(Date.now()+r.delay).toISOString(),e.log.info({nodeId:i,tunnelUrl:new URL(n.config.tunnelUrl).origin,attempt:r.attempt,delay:r.delay},"node agent reverse tunnel reconnect scheduled"))},d=(n,s)=>{let d;s.status=s.lastDisconnectedAt?"reconnecting":"connecting",s.error=void 0,s.nextRetryAt=void 0;try{d=rc(e,{...s.config,nodeId:i,port:()=>e.nodeAgentState.currentListenerPort,token:r})}catch(e){return s.status="failed",s.lastDisconnectedAt=(new Date).toISOString(),s.error=e instanceof Error?e.message:String(e),void c(n,s)}s.socket=d;const l=new ac({connectTimeoutMs:t.connectTimeoutMs,handshakeTimeoutMs:t.handshakeTimeoutMs,heartbeatIntervalMs:t.heartbeatIntervalMs,heartbeatTimeoutMs:t.heartbeatTimeoutMs,stableThresholdMs:t.stableThresholdMs,ping:()=>d.ping(),onTimeout:e=>{o.get(n)===s&&s.socket===d&&(s.status="failed",s.error=`Reverse tunnel ${e} timeout.`,d.terminate())},onStable:()=>s.retry.reset()});return s.supervisor=l,l.start(),d.on("open",()=>{o.get(n)===s&&s.socket===d&&(s.status="connecting",l.opened())}),d.on("message",t=>{if(o.get(n)!==s||s.socket!==d||"connected"===s.status)return;let r;try{r=JSON.parse(String(t))}catch{return}const a=r&&"object"==typeof r?r.type:void 0;"control-plane.hello"!==a&&"control-plane.identified"!==a||(l.activity(),l.healthy(),s.status="connected",s.lastConnectedAt=(new Date).toISOString(),s.nextRetryAt=void 0,s.error=void 0,e.log.info({nodeId:i,tunnelUrl:new URL(s.config.tunnelUrl).origin},"node agent reverse tunnel connected"))}),d.on("pong",()=>l.pong()),d.on("close",(t,r)=>{o.get(n)===s&&s.socket===d&&(l.close(),s.socket=void 0,s.lastDisconnectedAt=(new Date).toISOString(),s.error=`WebSocket closed${t?` (${t})`:""}${r?`: ${Buffer.isBuffer(r)?r.toString("utf8"):String(r)}`:""}`,a||(e.log.warn({nodeId:i,tunnelUrl:new URL(s.config.tunnelUrl).origin,code:t,reason:Buffer.isBuffer(r)?r.toString("utf8"):String(r||"")},"node agent reverse tunnel disconnected"),c(n,s)))}),d.on("error",e=>{o.get(n)===s&&s.socket===d&&(s.status="failed",s.error=e instanceof Error?e.message:String(e),d.terminate())}),d},l=(e,t)=>{const n=o.get(e);n?.retry.cancel(),n?.supervisor?.close();const i={config:t,retry:new Br,status:"connecting"};return o.set(e,i),n?.socket?.close(1e3,"Reverse tunnel reconnecting."),d(e,i)},u=(e,t)=>e.tunnelUrl===t.tunnelUrl&&e.keyId===t.keyId&&e.secret===t.secret;return{connectConfigured:()=>{a=!1;const n=new Map,r=s.resolvedControlPlaneAccess(),c=new Set;for(const{connection:t,pairing:s}of r.connections){if(!t.enabled)continue;if(!s){e.log.warn({nodeId:i,connectionId:t.id,pairingKeyId:t.pairingKeyId},"node agent control-plane connection has no pairing");continue}const r=cc(t.url);n.set(t.id,{tunnelUrl:r,keyId:s.keyId,secret:s.secret}),c.add(r)}const d=function(e){const t=e.controlPlaneTunnelUrl||process.env.TASK_HANDOFF_CONTROL_PLANE_TUNNEL_URL;return t?new URL(t).toString():void 0}(t);if(d&&!c.has(d)){const e=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);n.set(`explicit:${d}`,{tunnelUrl:d,keyId:e?.keyId,secret:e?.secret}),c.add(d)}const m=r.hasPersistedAccess?void 0:function(){const e=process.env.TASK_HANDOFF_CONTROL_PLANE_URL;if(!e)return;const t=new URL(Ia,e);return t.protocol="https:"===t.protocol?"wss:":"ws:",t.toString()}();if(m&&!c.has(m)){const e=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);n.set(`bootstrap:${m}`,{tunnelUrl:m,keyId:e?.keyId,secret:e?.secret})}(e=>{for(const[t,n]of o)e.has(t)||(n.retry.cancel(),n.supervisor?.close(),o.delete(t),n.socket?.close(1e3,"Reverse tunnel configuration removed."));for(const[t,n]of e){const e=o.get(t);e&&u(e.config,n)||l(t,n)}})(n)},state:e=>{const t=o.get(e);if(t)return{status:t.status,connection:t.supervisor?.diagnostics(),...t.lastConnectedAt?{lastConnectedAt:t.lastConnectedAt}:{},...t.lastDisconnectedAt?{lastDisconnectedAt:t.lastDisconnectedAt}:{},...t.nextRetryAt?{nextRetryAt:t.nextRetryAt}:{},...t.error?{error:t.error}:{}}},closeAll:()=>{a=!0;for(const e of o.values())e.retry.cancel(),e.supervisor?.close(),e.socket?.close(1001,"Node agent shutting down.");o.clear()}}}({log:h.log,inject:e=>h.inject(e),nodeAgentEventForwarder:h.nodeAgentEventForwarder,nodeAgentState:g},p,r,f);h.decorate("nodeAgentReverseTunnels",y);const I=new fa({app:h,state:g,settings:l,config:u,source:d?"persisted":"bootstrap",onActiveListener:m});let A;h.decorate("nodeAgentListenerManager",I),function(e){let t=!1;const n=async n=>{if(!t){t=!0,y.closeAll(),A?.close();try{await e.close()}finally{process.exitCode=n?0:process.exitCode}}},i=()=>{n("SIGINT")},r=()=>{n("SIGTERM")};process.once("SIGINT",i),process.once("SIGTERM",r),e.addHook("onClose",async()=>{process.off("SIGINT",i),process.off("SIGTERM",r)})}(h),h.addHook("onClose",async()=>{A?.close(),s.release()});try{await h.ready();const s=e.ipcPath||process.env.TASK_HANDOFF_NODE_AGENT_IPC_PATH||ys(r.dataDir);A=await async function(e,r){!function(e,i=process.platform){if("win32"!==i){t.mkdirSync(n.dirname(e),{recursive:!0,mode:448});try{t.chmodSync(n.dirname(e),448)}catch{}try{t.unlinkSync(e)}catch(e){if("ENOENT"!==e.code)throw e}}}(r);const s=i.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(r,()=>{s.off("error",t),e()})}),s}(h,s),await I.start(),y.connectConfigured(),h.nodeAgentStartRecoverySupervisor?.()}catch(e){throw await h.close(),e}}catch(e){throw s.release(),e}var o,a}function Kc(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 Gc(e){if("local-ipc"!==e&&"local-loopback"!==e)throw new Error("Connection mode must be local-ipc or local-loopback.");return e}function Jc(e){const t=Number(e);if(!Number.isInteger(t)||t<=0)throw new Error("Expiry must be a positive integer.");return t}(async function(){const t=new e.Command;t.name("task-handoff-node-agent").description("Run a TaskHandoff node agent.").version(E("@task-handoff/cli")).option("--host <host>","Node agent host",process.env.TASK_HANDOFF_NODE_AGENT_HOST||"127.0.0.1").option("-p, --port <port>","Node agent port",Kc,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",Gc).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 Bc({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",Jc).option("--json","Print raw JSON output").action(async e=>{const n=t.opts(),r=e.ipcPath||n.ipcPath||process.env.TASK_HANDOFF_NODE_AGENT_IPC_PATH,s=e.dataDir||n.dataDir||process.env.TASK_HANDOFF_NODE_AGENT_DATA_DIR,o=e.endpoint?void 0:r||ys(s||ms()),a=await async function(e){const t={"content-type":"application/json",...e.token?{authorization:`Bearer ${e.token}`}:{}},n=JSON.stringify({...e.expiresInMs?{expiresInMs:e.expiresInMs}:{}}),r=e.endpoint?await fetch(`${e.endpoint.replace(/\/$/,"")}/api/node-agent/pairing/invites`,{method:"POST",headers:t,body:n}):await async function(e,t,n={}){const r=n.method||"GET",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,c)=>{const d=i.request({socketPath:e,method:r,path:`/api/node-agent${t}`,headers:Object.fromEntries(o.entries())},e=>{const t=e.statusCode||500;a(new Response("HEAD"!==r&&204!==t&&205!==t&&304!==t?h.Readable.toWeb(e):null,{status:t,headers:e.headers}))});d.on("error",c);const l=()=>d.destroy(new DOMException("The operation was aborted.","AbortError"));n.signal?.aborted?l():n.signal?.addEventListener("abort",l,{once:!0}),d.once("close",()=>n.signal?.removeEventListener("abort",l)),void 0!==s&&d.write(s),d.end()})}(e.ipcPath,"/pairing/invites",{method:"POST",headers:t,body:n}),s=await r.json().catch(()=>({}));if(!r.ok)throw new Error(s.error?.message||`Node agent pairing invite failed with HTTP ${r.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,t,n=require("commander"),i=require("node:fs"),r=require("node:path"),s=require("node:http"),o=require("node:url"),a=require("fastify"),c=require("@fastify/websocket"),d=require("zod"),l=require("node:os"),u=require("node:crypto"),m=require("node:child_process"),p=require("node-pty"),h=require("ws"),g=require("node:net"),f=require("node:stream"),y=require("node:fs/promises"),I=require("node:stream/promises"),A=require("tar"),b=require("write-file-atomic"),w=require("semver"),v="undefined"!=typeof document?document.currentScript:null;function E(e,t){try{const n=JSON.parse(i.readFileSync(e,"utf8"));if(t&&n.name!==t)return;return"string"==typeof n.version&&n.version.trim()?n.version.trim():void 0}catch{return}}function N(e){if(e)try{return r.dirname(i.realpathSync(e))}catch{return}}function S(e,t=process.env,n=e){const i=t.TASK_HANDOFF_VERSION?.trim();if(i)return i;const s=n.split("/").at(-1),o=process.argv[1]?r.resolve(process.argv[1]):void 0,a=o?r.dirname(o):void 0,c=[N(o),a,process.cwd()].filter(e=>Boolean(e));for(const t of new Set(c)){let n=t;for(;;){const t=E(r.join(n,"package.json"),e);if(t)return t;const i=r.dirname(n);if(i===n)break;n=i}}let d;for(const e of new Set(c)){let t=e;for(;;){if(s){const e=E(r.join(t,"packages",s,"package.json"),n);if(e)return e}d||=E(r.join(t,"package.json"));const e=r.dirname(t);if(e===t)break;t=e}}return d||"unknown"}var z=function(){if(t)return e;t=1;const n=i,{spawnSync:r}=m;return e={processStartIdentity:function(e,t=process.platform){if(Number.isInteger(e)&&!(e<=0)){if("linux"===t)try{const t=n.readFileSync(`/proc/${e}/stat`,"utf8"),i=t.lastIndexOf(")");if(i<0)return;const r=t.slice(i+2).trim().split(/\s+/)[19];return r?`linux:${r}`:void 0}catch{return}if(["darwin","freebsd","openbsd","aix","sunos"].includes(t)){const n=r("ps",["-o","lstart=","-p",String(e)],{encoding:"utf8",timeout:1e3}),i=0===n.status?n.stdout.trim().replace(/\s+/g," "):"";return i?`${t}:${i}`:void 0}if("win32"===t){const t=r("powershell.exe",["-NoProfile","-NonInteractive","-Command",`(Get-Process -Id ${e} -ErrorAction Stop).StartTime.ToUniversalTime().Ticks`],{encoding:"utf8",timeout:2e3}),n=0===t.status?t.stdout.trim():"";return/^\d+$/.test(n)?`win32:${n}`:void 0}}}}}();class T 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 _(e){return r.join(e,"owner.json")}function C(e){return r.join(e,"initializing.json")}function k(e){return r.join(e,"recovering.json")}function O(e){return Number.isInteger(e)&&Number(e)>0}function R(e){try{const t=JSON.parse(i.readFileSync(_(e),"utf8"));if(O(t.pid)&&"string"==typeof t.startTime){const e=t;return{pid:e.pid,hostname:"string"==typeof e.hostname&&e.hostname?e.hostname:l.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(!(O(t.pid)&&"string"==typeof t.hostname&&t.hostname&&"string"==typeof t.command&&"string"==typeof t.acquiredAt&&Number.isFinite(Date.parse(t.acquiredAt))&&"string"==typeof t.token&&t.token))return;return t}catch{return}}const x=R;function D(e){if(!O(e))return!1;try{return process.kill(Number(e),0),!0}catch(e){return"EPERM"===e.code}}function P(e){if(!e||!D(e.pid))return!1;if(!e.startIdentity)return!0;const t=z.processStartIdentity(e.pid);return void 0===t||t===e.startIdentity}function M(e,t){const n=r.join(e,`.owner-${t.token}.tmp`);i.writeFileSync(n,`${JSON.stringify(t,null,2)}\n`,{encoding:"utf8",mode:384,flag:"wx"});const s=j(e);if(s?.token!==t.token)throw F(n),new Error(`Process lock initialization was superseded: ${e}`);i.renameSync(n,_(e)),F(C(e))}function L(e,t,n){const s=x(e);if(s?.token!==t.token)return!1;const o={...t};for(const[e,t]of Object.entries(n))void 0===t?delete o[e]:Object.assign(o,{[e]:t});const a=r.join(e,`.owner-update-${t.token}-${u.randomUUID()}.tmp`);try{if(i.writeFileSync(a,`${JSON.stringify(o,null,2)}\n`,{encoding:"utf8",mode:384,flag:"wx"}),x(e)?.token!==t.token)return!1;i.renameSync(a,_(e));for(const e of Object.keys(t))delete t[e];return Object.assign(t,o),!0}catch(e){if("ENOENT"===e.code)return!1;throw e}finally{F(a)}}function j(e){try{return JSON.parse(i.readFileSync(C(e),"utf8"))}catch{return}}function $(e){const t=j(e);return O(t?.pid)&&P({pid:t.pid,startIdentity:t.startIdentity})}function F(e){try{i.unlinkSync(e)}catch(e){if("ENOENT"!==e.code)throw e}}function U(){Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,20)}function V(e){try{const t=j(e),n=Date.parse(t?.startedAt||"");return Number.isFinite(n)?Math.max(0,Date.now()-n):Math.max(0,Date.now()-i.statSync(e).mtimeMs)}catch{return 0}}function H(e,t){try{return i.writeFileSync(k(e),`${JSON.stringify({token:t,pid:process.pid,startedAt:(new Date).toISOString()})}\n`,{encoding:"utf8",mode:384,flag:"wx"}),!0}catch(n){if("EEXIST"===n.code)return!!function(e){const t=k(e),n=q(t),s=Date.parse(n?.startedAt||"");if(D(n?.pid)||Number.isFinite(s)&&Date.now()-s<2e3)return!1;const o=r.join(e,`.recovering-${u.randomUUID()}.stale`);try{i.renameSync(t,o)}catch(e){if(["ENOENT","EEXIST"].includes(e.code||""))return!1;throw e}const a=q(o);if(a?.token===n?.token)return F(o),!0;try{i.linkSync(o,t)}catch(e){if("EEXIST"!==e.code)throw e}finally{F(o)}return!1}(e)&&H(e,t);if("ENOENT"===n.code)return!1;throw n}}function q(e){try{return JSON.parse(i.readFileSync(e,"utf8"))}catch{return}}function B(e,t){return q(k(e))?.token===t}function K(){return(new Date).toISOString()}const G=6048e5;function J(e,t){const n=r.resolve(e),i=r.resolve(n,t);if(r.dirname(i)!==n||r.basename(i)!==t)throw new Error(`Retention entry is not a direct child of its managed root: ${t}`);return i}function W(e){if(i.existsSync(e)){const t=i.lstatSync(e);if(!t.isDirectory()||t.isSymbolicLink())throw new Error(`Managed persistence path must be a real directory: ${e}`)}i.mkdirSync(e,{recursive:!0,mode:448}),i.chmodSync(e,448)}const Y=20971520,X=41943040,Q="ai.sessions",Z="ai-session.snapshot",ee="ai-session.patch",te="ai-session.removed",ne="ai-session.message-delta",ie="ai-session.timeline-item",re=d.z.string().trim().min(1).max(80),se=d.z.enum(["app-session","ai-session"]),oe=d.z.enum(["image","file"]),ae={scopeType:d.z.enum(["session","create-request"]),scopeId:d.z.string().trim().min(1).max(160),kind:oe,name:d.z.string().trim().min(1).max(240),mime:d.z.string().trim().min(1).max(120)};d.z.object({...ae,size:d.z.coerce.number().int().positive().max(Y)}).strict();const ce=d.z.string().regex(/^cia_[a-f0-9]{24}$/);d.z.object({attachmentId:ce,...ae,size:d.z.number().int().positive().max(Y)}).strict(),d.z.object({offset:d.z.coerce.number().int().nonnegative()}).strict(),d.z.object({attachmentId:ce,offset:d.z.number().int().nonnegative()}),d.z.object({id:ce,kind:oe,name:d.z.string().trim().min(1).max(240),mime:d.z.string().trim().min(1).max(120),size:d.z.number().int().positive().max(Y),expiresAt:d.z.string().datetime()});const de=d.z.object({id:d.z.string().trim().min(1).max(120),kind:oe,name:d.z.string().trim().min(1).max(240),mime:d.z.string().trim().min(1).max(120),size:d.z.number().int().min(0).max(Number.MAX_SAFE_INTEGER)}),le=d.z.enum(["available","expired","missing"]),ue=de.extend({contentState:le.default("available")}).strict(),me=d.z.object({id:d.z.string().trim().min(1).max(240),text:d.z.string(),attachments:d.z.array(ue).max(6).default([])}).strict(),pe=d.z.enum(["running","waiting","idle","failed"]);d.z.object({instanceId:d.z.string().trim().min(1).max(160),sessionId:d.z.string().trim().min(1).max(120),unread:d.z.boolean(),sessionUpdatedAt:d.z.string().datetime(),updatedAt:d.z.string().datetime()}).strict();const he=d.z.enum(["thinking","tool","editing","approval","responding","unknown"]),ge=d.z.object({id:d.z.string().trim().min(1).max(240).optional(),kind:d.z.string().trim().min(1).max(80).optional(),name:d.z.string().trim().min(1).max(120),inputPreview:d.z.string().trim().max(500).optional(),startedAt:d.z.string().datetime().optional()}).strict(),fe=d.z.enum(["running","completed","failed","waiting"]),ye=d.z.object({id:d.z.string().trim().min(1).max(240),turnId:d.z.string().trim().min(1).max(240)}).strict(),Ie=ye.extend({type:d.z.literal("user-message"),text:d.z.string(),attachments:d.z.array(ue).max(6).optional()}).strict(),Ae=ye.extend({type:d.z.literal("ai-message"),text:d.z.string()}).strict(),be=ye.extend({type:d.z.literal("activity"),activityKind:d.z.string().trim().min(1).max(120),title:d.z.string().trim().min(1).max(240),status:fe.optional(),summary:d.z.string().max(4e3).optional(),input:d.z.string().max(1e5).optional(),output:d.z.string().max(1e6).optional(),paths:d.z.array(d.z.string().trim().min(1).max(4096)).max(500).optional(),exitCode:d.z.number().int().optional(),durationMs:d.z.number().int().nonnegative().optional()}).strict(),we=d.z.discriminatedUnion("type",[Ie,Ae,be]);d.z.object({sessionId:d.z.string().trim().min(1).max(120),providerSessionId:d.z.string().trim().min(1).max(240),items:d.z.array(we),generatedAt:d.z.string().datetime()}).strict(),d.z.object({sessionId:d.z.string().trim().min(1).max(120),turnId:d.z.string().trim().min(1).max(240),items:d.z.array(we),generatedAt:d.z.string().datetime()}).strict();const ve=d.z.enum(["pending-init","running","interrupted","completed","errored","shutdown","not-found"]),Ee=d.z.enum(["started","interacted","interrupted"]),Ne=d.z.object({threadId:d.z.string().trim().min(1).max(240),path:d.z.string().trim().max(4096).optional(),status:ve,activity:Ee.optional(),message:d.z.string().trim().max(1e3).optional(),updatedAt:d.z.string().datetime()}).strict(),Se=d.z.object({toolCalls:d.z.number().int().min(0).default(0),edits:d.z.number().int().min(0).default(0),approvals:d.z.number().int().min(0).default(0)}).strict().default({toolCalls:0,edits:0,approvals:0}),ze=d.z.object({send:d.z.boolean().optional(),interrupt:d.z.boolean().optional(),approval:d.z.boolean().optional(),fork:d.z.boolean().optional(),openApp:d.z.boolean().optional(),close:d.z.boolean().optional()}).strict(),Te=d.z.object({kind:d.z.literal("fork"),parentProviderSessionId:d.z.string().trim().min(1).max(240),throughTurnId:d.z.string().trim().min(1).max(240).optional()}).strict(),_e=d.z.union([de.extend({source:d.z.object({type:d.z.literal("inline"),encoding:d.z.literal("base64"),data:d.z.string().min(1).max(31457280)}).strict()}).strict().superRefine((e,t)=>{const n="image"===e.kind?Y:512e3;(e.size<=0||("file"===e.kind?e.size>=n:e.size>n))&&t.addIssue({code:d.z.ZodIssueCode.custom,path:["size"],message:`Inline ${e.kind} must be between 1 byte and ${n} bytes.`})}),de.extend({source:d.z.object({type:d.z.literal("runtime-path"),path:d.z.string().trim().min(1).max(4096)}).strict()}).strict()]),Ce=de.extend({sourceType:d.z.enum(["inline","runtime-path"])}).strict(),ke=d.z.union([d.z.object({id:d.z.string().trim().min(1).max(120),kind:oe.optional(),source:d.z.object({type:d.z.literal("upload-ref")}).strict().default({type:"upload-ref"})}).strict(),d.z.object({id:d.z.string().trim().min(1).max(120),kind:oe,name:d.z.string().trim().min(1).max(240),mime:d.z.string().trim().min(1).max(120),size:d.z.number().int().min(0).max(Number.MAX_SAFE_INTEGER),source:d.z.object({type:d.z.literal("runtime-path"),path:d.z.string().trim().min(1).max(4096)}).strict()}).strict()]),Oe=d.z.enum(["auto","queue","steer","immediate"]),Re=d.z.enum(["ask","auto-review","full-access"]),xe=d.z.enum(["review","rename","goal","compact"]);d.z.object({command:xe,argument:d.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.`})}),d.z.object({command:xe,value:d.z.string().max(4e3).optional(),turnId:d.z.string().trim().min(1).max(240).optional()}).strict(),d.z.enum(["skill","app","plugin"]);const De=d.z.object({name:d.z.string().trim().min(1).max(240),path:d.z.string().trim().min(1).max(4096)}),Pe=d.z.discriminatedUnion("kind",[De.extend({kind:d.z.literal("skill"),path:d.z.string().trim().min(1).max(4096).refine(e=>e.startsWith("/"),"Skill paths must be absolute.")}).strict(),De.extend({kind:d.z.literal("app"),path:d.z.string().trim().min(7).max(4096).regex(/^app:\/\/[^\s/]+$/,"App paths must use app://<id>.")}).strict(),De.extend({kind:d.z.literal("plugin"),path:d.z.string().trim().min(10).max(4096).regex(/^plugin:\/\/[^\s/]+$/,"Plugin paths must use plugin://<id>.")}).strict()]),Me=d.z.array(Pe).max(20).default([]),Le=d.z.enum(["plugin","skill","file","directory","app"]),je=d.z.object({kind:Le,name:d.z.string().trim().min(1).max(240),description:d.z.string().trim().max(1e3).optional(),path:d.z.string().trim().min(1).max(4096),icon:d.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."})}),$e=d.z.object({category:d.z.enum(["skills","plugins","apps","files"]),code:d.z.string().trim().min(1).max(160),message:d.z.string().trim().min(1).max(2e3)}).strict();d.z.object({sessionId:d.z.string().trim().min(1).max(120),providerSessionId:d.z.string().trim().min(1).max(240),cwd:d.z.string().trim().min(1).max(4096),candidates:d.z.array(je).max(1e3).default([]),diagnostics:d.z.array($e).max(20).default([])}).strict(),d.z.object({query:d.z.string().trim().max(240).default("")}).strict(),d.z.object({sessionId:d.z.string().trim().min(1).max(120),cwd:d.z.string().trim().min(1).max(4096),query:d.z.string().trim().max(240),requestId:d.z.string().trim().min(1).max(160),candidates:d.z.array(je.refine(e=>"file"===e.kind||"directory"===e.kind,"File search only returns files and directories.")).max(200).default([]),complete:d.z.boolean().default(!1)}).strict();const Fe=d.z.object({message:d.z.string().trim().min(1).max(2e4),mode:Oe.optional(),permissionMode:Re.optional()}),Ue=Fe.extend({attachments:d.z.array(_e).max(6).default([]),references:Me}).strict().superRefine((e,t)=>{e.attachments.reduce((e,t)=>e+("inline"===t.source.type?t.size:0),0)>X&&t.addIssue({code:d.z.ZodIssueCode.custom,path:["attachments"],message:"Inline attachments must be 41943040 bytes or less in total."})}),Ve=Fe.extend({attachments:d.z.array(ke).max(6).default([]),references:Me}).strict(),He=d.z.object({type:d.z.literal("runtime-path"),path:d.z.string().trim().min(1).max(4096).refine(e=>e.startsWith("/")||/^[A-Za-z]:[\\/]/.test(e),"Runtime paths must be absolute in the target controlled instance.")}).strict();Ue.extend({agent:re,cwd:He,cwdFolderId:d.z.string().trim().min(1).max(120).optional(),clientRequestId:d.z.string().trim().min(1).max(160)}).strict();const qe=d.z.object({mode:d.z.enum(["current-folder","worktree"]),branch:d.z.string().trim().min(1).max(1024)}).strict();Ve.extend({agent:re,cwdFolderId:d.z.string().trim().min(1).max(120).optional(),gitSelection:qe.optional(),clientRequestId:d.z.string().trim().min(1).max(160)}).strict(),d.z.object({disposition:d.z.enum(["created","already-created"]),aiSessionId:d.z.string().trim().min(1).max(120),providerSessionId:d.z.string().trim().min(1).max(240),creationSource:d.z.literal("ai-session")}).strict();const Be=d.z.object({mode:d.z.enum(["current","managed-worktree"]).default("current")}).strict().default({mode:"current"});d.z.object({clientRequestId:d.z.string().trim().min(1).max(160),throughTurnId:d.z.string().trim().min(1).max(240).optional(),workspace:Be.optional().default({mode:"current"})}).strict(),d.z.object({disposition:d.z.enum(["created","already-created"]),aiSessionId:d.z.string().trim().min(1).max(120),providerSessionId:d.z.string().trim().min(1).max(240),creationSource:d.z.literal("ai-session")}).strict(),d.z.object({clientRequestId:d.z.string().trim().min(1).max(160)}).strict(),d.z.object({disposition:d.z.enum(["opened","already-open"]),aiSessionId:d.z.string().trim().min(1).max(120),providerSessionId:d.z.string().trim().min(1).max(240),appSessionId:d.z.string().trim().min(1).max(120),creationSource:se}).strict(),d.z.object({clientRequestId:d.z.string().trim().min(1).max(160)}).strict(),d.z.object({disposition:d.z.enum(["closed","already-closed"]),aiSessionId:d.z.string().trim().min(1).max(120),providerSessionId:d.z.string().trim().min(1).max(240),creationSource:se}).strict(),d.z.object({code:d.z.enum(["invalid-request","not-found","unsupported","provider-unavailable","materialization-failed","open-app-failed","close-failed","conflict"]),message:d.z.string().trim().min(1).max(4e3),retryable:d.z.boolean().default(!1),aiSessionId:d.z.string().trim().min(1).max(120).optional(),providerSessionId:d.z.string().trim().min(1).max(240).optional()}).strict(),d.z.object({decision:d.z.enum(["allow","deny","skip"])}).strict(),d.z.object({expectedRevision:d.z.number().int().min(0),queueIds:d.z.array(d.z.string().trim().min(1).max(120)).max(100)}).strict(),d.z.object({expectedRevision:d.z.number().int().min(0),message:d.z.string().trim().min(1).max(2e4)}).strict(),d.z.object({code:d.z.string().trim().min(1).max(160),message:d.z.string(),instanceId:d.z.string().trim().min(1).max(160).optional(),nodeId:d.z.string().trim().min(1).max(160).optional(),route:d.z.string().trim().min(1).max(4096).optional()}).strict();const Ke=d.z.object({id:d.z.string().trim().min(1).max(120),messageId:d.z.string().trim().min(1).max(240).optional(),message:d.z.string().trim().min(1).max(2e4),attachments:d.z.array(Ce).max(6).default([]),references:Me,permissionMode:Re.optional(),status:d.z.enum(["queued","sending","failed"]).default("queued"),createdAt:d.z.string().datetime(),updatedAt:d.z.string().datetime(),error:d.z.string().trim().max(4e3).optional()}).strict(),Ge=d.z.object({revision:d.z.number().int().min(0).default(0),pendingCount:d.z.number().int().min(0).default(0),items:d.z.array(Ke).max(100).default([])}).strict().default({revision:0,pendingCount:0,items:[]}),Je=d.z.enum(["control","realtime","adapter-snapshot","transcript-tail","transcript-scan","process-scan","app-session"]),We=d.z.object({id:d.z.string().trim().min(1).max(240),status:d.z.enum(["running","completed"]),startedAt:d.z.string().datetime().optional(),completedAt:d.z.string().datetime().optional()}).strict(),Ye=d.z.object({id:d.z.string().trim().min(1).max(240),providerTurnId:d.z.string().trim().max(240).optional(),source:Je.optional(),userPrompt:d.z.string().trim().optional(),userMessages:d.z.array(me).max(100).optional(),status:d.z.enum(["queued","running","waiting","completed","failed"]).default("running"),phase:he.optional(),summary:d.z.string().trim().max(1e3).optional(),lastMessage:d.z.string().trim().optional(),lastMessageItemId:d.z.string().trim().max(240).optional(),contextCompactions:d.z.array(We).max(20).optional(),revision:d.z.number().int().min(0).default(0),sourcePriority:d.z.number().int().min(0).max(100).optional(),snapshotVersion:d.z.number().int().min(0).optional(),observedAt:d.z.string().datetime().optional(),startedAt:d.z.string().datetime().optional(),updatedAt:d.z.string().datetime().optional(),completedAt:d.z.string().datetime().optional()}).strict(),Xe=Ye.pick({id:!0,providerTurnId:!0,userPrompt:!0,userMessages:!0,status:!0,phase:!0,summary:!0,lastMessage:!0,contextCompactions:!0,startedAt:!0,updatedAt:!0,completedAt:!0}).strict(),Qe=d.z.object({id:d.z.string().trim().min(1).max(120),agent:re,creationSource:se.default("app-session"),appSessionId:d.z.string().trim().max(120).optional(),appId:d.z.string().trim().max(120).optional(),providerSessionId:d.z.string().trim().max(240).optional(),lineage:Te.optional(),providerMeta:d.z.record(d.z.string(),d.z.unknown()).optional(),appBindingKeys:d.z.array(d.z.string().trim().min(1).max(240)).max(20).optional(),actions:ze.optional(),activeTurnId:d.z.string().trim().max(240).optional(),title:d.z.string().trim().max(240).optional(),cwd:d.z.string().trim().max(4096).optional(),cwdFolderId:d.z.string().trim().min(1).max(120).optional(),userPrompt:d.z.string().trim().optional(),turns:d.z.array(Ye).max(50).optional(),status:pe.default("running"),phase:he.default("unknown"),summary:d.z.string().trim().max(1e3).optional(),lastMessage:d.z.string().trim().optional(),lastMessageItemId:d.z.string().trim().max(240).optional(),currentTool:ge.optional(),toolCallsSinceLastMessage:d.z.number().int().min(0).default(0),subAgents:d.z.array(Ne).max(50).default([]),transcriptPath:d.z.string().trim().max(4096).optional(),transcriptSize:d.z.number().int().min(0).optional(),startedAt:d.z.string().datetime(),updatedAt:d.z.string().datetime(),completedAt:d.z.string().datetime().optional(),error:d.z.string().trim().max(4e3).optional(),counters:Se,queue:Ge}).strict();d.z.object({session:Qe,provider:d.z.string().trim().min(1).max(80),action:d.z.enum(["send","queue","steer","interrupt","approval"]),decision:d.z.enum(["allow","deny","skip"]).optional(),turnId:d.z.string().trim().min(1).max(240).optional(),providerTurnId:d.z.string().trim().min(1).max(240).optional(),queueId:d.z.string().trim().min(1).max(120).optional()}).strict();const Ze=500,et=d.z.object({id:d.z.string().trim().min(1).max(120),agent:d.z.enum(["codex","claude"]),creationSource:se,providerSessionId:d.z.string().trim().min(1).max(240),lineage:Te.optional(),title:d.z.string().trim().max(240).optional(),userPrompt:d.z.string().trim().optional(),lastMessage:d.z.string().trim().optional(),cwd:d.z.string().trim().min(1).max(4096),cwdFolderId:d.z.string().trim().min(1).max(120).optional(),lastActiveAt:d.z.string().datetime(),archivedAt:d.z.string().datetime()}).strict();d.z.object({schemaVersion:d.z.literal(1).default(1),items:d.z.array(et).max(Ze).default([])}).strict(),d.z.object({items:d.z.array(et).max(Ze).default([])}).strict(),d.z.object({item:et,turns:d.z.array(Xe).max(50).default([])}).strict(),d.z.object({disposition:d.z.enum(["resumed","already-open"]),aiSessionId:d.z.string().trim().min(1).max(120),providerSessionId:d.z.string().trim().min(1).max(240),appSessionId:d.z.string().trim().min(1).max(120).optional(),creationSource:se}).strict();const tt=Ye.omit({userMessages:!0}),nt=Qe.pick({id:!0,agent:!0,creationSource:!0,appSessionId:!0,appId:!0,providerSessionId:!0,lineage:!0,providerMeta:!0,appBindingKeys:!0,actions:!0,activeTurnId:!0,title:!0,cwd:!0,cwdFolderId:!0,userPrompt:!0,turns:!0,status:!0,phase:!0,summary:!0,lastMessage:!0,lastMessageItemId:!0,currentTool:!0,toolCallsSinceLastMessage:!0,subAgents:!0,queue:!0,startedAt:!0,updatedAt:!0,error:!0}).extend({turns:d.z.array(tt).max(50).optional()}).strict(),it=d.z.object({runningCount:d.z.number().int().min(0).default(0),waitingCount:d.z.number().int().min(0).default(0),staleCount:d.z.number().int().min(0).default(0),sessions:d.z.array(nt).default([]),updatedAt:d.z.string().datetime()}).strict();d.z.object({streamId:d.z.string().trim().min(1).max(240),revision:d.z.number().int().min(0),lastEventAt:d.z.string().datetime(),snapshot:it}).strict(),it.pick({runningCount:!0,waitingCount:!0,staleCount:!0,updatedAt:!0}).extend({idleCount:d.z.number().int().min(0).default(0),problemCount:d.z.number().int().min(0).default(0),revision:d.z.number().int().min(0).optional()});const rt=d.z.enum(["provider-event","app-session-created","app-session-updated","app-session-deleted","discovery-scan","control-action","heartbeat-sync","startup"]),st=d.z.object({streamId:d.z.string().trim().min(1).max(240),instanceId:d.z.string().trim().min(1).max(160),nodeId:d.z.string().trim().min(1).max(160).optional(),revision:d.z.number().int().min(0),previousRevision:d.z.number().int().min(0).optional(),traceId:d.z.string().trim().min(1).max(160),generatedAt:d.z.string().datetime(),reason:rt}).strict(),ot=d.z.object({meta:st,snapshot:it}).strict(),at=d.z.object({meta:st,upserted:d.z.array(nt).default([]),removed:d.z.array(d.z.string().trim().min(1).max(120)).default([])}).strict(),ct=d.z.object({meta:st,sessionIds:d.z.array(d.z.string().trim().min(1).max(120)).default([]),expiresAt:d.z.string().datetime()}).strict();d.z.object({instanceId:d.z.string().trim().min(1).max(160),nodeId:d.z.string().trim().min(1).max(160).optional(),sessionId:d.z.string().trim().min(1).max(120),providerSessionId:d.z.string().trim().min(1).max(240),turnId:d.z.string().trim().min(1).max(240),itemId:d.z.string().trim().min(1).max(240),delta:d.z.string().min(1),generatedAt:d.z.string().datetime()}).strict(),d.z.object({instanceId:d.z.string().trim().min(1).max(160),nodeId:d.z.string().trim().min(1).max(160).optional(),sessionId:d.z.string().trim().min(1).max(120),providerSessionId:d.z.string().trim().min(1).max(240),item:we,generatedAt:d.z.string().datetime()}).strict(),d.z.object({streamId:d.z.string().trim().min(1).max(240),instanceId:d.z.string().trim().min(1).max(160),sinceRevision:d.z.number().int().min(0),latestRevision:d.z.number().int().min(0),earliestRetainedRevision:d.z.number().int().min(0),syncRequired:d.z.boolean().default(!1),events:d.z.array(d.z.discriminatedUnion("type",[d.z.object({type:d.z.literal(Z),payload:ot}).strict(),d.z.object({type:d.z.literal(ee),payload:at}).strict(),d.z.object({type:d.z.literal(te),payload:ct}).strict()])).default([])}).strict();const dt=d.z.object({source:Je,sourcePriority:d.z.number().int().min(0).max(100).optional(),observedAt:d.z.string().datetime().optional(),snapshotVersion:d.z.number().int().min(0).optional()}).strict(),lt=dt.extend({type:d.z.literal("snapshot"),agent:d.z.string().trim().min(1).max(80),creationSource:se.optional(),appSessionId:d.z.string().trim().max(120).optional(),appId:d.z.string().trim().max(120).optional(),providerSessionId:d.z.string().trim().max(240).optional(),lineage:Te.optional(),providerMeta:d.z.record(d.z.string(),d.z.unknown()).optional(),appBindingKeys:d.z.array(d.z.string().trim().min(1).max(240)).max(20).optional(),actions:ze.optional(),title:d.z.string().trim().max(240).optional(),cwd:d.z.string().trim().max(4096).optional(),cwdFolderId:d.z.string().trim().min(1).max(120).optional(),activeTurnId:d.z.string().trim().max(240).optional(),userPrompt:d.z.string().trim().optional(),turns:d.z.array(Ye).max(50).optional(),status:pe.optional(),phase:he.optional(),summary:d.z.string().trim().max(1e3).optional(),lastMessage:d.z.string().trim().optional(),lastMessageItemId:d.z.string().trim().max(240).optional(),error:d.z.string().trim().max(4e3).optional(),currentTool:ge.optional(),toolCallsSinceLastMessage:d.z.number().int().min(0).optional(),subAgents:d.z.array(Ne).max(50).optional(),transcriptPath:d.z.string().trim().max(4096).optional(),transcriptSize:d.z.number().int().min(0).optional(),replaceActivity:d.z.boolean().optional()}).strict(),ut=dt.extend({type:d.z.literal("event"),sessionId:d.z.string().trim().min(1).max(120),kind:d.z.enum(["lifecycle","send-ack","turn-started","user-message","assistant-message","approval-requested","turn-completed","session-error","tool-activity","sub-agent-activity","context-compaction"]),activeTurnId:d.z.string().trim().max(240).optional(),providerTurnId:d.z.string().trim().max(240).optional(),userPrompt:d.z.string().trim().optional(),userMessage:me.optional(),text:d.z.string().optional(),itemId:d.z.string().trim().max(240).optional(),status:pe.optional(),phase:he.optional(),summary:d.z.string().trim().max(1e3).optional(),error:d.z.string().trim().max(4e3).optional(),currentTool:ge.nullable().optional(),toolCallsSinceLastMessage:d.z.number().int().min(0).optional(),subAgents:d.z.array(Ne).max(50).optional(),contextCompaction:We.optional(),counters:d.z.object({toolCalls:d.z.number().int().min(0).optional(),edits:d.z.number().int().min(0).optional(),approvals:d.z.number().int().min(0).optional()}).strict().optional()}).strict().superRefine((e,t)=>{if("session-error"!==e.kind||e.error||t.addIssue({code:"custom",path:["error"],message:"session-error events require error"}),"context-compaction"===e.kind?e.contextCompaction||t.addIssue({code:"custom",path:["contextCompaction"],message:"context-compaction events require contextCompaction"}):void 0!==e.contextCompaction&&t.addIssue({code:"custom",path:["contextCompaction"],message:"contextCompaction is only valid for context-compaction events"}),"send-ack"!==e.kind&&"user-message"!==e.kind&&void 0!==e.userMessage&&t.addIssue({code:"custom",path:["userMessage"],message:"userMessage is only valid for send-ack and user-message events"}),"sub-agent-activity"===e.kind?e.subAgents||t.addIssue({code:"custom",path:["subAgents"],message:"sub-agent-activity events require subAgents"}):void 0!==e.subAgents&&t.addIssue({code:"custom",path:["subAgents"],message:"subAgents is only valid for sub-agent-activity events"}),"tool-activity"!==e.kind)return void 0!==e.currentTool&&t.addIssue({code:"custom",path:["currentTool"],message:"currentTool is only valid for tool-activity events"}),void(void 0!==e.toolCallsSinceLastMessage&&t.addIssue({code:"custom",path:["toolCallsSinceLastMessage"],message:"toolCallsSinceLastMessage is only valid for tool-activity events"}));"currentTool"in e||t.addIssue({code:"custom",path:["currentTool"],message:"tool-activity events require currentTool"}),void 0===e.toolCallsSinceLastMessage&&t.addIssue({code:"custom",path:["toolCallsSinceLastMessage"],message:"tool-activity events require toolCallsSinceLastMessage"})});d.z.discriminatedUnion("type",[lt,ut]);const mt=d.z.union([d.z.object({type:d.z.literal("schedule"),scheduleKind:d.z.literal("interval").default("interval"),intervalMs:d.z.number().int().min(1e3)}).strict(),d.z.object({type:d.z.literal("schedule"),scheduleKind:d.z.literal("daily"),timeOfDay:d.z.string().regex(/^([01]\d|2[0-3]):[0-5]\d$/),timezone:d.z.string().trim().min(1).max(120)}).strict(),d.z.object({type:d.z.literal("schedule"),scheduleKind:d.z.literal("weekly"),weekdays:d.z.array(d.z.number().int().min(0).max(6)).min(1).max(7),timeOfDay:d.z.string().regex(/^([01]\d|2[0-3]):[0-5]\d$/),timezone:d.z.string().trim().min(1).max(120)}).strict()]),pt=d.z.union([mt,d.z.object({type:d.z.literal("file-change"),roots:d.z.array(d.z.string().trim().min(1).max(4096)).min(1).max(50),globs:d.z.array(d.z.string().trim().min(1).max(500)).min(1).max(100),ignore:d.z.array(d.z.string().trim().min(1).max(500)).max(100).optional(),debounceMs:d.z.number().int().min(100).max(6e4).default(1500)}).strict(),d.z.object({type:d.z.literal("ai-session"),agent:d.z.string().trim().min(1).max(80).optional(),statuses:d.z.array(d.z.enum(["running","waiting","idle","failed"])).max(20).optional(),phases:d.z.array(d.z.enum(["thinking","tool","editing","approval","responding","unknown"])).max(20).optional()}).strict()]),ht=d.z.object({promptTemplate:d.z.string().trim().min(1).max(2e4)}).strict(),gt=d.z.object({cooldownMs:d.z.number().int().min(0).max(864e5).optional(),maxConcurrentRuns:d.z.number().int().min(1).max(20).default(1),whenBusy:d.z.enum(["skip","queue"]).default("skip")}).strict(),ft=d.z.object({configHash:d.z.string().trim().min(8).max(80),name:d.z.string().trim().min(1).max(160),description:d.z.string().trim().max(1e3).optional(),source:pt,action:ht,policy:gt.default({maxConcurrentRuns:1,whenBusy:"skip"}),createdAt:d.z.string().datetime(),updatedAt:d.z.string().datetime()}).strict(),yt=d.z.object({type:d.z.literal("ai-session"),aiSessionId:d.z.string().trim().min(1).max(160)}).strict(),It=d.z.object({configHash:d.z.string().trim().min(8).max(80),deploymentId:d.z.string().trim().min(1).max(240).optional(),instanceId:d.z.string().trim().min(1).max(160),origin:d.z.enum(["control-plane","controlled-instance"]).default("controlled-instance"),enabled:d.z.boolean().default(!0),target:yt,localName:d.z.string().trim().min(1).max(160).optional(),createdAt:d.z.string().datetime(),updatedAt:d.z.string().datetime()}).strict(),At=d.z.object({configHash:d.z.string().trim().min(8).max(80),deploymentId:d.z.string().trim().min(1).max(240).optional(),instanceId:d.z.string().trim().min(1).max(160),status:d.z.enum(["idle","running","disabled","error"]).default("idle"),lastTriggeredAt:d.z.string().datetime().optional(),lastCompletedAt:d.z.string().datetime().optional(),lastSkippedAt:d.z.string().datetime().optional(),lastError:d.z.string().trim().max(4e3).optional(),runCount:d.z.number().int().min(0).default(0),skippedCount:d.z.number().int().min(0).default(0)}).strict(),bt=d.z.object({id:d.z.string().trim().min(1).max(160),configHash:d.z.string().trim().min(8).max(80),deploymentId:d.z.string().trim().min(1).max(240).optional(),instanceId:d.z.string().trim().min(1).max(160),eventType:d.z.enum(["manual","schedule","file-change","ai-session"]),status:d.z.enum(["started","completed","failed","skipped"]),target:yt,promptPreview:d.z.string().trim().max(500),eventSummary:d.z.string().trim().max(1e3).optional(),error:d.z.string().trim().max(4e3).optional(),startedAt:d.z.string().datetime(),completedAt:d.z.string().datetime().optional()}).strict();d.z.object({schemaVersion:d.z.literal(1).default(1),configs:d.z.array(ft).default([]),deployments:d.z.array(It).default([]),runtime:d.z.array(At).default([]),recentRuns:d.z.array(bt).default([])}).strict();const wt=d.z.object({instanceId:d.z.string().trim().min(1).max(160),instanceName:d.z.string().trim().min(1).max(160),deployment:It,runtime:At.optional()}).strip(),vt=bt.extend({instanceName:d.z.string().trim().min(1).max(160).optional()}).strip(),Et=d.z.object({configHash:d.z.string().trim().min(8).max(80),config:ft,deploymentCount:d.z.number().int().min(0),enabledCount:d.z.number().int().min(0),runningCount:d.z.number().int().min(0),errorCount:d.z.number().int().min(0),ownedByControlPlane:d.z.boolean(),controlPlaneDeploymentCount:d.z.number().int().min(0),deployments:d.z.array(wt),recentRuns:d.z.array(vt)}).strip();d.z.object({updatedAt:d.z.string().datetime(),triggers:d.z.array(Et)}).strip(),d.z.object({name:ft.shape.name,description:ft.shape.description,source:pt,action:ht,policy:gt.partial().optional()}).strict(),d.z.object({scope:d.z.enum(["node","instance"]),nodeId:d.z.string().trim().min(1).max(160).optional(),instanceId:d.z.string().trim().min(1).max(160).optional(),code:d.z.string().trim().min(1).max(160),message:d.z.string().trim().min(1).max(4e3)}).strip();const Nt=d.z.string().regex(/^\d{4}-\d{2}-\d{2}$/,"Proxy protocol version must use YYYY-MM-DD format."),St=d.z.string().trim().min(1).max(160).regex(/^[a-zA-Z0-9][a-zA-Z0-9_.:-]*$/),zt=d.z.string().datetime(),Tt=d.z.string().trim().min(32).max(4096),_t=d.z.string().trim().max(2048).transform((e,t)=>{try{return function(e){const t=new URL(e.trim());if("https:"!==t.protocol||t.username||t.password||"/"!==t.pathname||t.search||t.hash)throw new Error("Proxy origin must be an HTTPS origin without credentials, path, query, or fragment.");return t.origin}(e)}catch(e){return t.addIssue({code:"custom",message:e instanceof Error?e.message:String(e)}),d.z.NEVER}});d.z.string().trim().min(1).max(4096).transform((e,t)=>{try{return function(e){const t=e.trim();if(!t.startsWith("/")||t.startsWith("//")||t.includes("\\")||/%25/i.test(t))throw new Error("Proxy route must be a single-encoded node-agent relative route.");const n=t.split("?",1)[0];let i,r;try{i=n.split("/").map(e=>decodeURIComponent(e))}catch{throw new Error("Proxy route contains invalid percent encoding.")}if(i.some(e=>".."===e||"."===e))throw new Error("Proxy route cannot traverse outside the node-agent API.");try{r=new URL(t,"https://node-agent.invalid")}catch{throw new Error("Proxy route is invalid.")}if("https://node-agent.invalid"!==r.origin||r.username||r.password)throw new Error("Proxy route cannot select an absolute upstream URL.");return`${r.pathname}${r.search}`}(e)}catch(e){return t.addIssue({code:"custom",message:e instanceof Error?e.message:String(e)}),d.z.NEVER}});const Ct=d.z.enum(Object.values({ProtocolUnsupported:"CONTROL_PLANE_PROXY_PROTOCOL_UNSUPPORTED",InviteInvalid:"CONTROL_PLANE_PROXY_INVITE_INVALID",InviteExpired:"CONTROL_PLANE_PROXY_INVITE_EXPIRED",InviteConsumed:"CONTROL_PLANE_PROXY_INVITE_CONSUMED",InviteRevoked:"CONTROL_PLANE_PROXY_INVITE_REVOKED",TargetUnavailable:"CONTROL_PLANE_PROXY_TARGET_UNAVAILABLE",TargetMismatch:"CONTROL_PLANE_PROXY_TARGET_MISMATCH",BindingUnknown:"CONTROL_PLANE_PROXY_BINDING_UNKNOWN",BindingRevoked:"CONTROL_PLANE_PROXY_BINDING_REVOKED",BindingIdentityConflict:"CONTROL_PLANE_PROXY_BINDING_IDENTITY_CONFLICT",AuthenticationFailed:"CONTROL_PLANE_PROXY_AUTHENTICATION_FAILED",RouteInvalid:"CONTROL_PLANE_PROXY_ROUTE_INVALID",HeaderInvalid:"CONTROL_PLANE_PROXY_HEADER_INVALID",ResourceLimit:"CONTROL_PLANE_PROXY_RESOURCE_LIMIT",SnapshotRequired:"CONTROL_PLANE_PROXY_SNAPSHOT_REQUIRED",Unavailable:"CONTROL_PLANE_PROXY_UNAVAILABLE",TransportFailed:"CONTROL_PLANE_PROXY_TRANSPORT_FAILED"})),kt=d.z.object({code:Ct,message:d.z.string().trim().min(1).max(2048),retryable:d.z.boolean(),details:d.z.record(d.z.string(),d.z.unknown()).optional()}).strict(),Ot=d.z.enum(["active","revoked"]),Rt=d.z.object({id:St,targetNodeId:St,status:Ot,createdBy:St,expiresAt:zt,revokedAt:zt.optional(),createdAt:zt,updatedAt:zt}).strict();d.z.object({targetNodeId:St,expiresInSeconds:d.z.number().int().min(60).max(3600).default(600)}).strict(),d.z.object({invite:Rt,token:d.z.string().trim().min(24).max(512),proxyOrigin:_t,protocolVersion:Nt}).strict();const xt=d.z.enum(["active","revoked"]),Dt=d.z.object({id:St,claimId:St,sourceControlPlaneId:St,targetNodeId:St,bindingKeyId:St,status:xt,revision:d.z.number().int().positive(),lastError:kt.optional(),revokedAt:zt.optional(),createdAt:zt,updatedAt:zt}).strict();d.z.object({protocolVersion:Nt,inviteToken:d.z.string().trim().min(24).max(512).optional(),claimId:St,sourceControlPlaneId:St,targetNodeId:St.optional(),bindingKeyId:St,credential:Tt}).strict(),d.z.object({sourceControlPlaneId:St,bindingKeyId:St,credential:Tt}).strict();const Pt=d.z.object({id:St,name:d.z.string().trim().min(1).max(160),status:d.z.enum(["unknown","online","offline","degraded"]),health:d.z.enum(["unknown","ok","degraded","failed"]),lastSeenAt:zt.optional(),capabilities:d.z.record(d.z.string(),d.z.unknown()).default({})}).strict(),Mt=d.z.object({protocolVersion:Nt,binding:Dt,streamId:St,revision:d.z.number().int().nonnegative(),observedAt:zt,target:Pt}).strict(),Lt=d.z.object({type:d.z.literal("control-plane-proxy.event"),protocolVersion:Nt,streamId:St,bindingId:St,sourceControlPlaneId:St,targetNodeId:St,revision:d.z.number().int().positive(),source:d.z.object({id:d.z.string().trim().min(1).max(512),seq:d.z.number().int().nonnegative()}).strict(),target:Pt,event:d.z.object({type:d.z.string().trim().min(1).max(240),topic:d.z.string().trim().min(1).max(240),createdAt:zt}).strict()}).strict(),jt=d.z.object({type:d.z.literal("control-plane-proxy.events.ready"),protocolVersion:Nt,streamId:St,bindingId:St,sourceControlPlaneId:St,targetNodeId:St,latestRevision:d.z.number().int().nonnegative(),earliestRetainedRevision:d.z.number().int().nonnegative()}).strict(),$t=d.z.object({type:d.z.literal("control-plane-proxy.snapshot-required"),protocolVersion:Nt,streamId:St,bindingId:St,sourceControlPlaneId:St,targetNodeId:St,sinceRevision:d.z.number().int().nonnegative(),latestRevision:d.z.number().int().nonnegative(),earliestRetainedRevision:d.z.number().int().nonnegative(),error:kt}).strict();d.z.discriminatedUnion("type",[Lt,jt,$t]),d.z.object({protocolVersion:Nt,binding:Dt,target:Mt.shape.target}).strict(),d.z.object({id:St,claimId:St,proxyOrigin:_t,requestedName:d.z.string().trim().min(1).max(160).optional(),sourceControlPlaneId:St,targetNodeId:St.optional(),bindingKeyId:St,credential:Tt,status:d.z.enum(["pending","compensation-required"]),createdAt:zt,updatedAt:zt,expiresAt:zt}).strict().omit({credential:!0}),d.z.object({id:St,nodeId:St,proxyOrigin:_t,proxyBindingId:St,targetNodeId:St,sourceControlPlaneId:St,bindingKeyId:St,credential:Tt,createdAt:zt,updatedAt:zt}).strict();const Ft="2026-08-20",Ut=new Set(["2026-08-01","2026-08-16","2026-08-17",Ft]),Vt=d.z.string().regex(/^\d{4}-\d{2}-\d{2}$/,"Protocol version must use YYYY-MM-DD format."),Ht=d.z.string().trim().min(1).max(120);function qt(){return{features:{appRuntime:!1,tty:!1,gui:!1,browser:!1,screenshots:!1,logs:!1,aiSessionWorkspaceSelection:!1,aiSessionPersistenceSettings:!1,aiSessionTimeline:{sessionReadAgents:[],turnReadAgents:[],liveItemAgents:[]},aiSessionConversationAttachments:{metadataAgents:[],contentAgents:[],uploadAgents:[],retentionSettings:!1}}}}const Bt=d.z.object({sessionReadAgents:d.z.array(Ht).max(100).default([]),turnReadAgents:d.z.array(Ht).max(100).default([]),liveItemAgents:d.z.array(Ht).max(100).default([])}).passthrough(),Kt=d.z.object({metadataAgents:d.z.array(Ht).max(100).default([]),contentAgents:d.z.array(Ht).max(100).default([]),uploadAgents:d.z.array(Ht).max(100).default([]),retentionSettings:d.z.boolean().default(!1)}).passthrough(),Gt=d.z.object({appRuntime:d.z.boolean().default(!1),tty:d.z.boolean().default(!1),gui:d.z.boolean().default(!1),browser:d.z.boolean().default(!1),screenshots:d.z.boolean().default(!1),logs:d.z.boolean().default(!1),aiSessionWorkspaceSelection:d.z.boolean().default(!1),aiSessionPersistenceSettings:d.z.boolean().default(!1),aiSessionTimeline:Bt.default(function(){return{sessionReadAgents:[],turnReadAgents:[],liveItemAgents:[]}}),aiSessionConversationAttachments:Kt.optional()}).passthrough(),Jt=d.z.object({features:Gt.default(function(){return{appRuntime:!1,tty:!1,gui:!1,browser:!1,screenshots:!1,logs:!1,aiSessionWorkspaceSelection:!1,aiSessionPersistenceSettings:!1,aiSessionTimeline:{sessionReadAgents:[],turnReadAgents:[],liveItemAgents:[]},aiSessionConversationAttachments:{metadataAgents:[],contentAgents:[],uploadAgents:[],retentionSettings:!1}}})}).passthrough();function Wt(e){const t={features:{appRuntime:!1,tty:!1,gui:!1,browser:!1,screenshots:!1,logs:!1,aiSessionWorkspaceSelection:!1,aiSessionPersistenceSettings:!1,aiSessionTimeline:{sessionReadAgents:[],turnReadAgents:[],liveItemAgents:[]},aiSessionConversationAttachments:{metadataAgents:[],contentAgents:[],uploadAgents:[],retentionSettings:!1}}};if(!e||"object"!=typeof e||Array.isArray(e))return t;const n=e,i=n.features;if(!i||"object"!=typeof i||Array.isArray(i))return t;const r=i,s={appRuntime:!1,tty:!1,gui:!1,browser:!1,screenshots:!1,logs:!1,aiSessionWorkspaceSelection:!1,aiSessionPersistenceSettings:!1,aiSessionTimeline:{sessionReadAgents:[],turnReadAgents:[],liveItemAgents:[]},aiSessionConversationAttachments:{metadataAgents:[],contentAgents:[],uploadAgents:[],retentionSettings:!1}};for(const e of["appRuntime","tty","gui","browser","screenshots","logs","aiSessionWorkspaceSelection","aiSessionPersistenceSettings"]){const t=d.z.boolean().safeParse(r[e]);t.success&&(s[e]=t.data)}const o=Bt.safeParse(r.aiSessionTimeline);o.success&&(s.aiSessionTimeline=o.data);const a=Kt.safeParse(r.aiSessionConversationAttachments);return a.success&&(s.aiSessionConversationAttachments=a.data),Jt.parse({...n,features:{...r,...s}})}const Yt=d.z.string().trim().min(1).max(120).regex(/^[a-zA-Z0-9][a-zA-Z0-9_.:-]*$/),Xt=d.z.string().datetime(),Qt=d.z.record(d.z.string(),d.z.string()).default({}),Zt=d.z.record(d.z.string(),d.z.string()).default({}),en=d.z.object({encoding:d.z.enum(["utf8","base64"]),data:d.z.string()}).strict().superRefine((e,t)=>{"base64"===e.encoding&&Buffer.from(e.data,"base64").toString("base64")!==e.data&&t.addIssue({code:"custom",path:["data"],message:"Node tunnel binary body must use canonical base64 encoding."})});function tn(e){if(null==e)return;const t=en.parse(e);return"utf8"===t.encoding?t.data:Buffer.from(t.data,"base64")}const nn=/^[A-Za-z0-9_][A-Za-z0-9_.-]{0,127}$/,rn=/^sha256:([a-fA-F0-9]{64})$/,sn=/^(?:localhost|[a-z0-9](?:[a-z0-9.-]*[a-z0-9])?)(?::[1-9][0-9]{0,4})?$/,on=/^[a-z0-9]+(?:(?:[._]|__|-+)[a-z0-9]+)*$/;function an(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?rn.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&&!nn.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&&!sn.test(u[0].toLowerCase()))throw new Error("Docker image registry host or port is invalid.");if(!p.length||p.some(e=>!on.test(e)))throw new Error("Docker image repository names must be lowercase and use valid separators.");const h=u.map((e,t)=>m&&0===t?e.toLowerCase():e).join("/"),g=s?`sha256:${s[1].toLowerCase()}`:void 0;return`${h}${d?`:${d}`:""}${g?`@${g}`:""}`}function cn(e){const t=an(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 dn=d.z.string().trim().min(1).max(512).transform((e,t)=>{try{return an(e)}catch(e){return t.addIssue({code:"custom",message:e instanceof Error?e.message:String(e)}),d.z.NEVER}}),ln=d.z.string().trim().transform((e,t)=>{const n=rn.exec(e);return n?`sha256:${n[1].toLowerCase()}`:(t.addIssue({code:"custom",message:"Docker image digest must use sha256 followed by 64 hexadecimal characters."}),d.z.NEVER)}),un=d.z.object({codexModelHash:Yt.nullable().optional(),claudeModelHash:Yt.nullable().optional()}).strict().default({}),mn=d.z.object({imageId:Yt,tag:d.z.string().trim().min(1).max(128).regex(nn).optional()}).strict(),pn=d.z.discriminatedUnion("type",[d.z.object({type:d.z.literal("image"),imageSelection:mn}).strict(),d.z.object({type:d.z.literal("template"),environmentTemplateId:Yt}).strict()]),hn=d.z.enum(["creating","ready","failed","deleting"]),gn=d.z.enum(["linux","darwin","win32","freebsd","openbsd","aix","sunos","unknown"]),fn=d.z.enum(["x64","arm64","arm","ia32","ppc64","s390x","riscv64","unknown"]),yn=d.z.object({code:d.z.string().trim().min(1).max(120),message:d.z.string().trim().min(1).max(2048),phase:d.z.enum(["validate","commit","inspect","security-check","persist","delete","recovery"]).optional()}).strict(),In=d.z.object({templateId:Yt,nodeId:Yt,imageId:ln,name:d.z.string().trim().min(1).max(160),platform:gn,architecture:fn}).strict(),An=d.z.enum(["data","agent-home","workspace"]),bn=d.z.object({deleteVolumes:d.z.boolean()}).strict(),wn=d.z.object({role:An,name:d.z.string().trim().min(1).max(255),mountPath:d.z.string().trim().startsWith("/").max(4096),status:d.z.enum(["deleted","retained","missing","failed"]),error:d.z.object({code:d.z.string().trim().min(1).max(120),message:d.z.string().trim().min(1).max(2048)}).strict().optional()}).strict(),vn=d.z.object({instanceId:Yt,containerDeleted:d.z.boolean(),completed:d.z.boolean(),deletedVolumes:d.z.array(wn),retainedVolumes:d.z.array(wn),volumeResults:d.z.array(wn)}).strict(),En={img_default:"market_taskhandoff_browser",img_codex:"market_taskhandoff_codex",img_ai:"market_taskhandoff_ai"};function Nn(e,t){if(e&&"object"==typeof e&&!Array.isArray(e)){const t=e;return{imageId:"string"==typeof t.imageId&&En[t.imageId]||t.imageId,..."string"==typeof t.tag?{tag:t.tag}:{}}}if("string"==typeof t)return{imageId:En[t]||t}}function Sn(e){if(!e||"object"!=typeof e||Array.isArray(e))return e;const t=e,{defaultImageId:n,...i}=t;return{...i,defaultImageSelection:Nn(t.defaultImageSelection,n)}}const zn=d.z.object({id:Yt,name:d.z.string().trim().min(1).max(120),kind:d.z.enum(["tty","gui","web"]),source:d.z.enum(["builtin","custom"]),availability:d.z.enum(["available","missing-dependency"]),capabilities:d.z.object({automation:d.z.enum(["cdp"]).optional(),supportsCwdSelection:d.z.boolean().default(!1)}).strict().default({supportsCwdSelection:!1}),diagnosticCode:d.z.enum(["APP_EXECUTABLE_NOT_FOUND"]).optional()}).strict(),Tn=d.z.object({code:d.z.enum(["APP_CATALOG_INVALID"]),message:d.z.string().trim().min(1).max(500)}).strict(),_n=d.z.object({items:d.z.array(zn).max(256),observedAt:Xt,issues:d.z.array(Tn).max(32).default([])}).strict(),Cn=d.z.object({id:Yt,name:d.z.string().trim().min(1).max(160),sourceInstanceId:Yt,nodeId:Yt,imageId:ln.optional(),internalTag:d.z.string().trim().min(1).max(512).optional(),platform:gn.optional(),architecture:fn.optional(),sizeBytes:d.z.number().int().nonnegative().optional(),status:hn,error:yn.optional(),createdAt:Xt,updatedAt:Xt}).strict().superRefine((e,t)=>{if("ready"===e.status)for(const n of["imageId","internalTag","platform","architecture","sizeBytes"])void 0===e[n]&&t.addIssue({code:"custom",path:[n],message:`Ready environment template requires ${n}.`});"failed"!==e.status||e.error||t.addIssue({code:"custom",path:["error"],message:"Failed environment template requires an error diagnostic."})}),kn=d.z.enum(["apt","dnf","brew","npm"]),On=d.z.enum(["user","passwordless-sudo","root"]),Rn=d.z.object({platform:gn,arch:fn,installers:d.z.array(kn).max(8),privilege:On,installerAccess:d.z.object({npmGlobalWritable:d.z.boolean().optional()}).strict().optional()}).strict(),xn=d.z.enum(["installed","not-installed","broken","unsupported"]),Dn=d.z.enum(["recipe","bundled","external","none"]),Pn=d.z.object({code:d.z.enum(["BUNDLED","EXTERNALLY_MANAGED","ALREADY_INSTALLED","NOT_INSTALLED","UNSUPPORTED_PLATFORM","INSTALLER_UNAVAILABLE","INSTALLER_NOT_WRITABLE","INSUFFICIENT_PRIVILEGE","OPERATION_IN_PROGRESS"]),message:d.z.string().trim().min(1).max(500)}).strict(),Mn=d.z.object({id:Yt,name:d.z.string().trim().min(1).max(120),kind:d.z.enum(["tty","gui","web"]),description:d.z.string().trim().max(500).optional(),state:xn,managementSource:Dn,version:d.z.string().trim().max(120).optional(),canInstall:d.z.boolean(),canUninstall:d.z.boolean(),installReason:Pn.optional(),uninstallReason:Pn.optional(),activeJobId:Yt.optional()}).strict(),Ln=d.z.enum(["install","uninstall"]),jn=d.z.enum(["queued","running","succeeded","failed","cancelled","interrupted"]),$n=d.z.object({current:d.z.number().finite().nonnegative().optional(),total:d.z.number().finite().positive().optional(),unit:d.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"]}),Fn=d.z.object({executable:d.z.string().trim().min(1).max(4096),args:d.z.array(d.z.string().max(4096)).max(128)}).strict(),Un=d.z.object({code:d.z.string().trim().min(1).max(120).regex(/^[a-z0-9][a-z0-9._-]*$/),message:d.z.string().trim().min(1).max(4096),retryable:d.z.boolean(),sessionIds:d.z.array(Yt).max(64).optional()}).strict(),Vn=d.z.object({id:Yt,requestId:Yt.optional(),appId:Yt,operation:Ln,state:jn,phase:d.z.string().trim().min(1).max(120).optional(),progress:$n.optional(),command:Fn.optional(),logTail:d.z.string().max(32768).optional(),logTruncated:d.z.boolean().optional(),error:Un.optional(),requestedAt:Xt,startedAt:Xt.optional(),finishedAt:Xt.optional(),updatedAt:Xt}).strict(),Hn=d.z.object({streamId:Yt,sequence:d.z.number().int().nonnegative(),capabilities:Rn,apps:d.z.array(Mn).max(256),activeJobs:d.z.array(Vn).max(256),recentJobs:d.z.array(Vn).max(256),observedAt:Xt}).strict();d.z.object({requestId:Yt.optional()}).strict(),d.z.object({job:Vn}).strict(),d.z.object({type:d.z.literal("app-management"),streamId:Yt,sequence:d.z.number().int().nonnegative(),observedAt:Xt,job:Vn.optional(),snapshot:Hn.optional()}).strict().refine(e=>void 0!==e.job||void 0!==e.snapshot,{message:"An app management event requires a job or snapshot."});const qn=d.z.object({component:d.z.enum(["control-plane","node-agent","controlled-instance"]),packageName:d.z.string().trim().max(160).optional(),packageVersion:d.z.string().trim().max(80).optional(),protocolVersion:Vt.optional(),buildId:d.z.string().trim().max(160).optional(),builtAt:d.z.string().trim().max(120).optional(),gitCommit:d.z.string().trim().max(120).optional(),imageRef:d.z.string().trim().max(512).optional(),imageDigest:d.z.string().trim().max(240).optional()}).strict();d.z.object({data:d.z.object({ok:d.z.literal(!0),role:d.z.literal("control-plane"),protocolVersion:Vt,build:qn.extend({component:d.z.literal("control-plane"),packageVersion:d.z.string().trim().min(1).max(80)}).loose(),serverTime:Xt}).loose()}).loose();const Bn=d.z.enum(["stable","beta","alpha"]),Kn=d.z.object({packageName:d.z.literal("@task-handoff/controlled-instance"),version:d.z.string().trim().min(1).max(80),platform:d.z.string().trim().min(1).max(40),arch:d.z.string().trim().min(1).max(40),formatVersion:d.z.number().int().positive(),launcherAbi:d.z.number().int().positive(),entrypoint:d.z.string().trim().min(1).max(512),sha256:d.z.string().regex(/^[a-f0-9]{64}$/)}).strict(),Gn=d.z.object({code:d.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:d.z.string().trim().min(1).max(4096),expectedVersion:d.z.string().trim().min(1).max(80).optional(),actualVersion:d.z.string().trim().min(1).max(80).optional(),retryable:d.z.boolean().default(!1)}).strict(),Jn=d.z.object({desiredVersion:d.z.string().trim().min(1).max(80),actualVersion:d.z.string().trim().min(1).max(80).optional(),phase:d.z.enum(["pending","draining","installing","restarting","verifying","matched","failed"]),attempt:d.z.number().int().nonnegative().default(0),lastAttemptAt:Xt.optional(),matchedAt:Xt.optional(),error:Gn.optional()}).strict(),Wn=d.z.object({runningInstanceCount:d.z.number().int().nonnegative(),stoppedInstanceCount:d.z.number().int().nonnegative(),activeInstanceCount:d.z.number().int().nonnegative(),restartInstanceCount:d.z.number().int().nonnegative(),runningInstanceIds:d.z.array(Yt).max(1024).default([]),stoppedInstanceIds:d.z.array(Yt).max(1024).default([]),activeInstanceIds:d.z.array(Yt).max(1024).default([])}).strict(),Yn=d.z.object({phase:d.z.enum(["queued","updating-node","restarting-node","converging-instances","succeeded","degraded","failed"]),desiredVersion:d.z.string().trim().min(1).max(80),nodeVersion:d.z.string().trim().min(1).max(80).optional(),expectedInstanceIds:d.z.array(Yt).max(1024).default([]),expectedInstanceCount:d.z.number().int().nonnegative(),matchedInstanceCount:d.z.number().int().nonnegative(),pendingInstanceCount:d.z.number().int().nonnegative(),failedInstanceCount:d.z.number().int().nonnegative(),deferredInstanceCount:d.z.number().int().nonnegative().default(0)}).strict(),Xn=d.z.object({channel:Bn.default("stable")}).strict(),Qn=d.z.object({source:d.z.literal("npm"),channel:Bn,currentVersion:d.z.string().trim().max(240).optional(),availableVersion:d.z.string().trim().min(1).max(240),artifactRef:d.z.string().trim().min(1).max(512).optional(),runtimeArtifacts:d.z.array(Kn).default([]),impact:Wn,updateAvailable:d.z.boolean(),supported:d.z.boolean().default(!0),reason:d.z.string().trim().max(2048).optional(),checkedAt:Xt,preflightToken:d.z.string().trim().min(16).max(240).optional()}).strict(),Zn=d.z.object({id:Yt,nodeId:Yt,source:d.z.literal("npm"),channel:Bn,fromVersion:d.z.string().trim().max(240).optional(),toVersion:d.z.string().trim().min(1).max(240),artifactRef:d.z.string().trim().min(1).max(512).optional(),runtimeArtifacts:d.z.array(Kn).default([]),impact:Wn,rollout:Yn,status:d.z.enum(["queued","updating-node","restarting-node","converging-instances","succeeded","degraded","failed"]),error:Gn.optional(),startedAt:Xt.optional(),completedAt:Xt.optional(),createdAt:Xt,updatedAt:Xt}).strict(),ei=d.z.object({channel:Bn,targetVersion:d.z.string().trim().min(1).max(240),preflightToken:d.z.string().trim().min(16).max(240)}).strict(),ti=d.z.object({type:d.z.enum(["branch","tag","commit"]),name:d.z.string().trim().min(1).max(240).optional(),commit:d.z.string().trim().max(80).optional()}).strict(),ni=d.z.object({type:d.z.enum(["none","ssh-key","https-token"]).default("none"),secretId:d.z.string().trim().min(1).max(120).optional()}).strict(),ii=d.z.object({depth:d.z.number().int().positive().max(1e5).optional(),submodules:d.z.boolean().default(!1),lfs:d.z.boolean().default(!1),subdirectory:d.z.string().trim().max(240).default("")}).strict();d.z.object({id:Yt,name:d.z.string().trim().min(1).max(160),url:d.z.string().trim().min(1).max(2048),provider:d.z.string().trim().max(80).optional(),ref:ti.default({type:"branch",name:"main"}),auth:ni.default({type:"none"}),clone:ii.default({submodules:!1,lfs:!1,subdirectory:""}),defaultImageSelection:mn.optional(),labels:Qt,createdAt:Xt,updatedAt:Xt}).strict();const ri=d.z.object({id:Yt,nodeId:Yt,name:d.z.string().trim().min(1).max(160),path:d.z.string().trim().min(1).max(4096),defaultImageSelection:mn.optional(),labels:Qt,createdAt:Xt,updatedAt:Xt}).strict(),si=d.z.discriminatedUnion("type",[d.z.object({type:d.z.literal("git-repository"),repositoryId:Yt.optional(),url:d.z.string().trim().min(1).max(2048),provider:d.z.string().trim().max(80).optional(),ref:ti.default({type:"branch",name:"main"}),auth:ni.default({type:"none"}),clone:ii.default({submodules:!1,lfs:!1,subdirectory:""})}).strict(),d.z.object({type:d.z.literal("git-template"),url:d.z.string().trim().min(1).max(2048),templateId:d.z.string().trim().min(1).max(120).optional(),ref:ti.default({type:"branch",name:"main"}),auth:ni.default({type:"none"}),clone:ii.default({submodules:!1,lfs:!1,subdirectory:""})}).strict(),d.z.object({type:d.z.literal("local-folder"),localFolderId:Yt.optional(),path:d.z.string().trim().min(1).max(4096),ownerNodeId:Yt.optional()}).strict()]),oi=d.z.object({mode:d.z.enum(["local-bind","git-clone","empty-volume","persistent-volume"]),path:d.z.string().trim().min(1).max(4096).default("/workspace"),volumeName:d.z.string().trim().max(240).optional(),readOnly:d.z.boolean().default(!1)}).strict(),ai=d.z.enum(["codex","claude"]),ci=d.z.object({id:Yt,name:d.z.string().trim().min(1).max(160),source:si,defaultImageSelection:mn.optional(),defaultNodeId:Yt.optional(),defaultRuntimeId:Yt.optional(),workspacePolicy:oi,labels:Qt,createdAt:Xt,updatedAt:Xt}).strict(),di=d.z.object({id:Yt,name:d.z.string().trim().min(1).max(160),endpoint:d.z.string().trim().min(1).max(2048),key:d.z.string().trim().min(1).max(4096),model:d.z.string().trim().min(1).max(240),app:ai,enabled:d.z.boolean().default(!0),order:d.z.number().int().min(0).max(1e6).default(0),labels:Qt,createdAt:Xt,updatedAt:Xt}).strict(),li=di,ui=di.omit({key:!0}).extend({keyPreview:d.z.string().trim().min(1).max(160),keySet:d.z.boolean()}).strict(),mi=ui.extend({referenceCount:d.z.number().int().min(0)}).strict(),pi=d.z.object({instanceId:Yt,codexModelHash:Yt.optional(),claudeModelHash:Yt.optional(),updatedAt:Xt}).strict(),hi=d.z.discriminatedUnion("type",[d.z.object({type:d.z.literal("control-plane"),name:di.shape.name,enabled:di.shape.enabled,order:di.shape.order}).strict(),d.z.object({type:d.z.literal("node"),nodeId:Yt,name:di.shape.name,enabled:di.shape.enabled,order:di.shape.order,referenceCount:d.z.number().int().min(0)}).strict()]),gi=d.z.object({id:Yt,model:ui,locations:d.z.array(hi).min(1),referenceCount:d.z.number().int().min(0).default(0)}).strict(),fi=d.z.object({nodeId:Yt,code:d.z.string().trim().min(1).max(120),message:d.z.string().trim().min(1).max(2e3)}).strict();d.z.object({models:d.z.array(gi),nodeDiagnostics:d.z.array(fi).default([]),updatedAt:Xt}).strict();const yi=di.omit({id:!0,createdAt:!0,updatedAt:!0}).strict(),Ii=yi.partial().strict(),Ai=di,bi=d.z.object({modelSelection:un,codexModelHash:Yt.optional(),claudeModelHash:Yt.optional()}).strict();function wi(e){const t={app:ai.parse(e.app),endpoint:di.shape.endpoint.parse(e.endpoint),key:di.shape.key.parse(e.key),model:di.shape.model.parse(e.model)};return`mdl_${u.createHash("sha256").update(JSON.stringify(t)).digest("hex")}`}const vi=d.z.enum(["market","custom"]),Ei=d.z.enum(["active","deprecated","yanked"]),Ni=d.z.discriminatedUnion("kind",[d.z.object({kind:d.z.literal("builtin"),key:d.z.string().trim().min(1).max(120)}).strict(),d.z.object({kind:d.z.literal("remote"),url:d.z.string().trim().url().max(2048),mediaType:d.z.enum(["image/png","image/jpeg","image/webp"]).optional(),digest:ln.optional()}).strict()]),Si=d.z.array(d.z.string().trim().min(1).max(80)).default([]),zi=d.z.array(d.z.string().trim().min(1).max(120)).default([]),Ti=d.z.record(d.z.string().trim().min(2).max(35),d.z.string().trim().min(1).max(4096)),_i=d.z.object({os:d.z.string().trim().min(1).max(40),architecture:d.z.string().trim().min(1).max(40),digest:ln.optional(),downloadSizeBytes:d.z.number().int().positive().optional(),unpackedSizeBytes:d.z.number().int().positive().optional()}).strict(),Ci=d.z.object({name:d.z.string().trim().min(1).max(128).regex(nn),version:d.z.string().trim().min(1).max(160).optional(),reference:dn,manifestDigest:ln.optional(),publishedAt:Xt.optional(),platforms:d.z.array(_i).default([]),status:Ei.default("active")}).strict(),ki=d.z.object({id:Yt,publisher:d.z.string().trim().min(1).max(160),slug:d.z.string().trim().min(1).max(160),name:d.z.string().trim().min(1).max(160),description:d.z.string().trim().min(1).max(4096),localizedDescriptions:Ti.optional(),cover:Ni.optional(),repository:d.z.string().trim().min(1).max(512),defaultTag:d.z.string().trim().min(1).max(128).regex(nn),tags:d.z.array(Ci).min(1),capabilities:Si,optionalApps:zi,defaultEnv:Zt,labels:Qt,status:Ei.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."})});d.z.object({protocolVersion:Vt,catalogId:Yt,revision:d.z.string().trim().min(1).max(240),source:d.z.enum(["embedded","remote","cache"]),generatedAt:Xt,expiresAt:Xt.optional(),items:d.z.array(ki)}).strict(),d.z.object({source:d.z.enum(["embedded","remote","cache"]),state:d.z.enum(["ready","refreshing","stale","failed"]),revision:d.z.string().trim().min(1).max(240),updatedAt:Xt,error:d.z.string().trim().max(4096).optional()}).strict(),d.z.object({id:Yt,origin:d.z.literal("custom"),name:d.z.string().trim().min(1).max(160),description:d.z.string().trim().max(4096).optional(),localizedDescriptions:Ti.optional(),cover:Ni.optional(),reference:dn,repository:d.z.string().trim().min(1).max(512),tag:d.z.string().trim().min(1).max(128).regex(nn).optional(),pullPolicy:d.z.literal("if-not-present").default("if-not-present"),capabilities:Si,optionalApps:zi,defaultEnv:Zt,labels:Qt,createdAt:Xt,updatedAt:Xt}).strict();const Oi=d.z.object({name:d.z.string().trim().min(1).max(128).regex(nn),version:d.z.string().trim().min(1).max(160).optional(),reference:dn,manifestDigest:ln.optional(),status:Ei}).strict(),Ri=d.z.object({id:Yt,origin:vi,name:d.z.string().trim().min(1).max(160),description:d.z.string().trim().max(4096).optional(),localizedDescriptions:Ti.optional(),cover:Ni,repository:d.z.string().trim().min(1).max(512),tag:d.z.string().trim().min(1).max(128).regex(nn).optional(),availableTags:d.z.array(Oi),reference:dn,digest:ln.optional(),downloadSizeBytes:d.z.number().int().positive().optional(),unpackedSizeBytes:d.z.number().int().positive().optional(),capabilities:Si,optionalApps:zi,defaultEnv:Zt,labels:Qt,readOnly:d.z.boolean(),lifecycleStatus:Ei.optional(),market:d.z.object({catalogId:Yt,catalogRevision:d.z.string().trim().min(1).max(240),publisher:d.z.string().trim().min(1).max(160),version:d.z.string().trim().min(1).max(160).optional()}).strict().optional()}).strict(),xi=d.z.object({id:Yt,origin:vi,name:d.z.string().trim().min(1).max(160),description:d.z.string().trim().max(4096).optional(),localizedDescriptions:Ti.optional(),cover:Ni.optional(),repository:d.z.string().trim().min(1).max(512),tag:d.z.string().trim().min(1).max(128).regex(nn).optional(),requestedReference:dn,resolvedDigest:ln.optional(),resolvedReference:dn.optional(),downloadSizeBytes:d.z.number().int().positive().optional(),pullPolicy:d.z.literal("if-not-present").default("if-not-present"),capabilities:Si,optionalApps:zi,defaultEnv:Zt,labels:Qt,market:d.z.object({catalogId:Yt,catalogRevision:d.z.string().trim().min(1).max(240),publisher:d.z.string().trim().min(1).max(160),version:d.z.string().trim().min(1).max(160).optional()}).strict().optional(),createdAt:Xt,updatedAt:Xt}).strict(),Di=d.z.object({phase:d.z.enum(["checking-image","pulling-image","resolving-image","ready","failed"]),requestedReference:dn,generation:d.z.number().int().nonnegative().default(0),error:d.z.string().trim().max(4096).optional(),startedAt:Xt,updatedAt:Xt}).strict(),Pi="image.pull.terminal.output",Mi="image.pull.terminal.finished",Li=d.z.object({instanceId:Yt,generation:d.z.number().int().nonnegative(),requestedReference:dn,sequence:d.z.number().int().nonnegative(),observedAt:Xt}).strict(),ji=Li.extend({data:d.z.string().min(1).max(65536),replay:d.z.boolean().optional()}).strict(),$i=Li.extend({outcome:d.z.enum(["succeeded","failed"])}).strict();Li.extend({status:d.z.enum(["connecting","pulling","extracting","complete","failed"]),layers:d.z.object({total:d.z.number().int().nonnegative(),completed:d.z.number().int().nonnegative(),downloaded:d.z.number().int().nonnegative(),downloading:d.z.number().int().nonnegative(),extracting:d.z.number().int().nonnegative()}).strict(),bytes:d.z.object({current:d.z.number().finite().nonnegative(),total:d.z.number().finite().positive()}).strict().optional(),percent:d.z.number().finite().min(0).max(100).optional(),message:d.z.string().trim().min(1).max(500),terminalTail:d.z.string().max(262144).optional(),terminalTruncated:d.z.boolean().optional()}).strict();const Fi=d.z.discriminatedUnion("kind",[d.z.object({kind:d.z.literal("direct")}).strict(),d.z.object({kind:d.z.literal("control-plane-proxy"),proxyId:Yt,proxyBindingId:Yt,targetNodeId:Yt}).strict()]);d.z.object({pingRttMs:d.z.number().nonnegative().optional(),pingRttP95Ms:d.z.number().nonnegative().optional(),consecutiveReconnects:d.z.number().int().nonnegative(),nextRetryAt:Xt.optional()}).strict();const Ui=d.z.object({reachability:d.z.enum(["unknown","reachable","unreachable"]),bindingStatus:d.z.enum(["unknown","active","revoked"]),bindingRevision:d.z.number().int().positive().optional(),streamId:d.z.string().trim().min(1).max(160).optional(),revision:d.z.number().int().nonnegative().optional(),observedAt:Xt.optional(),target:Pt.optional(),lastError:kt.optional(),updatedAt:Xt}).strict(),Vi=d.z.object({id:Yt,name:d.z.string().trim().min(1).max(160),connectionMode:d.z.enum(["local-ipc","local-loopback","direct-http","reverse-wss","control-plane-proxy"]).default("direct-http"),connectionPath:Fi.default({kind:"direct"}),connectionEnabled:d.z.boolean().default(!0),auth:d.z.object({mode:d.z.enum(["local-static-key","paired-hmac","proxy-binding"]).default("local-static-key"),keyId:Yt.optional(),secret:d.z.string().trim().max(4096).optional(),pairedAt:Xt.optional(),pairing:d.z.object({status:d.z.enum(["pending","paired","expired"]).default("pending"),joinToken:d.z.string().trim().max(4096).optional(),expiresAt:Xt.optional()}).strict().optional()}).strict().default({mode:"local-static-key"}),endpoint:d.z.string().trim().max(2048).optional(),controlEndpoint:d.z.string().trim().max(2048).optional(),containerEndpoint:d.z.string().trim().max(2048).optional(),publicWebBase:d.z.string().trim().max(2048).optional(),status:d.z.enum(["unknown","online","offline","degraded"]).default("unknown"),health:d.z.enum(["unknown","ok","degraded","failed"]).default("unknown"),capabilities:d.z.record(d.z.string(),d.z.unknown()).default({}),proxyState:Ui.optional(),appInventory:_n.optional(),labels:Qt,lastSeenAt:Xt.optional(),createdAt:Xt,updatedAt:Xt}).strict().superRefine((e,t)=>{"control-plane-proxy"===e.connectionPath.kind&&"control-plane-proxy"!==e.connectionMode&&t.addIssue({code:"custom",path:["connectionPath"],message:"Control-plane proxy paths require control-plane-proxy connection mode."}),"control-plane-proxy"===e.connectionMode&&"control-plane-proxy"!==e.connectionPath.kind&&t.addIssue({code:"custom",path:["connectionPath"],message:"Control-plane proxy nodes require a control-plane-proxy connection path."})}),Hi=d.z.object({id:Yt,nodeId:Yt,name:d.z.string().trim().min(1).max(160),type:d.z.enum(["docker","kubernetes","local"]),status:d.z.enum(["unknown","online","offline","degraded"]).default("unknown"),accessStrategy:d.z.enum(["node-proxy","direct-port","kubernetes-ingress","kubernetes-port-forward"]).default("node-proxy"),capabilities:d.z.record(d.z.string(),d.z.unknown()).default({}),labels:Qt,createdAt:Xt,updatedAt:Xt}).strict(),qi=d.z.object({instanceId:Yt,runtimeKind:d.z.literal("docker"),state:d.z.enum(["pending","available","stopped","unavailable"]),sampledAt:Xt,cpu:d.z.object({usagePercent:d.z.number().nonnegative()}).strict().optional(),memory:d.z.object({usageBytes:d.z.number().nonnegative(),limitBytes:d.z.number().nonnegative().optional(),usagePercent:d.z.number().nonnegative().optional()}).strict().optional(),network:d.z.object({rxBytes:d.z.number().nonnegative(),txBytes:d.z.number().nonnegative()}).strict().optional(),blockIo:d.z.object({readBytes:d.z.number().nonnegative(),writeBytes:d.z.number().nonnegative()}).strict().optional(),pids:d.z.number().int().nonnegative().optional(),error:d.z.string().trim().max(2048).optional()}).strict(),Bi=d.z.object({modelEndpointProbe:d.z.boolean().optional(),aiSessionHistoryLimit:d.z.boolean().optional(),aiSessionAttachmentRetention:d.z.boolean().optional(),folderPlaces:d.z.boolean().optional(),localFolderNameUpdate:d.z.boolean().optional()}).strip();d.z.object({ok:d.z.boolean().optional(),role:d.z.string().optional(),nodeId:Yt.optional(),platform:gn.optional(),arch:fn.optional(),protocolVersion:Vt.optional(),capabilities:Bi.optional(),build:qn.strip().optional(),process:d.z.object({pid:d.z.number().int().positive(),startIdentity:d.z.string().trim().min(1).optional()}).strip().optional(),listener:d.z.object({host:d.z.string().trim().min(1),port:d.z.number().int().min(1).max(65535)}).strip().optional(),instanceProxy:d.z.object({requests:d.z.number().int().nonnegative(),active:d.z.number().int().nonnegative(),completed:d.z.number().int().nonnegative(),aborted:d.z.number().int().nonnegative(),limitRejected:d.z.number().int().nonnegative(),responseBytes:d.z.number().nonnegative(),totalDurationMs:d.z.number().nonnegative(),maxResponseBytes:d.z.number().int().nonnegative()}).partial().strip().optional(),serverTime:Xt.optional()}).strip();const Ki=d.z.object({bindScope:d.z.enum(["loopback","all-ipv4"]),port:d.z.number().int().min(1).max(65535)}).strict(),Gi=Ki.extend({host:d.z.enum(["127.0.0.1","0.0.0.0"]),status:d.z.enum(["listening","error"]),source:d.z.enum(["bootstrap","persisted"]),error:d.z.string().trim().max(2048).optional()}).strict(),Ji=Ki;d.z.object({nodeId:Yt,joinToken:d.z.string().trim().min(1),expiresAt:Xt}).passthrough(),d.z.object({nodeId:Yt,keyId:Yt,secret:d.z.string().regex(/^[A-Za-z0-9_-]{32,128}$/),pairedAt:Xt}).strict();const Wi=d.z.object({id:Yt,keyId:Yt,name:d.z.string().trim().min(1).max(160).optional(),pairedAt:Xt,updatedAt:Xt,current:d.z.boolean()}).passthrough();d.z.object({keyId:Yt,revoked:d.z.literal(!0),revokedAt:Xt}).strict(),d.z.object({id:Yt,pairingKeyId:Yt,url:d.z.string().trim().min(1).max(2048),name:d.z.string().trim().min(1).max(160).optional(),enabled:d.z.boolean(),createdAt:Xt,updatedAt:Xt,status:d.z.enum(["disabled","connecting","connected","reconnecting","failed"]),pingRttMs:d.z.number().nonnegative().optional(),pingRttP95Ms:d.z.number().nonnegative().optional(),consecutiveReconnects:d.z.number().int().nonnegative().optional(),nextRetryAt:Xt.optional(),lastConnectedAt:Xt.optional(),lastDisconnectedAt:Xt.optional(),error:d.z.string().optional()}).passthrough(),d.z.object({pairing:Wi,connection:d.z.object({id:Yt,pairingKeyId:Yt,url:d.z.string().trim().min(1).max(2048),name:d.z.string().trim().min(1).max(160).optional(),enabled:d.z.boolean(),createdAt:Xt,updatedAt:Xt}).passthrough(),tunnel:d.z.object({status:d.z.enum(["disabled","saved","connecting","connected","failed"]),error:d.z.string().trim().max(2048).optional()}).passthrough()}).passthrough(),d.z.object({deleted:d.z.boolean().optional()}).passthrough();const Yi=d.z.object({repository:d.z.string().trim().optional(),tag:d.z.string().trim().optional(),id:d.z.string().trim(),createdSince:d.z.string().trim().optional(),size:d.z.string().trim().optional(),sizeBytes:d.z.number().int().nonnegative().optional(),reference:d.z.string().trim().min(1),repoDigests:d.z.array(d.z.string().trim().min(1).max(512)).default([])}).passthrough();d.z.object({image:Ri,status:d.z.enum(["available","pull-required","unknown"]),localImage:Yi.optional(),localSizeBytes:d.z.number().int().nonnegative().optional(),downloadSizeBytes:d.z.number().int().positive().optional(),unpackedSizeBytes:d.z.number().int().positive().optional(),error:d.z.string().trim().max(2048).optional()}).strict();const Xi=d.z.lazy(()=>d.z.object({name:d.z.string().trim().min(1),path:d.z.string().trim().min(1).max(4096),children:d.z.array(Xi)}).passthrough());d.z.object({kind:d.z.enum(["home","root"]),name:d.z.string().trim().min(1),path:d.z.string().trim().min(1).max(4096)}).passthrough(),d.z.object({status:d.z.number().int().min(100).max(599).optional(),headers:d.z.record(d.z.string(),d.z.string()).optional(),bodyBase64:d.z.string().optional()}).passthrough();const Qi=d.z.object({strategy:d.z.enum(["node-proxy","direct-port","kubernetes-ingress","kubernetes-port-forward"]).default("node-proxy"),web:d.z.string().trim().max(2048).optional(),api:d.z.string().trim().max(2048).optional(),vnc:d.z.string().trim().max(2048).optional(),tty:d.z.string().trim().max(2048).optional(),logs:d.z.string().trim().max(2048).optional(),status:d.z.enum(["unknown","reachable","endpoint-unreachable"]).default("unknown")}).strict(),Zi=d.z.object({...Qi.shape}).strict(),er=d.z.object({strategy:d.z.enum(["control-plane-proxy","direct-port","node-proxy","kubernetes-ingress","kubernetes-port-forward"]).default("control-plane-proxy"),web:d.z.string().trim().max(2048).optional(),api:d.z.string().trim().max(2048).optional(),ws:d.z.string().trim().max(2048).optional(),status:d.z.enum(["unknown","reachable","endpoint-unreachable"]).default("unknown")}).strict().default({strategy:"control-plane-proxy",status:"unknown"}),tr=d.z.object({mode:d.z.enum(["local-bind","git-clone","empty-volume","persistent-volume"]).optional(),status:d.z.enum(["unknown","pending","ready","failed"]).default("unknown"),path:d.z.string().trim().max(4096).optional(),resolvedCommit:d.z.string().trim().max(120).optional(),error:d.z.string().trim().max(2048).optional()}).passthrough(),nr=d.z.object({id:Yt,name:d.z.string().trim().min(1).max(160),projectId:Yt.optional(),source:si,sourceSnapshot:d.z.record(d.z.string(),d.z.unknown()).default({}),modelSelection:un,nodeId:Yt,runtimeId:Yt,imageSelection:mn.optional(),environmentSource:pn.optional(),environmentTemplateOrigin:In.optional(),imageSnapshot:xi.optional(),imageProvisioning:Di.optional(),stateRevision:d.z.number().int().min(0).default(0),processIncarnationId:d.z.string().trim().min(1).max(120).optional(),status:d.z.enum(["created","provisioning","starting","registering","registered","running","stopping","stopped","deleting","failed","unhealthy"]).default("created"),health:d.z.enum(["unknown","ok","degraded","failed"]).default("unknown"),connectionStatus:d.z.enum(["unknown","online","offline","endpoint-unreachable"]).default("unknown"),agentStatus:d.z.enum(["unknown","online","offline"]).default("unknown"),targetStatus:d.z.enum(["unknown","reachable","endpoint-unreachable"]).default("unknown"),uiAccessStatus:d.z.enum(["unknown","reachable","endpoint-unreachable"]).default("unknown"),controlMode:d.z.enum(["standalone","controlled"]).default("controlled"),protocolVersion:Vt.optional(),instanceVersion:d.z.string().trim().max(80).optional(),build:qn.optional(),runtimeVersion:Jn.optional(),ready:d.z.boolean().default(!1),capabilities:Jt.default(qt),appInventory:_n.optional(),config:d.z.object({autoImportAgentConfigs:d.z.boolean().default(!0),defaultCodexPermissionMode:Re.default("ask"),aiSessionHistoryLimit:d.z.number().int().min(1).max(Ze).default(50),aiSessionAttachmentRetentionDays:d.z.number().int().min(0).max(365).default(30)}).strict().default({autoImportAgentConfigs:!0,defaultCodexPermissionMode:"ask",aiSessionHistoryLimit:50,aiSessionAttachmentRetentionDays:30}),workspace:tr.default({status:"unknown"}),target:Qi.default({strategy:"direct-port",status:"unknown"}),access:er,apps:d.z.object({runningCount:d.z.number().int().min(0).default(0),problemCount:d.z.number().int().min(0).default(0),updatedAt:Xt.optional(),revision:d.z.number().int().min(0).optional()}).strict().default({runningCount:0,problemCount:0}),aiSessions:it.default(()=>({runningCount:0,waitingCount:0,staleCount:0,sessions:[],updatedAt:(new Date).toISOString()})),triggers:d.z.object({enabledCount:d.z.number().int().min(0).default(0),runningCount:d.z.number().int().min(0).default(0),errorCount:d.z.number().int().min(0).default(0),configs:d.z.array(d.z.object({configHash:d.z.string().trim().min(1),config:ft,deployments:d.z.array(It).default([]),runtime:d.z.array(At).default([])}).strict()).default([]),recentRuns:d.z.array(bt).default([])}).strict().optional(),runtime:d.z.object({kind:d.z.string().trim().max(80).optional(),containerName:d.z.string().trim().max(240).optional(),containerId:d.z.string().trim().max(240).optional(),workspacePath:d.z.string().trim().max(4096).optional(),pid:d.z.number().int().positive().optional(),port:d.z.number().int().positive().max(65535).optional(),labels:d.z.record(d.z.string(),d.z.string()).default({})}).strict().default({labels:{}}),registrationToken:d.z.string().trim().min(1).max(240).optional(),lastHeartbeatAt:Xt.optional(),createdAt:Xt,updatedAt:Xt}).strict(),ir="instance.lifecycle.snapshot",rr=d.z.object({instanceId:nr.shape.id,revision:d.z.number().int().min(0),updatedAt:Xt,status:nr.shape.status.unwrap(),health:nr.shape.health.unwrap(),connectionStatus:nr.shape.connectionStatus.unwrap(),accessStatus:d.z.enum(["reachable","endpoint-unreachable"]),imageProvisioning:Di.optional(),workspace:tr,runtime:nr.shape.runtime.unwrap(),runtimeVersion:Jn.optional(),ready:d.z.boolean(),lastHeartbeatAt:Xt.optional()}).strict();function sr(e,t){return nr.safeParse(or(e,t))}function or(e,t){if(!e||"object"!=typeof e||Array.isArray(e))return e;const n=e,i=new Set(Object.keys(nr.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=Wt(e)}else r.capabilities=Wt(void 0);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=dr(e,["id","name","kind","source","availability","diagnosticCode"]);return!i||"object"!=typeof i||Array.isArray(i)?i:{...i,capabilities:dr(e.capabilities,["automation","supportsCwdSelection"])}}):i.items,issues:Array.isArray(i.issues)?i.issues.map(e=>dr(e,["code","message"])):i.issues},s=_n.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=si.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=dr(i,o);if("local-folder"!==r){const e=ar(ti,dr(i.ref,["type","name","commit"]),"source.ref",t,n),r=ar(ni,dr(i.auth,["type","secretId"]),"source.auth",t,n),s=ar(ii,dr(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=ar(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=ar(qn,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=ar(nt,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:Xt.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"}),it.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=ar(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=dr(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=dr(e,t)}return s.action=dr(r.action,["promptTemplate"]),s.policy=dr(r.policy,["cooldownMs","maxConcurrentRuns","whenBusy"]),ar(ft,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,It,`triggers.configs.${i}.deployments`),runtime:r(s.runtime,At,`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,bt,"triggers.recentRuns")}}(n.triggers,t,"string"==typeof n.id?n.id:void 0),r.apps=ar(nr.shape.apps.unwrap(),dr(n.apps,["runningCount","problemCount","updatedAt","revision"]),"apps",t,"string"==typeof n.id?n.id:void 0)||{runningCount:0,problemCount:0},r.config=ar(nr.shape.config.unwrap(),dr(n.config,["autoImportAgentConfigs","defaultCodexPermissionMode","aiSessionHistoryLimit","aiSessionAttachmentRetentionDays"]),"config",t,"string"==typeof n.id?n.id:void 0)||{autoImportAgentConfigs:!0,defaultCodexPermissionMode:"ask",aiSessionHistoryLimit:50,aiSessionAttachmentRetentionDays:30},r.modelSelection=ar(un.unwrap(),dr(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=an(s)}catch{if(!s.includes("@")&&s.lastIndexOf(":")<=s.lastIndexOf("/"))try{s=an(`${s}:latest`)}catch{}}try{r=s?cn(s):void 0}catch{}return{id:t.id,origin:"custom",name:t.name,description:t.description,localizedDescriptions:t.localizedDescriptions,cover:dr(t.cover,["kind","key","url","mediaType","digest"]),reference: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?cn(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?dr(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=dr(n.imageSelection,["imageId","tag"]);r.imageSelection=o||(s?{imageId:s,tag:r.imageSnapshot?.tag}:void 0),r.imageProvisioning=ar(Di,dr(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(Jn.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(Gn.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=Xt.safeParse(i.lastAttemptAt),m=Xt.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=ar(tr,n.workspace,"workspace",t,"string"==typeof n.id?n.id:void 0)||{status:"unknown"},r.environmentSource=ar(pn,n.environmentSource,"environmentSource",t,"string"==typeof n.id?n.id:void 0),r.environmentTemplateOrigin=ar(In,n.environmentTemplateOrigin,"environmentTemplateOrigin",t,"string"==typeof n.id?n.id:void 0),r.runtime=ar(nr.shape.runtime.unwrap(),n.runtime,"runtime",t,"string"==typeof n.id?n.id:void 0)||{labels:{}},r.target=ar(Qi,dr(n.target??n.endpoints,["strategy","web","api","vnc","tty","logs","status"]),"target",t,"string"==typeof n.id?n.id:void 0)||{strategy:"direct-port",status:"unknown"},r.access=ar(er,dr(n.access,["strategy","web","api","ws","status"]),"access",t,"string"==typeof n.id?n.id:void 0)||{strategy:"control-plane-proxy",status:"unknown"};for(const[e,i]of Object.entries(nr.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 ar(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=cr(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=cr(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 cr(e,t){let n=e;for(const e of t){if(!n||"object"!=typeof n)return;n=n[e]}return n}function dr(e,t){if(!e||"object"!=typeof e||Array.isArray(e))return e;const n=e;return Object.fromEntries(t.filter(e=>Object.prototype.hasOwnProperty.call(n,e)).map(e=>[e,n[e]]))}const lr=d.z.object({instanceId:Yt.optional(),projectId:Yt.optional(),source:si.optional(),nodeId:Yt.optional(),runtimeId:Yt.optional(),imageSelection:mn.optional(),instanceVersion:d.z.string().trim().max(80).optional(),protocolVersion:Vt,build:qn.optional(),controlMode:d.z.enum(["standalone","controlled"]).default("controlled"),capabilities:Jt.default(qt),appInventory:_n.optional(),target:Zi.optional(),workspace:tr.default({status:"unknown"}),registrationToken:d.z.string().trim().max(240).optional(),processIncarnationId:d.z.string().trim().min(1).max(120).optional()}).strict().superRefine((e,t)=>{Ut.has(e.protocolVersion)&&!e.appInventory&&t.addIssue({code:"custom",path:["appInventory"],message:"Current protocol register payload requires appInventory."})}),ur=d.z.object({status:nr.shape.status.optional(),health:nr.shape.health.optional(),protocolVersion:Vt,build:qn.optional(),capabilities:nr.shape.capabilities.optional(),appInventory:_n.optional(),apps:nr.shape.apps.optional(),aiSessions:nr.shape.aiSessions.optional(),triggers:nr.shape.triggers.optional(),workspace:tr.optional(),target:Zi.optional(),processIncarnationId:d.z.string().trim().min(1).max(120).optional()}).strict().superRefine((e,t)=>{Ut.has(e.protocolVersion)&&!e.appInventory&&t.addIssue({code:"custom",path:["appInventory"],message:"Current protocol heartbeat payload requires appInventory."})}),mr=d.z.enum(["web","telegram","wechat","dingding","lark"]);function pr(e,t){let n=yr(t);for(let t=0;t<100;t+=1){const t=e.safeParse(n);if(t.success)return t;const i=hr(t.error.issues);let r=!1;for(const e of i){const t=fr(n,e.path);if(t&&"object"==typeof t&&!Array.isArray(t))for(const n of e.keys)Object.prototype.hasOwnProperty.call(t,n)&&(delete t[n],r=!0)}if(!r)return t}return e.safeParse(n)}function hr(e,t=[]){const n=[];for(const i of e){if("unrecognized_keys"===i.code){n.push({code:"unrecognized_keys",keys:i.keys,path:[...t,...i.path]});continue}if("invalid_union"!==i.code||!Array.isArray(i.errors))continue;const e=i.errors.filter(e=>Array.isArray(e));if(!e.length)continue;const r=e.reduce((e,t)=>gr(t)<gr(e)?t:e);n.push(...hr(r,[...t,...i.path]))}return n}function gr(e){return e.reduce((e,t)=>{if("unrecognized_keys"===t.code)return e;if("invalid_union"!==t.code||!Array.isArray(t.errors))return e+1;const n=t.errors.filter(e=>Array.isArray(e));return e+(n.length?Math.min(...n.map(gr)):1)},0)}function fr(e,t){let n=e;for(const e of t){if(!n||"object"!=typeof n)return;n=n[e]}return n}function yr(e){return Array.isArray(e)?e.map(yr):e&&"object"==typeof e?Object.getPrototypeOf(e)!==Object.prototype&&null!==Object.getPrototypeOf(e)?e:Object.fromEntries(Object.entries(e).map(([e,t])=>[e,yr(t)])):e}function Ir(e,t,n={}){return new Promise((i,r)=>{if(n.signal?.aborted)return void r(Object.assign(new Error(`${e} was aborted.`),{code:"RUNTIME_COMMAND_ABORTED"}));const s=m.spawn(e,t,{stdio:["ignore","pipe","pipe"]}),o=[],a=[];let c=!1;const d=n.timeoutMs?setTimeout(()=>{c=!0,s.kill("SIGKILL")},n.timeoutMs):void 0;let l=!1;const u=()=>{l=!0,s.kill("SIGKILL")},p=()=>{d&&clearTimeout(d),n.signal?.removeEventListener("abort",u)};n.signal?.addEventListener("abort",u,{once:!0}),d?.unref?.(),s.stdout.on("data",e=>o.push(Buffer.from(e))),s.stderr.on("data",e=>a.push(Buffer.from(e))),s.on("error",e=>{p(),r(e)}),s.on("close",t=>{p();const s={stdout:Buffer.concat(o).toString("utf8").trim(),stderr:Buffer.concat(a).toString("utf8").trim()};if(c){const t=new Error(`${e} timed out after ${n.timeoutMs}ms`);return Object.assign(t,{statusCode:504,code:"RUNTIME_COMMAND_TIMEOUT",details:s}),void r(t)}if(l)return void r(Object.assign(new Error(`${e} was aborted.`),{code:"RUNTIME_COMMAND_ABORTED",details:s}));if(0===t)return void i(s);const d=new Error(s.stderr||`${e} exited with code ${t}`);Object.assign(d,{statusCode:502,code:"RUNTIME_EXECUTOR_FAILED",details:s}),r(d)})})}d.z.object({id:Yt,channel:mr,name:d.z.string().trim().min(1).max(160),enabled:d.z.boolean().default(!1),token:d.z.string().trim().max(4096).optional(),defaultChatId:d.z.string().trim().max(240).optional(),allowedUserIds:d.z.array(d.z.string().trim().min(1).max(240)).default([]),pollIntervalMs:d.z.number().int().positive().max(6e4).default(3e3),settings:d.z.record(d.z.string(),d.z.unknown()).default({}),createdAt:Xt,updatedAt:Xt}).strict(),d.z.object({id:Yt,channel:mr,bridgeId:Yt.optional(),chatSessionId:d.z.string().trim().min(1).max(240),userId:d.z.string().trim().max(240).optional(),activeProjectId:Yt.optional(),activeInstanceId:Yt.optional(),activeAiSessionId:d.z.string().trim().min(1).max(120).optional(),lastUsedAt:Xt,createdAt:Xt,updatedAt:Xt}).strict(),d.z.object({source:d.z.object({type:d.z.literal("chat-gateway").default("chat-gateway"),channel:mr,bridgeId:Yt.optional(),chatSessionId:d.z.string().trim().min(1).max(240),userId:d.z.string().trim().max(240).optional()}).strict(),message:d.z.object({text:d.z.string().trim().max(2e4).default(""),attachments:d.z.array(_e).max(6).default([])}).strict().superRefine((e,t)=>{e.attachments.reduce((e,t)=>e+("inline"===t.source.type?t.size:0),0)>X&&t.addIssue({code:d.z.ZodIssueCode.custom,path:["attachments"],message:"Inline attachments must be 41943040 bytes or less in total."})}),target:d.z.object({instanceId:Yt,aiSessionId:d.z.string().trim().min(1).max(120)}).strict().optional()}).strict(),d.z.object({id:Yt,instanceId:Yt,projectId:Yt.optional(),aiSessionId:d.z.string().trim().min(1).max(120),providerSessionId:d.z.string().trim().max(240).optional(),result:d.z.string().default(""),timeoutMs:d.z.number().positive().optional(),source:d.z.string().trim().max(120).optional(),kind:d.z.enum(["task","approval"]).default("task"),status:d.z.enum(["pending","unreachable"]).default("pending"),error:d.z.string().trim().max(2048).optional(),lastSeenAt:Xt}).strict();const Ar=(e,t,n={})=>new Promise((i,r)=>{if(n.signal?.aborted)return void r(Object.assign(new Error(`${e} was aborted.`),{code:"RUNTIME_COMMAND_ABORTED"}));const s=[];let o,a=!1,c=!1;try{o=p.spawn(e,t,{name:"xterm-256color",cols:n.cols||120,rows:n.rows||40,cwd:process.cwd(),env:process.env})}catch(e){return void r(e)}const d=n.timeoutMs?setTimeout(()=>{a=!0,o.kill("SIGKILL")},n.timeoutMs):void 0,l=()=>{c=!0;try{o.kill("SIGKILL")}catch{}};n.signal?.addEventListener("abort",l,{once:!0}),d?.unref?.(),o.onData(e=>{s.push(e),n.onData?.(e)}),o.onExit(({exitCode:t})=>{d&&clearTimeout(d),n.signal?.removeEventListener("abort",l);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})):c?r(Object.assign(new Error(`${e} was aborted.`),{code:"RUNTIME_COMMAND_ABORTED",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 br{inFlight=new Map;runCommand;runTerminalCommand;constructor(e=Ir,t){this.runCommand=e,this.runTerminalCommand=t||function(e){return e===Ir?Ar:async(t,n,i={})=>{const r=await e(t,n,{timeoutMs:i.timeoutMs,signal:i.signal});return r.stdout&&i.onData?.(r.stdout),r.stderr&&i.onData?.(r.stderr),r}}(e)}ensure(e,t,n,i){const r=an(e),s=this.inFlight.get(r);if(s)return t&&(s.phaseListeners.add(t),s.phase&&t(s.phase)),n&&(s.terminalListeners.add(n),s.terminalTail&&n({sequence:s.terminalSequence,data:s.terminalTail,replay:!0})),this.bindAbort(s,i),s.promise;const o=new Set,a=new Set;t&&o.add(t),n&&a.add(n);const c={promise:Promise.resolve(void 0),controller:new AbortController,abortDisposers:new Set,phaseListeners:o,terminalListeners:a,terminalSequence:0,terminalTail:""};return this.bindAbort(c,i),c.promise=this.ensureOnce(r,e=>{c.phase=e,o.forEach(t=>t(e))},e=>{c.terminalSequence+=1,c.terminalTail=`${c.terminalTail}${e}`.slice(-262144);const t={sequence:c.terminalSequence,data:e};a.forEach(e=>e(t))},c.controller.signal).finally(()=>{this.inFlight.delete(r);for(const e of c.abortDisposers)e();c.abortDisposers.clear()}),this.inFlight.set(r,c),c.promise}bindAbort(e,t){if(!t)return;if(t.aborted)return void e.controller.abort();const n=()=>e.controller.abort();t.addEventListener("abort",n,{once:!0}),e.abortDisposers.add(()=>t.removeEventListener("abort",n))}async ensureOnce(e,t,n,i){t("checking-image");let r=await this.inspect(e,i).catch(e=>{if(i.aborted)throw e}),s=!1;r||(t("pulling-image"),await this.runTerminalCommand("docker",["pull",e],{cols:120,rows:40,signal:i,onData:n}),s=!0,r=await this.inspect(e,i)),t("resolving-image");const o=(a=r,Array.isArray(a.RepoDigests)?a.RepoDigests.filter(e=>"string"==typeof e):[]).find(e=>/@sha256:[a-fA-F0-9]{64}$/.test(e));var a;const c=o?.split("@").at(-1)?.toLowerCase();return{requestedReference:e,...c?{resolvedDigest:c}:{},resolvedReference:o||e,pulled:s}}async inspect(e,t){const n=await this.runCommand("docker",["image","inspect",e,"--format","{{json .}}"],{signal:t});return JSON.parse(n.stdout.trim()||"{}")}}function wr(e){if(!e)return;const t=/^([0-9]+(?:\.[0-9]+)?)\s*(B|kB|MB|GB|TB)$/i.exec(e.trim());if(!t)return;const n=Number(t[1])*{b:1,kb:1e3,mb:1e6,gb:1e9,tb:1e12}[t[2].toLowerCase()];return Number.isSafeInteger(Math.round(n))?Math.round(n):void 0}const vr="/run/task-handoff/bootstrap",Er=`${vr}/entrypoint.sh`,Nr="/bin/bash",Sr=`${vr}/runtime-installer.mjs`,zr="/opt/task-handoff/instance-runtime";function Tr(e,t){return{role:"runtime",name:`${qr(e)}-runtime`,mountPath:zr,labels:{"task-handoff.owner":"task-handoff","task-handoff.instance-id":e,"task-handoff.node-id":t,"task-handoff.volume-role":"runtime"}}}function _r(e){return function(e,t,n){const i=qr(e);return[{role:"data",suffix:"data",mountPath:"/data"},{role:"agent-home",suffix:"agent-home",mountPath:"/home/agent"},..."local-folder"===n.type?[]:[{role:"workspace",suffix:"workspace",mountPath:"/workspace"}]].map(({role:n,suffix:r,mountPath:s})=>({role:n,name:`${i}-${r}`,mountPath:s,labels:{"task-handoff.owner":"task-handoff","task-handoff.instance-id":e,"task-handoff.node-id":t,"task-handoff.volume-role":n}}))}(e.instance.id,e.node?.id||"node_unset",e.project.source)}const Cr=new Set(["TASK_HANDOFF_REGISTRATION_TOKEN","OPENAI_API_KEY","OPENAI_BASE_URL","CODEX_MODEL","TASK_HANDOFF_CODEX_BASE_URL","TASK_HANDOFF_CODEX_MODEL","TASK_HANDOFF_CODEX_MODEL_ID","ANTHROPIC_API_KEY","ANTHROPIC_BASE_URL","CLAUDE_MODEL","TASK_HANDOFF_CLAUDE_MODEL","TASK_HANDOFF_CLAUDE_MODEL_ID"]);function kr(e,t=[]){const n=e&&"object"==typeof e&&!Array.isArray(e)?e:{},i=n.Config&&"object"==typeof n.Config&&!Array.isArray(n.Config)?n.Config:n,r=new Set;for(const e of Array.isArray(i.Env)?i.Env:[]){if("string"!=typeof e)continue;const n=e.indexOf("="),i=-1===n?e:e.slice(0,n),s=-1===n?"":e.slice(n+1);Cr.has(i)&&r.add(`Config.Env.${i}`),t.some(e=>e&&s.includes(e))&&r.add(`Config.Env.${i||"unknown"}`)}if(i.Labels&&"object"==typeof i.Labels&&!Array.isArray(i.Labels))for(const[e,n]of Object.entries(i.Labels))(Cr.has(e)||"string"==typeof n&&t.some(e=>e&&n.includes(e)))&&r.add(`Config.Labels.${e}`);if(r.size)throw Object.assign(new Error(`Docker configuration contains instance-private values in ${[...r].sort().join(", ")}.`),{statusCode:409,code:"ENVIRONMENT_TEMPLATE_SECRET_IN_DOCKER_CONFIG",findings:[...r].sort()})}class Or{runCommand;publishHost;images;launcherAssetsDir;portResolutionRetryDelaysMs;constructor(e=Ir,t={}){this.runCommand=e,this.images=t.imageService||new br(e),this.publishHost=t.publishHost||"127.0.0.1",this.launcherAssetsDir=t.launcherAssetsDir||Lr(),this.portResolutionRetryDelaysMs=t.portResolutionRetryDelaysMs?.length?t.portResolutionRetryDelaysMs:[0,100,250,500,1e3]}async start(e){Gr(e);const t=e.instance.runtime.containerName||qr(e.instance.id),n=await this.inspectContainerForStart(t);if(n){Vr(t,n.id,e.instance.runtime.containerId,"before start","RUNTIME_EXECUTOR_FAILED");const i=n.labels["task-handoff.instance-id"];if(i!==e.instance.id)throw $r("RUNTIME_EXECUTOR_FAILED",`Docker container ${t} belongs to ${i||"an unknown instance"}, not ${e.instance.id}.`);const s=n.mounts.find(e=>"bind"===e.type&&e.destination===vr);if("1"!==n.labels["task-handoff.bootstrap-abi"]||n.entrypoint[0]!==Nr||n.command[0]!==Er||!s?.source||r.resolve(s.source)!==r.resolve(this.launcherAssetsDir)){const i=new Set(_r(e).flatMap(e=>n.mounts.some(t=>"volume"===t.type&&t.name===e.name&&t.destination===e.mountPath)?[e.name]:[]));return await this.createPersistentVolumes(e,i),this.recreateWithAuthoritativeBootstrap(e,t,n)}await this.createRuntimeVolume(e),await this.validatePersistentVolumes(e,n.mounts);try{await this.runCommand("docker",["start",t])}catch(e){throw $r("RUNTIME_EXECUTOR_FAILED",`Could not start Docker container ${t}.`,e)}return this.resumedContainerResult(e,t,n.id)}if(e.instance.environmentTemplateOrigin){const t=await this.inspectEnvironmentTemplateImage(e.instance.environmentTemplateOrigin.imageId);if(t.imageId!==e.instance.environmentTemplateOrigin.imageId||t.platform!==e.instance.environmentTemplateOrigin.platform||t.architecture!==e.instance.environmentTemplateOrigin.architecture)throw Object.assign(new Error(`Environment template image identity or platform changed for instance ${e.instance.id}.`),{statusCode:409,code:"ENVIRONMENT_TEMPLATE_IMAGE_IDENTITY_MISMATCH"})}else await this.images.ensure(e.image.resolvedReference||e.image.requestedReference);let i;await this.createPersistentVolumes(e);try{i=await this.runCommand("docker",Kr(e,t,{publishHost:this.publishHost,launcherAssetsDir:this.launcherAssetsDir}))}catch(e){throw $r("RUNTIME_EXECUTOR_FAILED",`Could not create Docker container ${t}.`,e)}return this.bootstrapResult(e,t,i.stdout||void 0)}async recreateWithAuthoritativeBootstrap(e,t,n){const i=`${t}-pre-bootstrap-${n.id.slice(0,12)}`;n.running&&await this.runCommand("docker",["stop",t]);try{await this.runCommand("docker",["rename",t,i])}catch(e){throw n.running&&await this.runCommand("docker",["start",t]).catch(()=>({stdout:"",stderr:""})),$r("RUNTIME_EXECUTOR_FAILED",`Could not preserve Docker container ${t} before bootstrap migration.`,e)}try{const r=await this.runCommand("docker",Kr(e,t,{publishHost:this.publishHost,launcherAssetsDir:this.launcherAssetsDir,imageReference:n.image}));return this.bootstrapResult(e,t,r.stdout||void 0,i)}catch(e){throw await this.runCommand("docker",["rm","-f",t]).catch(()=>({stdout:"",stderr:""})),await this.runCommand("docker",["rename",i,t]).catch(()=>({stdout:"",stderr:""})),n.running&&await this.runCommand("docker",["start",t]).catch(()=>({stdout:"",stderr:""})),$r("RUNTIME_EXECUTOR_FAILED",`Could not recreate Docker container ${t} with the node-agent bootstrap.`,e)}}async inspectContainerConfigSecurity(e,t){kr(await this.runCommand("docker",["inspect","--format","{{json .}}",e]).then(e=>JSON.parse(e.stdout||"{}")).catch(t=>{throw $r("ENVIRONMENT_TEMPLATE_CONTAINER_INSPECT_FAILED",`Could not inspect Docker container ${e}.`,t)}),t)}async inspectImageConfigSecurity(e,t){kr(await this.runCommand("docker",["image","inspect","--format","{{json .}}",e]).then(e=>JSON.parse(e.stdout||"{}")).catch(e=>{throw $r("ENVIRONMENT_TEMPLATE_IMAGE_INSPECT_FAILED","Could not inspect Docker image configuration.",e)}),t)}async commitEnvironmentTemplate(e,t,n){const i=await this.inspectContainerId(e);if(!i)throw $r("ENVIRONMENT_TEMPLATE_CONTAINER_NOT_FOUND",`Docker container ${e} does not exist.`);Vr(e,i,t,"before environment template commit","ENVIRONMENT_TEMPLATE_CONTAINER_IDENTITY_MISMATCH");try{const t=(await this.runCommand("docker",["commit",e,n])).stdout.trim();if(!t)throw new Error("Docker commit did not return an image id.");return t}catch(t){throw $r("ENVIRONMENT_TEMPLATE_COMMIT_FAILED",`Could not save Docker container ${e} as an environment template.`,t)}}async inspectEnvironmentTemplateImage(e){try{const t=await this.runCommand("docker",["image","inspect","--format","{{json .}}",e]),n=JSON.parse(t.stdout||"{}"),i="string"==typeof n.Id?n.Id:"",r=Pr(n.Os),s=Mr(n.Architecture),o="number"==typeof n.Size?n.Size:Number.NaN;if(!/^sha256:[a-f0-9]{64}$/.test(i)||!r||!s||!Number.isSafeInteger(o)||o<0)throw new Error("Docker image inspection did not return a valid immutable identity.");return{imageId:i,platform:r,architecture:s,sizeBytes:o}}catch(e){throw $r("ENVIRONMENT_TEMPLATE_IMAGE_INSPECT_FAILED","Could not inspect the committed environment template image.",e)}}async untagEnvironmentTemplate(e,t){try{const n=t||(await this.inspectEnvironmentTemplateImage(e)).imageId;return await this.runCommand("docker",["tag",n,jr(n)]),await this.runCommand("docker",["image","rm",e]),n}catch(e){const t=Fr(e)?.toLowerCase()||"";if(t.includes("no such image")||t.includes("no such object"))return;throw $r("ENVIRONMENT_TEMPLATE_UNTAG_FAILED","Could not remove the environment template tag.",e)}}async garbageCollectEnvironmentTemplateImage(e){try{try{await this.runCommand("docker",["image","rm",jr(e)])}catch(e){const t=Fr(e)?.toLowerCase()||"";if(t.includes("being used by")||t.includes("is referenced")||t.includes("conflict"))return!1;if(!t.includes("no such image")&&!t.includes("no such object"))throw e}return await this.runCommand("docker",["image","rm",e]),!0}catch(e){const t=Fr(e)?.toLowerCase()||"";if(t.includes("being used by")||t.includes("is referenced")||t.includes("conflict"))return!1;if(t.includes("no such image")||t.includes("no such object"))return!0;throw $r("ENVIRONMENT_TEMPLATE_GC_FAILED","Could not garbage collect the environment template image.",e)}}async createPersistentVolumes(e,t=new Set){const n=Tr(e.instance.id,e.node?.id||"node_unset");for(const i of[..._r(e),n])await this.createVolume(i),await this.validateOwnedVolume(e.instance.id,i,t.has(i.name))}async createRuntimeVolume(e){await this.createVolume(Tr(e.instance.id,e.node?.id||"node_unset"))}async createVolume(e){const t=["volume","create"];for(const[n,i]of Object.entries(e.labels).sort(([e],[t])=>e.localeCompare(t)))t.push("--label",`${n}=${i}`);t.push(e.name);try{await this.runCommand("docker",t)}catch(t){throw $r("INSTANCE_VOLUME_CREATE_FAILED",`Could not create managed volume ${e.name}.`,t)}}async validatePersistentVolumes(e,t){for(const n of _r(e)){await this.validateOwnedVolume(e.instance.id,n);const i=t.find(e=>"volume"===e.type&&e.destination===n.mountPath);if(!i||i.name!==n.name)throw Object.assign(new Error(`Docker container mount for ${n.role} does not match managed volume ${n.name}.`),{statusCode:409,code:"INSTANCE_VOLUME_MOUNT_IDENTITY_MISMATCH"})}const n=Tr(e.instance.id,e.node?.id||"node_unset");await this.validateOwnedVolume(e.instance.id,n);const i=t.find(e=>"volume"===e.type&&e.destination===n.mountPath);if(!i||i.name!==n.name)throw Object.assign(new Error(`Docker container runtime mount does not match ${n.name}.`),{statusCode:409,code:"INSTANCE_VOLUME_MOUNT_IDENTITY_MISMATCH"});if("local-folder"===e.project.source.type){const n=t.find(t=>t.destination===(e.project.workspacePolicy.path||"/workspace"));if(!n||"bind"!==n.type||r.resolve(n.source||"")!==r.resolve(e.project.source.path))throw Object.assign(new Error(`Docker container workspace bind does not match local folder ${e.project.source.path}.`),{statusCode:409,code:"INSTANCE_WORKSPACE_MOUNT_IDENTITY_MISMATCH"})}}async validateOwnedVolume(e,t,n=!1){let i;try{i=await this.runCommand("docker",["volume","inspect","--format","{{json .}}",t.name])}catch(e){throw $r("INSTANCE_VOLUME_INSPECT_FAILED",`Could not inspect managed volume ${t.name}.`,e)}try{const r=JSON.parse(i.stdout||"{}"),s=r.Labels&&"object"==typeof r.Labels&&!Array.isArray(r.Labels)?r.Labels:{},o=r.Name===t.name&&"task-handoff"===s["task-handoff.owner"]&&s["task-handoff.instance-id"]===e&&s["task-handoff.volume-role"]===t.role,a=n&&r.Name===t.name&&0===Object.keys(s).length;if(!o&&!a)throw new Error("volume name or ownership labels do not match")}catch(n){throw Object.assign(new Error(`Managed volume ${t.name} identity does not match instance ${e}.`,{cause:n}),{statusCode:409,code:"INSTANCE_VOLUME_IDENTITY_MISMATCH"})}}async runningResult(e,t,n){const i=await this.publishedEndpoint(t),r=e.node?.id||"node_unset",s=e.runtime?.id||"runtime_local_docker";return{status:"registering",health:"unknown",connectionStatus:"online",agentStatus:"unknown",targetStatus:"unknown",uiAccessStatus:"unknown",target:{strategy:"direct-port",status:"reachable",...i},workspace:{mode:e.project.workspacePolicy.mode,status:"pending",path:e.project.workspacePolicy.path},runtime:{...e.instance.runtime,kind:"docker",containerName:t,...n?{containerId:n}:{},labels:{...e.instance.runtime.labels,"task-handoff.instance-id":e.instance.id,"task-handoff.project-id":e.project.id,"task-handoff.node-id":r,"task-handoff.runtime-id":s,"task-handoff.image-id":e.image.id}}}}async resumedContainerResult(e,t,n){const i=this.bootstrapResult(e,t,n);return{...i,target:{...i.target,...await this.publishedEndpoint(t)}}}async publishedEndpoint(e){const t=`http://127.0.0.1:${await this.containerPort(e,"8080/tcp")}`;return{web:t,api:`${t}/api`}}async resolveInstanceWeb(e){const t=e.instance.runtime.containerName||qr(e.instance.id),n=await this.inspectContainerId(t);if(!n)throw $r("INSTANCE_RUNTIME_ENDPOINT_UNAVAILABLE",`Docker container ${t} does not exist.`);return Vr(t,n,e.instance.runtime.containerId,"while resolving its web endpoint","INSTANCE_RUNTIME_ENDPOINT_UNAVAILABLE"),(await this.publishedEndpoint(t)).web}bootstrapResult(e,t,n,i){return{status:"starting",health:"unknown",connectionStatus:"unknown",agentStatus:"unknown",targetStatus:"unknown",uiAccessStatus:"unknown",target:{strategy:"direct-port",status:"unknown"},workspace:{mode:e.project.workspacePolicy.mode,status:"pending",path:e.project.workspacePolicy.path},runtime:{...e.instance.runtime,kind:"docker",containerName:t,...n?{containerId:n}:{},labels:{...e.instance.runtime.labels,"task-handoff.bootstrap-abi":"1",...i?{"task-handoff.bootstrap-backup":i}:{}}}}}async stop(e){const t=e.instance.runtime.containerName||qr(e.instance.id);try{await this.runCommand("docker",["stop",t])}catch(e){if(!Ur(e))throw $r("RUNTIME_EXECUTOR_FAILED",`Could not stop Docker container ${t}.`,e)}return{status:"stopped",health:"unknown",connectionStatus:"offline",target:{...e.instance.target,status:"unknown"},runtime:e.instance.runtime}}async restart(e,t){Gr(e);const n=e.instance.runtime.containerName||qr(e.instance.id),i=await this.inspectContainerId(n);if(!i)throw $r("INSTANCE_RUNTIME_RESTART_FAILED",`Docker container ${n} does not exist.`);Vr(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 $r("INSTANCE_RUNTIME_RESTART_FAILED",`Docker container identity changed while restarting ${n}.`);return Vr(n,r,t,"after restart","INSTANCE_RUNTIME_RESTART_FAILED"),this.runningResult(e,n,r)}async delete(e,t){const n=e.instance.runtime.containerName||qr(e.instance.id),i=await this.inspectContainerForStart(n),r=new Set;if(i){Vr(n,i.id,e.instance.runtime.containerId,"before delete","RUNTIME_EXECUTOR_FAILED");const t=i.labels["task-handoff.instance-id"];if(t!==e.instance.id)throw $r("RUNTIME_EXECUTOR_FAILED",`Docker container ${n} belongs to ${t||"an unknown instance"}, not ${e.instance.id}.`);for(const t of _r(e))i.mounts.some(e=>"volume"===e.type&&e.name===t.name&&e.destination===t.mountPath)&&r.add(t.name);try{await this.runCommand("docker",["rm","-f",i.id])}catch(e){if(!Ur(e))throw $r("RUNTIME_EXECUTOR_FAILED",`Could not delete Docker container ${n}.`,e)}}const s=[];for(const n of _r(e))if(t.deleteVolumes)try{const t=await this.inspectVolumeForDelete(n.name);if(!t){s.push({role:n.role,name:n.name,mountPath:n.mountPath,status:"missing"});continue}const i=t.name===n.name&&"task-handoff"===t.labels["task-handoff.owner"]&&t.labels["task-handoff.instance-id"]===e.instance.id&&t.labels["task-handoff.volume-role"]===n.role,o=r.has(n.name)&&t.name===n.name&&0===Object.keys(t.labels).length;if(!i&&!o)throw Object.assign(new Error(`Managed volume ${n.name} ownership does not match instance ${e.instance.id}.`),{code:"INSTANCE_VOLUME_IDENTITY_MISMATCH"});await this.runCommand("docker",["volume","rm",n.name]),s.push({role:n.role,name:n.name,mountPath:n.mountPath,status:"deleted"})}catch(e){s.push({role:n.role,name:n.name,mountPath:n.mountPath,status:"failed",error:{code:"object"==typeof e&&e&&"code"in e&&"string"==typeof e.code?e.code:"INSTANCE_VOLUME_DELETE_FAILED",message:e instanceof Error?e.message:String(e)}})}else s.push({role:n.role,name:n.name,mountPath:n.mountPath,status:"retained"});return await this.deleteRuntimeVolume(e),vn.parse({instanceId:e.instance.id,containerDeleted:!0,completed:s.every(e=>"failed"!==e.status),deletedVolumes:s.filter(e=>"deleted"===e.status||"missing"===e.status),retainedVolumes:s.filter(e=>"retained"===e.status),volumeResults:s})}async deleteRuntimeVolume(e){const t=Tr(e.instance.id,e.node?.id||"node_unset"),n=await this.inspectVolumeForDelete(t.name);if(n){if(n.name!==t.name||"task-handoff"!==n.labels["task-handoff.owner"]||n.labels["task-handoff.instance-id"]!==e.instance.id||"runtime"!==n.labels["task-handoff.volume-role"])throw $r("INSTANCE_VOLUME_IDENTITY_MISMATCH",`Runtime volume ${t.name} ownership does not match instance ${e.instance.id}.`);try{await this.runCommand("docker",["volume","rm",t.name])}catch(e){throw $r("INSTANCE_VOLUME_DELETE_FAILED",`Could not delete runtime volume ${t.name}.`,e)}}}async inspectVolumeForDelete(e){try{const t=await this.runCommand("docker",["volume","inspect","--format","{{json .}}",e]),n=JSON.parse(t.stdout||"{}");return{name:"string"==typeof n.Name?n.Name:"",labels:n.Labels&&"object"==typeof n.Labels&&!Array.isArray(n.Labels)?Object.fromEntries(Object.entries(n.Labels).filter(e=>"string"==typeof e[1])):{}}}catch(t){if(function(e){const t=Fr(e)?.toLowerCase()||"";return t.includes("no such volume")||t.includes("no such object")}(t))return;throw $r("INSTANCE_VOLUME_INSPECT_FAILED",`Could not inspect managed volume ${e}.`,t)}}async installRuntime(e){const t=await this.installRuntimeRelease(e);Vr(e.containerName,t,e.expectedContainerId,"before runtime restart","INSTANCE_RUNTIME_RESTART_FAILED");try{await this.runCommand("docker",["restart",t])}catch(t){throw $r("INSTANCE_RUNTIME_RESTART_FAILED",`Could not restart Docker container ${e.containerName}.`,t)}const n=await this.inspectContainerId(e.containerName);if(!n||n!==t)throw $r("INSTANCE_RUNTIME_RESTART_FAILED",`Docker container identity changed while updating ${e.containerName}.`);return Vr(e.containerName,n,e.expectedContainerId,"after runtime restart","INSTANCE_RUNTIME_RESTART_FAILED"),this.inspectRuntimeVersion(e.containerName)}async installRuntimeRelease(e){const t=await this.inspectContainerId(e.containerName);if(!t)throw $r("INSTANCE_RUNTIME_INSTALL_FAILED",`Docker container ${e.containerName} does not exist.`);Vr(e.containerName,t,e.expectedContainerId,"before runtime install","INSTANCE_RUNTIME_INSTALL_FAILED");const n=`/opt/task-handoff/instance-runtime/incoming/task-handoff-runtime-${i=e.identity.version,i.replace(/[^0-9A-Za-z.+_-]/g,"-")}-${e.identity.sha256.slice(0,12)}.tar.gz`;var i;await this.runCommand("docker",["exec","--user","0",t,"install","-d","-o","root","-g","root","-m","0755","/opt/task-handoff/instance-runtime/incoming"]),await this.runCommand("docker",["cp",e.artifactPath,`${t}:${n}`]);try{await this.runCommand("docker",["exec","--user","0",t,"node",Sr,"install","--artifact",n,"--version",e.identity.version,"--sha256",e.identity.sha256,"--platform",e.identity.platform,"--arch",e.identity.arch,"--launcher-abi",String(e.identity.launcherAbi)])}catch(t){throw $r("INSTANCE_RUNTIME_INSTALL_FAILED",`Could not install controlled-instance ${e.identity.version} in ${e.containerName}.`,t)}finally{await this.runCommand("docker",["exec","--user","0",t,"rm","-f",n]).catch(()=>({stdout:"",stderr:""}))}const r=await this.inspectContainerId(e.containerName);if(!r||r!==t)throw $r("INSTANCE_RUNTIME_INSTALL_FAILED",`Docker container identity changed while installing ${e.containerName}.`);return Vr(e.containerName,r,e.expectedContainerId,"after runtime install","INSTANCE_RUNTIME_INSTALL_FAILED"),t}async inspectRuntimeVersion(e){const t=await this.inspectContainerId(e);if(!t)return{};const n=await this.runCommand("docker",["exec","--user","agent",e,"node",Sr,"verify-active"]).catch(()=>{});if(!n?.stdout)return{containerId:t};try{const e=pr(Kn,JSON.parse(n.stdout));return e.success?{containerId:t,...e.data}:{containerId:t}}catch{return{containerId:t}}}async removeBootstrapBackup(e,t){const n=await this.inspectContainerForStart(e);if(n){if(n.labels["task-handoff.instance-id"]!==t)throw $r("RUNTIME_EXECUTOR_FAILED",`Docker bootstrap backup ${e} does not belong to ${t}.`);await this.runCommand("docker",["rm","-f",e])}}async inspectRuntimeTarget(e){let t,n;if(e){const i=await this.runCommand("docker",["inspect","--format","{{json .}}",e]).then(e=>JSON.parse(e.stdout.trim()||"{}")).catch(()=>{});if(t=i?.Platform,"string"==typeof i?.Image&&i.Image){const e=await this.runCommand("docker",["image","inspect","--format","{{json .}}",i.Image]).then(e=>JSON.parse(e.stdout.trim()||"{}")).catch(()=>{});t=e?.Os||t,n=e?.Architecture}}if(!t||!n){const e=await this.runCommand("docker",["info","--format","{{json .}}"]).then(e=>JSON.parse(e.stdout.trim()||"{}")).catch(e=>{throw $r("INSTANCE_BASE_RUNTIME_INCOMPATIBLE","Could not inspect the Docker runtime target.",e)});t||=e.OSType,n||=e.Architecture}const i=Pr(t),r=Mr(n);if(!i||!r)throw $r("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Docker reported an unsupported runtime target ${String(t||"unknown")}/${String(n||"unknown")}.`);return{platform:i,arch:r,launcherAbi:1}}async installRuntimeReleaseWithRecovery(e){const t=e.containerName,n=await this.inspectContainerForStart(t);if(!n)throw $r("INSTANCE_RUNTIME_INSTALL_FAILED",`Docker container ${t} does not exist.`);if(Vr(t,n.id,e.expectedContainerId,"before runtime install recovery","INSTANCE_RUNTIME_INSTALL_FAILED"),n.running)return await this.installRuntimeLauncher(t,n.id),void await this.installRuntimeRelease({...e,expectedContainerId:n.id});if(!n.image)throw $r("INSTANCE_RUNTIME_INSTALL_FAILED",`Docker container ${t} does not expose its immutable image identity.`);const i="/run/task-handoff/runtime-rescue-artifact.tar.gz",s=[`test -r ${Er}`,`test -r ${vr}/instance-launcher.sh`,`test -r ${Sr}`,`install -d -o root -g root -m 0755 ${zr} ${zr}/releases ${zr}/staging ${zr}/incoming`,`chown -R root:root ${zr}`,`chmod -R go-w ${zr}`,`node ${Sr} install --artifact "$1" --version "$2" --sha256 "$3" --platform "$4" --arch "$5" --launcher-abi "$6"`].join("; ");try{await this.runCommand("docker",["run","--rm","--user","0:0","--volumes-from",n.id,"--mount",`type=bind,source=${r.resolve(e.artifactPath)},target=${i},readonly`,"--entrypoint",Nr,n.image,"-ceu",s,"task-handoff-runtime-rescue",i,e.identity.version,e.identity.sha256,e.identity.platform,e.identity.arch,String(e.identity.launcherAbi)])}catch(n){throw $r("INSTANCE_RUNTIME_INSTALL_FAILED",`Could not rescue controlled-instance ${e.identity.version} in stopped container ${t}.`,n)}const o=await this.inspectContainerForStart(t);if(!o)throw $r("INSTANCE_RUNTIME_INSTALL_FAILED",`Docker container ${t} disappeared during runtime install recovery.`);if(Vr(t,o.id,n.id,"after runtime install recovery","INSTANCE_RUNTIME_INSTALL_FAILED"),o.running)throw $r("INSTANCE_RUNTIME_INSTALL_FAILED",`Stopped Docker container ${t} changed lifecycle state during runtime install recovery.`)}async installRuntimeLauncher(e,t){const n=await this.inspectContainerId(e);if(!n)throw $r("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Docker container ${e} does not exist.`);Vr(e,n,t,"before runtime launcher install","INSTANCE_BASE_RUNTIME_INCOMPATIBLE");try{await this.runCommand("docker",["exec","--user","0",n,"bash","-ceu",`test -r ${Er}; test -r ${vr}/instance-launcher.sh; test -r ${Sr}; install -d -o root -g root -m 0755 /opt/task-handoff/instance-runtime /opt/task-handoff/instance-runtime/releases /opt/task-handoff/instance-runtime/staging /opt/task-handoff/instance-runtime/incoming; chown -R root:root /opt/task-handoff/instance-runtime; chmod -R go-w /opt/task-handoff/instance-runtime`])}catch(t){throw $r("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Could not install the runtime launcher in ${e}.`,t)}const i=await this.inspectContainerId(e);if(i!==n)throw $r("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Docker container identity changed while installing the runtime launcher in ${e}.`);Vr(e,i,t,"after runtime launcher install","INSTANCE_BASE_RUNTIME_INCOMPATIBLE")}async inspectContainerId(e){try{return(await this.runCommand("docker",["inspect","--format","{{.Id}}",e])).stdout.trim()||void 0}catch(t){if(Ur(t))return;throw $r("RUNTIME_EXECUTOR_FAILED",`Could not inspect Docker container ${e}.`,t)}}async inspectContainerForStart(e){let t;try{t=await this.runCommand("docker",["inspect","--format","{{json .}}",e])}catch(t){if(Ur(t))return;throw $r("RUNTIME_EXECUTOR_FAILED",`Could not inspect Docker container ${e}.`,t)}try{const e=JSON.parse(t.stdout||"{}");if("string"!=typeof e.Id||!e.Id)throw new Error("Docker inspect did not return a container id.");const n=e.Config?.Labels&&"object"==typeof e.Config.Labels&&!Array.isArray(e.Config.Labels)?Object.fromEntries(Object.entries(e.Config.Labels).filter(e=>"string"==typeof e[1])):{},i=Array.isArray(e.Mounts)?e.Mounts.flatMap(e=>{if(!e||"object"!=typeof e||Array.isArray(e))return[];const t=e,n="volume"===t.Type||"bind"===t.Type?t.Type:void 0,i="string"==typeof t.Destination?t.Destination:void 0;return n&&i?[{type:n,destination:i,name:"string"==typeof t.Name?t.Name:void 0,source:"string"==typeof t.Source?t.Source:void 0}]:[]}):[],r=Array.isArray(e.Config?.Entrypoint)?e.Config.Entrypoint.filter(e=>"string"==typeof e):"string"==typeof e.Config?.Entrypoint?[e.Config.Entrypoint]:[],s=Array.isArray(e.Config?.Cmd)?e.Config.Cmd.filter(e=>"string"==typeof e):"string"==typeof e.Config?.Cmd?[e.Config.Cmd]:[];return{id:e.Id,image:"string"==typeof e.Image?e.Image:void 0,running:!0===e.State?.Running,entrypoint:r,command:s,labels:n,mounts:i}}catch(t){throw $r("RUNTIME_EXECUTOR_FAILED",`Docker returned invalid inspection data for ${e}.`,t)}}async containerPort(e,t){let n,i=!1;for(const r of this.portResolutionRetryDelaysMs){r>0&&await Dr(r);try{const n=Rr((await this.runCommand("docker",["port",e,t])).stdout);if(n)return n}catch(e){n=e}try{const n=xr((await this.runCommand("docker",["inspect","--format","{{json .NetworkSettings.Ports}}",e])).stdout,t);if(i=!0,n)return n}catch(e){n=e}}if(i)throw $r("RUNTIME_EXECUTOR_FAILED",`Docker container ${e} does not publish ${t}.`);throw $r("RUNTIME_EXECUTOR_FAILED",`Could not resolve the published port for Docker container ${e}.`,n)}}function Rr(e){const t=e.split(/\r?\n/).find(Boolean);return t?.match(/:(\d+)$/)?.[1]}function xr(e,t){const n=JSON.parse(e||"null");if(!n||"object"!=typeof n||Array.isArray(n))return;const i=n[t];if(Array.isArray(i))for(const e of i){if(!e||"object"!=typeof e||Array.isArray(e))continue;const t=e.HostPort;if("string"==typeof t&&/^\d+$/.test(t))return t}}function Dr(e){return new Promise(t=>setTimeout(t,e))}function Pr(e){return"linux"===e||"darwin"===e?e:"windows"===e||"win32"===e?"win32":void 0}function Mr(e){return"amd64"===e||"x86_64"===e||"x64"===e?"x64":"arm64"===e||"aarch64"===e?"arm64":void 0}function Lr(){const e=("undefined"==typeof document?require("url").pathToFileURL(__filename).href:v&&"SCRIPT"===v.tagName.toUpperCase()&&v.src||new URL("cli.js",document.baseURI).href)?r.dirname(o.fileURLToPath("undefined"==typeof document?require("url").pathToFileURL(__filename).href:v&&"SCRIPT"===v.tagName.toUpperCase()&&v.src||new URL("cli.js",document.baseURI).href)):__dirname,t=[r.resolve(e,"../../../../../docker"),r.resolve(e,"../docker"),r.resolve(e,"../../docker")];return t.find(e=>i.existsSync(r.join(e,"runtime-installer.mjs")))||t[0]}function jr(e){return`task-handoff/environment-image:${e.replace(/^sha256:/,"")}`}function $r(e,t,n){const i=Fr(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 Fr(e){if(!e||"object"!=typeof e)return void 0===e?void 0:String(e);const t=e,n=t.details?.stderr||t.details?.stdout;return"string"==typeof n&&n.trim()?n.trim():"string"==typeof t.message&&t.message.trim()?t.message.trim():void 0}function Ur(e){const t=Fr(e)?.toLowerCase()||"";return t.includes("no such container")||t.includes("no such object")}function Vr(e,t,n,i,r){if(n&&t!==n)throw $r(r,`Docker container ${e} identity mismatch ${i}: expected ${n}, got ${t}.`)}async function Hr(e=Ir){return async function(e=Ir){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:wr(t.Size),reference:s,repoDigests:o}}).filter(e=>Boolean(e.reference))}(e)}function qr(e){return`task-handoff-${e.replace(/[^a-zA-Z0-9_.-]/g,"-")}`}function Br(e,t,n){e.push("-e",`${t}=${n}`)}function Kr(e,t,n={}){const i=n.publishHost||"127.0.0.1",s=r.resolve(n.launcherAssetsDir||Lr()),o=e.node?.id||"node_unset",a=e.runtime?.id||"runtime_local_docker",c=["run","-d","--name",t,"--user","0:0","--label",`task-handoff.instance-id=${e.instance.id}`,"--label",`task-handoff.project-id=${e.project.id}`,"--label",`task-handoff.node-id=${o}`,"--label",`task-handoff.runtime-id=${a}`,"--label",`task-handoff.image-id=${e.image.id}`,"--label","task-handoff.bootstrap-abi=1","--shm-size","1gb","--security-opt","seccomp=unconfined","--network","bridge","--no-healthcheck","--add-host","host.docker.internal:host-gateway","--tmpfs","/tmp:rw,mode=1777","-p",`${i}::8080`];if(!e.privateConfigPath)throw Object.assign(new Error(`Instance ${e.instance.id} private config was not materialized.`),{statusCode:409,code:"INSTANCE_PRIVATE_CONFIG_MISSING"});c.push("--mount",`type=bind,src=${e.privateConfigPath},dst=/run/task-handoff/instance-private-config.json,readonly`,"--mount",`type=bind,src=${s},dst=${vr},readonly`,"--entrypoint",Nr);for(const t of _r(e))c.push("--mount",`type=volume,src=${t.name},dst=${t.mountPath}`);const d=Tr(e.instance.id,e.node?.id||"node_unset");c.push("--mount",`type=volume,src=${d.name},dst=${d.mountPath}`);const l={TASK_HANDOFF_CONTROL_MODE:"controlled",TASK_HANDOFF_NODE_AGENT_URL:e.nodeAgentUrl||e.node?.endpoint||"",TASK_HANDOFF_INSTANCE_ID:e.instance.id,TASK_HANDOFF_INSTANCE_NAME:e.instance.name,TASK_HANDOFF_PROJECT_ID:e.project.id,TASK_HANDOFF_NODE_ID:o,TASK_HANDOFF_RUNTIME_ID:a,TASK_HANDOFF_IMAGE_ID:e.image.id,TASK_HANDOFF_INSTANCE_LAUNCHER:`${vr}/instance-launcher.sh`,...e.image.tag?{TASK_HANDOFF_IMAGE_TAG:e.image.tag}:{},TASK_HANDOFF_CHAT_BRIDGES:"none",TASK_HANDOFF_WORKSPACE:e.project.workspacePolicy.path||"/workspace",TASK_HANDOFF_WORKSPACE_MODE:e.project.workspacePolicy.mode};for(const[e,t]of Object.entries(l))Br(c,e,t);"local-folder"===e.project.source.type?c.push("-v",`${e.project.source.path}:${e.project.workspacePolicy.path||"/workspace"}:${e.project.workspacePolicy.readOnly?"ro":"rw"}`):(Br(c,"TASK_HANDOFF_PROJECT_SOURCE",JSON.stringify(e.project.source)),Br(c,"TASK_HANDOFF_WORKSPACE_POLICY",JSON.stringify(e.project.workspacePolicy)),Br(c,"TASK_HANDOFF_GIT_URL",e.project.source.url),e.project.source.ref?.commit?Br(c,"TASK_HANDOFF_GIT_COMMIT",e.project.source.ref.commit):e.project.source.ref?.name&&Br(c,"TASK_HANDOFF_GIT_REF",e.project.source.ref.name),e.project.source.clone?.depth&&Br(c,"TASK_HANDOFF_GIT_DEPTH",String(e.project.source.clone.depth)),Br(c,"TASK_HANDOFF_GIT_SUBMODULES",e.project.source.clone?.submodules?"true":"false"),Br(c,"TASK_HANDOFF_GIT_LFS",e.project.source.clone?.lfs?"true":"false"),e.project.source.clone?.subdirectory&&Br(c,"TASK_HANDOFF_WORKSPACE_SUBDIRECTORY",e.project.source.clone.subdirectory));for(const[t,n]of Object.entries(e.image.defaultEnv))Br(c,t,n);return c.push(n.imageReference||e.instance.environmentTemplateOrigin?.imageId||e.image.resolvedReference||e.image.requestedReference,Er,"task-handoff","web"),c}function Gr(e){if("local-folder"===e.project.source.type&&e.project.source.ownerNodeId&&e.project.source.ownerNodeId!==e.node.id){const e=new Error("Local folder projects can only start on the node that owns the folder.");throw Object.assign(e,{statusCode:400,code:"LOCAL_FOLDER_REQUIRES_OWNER_NODE"}),e}if(!e.image.requestedReference?.trim()){const e=new Error("Image profile must reference a registered image.");throw Object.assign(e,{statusCode:400,code:"IMAGE_PROFILE_INVALID"}),e}}d.z.object({type:d.z.literal("snapshot"),data:d.z.string(),pendingEscape:d.z.string(),cols:d.z.number().int().positive(),rows:d.z.number().int().positive()}).passthrough();const Jr=d.z.enum(["created","starting","running","stopping","stopped","exited","failed","closed","terminated","unknown"]),Wr=d.z.enum(["tty","vnc","web"]);d.z.object({mode:Wr,url:d.z.string().trim().min(1).max(4096),token:d.z.string().trim().min(1).max(512),expiresAt:d.z.string().datetime()}).strict(),d.z.object({revoked:d.z.boolean()}).strict();const Yr=d.z.object({type:d.z.enum(["app-session","provider-session","adapter-key"]),id:d.z.string().trim().min(1).max(240),agent:d.z.string().trim().min(1).max(80).optional(),adapter:d.z.string().trim().min(1).max(80).optional(),key:d.z.string().trim().min(1).max(240).optional()}).strict(),Xr=d.z.record(d.z.string(),d.z.unknown()).and(d.z.object({id:d.z.string().trim().min(1).max(160),appId:d.z.string().trim().min(1).max(160).optional(),title:d.z.string().trim().max(240).optional(),kind:d.z.string().trim().max(80).optional(),status:Jr.default("unknown"),bindings:d.z.array(Yr).max(40).default([]),workspace:d.z.object({cwd:d.z.string().trim().max(4096).optional()}).strict().optional(),createdAt:d.z.string().datetime().optional(),updatedAt:d.z.string().datetime().optional()})),Qr=d.z.object({runningCount:d.z.number().int().min(0).default(0),problemCount:d.z.number().int().min(0).default(0),sessions:d.z.array(Xr).default([]),updatedAt:d.z.string().datetime()}).strict();d.z.object({streamId:d.z.string().trim().min(1).max(240),revision:d.z.number().int().min(0),lastEventAt:d.z.string().datetime(),snapshot:Qr}).strict(),Qr.pick({runningCount:!0,problemCount:!0,updatedAt:!0}).extend({revision:d.z.number().int().min(0).optional()});const Zr=d.z.enum(["app-session-created","app-session-updated","app-session-deleted","app-session-recovered","control-action","heartbeat-sync","startup"]),es=d.z.object({streamId:d.z.string().trim().min(1).max(240),instanceId:d.z.string().trim().min(1).max(160),nodeId:d.z.string().trim().min(1).max(160).optional(),revision:d.z.number().int().min(0),previousRevision:d.z.number().int().min(0).optional(),traceId:d.z.string().trim().min(1).max(160),generatedAt:d.z.string().datetime(),reason:Zr}).strict(),ts=d.z.object({meta:es,snapshot:Qr}).strict(),ns=d.z.object({meta:es,session:Xr}).strict(),is=d.z.object({meta:es,sessionId:d.z.string().trim().min(1).max(160),tombstone:Xr.optional(),expiresAt:d.z.string().datetime().optional()}).strict();function rs(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"}d.z.object({streamId:d.z.string().trim().min(1).max(240),instanceId:d.z.string().trim().min(1).max(160),sinceRevision:d.z.number().int().min(0),latestRevision:d.z.number().int().min(0),earliestRetainedRevision:d.z.number().int().min(0),syncRequired:d.z.boolean().default(!1),events:d.z.array(d.z.discriminatedUnion("type",[d.z.object({type:d.z.literal("app-session.snapshot"),payload:ts}).strict(),d.z.object({type:d.z.literal("app-session.patch"),payload:ns}).strict(),d.z.object({type:d.z.literal("app-session.removed"),payload:is}).strict()])).default([])}).strict();const ss=d.z.object({replaySince:d.z.string().datetime().optional(),messageDeltas:d.z.object({allInstances:d.z.boolean().default(!1),instanceIds:d.z.array(d.z.string().trim().min(1).max(160)).max(1e3).default([])}).default({allInstances:!1,instanceIds:[]}),timelineAllSessions:d.z.boolean().default(!1),timelineSessions:d.z.array(d.z.object({instanceId:d.z.string().trim().min(1).max(160),sessionId:d.z.string().trim().min(1).max(120)})).max(1e3).default([])}),os=d.z.enum(["ai.sessions","app.sessions"]),as=d.z.object({topic:os,instanceId:d.z.string().trim().min(1).max(160),streamId:d.z.string().trim().min(1).max(240),latestRevision:d.z.number().int().min(0),earliestRetainedRevision:d.z.number().int().min(0)}).strict(),cs=d.z.object({protocolVersion:d.z.literal(1),streams:d.z.array(as)}).strict();function ds(e,t=Math.random){const n=Math.max(1,Math.floor(e));if(1===n)return 0;if(2===n)return 250;const i=Math.min(6e4,250*2**(n-2));return Math.min(6e4,Math.round(i*(.75+.5*t())))}class ls{retryNumber=0;random;constructor(e=Math.random){this.random=e}get attempts(){return this.retryNumber}next(){return this.retryNumber+=1,{attempt:this.retryNumber,delay:ds(this.retryNumber,this.random)}}reset(){this.retryNumber=0}}class us{backoff;timer;constructor(e=Math.random){this.backoff=new ls(e)}get pending(){return Boolean(this.timer)}get attempts(){return this.backoff.attempts}schedule(e,t={}){if(this.timer)return;const n=this.backoff.next(),i=t.setTimeoutFn||setTimeout;return this.timer=i(()=>{this.timer=void 0,e()},n.delay),n}reset(e=clearTimeout){this.timer&&e(this.timer),this.timer=void 0,this.backoff.reset()}cancel(e=clearTimeout){this.timer&&e(this.timer),this.timer=void 0}}class ms extends us{}function ps(e,t=6e4){const n=[];for(let i=0;i<e.length;i+=t)n.push(e.slice(i,i+t));return n}class hs{sockets=new Map;socketUrls=new Map;retries=new Map;outputs=new Set;outputSubscriptions=new Map;imagePullTerminalByInstance=new Map;state;token;logger;safetyIntervalMs;lastAiSessionEventByInstance=new Map;lastAppSessionEventByInstance=new Map;timer;reconnectAttempts=0;safetyReconciliations=0;localSequence=0;createSocket;setIntervalFn;clearIntervalFn;setTimeoutFn;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 h(e,t)),this.setIntervalFn=n.setIntervalFn||setInterval,this.clearIntervalFn=n.clearIntervalFn||clearInterval,this.setTimeoutFn=n.setTimeoutFn||setTimeout}start(){this.sync(),this.timer=this.setIntervalFn(()=>{this.safetyReconciliations+=1,this.sync()},this.safetyIntervalMs)}stop(){this.timer&&(this.clearIntervalFn(this.timer),this.timer=void 0);for(const e of this.sockets.values())e.close();this.sockets.clear(),this.socketUrls.clear();for(const e of this.retries.values())e.timer.cancel();this.retries.clear(),this.outputs.clear(),this.outputSubscriptions.clear()}addOutput(e,t={}){let n;this.outputs.add(e),this.outputSubscriptions.set(e,t.expectsTransientSubscription?ss.parse({}):void 0),t.expectsTransientSubscription||void 0===t.legacyFallbackMs||(n=this.setTimeoutFn(()=>{n=void 0,this.outputs.has(e)&&void 0===this.outputSubscriptions.get(e)&&this.syncNow()},t.legacyFallbackMs));let i=!1;const r=()=>{i||(i=!0,this.outputs.delete(e),this.outputSubscriptions.delete(e),n&&clearTimeout(n),this.syncNow())};e.on("close",r),e.on("error",r);for(const t of this.state.listInstances()){const n=gs(t);n?this.sendForwarded(e,this.createEvent(ir,n,{instanceId:t.id})):this.logger?.warn?.({instanceId:t.id},"instance.lifecycle.snapshot.invalid")}for(const[t,n]of this.imagePullTerminalByInstance)ps(n.tail).forEach((i,r)=>this.sendForwarded(e,this.createEvent(Pi,{...n.output,sequence:n.output.sequence+r,data:i,...0===r?{replay:!0}:{}},{instanceId:t}))),n.finished&&this.sendForwarded(e,this.createEvent(Mi,n.finished,{instanceId:t}));return(t.expectsTransientSubscription||void 0===t.legacyFallbackMs)&&this.syncNow(),r}setOutputSubscription(e,t){if(!this.outputs.has(e))return!1;const n=ss.safeParse(t);if(!n.success)return!1;this.outputSubscriptions.set(e,n.data),this.syncNow();for(const[e,t]of this.sockets)this.sendInstanceSubscription(e,t);return!0}publish(e,t,n={}){this.rememberImagePullTerminal(e,t);const i=this.createEvent(e,t,n);for(const e of this.outputs)this.sendForwarded(e,i)}rememberImagePullTerminal(e,t){if(e===Pi){const e=pr(ji,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===Mi){const e=pr($i,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(ir,function(e){return rr.parse(fs(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:rs(e),createdAt:(new Date).toISOString(),payload:t,scope:n}}sendForwarded(e,t){const n=JSON.stringify({type:"node-agent.event.forwarded",event:t});this.sendOutput(e,n)}sendOutput(e,t){if(e.readyState!==h.OPEN)return!1;if(e.bufferedAmount+Buffer.byteLength(t,"utf8")>16777216){try{e.close(1013,"Event consumer is too slow.")}catch{}return!1}try{return e.send(t),!0}catch{try{e.close(1011,"Event delivery failed.")}catch{}return!1}}syncNow(){this.sync()}diagnostics(){const e=[...this.outputSubscriptions.values()];return{reconnectAttempts:this.reconnectAttempts,safetyReconciliations:this.safetyReconciliations,activeConnections:this.sockets.size,pendingRetries:[...this.retries.values()].filter(e=>e.timer.pending).length,safetyIntervalMs:this.safetyIntervalMs,transientDemand:{legacyOutputs:e.filter(e=>void 0===e).length,scopedOutputs:e.filter(e=>void 0!==e).length,messageDeltaAllInstances:e.some(e=>e?.messageDeltas.allInstances),messageDeltaInstanceCount:new Set(e.flatMap(e=>e?.messageDeltas.instanceIds||[])).size,timelineAllSessions:e.some(e=>e?.timelineAllSessions),timelineSessionCount:new Set(e.flatMap(e=>e?.timelineSessions.map(e=>JSON.stringify([e.instanceId,e.sessionId]))||[])).size}}}sync(){const e=new Set(this.state.listInstances().map(e=>e.id));for(const t of this.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=Is(e);if(!n)continue;t.add(e.id);const i=this.retries.get(e.id);i?.timer.pending&&i.url!==n&&(i.timer.cancel(),this.retries.delete(e.id)),this.socketUrls.get(e.id)!==n&&this.sockets.has(e.id)&&(this.sockets.get(e.id)?.close(),this.sockets.delete(e.id)),this.sockets.has(e.id)||this.retries.get(e.id)?.timer.pending||this.connect(e.id,n)}for(const[e,n]of this.sockets)if(!t.has(e)){n.close(),this.sockets.delete(e),this.socketUrls.delete(e);const t=this.retries.get(e);t?.timer.cancel(),this.retries.delete(e)}for(const[e,n]of this.retries)t.has(e)||(n.timer.cancel(),this.retries.delete(e),this.socketUrls.delete(e))}connect(e,t){const n=this.token?{authorization:`Bearer ${this.token}`}:void 0,i=this.createSocket(t,{headers:n});this.sockets.set(e,i),this.socketUrls.set(e,t),i.on("open",()=>{const n=this.retries.get(e);this.retries.set(e,{timer:n?.timer||new ms,url:t}),i.readyState===h.OPEN&&(this.sendInstanceSubscription(e,i),this.logger?.info?.({instanceId:e,url:t},"ai-session.event.forward.connect"),this.logger?.info?.({instanceId:e,url:t},"app-session.event.forward.connect"))}),i.on("message",t=>{const n=function(e,t){try{const n=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:rs(r),createdAt:"string"==typeof i.createdAt?i.createdAt:(new Date).toISOString(),payload:"payload"in i?i.payload:{},...!0===i.replay?{replay:!0}:{},scope:{...s,instanceId:t}}}catch{return}}(t,e);if(!n)return;if("streams.hello"===n.type){const t=pr(cs,n.payload);if(!t.success)return this.logger?.warn?.({instanceId:e,issues:t.error.issues},"session-stream.handshake.invalid"),void i.close(1002,"Incompatible session stream handshake.");this.retries.get(e)?.timer.reset();const r=JSON.stringify({type:"node-agent.streams.hello",instanceId:e,payload:t.data});for(const e of this.outputs)this.sendOutput(e,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===h.OPEN&&this.outputAccepts(e,n)&&this.sendOutput(e,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()})}sendInstanceSubscription(e,t){if(t.readyState!==h.OPEN)return;const n=[...this.outputs].map(e=>this.outputSubscriptions.get(e));if(n.some(e=>void 0===e))return void t.send(JSON.stringify({v:1,type:"subscribe",topics:[Q,"app.sessions","apps","instances"]}));const i=n.some(t=>t.messageDeltas.allInstances||t.messageDeltas.instanceIds.includes(e)),r=n.some(e=>e.timelineAllSessions),s=[...new Set(n.flatMap(t=>t.timelineSessions.filter(t=>t.instanceId===e).map(e=>e.sessionId)))],o=n.map(e=>e.replaySince).filter(e=>Boolean(e)).sort()[0];t.send(JSON.stringify({v:1,type:"subscribe",topics:[Z,ee,te,...i?[ne]:[],...r||s.length?[ie]:[],"app.sessions","apps","instances"],aiSessionTransient:{...o?{replaySince:o}:{},messageDeltas:{allInstances:i,instanceIds:[]},timelineAllSessions:r,timelineSessions:s.map(t=>({instanceId:e,sessionId:t}))}}))}outputAccepts(e,t){const n=this.outputSubscriptions.get(e);return!n||function(e,t){if(!e)return!0;if("ai-session.message-delta"!==t.type&&"ai-session.timeline-item"!==t.type)return!0;const n=t.payload&&"object"==typeof t.payload&&!Array.isArray(t.payload)?t.payload:{},i=String(n.instanceId||t.scope?.instanceId||"");return"ai-session.message-delta"===t.type?e.messageDeltas.allInstances||e.messageDeltas.instanceIds.includes(i):e.timelineAllSessions||e.timelineSessions.some(e=>e.instanceId===i&&e.sessionId===n.sessionId)}(n,t)}scheduleReconnect(e){const t=this.state.listInstances().find(t=>t.id===e),n=t&&Is(t);if(!n||!this.outputs.size)return;const i=this.retries.get(e)??{timer:new ms};if(i.timer.pending)return;i.url=n;const r=i.timer.schedule(()=>{this.sockets.has(e)||this.connect(e,n)},{setTimeoutFn:this.setTimeoutFn});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!==Q)return;if(t.type===ne||t.type===ie)return;const n=ys(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=ys(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 gs(e){const t=rr.safeParse(fs(e));return t.success?t.data:void 0}function fs(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 ys(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 Is(e){if(!function(e){return!1!==e.ready&&(!e.runtimeVersion||["matched","failed"].includes(e.runtimeVersion.phase))}(e))return;const t=e.target?.api||e.target?.web;if(t)try{const e=new URL("/api/events",t);return e.searchParams.set("aiSessionTransient","1"),e.protocol="https:"===e.protocol?"wss:":"ws:",e.toString()}catch{return}}const As=new Set(["provisioning","starting","registering","registered","running","unhealthy"]),bs=JSON.stringify({id:"{{.ID}}",name:"{{.Name}}",cpu:"{{.CPUPerc}}",memory:"{{.MemUsage}}",memoryPercent:"{{.MemPerc}}",network:"{{.NetIO}}",blockIo:"{{.BlockIO}}",pids:"{{.PIDs}}"});class ws{snapshots=new Map;runCommand;targets;publish;intervalMs;timer;inFlight;pendingTargets=new Map;collectingTargets=new Map;constructor(e,t,n,i=3e3){this.runCommand=e,this.targets=t,this.publish=n,this.intervalMs=i}start(){this.collect().catch(()=>{}),this.timer=setInterval(()=>{this.collect().catch(()=>{})},this.intervalMs)}stop(){this.timer&&clearInterval(this.timer),this.timer=void 0}async snapshot(e){const t=this.targets().find(t=>t.id===e);if(!t)return;if(!As.has(t.status))return Ts(t.id);const n=this.snapshots.get(e);return n&&Date.now()-Date.parse(n.sampledAt)<=this.intervalMs?n:(await this.collect([t]),this.snapshots.get(e))}async collect(e){const t=e||this.targets();if(!e){const e=new Set(t.map(e=>e.id));for(const t of this.snapshots.keys())e.has(t)||this.snapshots.delete(t)}for(const e of t){const t=vs(e);this.collectingTargets.get(e.id)!==t&&this.pendingTargets.set(e.id,e)}this.inFlight||(this.inFlight=this.drain().finally(()=>{this.inFlight=void 0})),await this.inFlight}async drain(){for(;this.pendingTargets.size;){const e=[...this.pendingTargets.values()];this.pendingTargets.clear();for(const t of e)this.collectingTargets.set(t.id,vs(t));try{await this.collectOnce(e)}finally{for(const t of e)this.collectingTargets.delete(t.id)}}}async collectOnce(e){const t=e.filter(e=>As.has(e.status)&&(e.runtime.containerId||e.runtime.containerName));for(const t of e.filter(e=>As.has(e.status)&&!e.runtime.containerId&&!e.runtime.containerName))this.update(_s(t.id));for(const t of e.filter(e=>!As.has(e.status)))this.update(Ts(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",bs,...n],{timeoutMs:5e3});this.applyDockerOutput(t,e.stdout,i)}catch(e){if(1===t.length)return void this.update(Cs(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",bs,t],{timeoutMs:5e3});this.applyDockerOutput([e],n.stdout,i)}catch(t){this.update(Cs(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=zs(e.id),s=zs(e.name),o=r||s;if(!o)continue;const a=Es(zs(e.memory)),c=Es(zs(e.network)),d=Es(zs(e.blockIo)),l=qi.parse({instanceId:o,runtimeKind:"docker",state:"available",sampledAt:t,cpu:Ns(e.cpu,"usagePercent"),memory:a?{usageBytes:a[0],...void 0!==a[1]?{limitBytes:a[1]}:{},...Ns(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:Ss(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}:Cs(t.id,n,"Container metrics were not returned by Docker."))}}update(e){const t=qi.parse(e);this.snapshots.set(t.instanceId,t),this.publish?.(t)}}function vs(e){return[e.status,e.runtime.containerId||"",e.runtime.containerName||""].join("\0")}function Es(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 Ns(e,t){const n=Number(zs(e).replace(/%$/,""));return Number.isFinite(n)&&n>=0?{[t]:n}:void 0}function Ss(e){const t=Number(zs(e));return Number.isFinite(t)&&t>=0?t:void 0}function zs(e){return"string"==typeof e||"number"==typeof e?String(e).trim():""}function Ts(e){return{instanceId:e,runtimeKind:"docker",state:"stopped",sampledAt:(new Date).toISOString()}}function _s(e){return{instanceId:e,runtimeKind:"docker",state:"pending",sampledAt:(new Date).toISOString()}}function Cs(e,t,n){return{instanceId:e,runtimeKind:"docker",state:"unavailable",sampledAt:t,error:n.slice(0,2048)}}function ks(e,t,n){return Object.assign(new Error(e),{statusCode:t,code:n})}function Os(e){const t=r.resolve(e);let n;try{n=i.statSync(t)}catch(e){const n=e&&"object"==typeof e?e.code:void 0;if("ENOENT"===n||"ENOTDIR"===n)throw ks(`Folder ${t} was not found.`,404,"NODE_FOLDER_PATH_NOT_FOUND");throw ks(`Folder ${t} is not accessible.`,403,"NODE_FOLDER_PATH_UNREADABLE")}if(!n.isDirectory())throw ks(`Path ${t} is not a folder.`,400,"NODE_FOLDER_PATH_NOT_DIRECTORY");try{i.accessSync(t,i.constants.R_OK|i.constants.X_OK)}catch{throw ks(`Folder ${t} is not accessible.`,403,"NODE_FOLDER_PATH_UNREADABLE")}return t}function Rs(e){try{return i.statSync(e).isDirectory()}catch{return!1}}function xs(){if("win32"!==process.platform)return[r.parse(r.resolve(process.cwd())).root];const e=r.parse(r.resolve(process.cwd())).root,t=Array.from({length:26},(e,t)=>`${String.fromCharCode(65+t)}:\\`);return[...new Set([e,...t])].filter(Rs)}function Ds(){const e=r.resolve(l.homedir()),t=xs().map(e=>r.resolve(e));return[...Rs(e)?[{kind:"home",name:r.basename(e)||e,path:e}]:[],...t.map(e=>({kind:"root",name:e,path:e}))]}function Ps(e,t){let n;try{n=i.statSync(e)}catch{return}if(!n.isDirectory())return;const s=r.resolve(e),o=r.basename(s)||s;let a=[];try{a=t>0?i.readdirSync(s,{withFileTypes:!0}):[]}catch{a=[]}const c=t>0?a.filter(e=>e.isDirectory()||e.isSymbolicLink()&&Rs(r.join(s,e.name))).sort((e,t)=>e.name.localeCompare(t.name)).slice(0,80).flatMap(e=>{const n=Ps(r.join(s,e.name),t-1);return n?[n]:[]}):[];return{name:o,path:s,children:c}}function Ms(e){return(e.path?[Os(e.path)]:xs()).flatMap(t=>{const n=Ps(t,e.depth);return n?[n]:[]})}function Ls(){return process.env.TASK_HANDOFF_NODE_AGENT_DATA_DIR||r.join(l.homedir(),".config","task-handoff","node-agent")}function js(e=Ls()){const t=r.resolve(e);return{dataDir:t,identityPath:r.join(t,"identity.json"),settingsPath:r.join(t,"runtime-settings.json"),localFoldersDir:r.join(t,"local-folders"),nodeRuntimesDir:r.join(t,"node-runtimes"),controlledInstancesDir:r.join(t,"controlled-instances"),environmentTemplatesDir:r.join(t,"environment-templates"),instancePrivateConfigsDir:r.join(t,"instance-private-configs"),nodeModelsDir:r.join(t,"models"),modelAssignmentsDir:r.join(t,"model-assignments"),modelEnvironmentsDir:r.join(t,"model-environments"),updatesDir:r.join(t,"updates"),logsDir:r.join(t,"logs")}}function $s(e,t){const n=r.extname(e);return`${n?e.slice(0,-n.length):e}.${t}${n}`}function Fs(e,t=10485760,n=2){if(!i.existsSync(e))return!1;const r=i.lstatSync(e);if(!r.isFile()||r.isSymbolicLink()||r.size<=t)return!1;if(n>0){!function(e,t){if(!(t<=0)){i.rmSync($s(e,t),{force:!0});for(let n=t-1;n>=1;n-=1){const t=$s(e,n);i.existsSync(t)&&i.renameSync(t,$s(e,n+1))}}}(e,n);const r=function(e,t){const n=i.statSync(e),r=Math.min(n.size,t),s=Buffer.allocUnsafe(r),o=i.openSync(e,"r");let a=0;try{for(;a<r;){const e=i.readSync(o,s,a,r-a,n.size-r+a);if(0===e)break;a+=e}}finally{i.closeSync(o)}return a===r?s:s.subarray(0,a)}(e,t);i.writeFileSync($s(e,1),r,{mode:384})}return i.truncateSync(e,0),i.chmodSync(e,384),!0}class Us{logsDir;localInstancesRoot;localInstancesTrashRoot;options;constructor(e,t={}){this.options=t,this.logsDir=e.logsDir,this.localInstancesRoot=r.join(e.dataDir,"local-instances"),this.localInstancesTrashRoot=r.join(e.dataDir,"local-instances-trash")}run(e){this.capNodeAgentLogs();const t=new Set(e);if(i.existsSync(this.localInstancesRoot)){W(this.localInstancesRoot);for(const e of i.readdirSync(this.localInstancesRoot,{withFileTypes:!0}))e.isDirectory()&&!e.isSymbolicLink()&&(t.has(e.name)?this.capControlledInstanceLogs(e.name):this.retire(e.name))}return function(e){if(!i.existsSync(e.trashRoot))return[];const t=e.nowMs??Date.now(),n=e.retentionMs??G,r=[];for(const s of i.readdirSync(e.trashRoot,{withFileTypes:!0})){const o=J(e.trashRoot,s.name);try{const e=Number(s.name.split("-",1)[0]);if(!Number.isFinite(e)||e+n>t)continue;const a=i.lstatSync(o);a.isSymbolicLink()?i.unlinkSync(o):a.isDirectory()?i.rmSync(o,{recursive:!0,force:!0}):i.unlinkSync(o),r.push(o)}catch(t){e.logger?.("retired persistence entry cleanup failed",{path:o,error:t instanceof Error?t.message:String(t)})}}return r}({trashRoot:this.localInstancesTrashRoot,retentionMs:this.options.retentionMs??G,nowMs:this.now(),logger:this.options.logger})}capActiveInstanceLogs(e){for(const t of e)this.capControlledInstanceLogs(t)}capNodeAgentLogs(){const e=[];for(const t of["node-agent.out.log","node-agent.err.log"]){const n=r.join(this.logsDir,t);try{Fs(n)&&e.push(n)}catch(e){this.options.logger?.("node-agent log rotation failed",{filePath:n,error:e instanceof Error?e.message:String(e)})}}return e}capControlledInstanceLogs(e){const t=r.resolve(this.localInstancesRoot,e);if(r.dirname(t)!==r.resolve(this.localInstancesRoot))return[];const n=r.join(t,"logs"),i=[];for(const t of["controlled-instance.out.log","controlled-instance.err.log"]){const s=r.join(n,t);try{Fs(s)&&i.push(s)}catch(t){this.options.logger?.("controlled instance log rotation failed",{instanceId:e,filePath:s,error:t instanceof Error?t.message:String(t)})}}return i}retire(e){try{return function(e){const t=J(e.sourceRoot,e.entryName);if(!i.existsSync(t))return;const n=i.lstatSync(t);if(!n.isDirectory()||n.isSymbolicLink())throw new Error(`Retention source must be a real directory: ${t}`);W(e.trashRoot);const r=e.nowMs??Date.now();let s=0,o=`${r}-${e.entryName}`;for(;i.existsSync(J(e.trashRoot,o));)s+=1,o=`${r}-${s}-${e.entryName}`;const a=J(e.trashRoot,o);return i.renameSync(t,a),a}({sourceRoot:this.localInstancesRoot,entryName:e,trashRoot:this.localInstancesTrashRoot,nowMs:this.now()})}catch(t){return void this.options.logger?.("local instance persistence retirement failed",{instanceId:e,error:t instanceof Error?t.message:String(t)})}}now(){return this.options.now?.()??Date.now()}}function Vs(e,t=process.platform){const n=r.resolve(e),i=u.createHash("sha256").update(n).digest("hex").slice(0,16);return"win32"===t?`\\\\.\\pipe\\task-handoff-node-agent-${i}`:r.join("/tmp",`task-handoff-node-agent-${process.getuid?.()??"user"}`,`${i}.sock`)}const Hs="runtime-manifest.json";class qs 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 Bs(e,t=""){const n=[],i=await y.readdir(r.join(e,t),{withFileTypes:!0});for(const s of i){const i=t?r.posix.join(t,s.name):s.name;if(!t&&i===Hs)continue;const o=r.join(e,...i.split("/"));if(s.isDirectory()){n.push(...await Bs(e,i));continue}if(s.isSymbolicLink()){const t=await y.readlink(o);if(r.isAbsolute(t))throw new qs("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload symlink is absolute: ${i}`);const s=r.resolve(r.dirname(o),t),a=r.relative(r.resolve(e),s);if(!a||".."===a||a.startsWith(`..${r.sep}`)||r.isAbsolute(a))throw new qs("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload symlink escapes the artifact: ${i}`);if(!await y.lstat(s).catch(()=>{}))throw new qs("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload symlink is broken: ${i}`);n.push({absolutePath:o,relativePath:i,kind:"symlink",target:t,size:Buffer.byteLength(t)});continue}if(!s.isFile())throw new qs("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload contains unsupported entry: ${i}`);const a=await y.lstat(o);n.push({absolutePath:o,relativePath:i,kind:"file",size:a.size})}return n}async function Ks(e){const t=(await Bs(e)).sort((e,t)=>function(e,t){return Buffer.compare(Buffer.from(e,"utf8"),Buffer.from(t,"utf8"))}(e.relativePath,t.relativePath)),n=u.createHash("sha256");for(const e of t){if(n.update("file"===e.kind?"F":"L","ascii"),n.update(Buffer.from(e.relativePath,"utf8")),n.update(Buffer.from([0])),n.update(Buffer.from(String(e.size),"ascii")),n.update(Buffer.from([0])),"file"===e.kind)for await(const t of i.createReadStream(e.absolutePath))n.update(t);else n.update(Buffer.from(e.target,"utf8"));n.update(Buffer.from([0]))}return n.digest("hex")}function Gs(e){for(const[t,n]of[["version",e.version],["platform",e.platform],["arch",e.arch]])if(!/^[0-9A-Za-z._-]+$/.test(n))throw new qs("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Invalid runtime artifact ${t}: ${n}`);return`${e.version}-${e.platform}-${e.arch}`}function Js(e,t){return`${Gs(e)}-${e.sha256}-${t}`}async function Ws(e){const t=u.createHash("sha256");for await(const n of i.createReadStream(e))t.update(n);return t.digest("hex")}class Ys{#e;#t;#n=new Map;constructor(e){this.#e=e.cacheDir,this.#t=e.fetchImpl??fetch}resolve(e,t){const n=Kn.parse(e);if(!/^[a-f0-9]{64}$/.test(t.archiveSha256))throw new qs("INSTANCE_RUNTIME_ARTIFACT_INVALID","Runtime archive SHA-256 is invalid.");if((t.archiveUrl?1:0)+(t.archivePath?1:0)!=1)throw new qs("INSTANCE_RUNTIME_ARTIFACT_INVALID","Runtime artifact source must specify exactly one archive location.");const i=Js(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,t){if(!/^[a-f0-9]{64}$/.test(t.archiveSha256))throw new qs("INSTANCE_RUNTIME_ARTIFACT_INVALID","Runtime archive SHA-256 is invalid.");const n=Js(e,t.archiveSha256),s=r.join(this.#e,"archives"),o=r.join(s,`${n}.tar.gz`);if(await y.mkdir(s,{recursive:!0}),await this.#r(o,e,t.archiveSha256))return{identity:e,archivePath:o,cacheHit:!0};await y.rm(o,{force:!0});const a=r.join(s,`.${n}.${u.randomUUID()}.part`);try{const n=await y.open(a,"wx");if(t.archivePath)await I.pipeline(i.createReadStream(t.archivePath),n.createWriteStream());else{const e=await this.#t(t.archiveUrl);if(!e.ok||!e.body)throw await n.close(),new qs("INSTANCE_RUNTIME_ARTIFACT_UNAVAILABLE",`Runtime artifact download failed with HTTP ${e.status}.`,{retryable:e.status>=500});await I.pipeline(e.body,n.createWriteStream())}if(await Ws(a)!==t.archiveSha256)throw new qs("INSTANCE_RUNTIME_ARTIFACT_INVALID","Downloaded runtime archive SHA-256 does not match release metadata.");return await this.#s(a,e),await y.rename(a,o),{identity:e,archivePath:o,cacheHit:!1}}catch(e){if(e instanceof qs)throw e;throw new qs("INSTANCE_RUNTIME_ARTIFACT_UNAVAILABLE","Could not download runtime artifact.",{cause:e,retryable:!0})}finally{await y.rm(a,{force:!0})}}async#r(e,t,n){try{return await Ws(e)===n&&(await this.#s(e,t),!0)}catch{return!1}}async#s(e,t){const n=r.join(this.#e,"validation",`${Gs(t)}-${u.randomUUID()}`);try{await async function(e,t){await y.mkdir(t,{recursive:!0});try{await A.extract({file:e,cwd:t,strict:!0,preservePaths:!1,filter:(e,t)=>{const n=r.posix.normalize(e.replace(/^\.\//,""));if(!n||".."===n||n.startsWith("../")||r.posix.isAbsolute(n))throw new qs("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime archive entry escapes the artifact root: ${e}`);const i=t.type;if("File"!==i&&"OldFile"!==i&&"Directory"!==i&&"SymbolicLink"!==i)throw new qs("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime archive contains unsupported entry type ${i??"unknown"}: ${e}`);return!0}})}catch(e){throw new qs("INSTANCE_RUNTIME_ARTIFACT_INVALID","Could not extract runtime artifact safely.",{cause:e})}}(e,n),await async function(e,t,n){const i=await async function(e){let t;try{t=JSON.parse(await y.readFile(r.join(e,Hs),"utf8"))}catch(e){throw new qs("INSTANCE_RUNTIME_ARTIFACT_INVALID","Runtime artifact manifest is missing or invalid JSON.",{cause:e})}const n=pr(Kn,t);if(!n.success)throw new qs("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime artifact manifest is invalid: ${n.error.message}`);return n.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 qs("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime artifact ${"sha256"===n?"SHA-256":n} mismatch: expected ${t[n]}, got ${e[n]}.`)}(i,t),1!==i.formatVersion)throw new qs("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Unsupported runtime artifact format ${i.formatVersion}.`);if(n?.platform&&"universal"!==i.platform&&i.platform!==n.platform)throw new qs("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime artifact platform ${i.platform} does not match ${n.platform}.`);if(n?.arch&&"universal"!==i.arch&&i.arch!==n.arch)throw new qs("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime artifact architecture ${i.arch} does not match ${n.arch}.`);if(void 0!==n?.launcherAbi&&i.launcherAbi>n.launcherAbi)throw new qs("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Runtime requires launcher ABI ${i.launcherAbi}, but the base runtime provides ${n.launcherAbi}.`);const s=function(e,t){if(!e||e.includes("\\")||r.posix.isAbsolute(e))throw new qs("INSTANCE_RUNTIME_ARTIFACT_INVALID",`${t} must be a non-empty POSIX relative path.`);const n=r.posix.normalize(e);if("."===n||".."===n||n.startsWith("../"))throw new qs("INSTANCE_RUNTIME_ARTIFACT_INVALID",`${t} escapes the runtime root.`);return n}(i.entrypoint,"Runtime entrypoint"),o=await y.lstat(r.join(e,...s.split("/"))).catch(()=>{});if(!o?.isFile())throw new qs("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime entrypoint is missing: ${s}`);const a=await Ks(e);if(a!==i.sha256)throw new qs("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload SHA-256 mismatch: expected ${i.sha256}, got ${a}.`);return i}(n,t,{platform:t.platform,arch:t.arch})}finally{await y.rm(n,{recursive:!0,force:!0})}}}async function Xs(e,t,n,i=fetch){if("linux"!==t||!["x64","arm64"].includes(n))throw new qs("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Managed controlled-instance updates require a Linux x64 or arm64 target, received ${t}/${n}.`);const s=await async function(e){const t=`controlled-instance-runtime-${e}-linux-universal`,n=function(){const e=process.env.TASK_HANDOFF_BUNDLED_RUNTIME_DIR?.trim();return r.resolve(e||r.join(r.dirname(process.argv[1]||process.cwd()),"..","runtime-artifacts"))}();try{const[i,s]=await Promise.all([y.readFile(r.join(n,`${t}.manifest.json`),"utf8"),y.readFile(r.join(n,`${t}.tar.gz.sha256`),"utf8")]),o=pr(Kn,JSON.parse(i));if(!o.success||o.data.version!==e||"linux"!==o.data.platform||"universal"!==o.data.arch)throw new qs("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 qs("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Bundled controlled-instance ${e} has an invalid archive checksum.`);return{identity:o.data,source:{archivePath:r.join(n,`${t}.tar.gz`),archiveSha256:a}}}catch(t){if("ENOENT"===t.code)return;if(t instanceof qs)throw t;throw new qs("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([i(c),i(l)]).catch(t=>{throw new qs("INSTANCE_RUNTIME_ARTIFACT_UNAVAILABLE",`Could not read release metadata for controlled-instance ${e}.`,{cause:t,retryable:!0})});if(!u.ok||!m.ok)throw new qs("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 qs("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Release manifest for controlled-instance ${e} is not valid JSON.`,{cause:t})}const h=pr(Kn,p);if(!h.success)throw new qs("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Release manifest for controlled-instance ${e} is invalid: ${h.error.message}`);if(h.data.version!==e||"linux"!==h.data.platform||"universal"!==h.data.arch)throw new qs("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Release identity mismatch: requested ${e}-linux-universal, received ${h.data.version}-${h.data.platform}-${h.data.arch}.`);const g=(await m.text()).trim().split(/\s+/)[0]?.toLowerCase();if(!g||!/^[a-f0-9]{64}$/.test(g))throw new qs("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Release checksum for controlled-instance ${e} is invalid.`);return{identity:h.data,source:{archiveUrl:d,archiveSha256:g}}}class Qs{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=ao(i.retryBaseDelayMs??1e3,"retryBaseDelayMs"),this.retryMaxDelayMs=ao(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");if(to(n))return this.storePhase(n,"pending");const r=n.runtimeVersion?.desiredVersion!==i||t.startRequested||no(n)?0:this.remainingRetryDelayMs(n.runtimeVersion);if(r>0&&(await this.delay(r),n=this.requireInstance(e),this.cancelled.has(e)))return this.storePhase(n,"pending");const s=Zs(n),o=s===i&&(await(this.hooks.isInstalled?.(n,i))??!0);if(this.cancelled.has(e))return this.storePhase(this.requireInstance(e),"pending");if(s===i&&o)return this.storeState(n,{desiredVersion:i,actualVersion:s,phase:"matched",attempt:n.runtimeVersion?.attempt||0,matchedAt:this.timestamp()},!no(n)&&"failed"!==n.health);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?io(t,n):ro("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,s,o)),no(n)&&!t.startRequested)return n;let a=!1,c=0;try{for(;c<this.maxAttempts;){if(this.cancelled.has(e))return this.storePhase(this.requireInstance(e),"pending");let r;try{if(n=this.storePhase(n,"draining"),await(this.hooks.beginDrain?.(n)),a=!0,n=this.requireInstance(e),eo(n)){const t=await this.waitUntil(e,this.drainTimeoutMs,e=>!eo(e));if(n=this.requireInstance(e),!t){if(this.cancelled.has(e))return this.storePhase(n,"pending");await(this.hooks.onForcedDrain?.(n))}}if(n=this.storePhase(this.requireInstance(e),"installing",!0),c+=1,await this.hooks.install(n,i),this.cancelled.has(e)||no(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=>Zs(e)===i);if(this.cancelled.has(e))return this.storePhase(this.requireInstance(e),"pending");if(!r)throw ro("INSTANCE_RUNTIME_VERIFICATION_FAILED",`Instance ${e} did not register controlled-instance ${i} after restart.`,i,Zs(this.requireInstance(e)),!0);const s=this.requireInstance(e);if(this.hooks.isInstalled&&!await this.hooks.isInstalled(s,i))throw ro("INSTANCE_RUNTIME_VERIFICATION_FAILED",`Instance ${e} reported controlled-instance ${i}, but its active runtime release is missing.`,i,Zs(s),!0);return this.storeState(s,{desiredVersion:i,actualVersion:i,phase:"matched",attempt:s.runtimeVersion?.attempt||1,matchedAt:this.timestamp()},!no(s)&&"failed"!==s.health)}catch(t){if(this.cancelled.has(e))return this.storePhase(this.requireInstance(e),"pending");r=so(t,i,Zs(this.store.get(e)))}n=this.requireInstance(e);const s=n.runtimeVersion?.attempt||1;if(!r.retryable||c>=this.maxAttempts)return this.storeBatchFailure(n,i,s>=this.maxAttempts&&r.retryable?oo(i,Zs(n),this.maxAttempts,r):r);n=this.storeState(n,{desiredVersion:i,...Zs(n)?{actualVersion:Zs(n)}:{},phase:"pending",attempt:s,lastAttemptAt:this.timestamp(),error:r}),await this.delay(this.retryDelayMs(s))}return this.storeBatchFailure(n,i,oo(i,Zs(n),this.maxAttempts,n.runtimeVersion?.error))}finally{a&&await(this.hooks.endDrain?.(this.requireInstance(e)))}}storeBatchFailure(e,t,n){const i=Zs(e);return this.storeState(e,{desiredVersion:t,...i?{actualVersion:i}:{},phase:"pending",attempt:e.runtimeVersion?.attempt||0,lastAttemptAt:this.timestamp(),error:n})}retryDelayMs(e){return Math.min(this.retryMaxDelayMs,this.retryBaseDelayMs*2**Math.max(0,e-1))}remainingRetryDelayMs(e){if(!e?.error||!e.lastAttemptAt)return 0;const t=Date.parse(e.lastAttemptAt);return Number.isFinite(t)?Math.max(0,t+this.retryDelayMs(e.attempt||1)-this.now().getTime()):0}storePhase(e,t,n=!1){const i=this.desiredVersion(),r=Zs(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:io(i,r)}:{}},"restarting"!==t&&void 0)}storeState(e,t,n){const i=this.store.get(e.id)||e;return this.store.put(nr.parse({...i,runtimeVersion:t,...void 0===n?{}:{ready:n},updatedAt:this.timestamp()}))}async waitUntil(e,t,n){const i=this.now().getTime()+t;for(;;){const t=this.store.get(e);if(t&&n(t))return!0;if(this.cancelled.has(e))return!1;if(this.now().getTime()>=i)return!1;await this.delay(Math.min(this.pollIntervalMs,Math.max(0,i-this.now().getTime())))}}requireInstance(e){const t=this.store.get(e);if(!t)throw new Error(`Instance ${e} was removed during runtime reconciliation.`);return t}timestamp(){return this.now().toISOString()}}function Zs(e){return e?.build?.packageVersion||e?.instanceVersion}function eo(e){return e.apps.runningCount>0||e.aiSessions.runningCount>0}function to(e){return Boolean(e.imageProvisioning&&"ready"!==e.imageProvisioning.phase)}function no(e){return["created","stopped","failed"].includes(e.status)}function io(e,t){return ro("INSTANCE_RUNTIME_VERSION_MISMATCH",`Expected controlled-instance ${e}, received ${t||"an unknown version"}.`,e,t,!0)}function ro(e,t,n,i,r){return{code:e,message:t,expectedVersion:n,...i?{actualVersion:i}:{},retryable:r}}function so(e,t,n){if(e&&"object"==typeof e&&"code"in e&&"message"in e){const i=e,r=Gn.shape.code.safeParse(i.code);if(r.success&&"string"==typeof i.message)return ro(r.data,i.message,t,n,"boolean"!=typeof i.retryable||i.retryable)}return ro("INSTANCE_RUNTIME_INSTALL_FAILED",e instanceof Error?e.message:String(e),t,n,!0)}function oo(e,t,n,i){const r=i?.message?` Last error: ${i.message}`:"";return ro(i?.code||"INSTANCE_RUNTIME_INSTALL_FAILED",`Runtime convergence paused after ${n} attempts and will retry.${r}`,e,t,!0)}function ao(e,t){if(!Number.isFinite(e)||e<0)throw new TypeError(`${t} must be a nonnegative finite number.`);return e}function co(e,t=448){i.mkdirSync(e,{recursive:!0,mode:t}),i.chmodSync(e,t)}function lo(e,t,n={}){const s=n.directoryMode??448,o=n.fileMode??384;co(r.dirname(e),s),b.sync(e,`${JSON.stringify(t,null,2)}\n`,{encoding:"utf8",mode:o}),i.chmodSync(e,o)}function uo(e,t){console.warn(JSON.stringify({message:e,...t}))}function mo(e){return e&&"object"==typeof e&&"issues"in e?{issues:e.issues}:{error:e instanceof Error?e.message:String(e)}}function po(e,t){const n=t.logger||uo;let r;try{r=JSON.parse(i.readFileSync(e,"utf8"))}catch(t){return void n("stored JSON could not be read",{filePath:e,...mo(t)})}if(!t.schema)return r;const s=t.sanitize?t.sanitize(r):r,o=t.schema.safeParse(s);if(o.success)return o.data;const a="strip"in t.schema&&"function"==typeof t.schema.strip?t.schema.strip().safeParse(s):void 0;if(a?.success)return n("unknown stored fields were ignored",{filePath:e,issues:o.error.issues}),a.data;n("stored record failed validation and was isolated",{filePath:e,issues:o.error.issues})}function ho(e){return`${e}_${u.randomUUID().replace(/-/g,"").slice(0,20)}`}function go(){return u.randomBytes(24).toString("base64url")}class fo{directory;options;permissionsInitialized=!1;constructor(e,t={}){this.directory=e,this.options=t}init(){if(this.permissionsInitialized&&i.existsSync(this.directory))return;co(this.directory,this.options.directoryMode??448);const e=this.options.fileMode??384;for(const t of i.readdirSync(this.directory).filter(e=>e.endsWith(".json")))i.chmodSync(r.join(this.directory,t),e);this.permissionsInitialized=!0}filePath(e){return r.join(this.directory,`${e}.json`)}list(){return this.init(),i.readdirSync(this.directory).filter(e=>e.endsWith(".json")).sort().flatMap(e=>{const t=po(r.join(this.directory,e),this.options);return t?[t]:[]})}get(e){this.init();const t=this.filePath(e);return i.existsSync(t)?po(t,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 lo(this.filePath(n.id),n,this.options),n}patch(e,t){const n=this.get(e);if(!n)return;const i={...n,...t,id:n.id,createdAt:n.createdAt,updatedAt:(new Date).toISOString()};return this.put(i)}delete(e){const t=this.filePath(e);return!!i.existsSync(t)&&(i.unlinkSync(t),!0)}}class yo{filePathValue;defaults;options;constructor(e,t,n={}){this.filePathValue=e,this.defaults=t,this.options=n}init(){co(r.dirname(this.filePathValue),this.options.directoryMode??448),i.existsSync(this.filePathValue)?i.chmodSync(this.filePathValue,this.options.fileMode??384):this.put(this.defaults())}get(){return this.init(),i.existsSync(this.filePathValue)?po(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 lo(this.filePathValue,n,this.options),n}}const Io=d.z.record(d.z.string(),d.z.string()),Ao=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 bo{directory;constructor(e){this.directory=e}get(e){try{return Io.parse(JSON.parse(i.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 i.existsSync(this.filePath(e))}listInstanceIds(){return i.existsSync(this.directory)?i.readdirSync(this.directory).filter(e=>e.endsWith(".json")).map(e=>e.slice(0,-5)).sort():[]}put(e,t){const n=Io.parse(t);i.mkdirSync(this.directory,{recursive:!0,mode:448});const r=this.filePath(e);return b.sync(r,`${JSON.stringify(n,null,2)}\n`,{encoding:"utf8",mode:384}),i.chmodSync(r,384),n}delete(e){i.rmSync(this.filePath(e),{force:!0})}filePath(e){return r.join(this.directory,`${e}.json`)}}class wo{directory;nodeId;constructor(e,t){this.directory=e,this.nodeId=t}init(){i.mkdirSync(this.directory,{recursive:!0,mode:448}),i.chmodSync(this.directory,448)}list(){return this.init(),i.readdirSync(this.directory).filter(e=>e.endsWith(".json")).sort().flatMap(e=>{const t=this.read(r.join(this.directory,e));return t?[t]:[]})}get(e){const t=this.filePath(e);return i.existsSync(t)?this.read(t):void 0}put(e){const t=li.parse(e);this.init();const n=this.filePath(t.id);return b.sync(n,`${JSON.stringify(t,null,2)}\n`,{encoding:"utf8",mode:384}),i.chmodSync(n,384),t}delete(e){const t=this.filePath(e);return!!i.existsSync(t)&&(i.unlinkSync(t),!0)}read(e){try{const t=JSON.parse(i.readFileSync(e,"utf8")),n=r.basename(e,".json"),s=li.safeParse(t);if(s.success&&s.data.id===n&&wi(s.data)===s.data.id)return s.data;const o=li.strip().safeParse(t);return o.success&&o.data.id===n&&wi(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 r.join(this.directory,`${e}.json`)}}class vo{directory;constructor(e){this.directory=e}init(){i.mkdirSync(this.directory,{recursive:!0,mode:448}),i.chmodSync(this.directory,448)}get(e){const t=this.filePath(e);if(i.existsSync(t))try{const n=JSON.parse(i.readFileSync(t,"utf8")),r=pi.safeParse(n);if(r.success)return r.data;const s=pi.strip().safeParse(n);if(s.success)return console.warn(JSON.stringify({message:"unknown stored model assignment fields were ignored",instanceId:e,filePath:t})),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 t=pi.parse(e);this.init();const n=this.filePath(t.instanceId);return b.sync(n,`${JSON.stringify(t,null,2)}\n`,{encoding:"utf8",mode:384}),i.chmodSync(n,384),t}delete(e){i.rmSync(this.filePath(e),{force:!0})}filePath(e){return r.join(this.directory,`${e}.json`)}}class Eo{models;assignments;legacyEnvironments;nodeId;instances;constructor(e,t,n){this.nodeId=t,this.instances=n,this.models=new wo(e.nodeModelsDir,t),this.assignments=new vo(e.modelAssignmentsDir),this.legacyEnvironments=new bo(e.modelEnvironmentsDir)}init(){this.models.init(),this.assignments.init(),this.migrateLegacyEnvironments()}list(){const e=new Map;for(const t of this.instances.list()){const n=this.assignments.get(t.id);for(const t of[n?.codexModelHash,n?.claudeModelHash])t&&e.set(t,(e.get(t)||0)+1)}return this.models.list().map(t=>this.toPublic(t,e.get(t.id)||0))}create(e){const t=K(),n=wi(e),i=this.models.get(n),r=li.parse({...e,id:n,enabled:e.enabled??!0,order:e.order??this.nextOrder(),labels:e.labels||{},createdAt:i?.createdAt||t,updatedAt:t});return this.toPublic(this.models.put(r),this.referenceIds(n).length)}deploy(e){const t=wi(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(li.parse(e));return this.toPublic(n,this.referenceIds(n.id).length)}update(e,t){const n=this.requireModel(e),i=li.parse({...n,...t,key:t.key?.trim()?t.key:n.key,createdAt:n.createdAt,updatedAt:K()}),r=wi(i),s=this.models.put(li.parse({...i,id:r}));return this.toPublic(s,this.referenceIds(r).length)}delete(e){this.requireModel(e);const t=this.referenceIds(e);if(t.length)throw Object.assign(new Error(`Model ${e} is assigned to ${t.length} instance${1===t.length?"":"s"}.`),{statusCode:409,code:"NODE_MODEL_IN_USE",instanceIds:t});return this.models.delete(e)}resolveProbeKey(e,t){const n=t?.trim()||(e?this.requireModel(e).key:"");if(!n)throw Object.assign(new Error("An API key is required to contact the model endpoint."),{statusCode:400,code:"MODEL_API_KEY_REQUIRED"});return n}assign(e,t){const n=this.instances.require(e);if(this.validateRef("codex",t.codexModelHash),this.validateRef("claude",t.claudeModelHash),void 0!==t.modelSelection.codexModelHash&&(t.modelSelection.codexModelHash??void 0)!==t.codexModelHash)throw Object.assign(new Error("Codex model selection does not match its node assignment."),{statusCode:400,code:"NODE_MODEL_SELECTION_MISMATCH"});if(void 0!==t.modelSelection.claudeModelHash&&(t.modelSelection.claudeModelHash??void 0)!==t.claudeModelHash)throw Object.assign(new Error("Claude model selection does not match its node assignment."),{statusCode:400,code:"NODE_MODEL_SELECTION_MISMATCH"});const i=this.assignments.get(e),r=pi.parse({instanceId:e,codexModelHash:t.codexModelHash,claudeModelHash:t.claudeModelHash,updatedAt:K()});this.assignments.put(r);try{return{assignment:r,instance:this.instances.put(nr.parse({...n,modelSelection:t.modelSelection,updatedAt:K()}))}}catch(t){throw i?this.assignments.put(i):this.assignments.delete(e),t}}resolvedEnvironment(e){const t=this.assignments.get(e);if(!t){if(this.legacyEnvironments.has(e))throw Object.assign(new Error(`Legacy model environment for instance ${e} requires manual migration.`),{statusCode:409,code:"NODE_MODEL_MIGRATION_REQUIRED"});return{}}return{...this.environmentForRef("codex",t.codexModelHash),...this.environmentForRef("claude",t.claudeModelHash)}}deleteInstanceMetadata(e){this.assignments.delete(e),this.legacyEnvironments.delete(e)}validateRef(e,t){if(!t)return;const n=this.requireModel(t);if(n.app!==e)throw Object.assign(new Error(`Model ${n.id} belongs to ${n.app}, not ${e}.`),{statusCode:400,code:"NODE_MODEL_APP_MISMATCH"});if(!n.enabled)throw Object.assign(new Error(`Model ${n.id} is disabled.`),{statusCode:409,code:"NODE_MODEL_DISABLED"})}environmentForRef(e,t){if(!t)return{};this.validateRef(e,t);const n=this.requireModel(t);return"codex"===e?{OPENAI_API_KEY:n.key,OPENAI_BASE_URL:n.endpoint,TASK_HANDOFF_CODEX_BASE_URL:n.endpoint,TASK_HANDOFF_CODEX_MODEL:n.model}:{ANTHROPIC_API_KEY:n.key,ANTHROPIC_BASE_URL:n.endpoint,TASK_HANDOFF_CLAUDE_MODEL:n.model}}requireModel(e){const t=this.models.get(e);if(!t)throw Object.assign(new Error(`Model ${e} was not found on node ${this.nodeId}.`),{statusCode:404,code:"NODE_MODEL_NOT_FOUND"});if(wi(t)!==t.id)throw Object.assign(new Error(`Stored model ${e} does not match its content hash.`),{statusCode:409,code:"NODE_MODEL_HASH_INVALID"});return t}referenceIds(e){return this.instances.list().filter(t=>{const n=this.assignments.get(t.id);return n?.codexModelHash===e||n?.claudeModelHash===e}).map(e=>e.id)}toPublic(e,t){const{key:n,...i}=e;return mi.parse({...i,keyPreview:n.length<=8?"set":`${n.slice(0,4)}...${n.slice(-4)}`,keySet:!0,referenceCount:t})}nextOrder(){return this.models.list().reduce((e,t)=>Math.max(e,t.order),0)+100}migrateLegacyEnvironments(){for(const e of this.legacyEnvironments.listInstanceIds()){if(!this.instances.has(e)){this.warnMigration(e,"instance-not-found");continue}if(this.assignments.get(e)){try{this.resolvedEnvironment(e),this.legacyEnvironments.delete(e)}catch{this.warnMigration(e,"existing-assignment-invalid")}continue}let t;try{t=this.legacyEnvironments.get(e)}catch{this.warnMigration(e,"sidecar-invalid");continue}if(!Object.keys(t).length){this.legacyEnvironments.delete(e);continue}if(Object.keys(t).some(e=>!Ao.has(e))){this.warnMigration(e,"unknown-fields");continue}const n=[];try{const i=this.migrateApp(t,"codex",n),r=this.migrateApp(t,"claude",n);if(!i&&!r)throw new Error("no complete model configuration");const s={...i?{codexModelHash:i}:{},...r?{claudeModelHash:r}:{}};this.assign(e,{modelSelection:s,codexModelHash:i,claudeModelHash:r}),this.resolvedEnvironment(e),this.legacyEnvironments.delete(e)}catch{this.assignments.delete(e);for(const e of n)this.models.delete(e);this.warnMigration(e,"mapping-failed")}}}migrateApp(e,t,n){const i=e["codex"===t?"OPENAI_API_KEY":"ANTHROPIC_API_KEY"],r="codex"===t?e.TASK_HANDOFF_CODEX_BASE_URL||e.OPENAI_BASE_URL:e.ANTHROPIC_BASE_URL,s="codex"===t?e.TASK_HANDOFF_CODEX_MODEL||e.CODEX_MODEL:e.TASK_HANDOFF_CLAUDE_MODEL||e.CLAUDE_MODEL;if(!i&&!r&&!s)return;if(!i||!r||!s)throw new Error("model configuration incomplete");const o=wi({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=K();return this.models.put(li.parse({id:o,name:`Migrated ${"codex"===t?"Codex":"Claude"} model`,endpoint:r,key:i,model:s,app:t,enabled:!0,order:this.nextOrder(),labels:{migratedFrom:"instance-model-environment"},createdAt:c,updatedAt:c})),n.push(o),o}warnMigration(e,t){console.warn(JSON.stringify({message:"legacy model environment was preserved because it could not be migrated",nodeId:this.nodeId,instanceId:e,reason:t}))}}function No(e,t){if(!e)return!0;const n=w.valid(e),i=w.valid(t);return n&&i?w.gt(i,n):e!==t}function So(){return process.env.TASK_HANDOFF_NPM_COMMAND||"npm"}function zo(e,t){const n=r.join(e,...t.split("/"),"package.json");try{const e=JSON.parse(i.readFileSync(n,"utf8"));if(e.name!==t||"string"!=typeof e.version||!e.version.trim())throw new Error(`Installed package manifest is invalid: ${n}`);return{name:t,version:e.version.trim()}}catch(e){if("ENOENT"===e.code)return;throw e}}async function To(e,t){const n=t?function(e){const t=function(e){let t=r.resolve(e);for(;t!==r.dirname(t);){if("node_modules"===r.basename(t)&&"lib"===r.basename(r.dirname(t)))return r.dirname(r.dirname(t));t=r.dirname(t)}}(e);if(!t)return;let n,s=r.resolve(e);for(;s!==r.dirname(s);){try{const e=JSON.parse(i.readFileSync(r.join(s,"package.json"),"utf8"));if("@task-handoff/node-agent"===e.name&&"string"==typeof e.version&&e.version.trim()&&(n=e.version.trim()),"@task-handoff/server"===e.name&&"string"==typeof e.version&&e.version.trim())return{packageName:"@task-handoff/server",currentVersion:e.version.trim(),relatedCurrentVersions:n?[n]:[],installPrefix:t}}catch(e){if("ENOENT"!==e.code)throw e}s=r.dirname(s)}return n?{packageName:"@task-handoff/node-agent",currentVersion:n,relatedCurrentVersions:[],installPrefix:t}:void 0}(t):void 0;if(n)return n;const s=(await e(So(),["root","--global"])).stdout.trim();if(!s)throw new Error("npm did not return its global module root.");const o=(await e(So(),["prefix","--global"])).stdout.trim();if(!r.isAbsolute(o))throw new Error(`npm did not return an absolute global prefix: ${o||"empty"}`);const a=zo(s,"@task-handoff/server"),c=zo(s,"@task-handoff/node-agent");return a?{packageName:"@task-handoff/server",currentVersion:a.version,relatedCurrentVersions:c?[c.version]:[],installPrefix:o}:{packageName:"@task-handoff/node-agent",currentVersion:c?.version,relatedCurrentVersions:[],installPrefix:o}}function _o(e){if(!e||"object"!=typeof e||Array.isArray(e))return e;const t=e,n="string"==typeof t.updatedAt?t.updatedAt:K(),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=Wn.strip().safeParse(t.impact).success?Wn.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}:Gn.strip().safeParse(t.error).success?Gn.strip().parse(t.error):t.error&&"object"==typeof t.error?{code:"NODE_UPDATE_FAILED",message:"string"==typeof t.error.message?t.error.message:"Stored update job contained an unknown error.",retryable:!1}:void 0:{code:"NODE_UPDATE_FAILED",message:`Stored update job used an unknown status: ${a}.`,retryable:!1},{target:m,error:p,...h}=t,g={phase:"succeeded"===c?"succeeded":"failed"===c?"failed":c||"queued",desiredVersion:d,expectedInstanceIds:[],expectedInstanceCount:0,matchedInstanceCount:0,pendingInstanceCount:0,failedInstanceCount:r||"failed"===c?1:0,deferredInstanceCount:0},f=Yn.strip().safeParse(t.rollout);return{...h,source:"npm",status:c,impact:l,runtimeArtifacts:Array.isArray(t.runtimeArtifacts)?t.runtimeArtifacts.flatMap(e=>{const t=Kn.strip().safeParse(e);return t.success?[t.data]:[]}):[],rollout:f.success?f.data:g,...u?{error:u}:{},...r?{completedAt:t.completedAt||n}:{}}}class Co{records;constructor(e){this.records=new fo(e.updatesDir,{schema:Zn,sanitize:_o})}init(){this.records.init()}list(){return this.records.list().sort((e,t)=>t.createdAt.localeCompare(e.createdAt))}create(e,t){const n=K();return this.records.put(Zn.parse({id:ho("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(Zn.parse({...n,...t,id:e,createdAt:n.createdAt,updatedAt:K()}))}reconcileRollouts(e,t,n={}){const i=new Map(e.map(e=>[e.id,e]));for(const e of this.list().filter(e=>["updating-node","restarting-node","converging-instances"].includes(e.status))){if(n.processStarted&&"restarting-node"===e.status&&t!==e.toVersion){this.patch(e.id,{status:"failed",rollout:{...e.rollout,phase:"failed",nodeVersion:t},error:{code:"NODE_UPDATE_FAILED",message:`Node agent restarted with version ${t}, expected ${e.toVersion}.`,retryable:!1},completedAt:K()});continue}const r="converging-instances"!==e.status&&t===e.toVersion?this.patch(e.id,{status:"converging-instances",rollout:{...e.rollout,phase:"converging-instances",nodeVersion:t}}):e;if("converging-instances"!==r.status)continue;const s=r.rollout.expectedInstanceIds,o=s.map(e=>i.get(e)),a=o.filter(e=>e?.ready&&"matched"===e.runtimeVersion?.phase&&e.runtimeVersion.actualVersion===r.toVersion).length,c=o.filter(e=>e&&["created","stopped","failed"].includes(e.status||"")&&"failed"!==e.runtimeVersion?.phase).length,d=o.filter(e=>!e||"failed"===e.runtimeVersion?.phase).length,l=Math.max(0,s.length-a-d-c),u=d>0?"degraded":0===l?"succeeded":"converging-instances";this.patch(r.id,{status:u,rollout:{...r.rollout,phase:u,nodeVersion:t,expectedInstanceCount:s.length,matchedInstanceCount:a,pendingInstanceCount:l,failedInstanceCount:d,deferredInstanceCount:r.impact.stoppedInstanceCount+c},..."succeeded"===u||"degraded"===u?{completedAt:K()}:{}})}}run(e,t){(async()=>{this.patch(e.id,{status:"updating-node",rollout:{...e.rollout,phase:"updating-node"},startedAt:K(),error:void 0});try{await t(e),this.patch(e.id,{status:"succeeded",completedAt:K()})}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:K()})}})()}}class ko{records;constructor(e){this.records=new fo(e.environmentTemplatesDir,{schema:Cn,sanitize:e=>function(e,t){if(!e||"object"!=typeof e||Array.isArray(e))return e;const n=e,i=new Set(["id","name","sourceInstanceId","nodeId","imageId","internalTag","platform","architecture","sizeBytes","status","error","createdAt","updatedAt"]),r="string"==typeof n.id?n.id:void 0;for(const e of Object.keys(n))i.has(e)||t?.({templateId:r,field:e});const s=dr(n,[...i]);if(n.error&&"object"==typeof n.error&&!Array.isArray(n.error)){const e=n.error;for(const n of Object.keys(e))["code","message","phase"].includes(n)||t?.({templateId:r,field:`error.${n}`});s.error=dr(e,["code","message","phase"])}return s}(e,e=>{console.warn(JSON.stringify({message:"unknown stored environment template field was ignored",...e}))})})}init(){this.records.init();for(const e of this.records.list())"creating"===e.status&&this.records.put(Cn.parse({...e,status:"failed",error:{code:"ENVIRONMENT_TEMPLATE_CREATION_INTERRUPTED",message:"Environment template creation was interrupted by a node-agent restart.",phase:"recovery"},updatedAt:K()}))}list(){return this.records.list()}get(e){return this.records.get(e)}put(e){return this.records.put(Cn.parse(e))}patch(e,t){return this.records.patch(e,t)}delete(e){return this.records.delete(e)}}const Oo=d.z.record(d.z.string().regex(/^[A-Za-z_][A-Za-z0-9_]*$/),d.z.string()),Ro=d.z.object({version:d.z.literal(1),instanceId:d.z.string().trim().min(1).max(120),instanceCredential:d.z.string().trim().min(1).max(240),environment:Oo,updatedAt:d.z.string().datetime()}).strict();class xo{directory;constructor(e){this.directory=e.instancePrivateConfigsDir}init(){i.mkdirSync(this.directory,{recursive:!0,mode:448}),i.chmodSync(this.directory,448);for(const e of i.readdirSync(this.directory).filter(e=>e.endsWith(".json")))i.chmodSync(r.join(this.directory,e),384)}filePath(e){return r.join(this.directory,`${e}.json`)}get(e){const t=this.filePath(e);if(!i.existsSync(t))return;const n=JSON.parse(i.readFileSync(t,"utf8")),r=n&&"object"==typeof n&&!Array.isArray(n)?n:{},s=Ro.parse({version:r.version,instanceId:r.instanceId,instanceCredential:r.instanceCredential??r.registrationToken,environment:r.environment,updatedAt:r.updatedAt});if(s.instanceId!==e)throw Object.assign(new Error(`Private config identity mismatch for instance ${e}.`),{statusCode:409,code:"INSTANCE_PRIVATE_CONFIG_IDENTITY_MISMATCH"});return void 0===r.instanceCredential&&void 0!==r.registrationToken&&this.put(s),s}put(e){const t=Ro.parse(e);this.init();const n=this.filePath(t.instanceId);return b.sync(n,`${JSON.stringify(t,null,2)}\n`,{encoding:"utf8",mode:384}),i.chmodSync(n,384),t}materialize(e,t,n){if(!t)throw Object.assign(new Error(`Instance ${e} does not have a long-lived credential.`),{statusCode:409,code:"INSTANCE_PRIVATE_CONFIG_CREDENTIAL_MISSING"});return this.put({version:1,instanceId:e,instanceCredential:t,environment:n,updatedAt:(new Date).toISOString()})}delete(e){i.rmSync(this.filePath(e),{force:!0})}}const Do=function(e,t=process.env,n=e){let i;return()=>{const r=t.TASK_HANDOFF_VERSION?.trim();return r||(i||=S(e,t,n),i)}}("@task-handoff/node-agent",process.env,"@task-handoff/control-plane");function Po(){return Do()}function Mo(e,t){return{code:"INSTANCE_RUNTIME_VERSION_MISMATCH",message:`Expected controlled-instance ${e}, received ${t||"an unknown version"}.`,expectedVersion:e,...t?{actualVersion:t}:{},retryable:!0}}function Lo(e){const t=Po();return e===t?{desiredVersion:t,actualVersion:e,phase:"matched",attempt:0,matchedAt:(new Date).toISOString()}:{desiredVersion:t,...e?{actualVersion:e}:{},phase:"pending",attempt:0,error:Mo(t,e)}}function jo(e,t,n=!0){if(!n)return Lo(t);const i=Po(),r=e.runtimeVersion;if(!r||r.desiredVersion!==i)return Lo(t);const s="INSTANCE_RUNTIME_VERSION_MISMATCH"!==r.error?.code?r.error:t===i?void 0:Mo(i,t);return Jn.parse({...r,desiredVersion:i,...t?{actualVersion:t}:{actualVersion:void 0},..."pending"===r.phase?{error:s||(t!==i?Mo(i,t):void 0)}:{}})}const $o="runtime_local_host",Fo="task-handoff.node-agent.builtin";function Uo(e){const t={...e};return delete t[Fo],t}function Vo(e){return"local-folder"===e.type?oi.parse({mode:"local-bind",path:"/workspace",readOnly:!1}):oi.parse({mode:"git-clone",path:"/workspace",readOnly:!1})}function Ho(e){const t=si.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 ci.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:Vo(t),labels:{},createdAt:e.createdAt,updatedAt:e.updatedAt})}function qo(e,t){throw Object.assign(new Error(t),{statusCode:403,code:e})}function Bo(e,t){e!==Ft&&console.warn(JSON.stringify({message:"protocol version mismatch",peer:t,expectedProtocolVersion:Ft,actualProtocolVersion:e||"missing",errorCode:"PROTOCOL_VERSION_MISMATCH"}))}function Ko(e){return"none"!==e.capabilities.artifactKind}function Go(e={}){return{...e,requiresImage:!1,supportsControlledInstanceApi:!0,supportsContainerLifecycle:!1,supportsAppSessions:!0,supportsHostSessions:!0,artifactKind:"none",isolation:"none"}}class Jo extends fo{onStored;privateConfigs;constructor(e,t,n){super(e,t),this.privateConfigs=n}setOnStored(e){this.onStored=e}put(e){const t=super.get(e.id)?.stateRevision||0,n=this.privateConfigs.get(e.id),i=e.registrationToken||n?.instanceCredential;i&&this.privateConfigs.materialize(e.id,i,n?.environment||{});const{registrationToken:r,...s}=e,o=super.put(nr.parse({...s,stateRevision:Math.max(e.stateRevision||0,t)+1})),a=this.hydrate(o);return this.onStored?.(a),a}get(e){const t=super.get(e);return t?this.hydrate(t):void 0}list(){return super.list().map(e=>this.hydrate(e))}hydrate(e){const t=this.privateConfigs.get(e.id)?.instanceCredential||e.registrationToken;return nr.parse({...e,registrationToken:t})}}class Wo{nodeId;paths;localFolders;nodeRuntimes;controlledInstances;environmentTemplates;instancePrivateConfigs;modelRegistry;updateJobs;node;listenerPort;containerUrlOverride;platform;constructor(e,t,n,i,r,s){this.paths=e,this.nodeId=t,this.localFolders=new fo(e.localFoldersDir,{schema:ri,sanitize:Sn}),this.nodeRuntimes=new fo(e.nodeRuntimesDir,{schema:Hi}),this.instancePrivateConfigs=new xo(e),this.controlledInstances=new Jo(e.controlledInstancesDir,{schema:nr,sanitize:e=>or(e,e=>{console.warn(JSON.stringify({message:"legacy controlled instance field was ignored",...e}))})},this.instancePrivateConfigs),this.environmentTemplates=new ko(e),this.modelRegistry=new Eo(e,t,{has:e=>Boolean(this.controlledInstances.get(e)),list:()=>this.listInstances(),require:e=>this.requireInstance(e),put:e=>this.controlledInstances.put(e)}),this.updateJobs=new Co(e),this.listenerPort=r,this.platform=s,this.containerUrlOverride=i;const o=K();this.node=Vi.parse({id:t,name:t,connectionMode:"direct-http",endpoint:n,controlEndpoint:n,containerEndpoint:this.containerUrl,publicWebBase:n?n.replace(/:\d+$/,""):void 0,status:"online",health:"ok",capabilities:{},labels:{},createdAt:o,updatedAt:o})}init(){this.localFolders.init();for(const e of this.localFolders.list())this.localFolders.put(e);if(this.nodeRuntimes.init(),this.instancePrivateConfigs.init(),this.controlledInstances.init(),this.environmentTemplates.init(),this.modelRegistry.init(),this.updateJobs.init(),this.updateJobs.reconcileRollouts(this.controlledInstances.list(),Po(),{processStarted:!0}),!this.nodeRuntimes.get("runtime_local_docker")){const e=K();this.nodeRuntimes.put(Hi.parse({id:"runtime_local_docker",nodeId:this.nodeId,name:"Local Docker",type:"docker",status:"unknown",accessStrategy:"direct-port",capabilities:{},labels:{},createdAt:e,updatedAt:e}))}if("win32"!==this.platform){const e=this.nodeRuntimes.get($o),t=K();this.nodeRuntimes.put(Hi.parse({id:$o,nodeId:this.nodeId,name:"Local Runtime",type:"local",status:e?.status||"unknown",accessStrategy:"node-proxy",capabilities:Go(e?.capabilities),labels:{...e?.labels,[Fo]:"true"},createdAt:e?.createdAt||t,updatedAt:e?.updatedAt||t}))}for(const e of this.nodeRuntimes.list())e.nodeId!==this.nodeId&&this.nodeRuntimes.put(Hi.parse({...e,nodeId:this.nodeId,updatedAt:K()}));for(const e of this.localFolders.list())e.nodeId!==this.nodeId&&this.localFolders.put(ri.parse({...e,nodeId:this.nodeId,updatedAt:K()}));this.normalizeInstanceRuntimeVersions()}normalizeInstanceRuntimeVersions(){for(const e of this.controlledInstances.list()){const t=Lo(e.build?.packageVersion||e.instanceVersion),n=Ko(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}:{...t,phase:"pending",attempt:r?.attempt||0,lastAttemptAt:r?.lastAttemptAt,error:r?.error||t.error}:t;this.controlledInstances.put(nr.parse({...e,ready:!1,runtimeVersion:s,updatedAt:K()}))}}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=K()}runningInstanceCount(){const e=new Set(["created","stopped","failed"]);return this.listInstances().filter(t=>!e.has(t.status)).length}createLocalFolder(e){const t=K(),n=Os(e.path),i=ri.parse({...e,name:e.name.trim()||r.basename(n),path:n,id:e.id||ho("folder"),nodeId:this.nodeId,labels:e.labels||{},createdAt:t,updatedAt:t});return this.localFolders.put(i)}updateLocalFolder(e,t){const n=this.localFolders.get(e);if(!n){const t=new Error(`Local folder ${e} was not found.`);throw Object.assign(t,{statusCode:404,code:"NODE_LOCAL_FOLDER_NOT_FOUND"})}return this.localFolders.put(ri.parse({...n,name:t.name.trim()||r.basename(n.path),updatedAt:K()}))}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=K(),n=Hi.parse({...e,id:e.id||ho("runtime"),nodeId:this.nodeId,accessStrategy:e.accessStrategy||(i=e.type,"docker"===i?"direct-port":"node-proxy"),capabilities:e.capabilities||{},labels:Uo(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[Fo]){const t=new Error(`Built-in runtime ${e} cannot be modified.`);throw Object.assign(t,{statusCode:400,code:"NODE_RUNTIME_BUILTIN"}),t}if("local"===n.type||"local"===t.type){const e="win32"===this.platform,t=new Error(e?"Local Runtime is not supported on Windows.":"Local Runtime is built in and cannot be configured manually.");throw Object.assign(t,{statusCode:e?400:409,code:e?"LOCAL_RUNTIME_UNSUPPORTED":"LOCAL_RUNTIME_BUILTIN"}),t}const i=Hi.parse({...n,...t,id:n.id,nodeId:this.nodeId,accessStrategy:t.accessStrategy||n.accessStrategy,capabilities:t.capabilities||n.capabilities,labels:t.labels?Uo(t.labels):n.labels,createdAt:n.createdAt,updatedAt:K()});return this.nodeRuntimes.put(i)}deleteRuntime(e){if("true"===this.requireRuntime(e).labels[Fo]){const t=new Error(`Built-in runtime ${e} cannot be deleted.`);throw Object.assign(t,{statusCode:400,code:"NODE_RUNTIME_BUILTIN"}),t}const t=this.listInstances().filter(t=>t.runtimeId===e);if(t.length){const n=new Error(`Runtime ${e} is used by ${t.length} instance${1===t.length?"":"s"}.`);throw Object.assign(n,{statusCode:409,code:"NODE_RUNTIME_IN_USE"}),n}return this.nodeRuntimes.delete(e)}checkRuntime(e,t){const n=this.requireRuntime(e);return t.check?t.check(n).then(e=>{const t=Hi.parse({...n,...e,id:n.id,nodeId:this.nodeId,createdAt:n.createdAt,updatedAt:K()});return this.nodeRuntimes.put(t)}):this.nodeRuntimes.put(Hi.parse({...n,status:"unknown",updatedAt:K()}))}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=sr(t);if(!n.success)throw function(e,t){const n=t.map(e=>`${e.path.join(".")||"body"}: ${e.message}`).join("; ");return Object.assign(new Error(`Stored instance ${e} is not compatible with protocol ${Ft}: ${n}`),{statusCode:409,code:"NODE_INSTANCE_PAYLOAD_INVALID"})}(e,n.error.issues);return n.data}applyInstanceLifecycle(e,t){return this.controlledInstances.put(function(e,t,n=(new Date).toISOString()){switch(t.type){case"start-requested":return nr.parse({...e,status:"starting",ready:!1,updatedAt:n});case"stop-requested":return nr.parse({...e,status:"stopping",ready:!1,updatedAt:n});case"stop-failed":return"stopping"!==e.status?e:nr.parse({...e,status:t.baseline.status,health:t.baseline.health,connectionStatus:t.baseline.connectionStatus,agentStatus:t.baseline.agentStatus,targetStatus:t.baseline.targetStatus,uiAccessStatus:t.baseline.uiAccessStatus,ready:t.baseline.ready,target:{...e.target,status:t.baseline.target.status},updatedAt:n});case"convergence-restart-requested":return nr.parse({...e,build:void 0,instanceVersion:void 0,ready:!1,updatedAt:n});case"runtime-lifecycle-completed":return function(e,t,n,i){if(t.stateRevision>e.stateRevision&&["failed","stopping","stopped","deleting"].includes(t.status))return t;const r=t.stateRevision>e.stateRevision&&t.lastHeartbeatAt!==e.lastHeartbeatAt&&"online"===t.agentStatus;return nr.parse({...t,...n,...r?{status:t.status,health:t.health,connectionStatus:t.connectionStatus,agentStatus:t.agentStatus,targetStatus:t.targetStatus,uiAccessStatus:t.uiAccessStatus}:{},ready:!!r&&t.ready,target:n.target?{...t.target,...n.target}:t.target,workspace:n.workspace?r?{...n.workspace,...t.workspace}:{...t.workspace,...n.workspace}:t.workspace,runtime:n.runtime?{...t.runtime,...n.runtime}:t.runtime,updatedAt:i})}(t.baseline,e,t.observation,n);case"stop-completed":return nr.parse({...e,status:"stopped",health:"unknown",connectionStatus:"offline",ready:!1,agentStatus:"offline",targetStatus:"unknown",uiAccessStatus:"unknown",target:{...e.target,status:"unknown"},updatedAt:n});case"runtime-exited":case"start-failed":return nr.parse({...e,status:"failed",ready:!1,health:"failed",connectionStatus:"offline",agentStatus:"offline",targetStatus:"unknown",uiAccessStatus:"unknown",workspace:{...e.workspace,error:(i=t.error,i instanceof Error?i.message:String(i))},updatedAt:n})}var i}(this.requireInstance(e),t))}listInstances(){return this.controlledInstances.list().flatMap(e=>{const t=sr(e);return t.success?[t.data]:[]})}resolvedAssignedModelEnvironment(e){return this.modelRegistry.resolvedEnvironment(e)}createInstance(e){const t=this.requireRuntime(e.runtimeId),n=K(),i=e.id||ho("inst"),s=si.parse(e.source),o=e.environmentSource||(e.imageSelection?{type:"image",imageSelection:e.imageSelection}:void 0);if("template"===o?.type&&"docker"!==t.type){const e=new Error(`Runtime ${t.name} does not support environment templates.`);throw Object.assign(e,{statusCode:409,code:"ENVIRONMENT_TEMPLATE_RUNTIME_UNSUPPORTED"}),e}const a="template"===o?.type?this.environmentTemplates.get(o.environmentTemplateId):void 0;if("template"===o?.type&&(!a||"ready"!==a.status)){const e=new Error(`Environment template ${o.environmentTemplateId} is not ready on node ${this.nodeId}.`);throw Object.assign(e,{statusCode:a?409:404,code:a?"ENVIRONMENT_TEMPLATE_NOT_READY":"ENVIRONMENT_TEMPLATE_NOT_FOUND"}),e}if(a&&a.nodeId!==this.nodeId){const e=new Error(`Environment template ${a.id} belongs to node ${a.nodeId}, not ${this.nodeId}.`);throw Object.assign(e,{statusCode:409,code:"ENVIRONMENT_TEMPLATE_NODE_MISMATCH"}),e}if(function(e){return"boolean"==typeof e.capabilities.requiresImage?e.capabilities.requiresImage:"local"!==e.type}(t)&&(!o||"image"===o.type&&!e.image)){const e=new Error(`Runtime ${t.name} requires an image.`);throw Object.assign(e,{statusCode:400,code:"NODE_RUNTIME_IMAGE_REQUIRED"}),e}if("local"===t.type&&"local-folder"!==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 c=a?xi.parse({id:a.id,origin:"custom",name:a.name,repository:"task-handoff/environment-template",tag:a.id.toLowerCase().replace(/[^a-z0-9_.-]/g,"-"),requestedReference:a.internalTag,resolvedDigest:a.imageId,resolvedReference:a.internalTag,downloadSizeBytes:a.sizeBytes||void 0,pullPolicy:"if-not-present",capabilities:[],optionalApps:[],defaultEnv:{},labels:{},createdAt:a.createdAt,updatedAt:a.updatedAt}):e.image?xi.parse(e.image):void 0,d="local"===t.type&&"local-folder"===s.type?r.resolve(s.path):void 0,l=nr.parse({id:i,name:e.name||`instance-${i.replace(/^inst_?/,"").slice(0,6)}`,source:s,sourceSnapshot:e.sourceSnapshot||{},modelSelection:e.modelSelection,projectId:e.projectId,nodeId:this.nodeId,runtimeId:t.id,imageSelection:"image"===o?.type?o.imageSelection:void 0,environmentSource:o,environmentTemplateOrigin:a?{templateId:a.id,nodeId:a.nodeId,imageId:a.imageId,name:a.name,platform:a.platform,architecture:a.architecture}:void 0,imageSnapshot:c,imageProvisioning:c&&"docker"===t.type&&"template"!==o?.type?{phase:"checking-image",requestedReference:c.requestedReference,generation:0,startedAt:n,updatedAt:n}:void 0,status:c&&"docker"===t.type&&"template"!==o?.type?"provisioning":"created",health:"unknown",connectionStatus:"unknown",agentStatus:"unknown",targetStatus:"unknown",uiAccessStatus:"unknown",controlMode:"controlled",ready:!1,runtimeVersion:Lo(),capabilities:{},config:{autoImportAgentConfigs:e.config?.autoImportAgentConfigs??!0,defaultCodexPermissionMode:e.config?.defaultCodexPermissionMode??("docker"===t.type?"full-access":"ask"),aiSessionHistoryLimit:e.config?.aiSessionHistoryLimit??50,aiSessionAttachmentRetentionDays:e.config?.aiSessionAttachmentRetentionDays??30},workspace:"local"===t.type?{mode:"local-bind",status:"unknown",path:d}:{status:"unknown"},target:{strategy:"node-proxy",status:"unknown"},runtime:"local"===t.type?{kind:"local",workspacePath:d,labels:{"task-handoff.runtime-kind":"local"}}:{labels:{}},registrationToken:go(),createdAt:n,updatedAt:n}),u=this.controlledInstances.put(l);return this.instancePrivateConfigs.materialize(u.id,u.registrationToken,this.resolvedAssignedModelEnvironment(u.id)),u}registerInstance(e,t,n){const i=lr.parse(t),r=K(),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}if(this.validateInstanceReport(s,i,n),i.processIncarnationId&&i.processIncarnationId===s.processIncarnationId)return s;Bo(i.protocolVersion,`Instance ${e}`);const o=i.build?.packageVersion||i.instanceVersion,a=Ko(this.requireRuntime(s.runtimeId)),c=jo(s,o,a),d=nr.parse({...s,status:"registered",health:o===Po()?"ok":"degraded",ready:!a&&o===Po(),connectionStatus:"online",agentStatus:"online",targetStatus:s.targetStatus,uiAccessStatus:s.uiAccessStatus,controlMode:i.controlMode,protocolVersion:i.protocolVersion,instanceVersion:i.instanceVersion,build:i.build,runtimeVersion:c,processIncarnationId:i.processIncarnationId||s.processIncarnationId,capabilities:i.capabilities,appInventory:i.appInventory,workspace:i.workspace,target:s.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=ur.parse(t);i.processIncarnationId&&r.processIncarnationId&&r.processIncarnationId!==i.processIncarnationId&&function(e,t){throw Object.assign(new Error(t),{statusCode:409,code:"INSTANCE_PROCESS_INCARNATION_MISMATCH"})}(0,`Instance ${e} report belongs to an obsolete controlled-instance process.`),Bo(r.protocolVersion,`Instance ${e}`);const s=K(),o=i.target,a=i.targetStatus,c=jo(i,r.build?.packageVersion||i.build?.packageVersion||i.instanceVersion,Ko(this.requireRuntime(i.runtimeId))),d=r.health||i.health,l="running"===(r.status||i.status)&&"failed"!==d,u=nr.parse({...i,...r,target:o,ready:l,health:d,runtimeVersion:c,processIncarnationId:r.processIncarnationId||i.processIncarnationId,agentStatus:"online",targetStatus:a,uiAccessStatus:a,connectionStatus:"online",build:r.build||i.build,lastHeartbeatAt:s,updatedAt:s});return this.controlledInstances.put(u)}validateInstanceReport(e,t,n){this.validateInstanceToken(e,n||t.registrationToken),t.instanceId&&t.instanceId!==e.id&&qo("INSTANCE_ID_MISMATCH",`Instance ${t.instanceId} cannot register as ${e.id}.`),t.nodeId&&t.nodeId!==this.nodeId&&qo("INSTANCE_NODE_MISMATCH",`Instance ${e.id} belongs to node ${this.nodeId}.`),t.runtimeId&&t.runtimeId!==e.runtimeId&&qo("INSTANCE_RUNTIME_MISMATCH",`Instance ${e.id} belongs to runtime ${e.runtimeId}.`),t.imageSelection&&t.imageSelection.imageId!==e.imageSelection?.imageId&&qo("INSTANCE_IMAGE_MISMATCH",`Instance ${e.id} belongs to image ${e.imageSelection?.imageId}.`)}validateInstanceToken(e,t){e.registrationToken&&t===e.registrationToken||qo("INSTANCE_REGISTRATION_TOKEN_INVALID",`Invalid registration token for instance ${e.id}.`)}context(e,t=this.resolvedAssignedModelEnvironment(e.id)){const n=e.imageSnapshot||xi.parse({id:"img_localhost",origin:"custom",name:"Localhost",repository:"localhost",tag:"local",requestedReference:"localhost:local",pullPolicy:"if-not-present",capabilities:[],optionalApps:[],defaultEnv:{},labels:{},createdAt:e.createdAt,updatedAt:e.updatedAt}),i=this.instancePrivateConfigs.materialize(e.id,e.registrationToken,t);return{project:Ho(e),image:n,node:this.node,runtime:this.requireRuntime(e.runtimeId),instance:e,nodeAgentUrl:this.containerUrl,modelEnv:t,privateConfigPath:this.instancePrivateConfigs.filePath(i.instanceId)}}}async function Yo(e,t){const n=function(e){const t=Zo(e),n=[],i=t.pathname.split("/").filter(Boolean).at(-1)||"";return ra(n,Qo(t.toString(),/^v\d+$/.test(i)?"models":"v1/models")),ra(n,new URL("/v1/models",t.origin).toString()),ra(n,new URL("/models",t.origin).toString()),n}(t.endpoint),i=Date.now();let r;for(const s of n){const n=await ea(e,s,{method:"GET",headers:{accept:"application/json",authorization:`Bearer ${t.key}`}});if(404===n.status||405===n.status){r=n.status;continue}if(!n.ok)throw na("MODEL_DISCOVERY_FAILED",n.status);const o=await ta(n,"MODEL_DISCOVERY_RESPONSE_INVALID"),a=Array.isArray(o.data)?o.data:void 0;if(!a)throw ia("MODEL_DISCOVERY_RESPONSE_INVALID","The model endpoint returned an invalid model list.",502);return{models:sa(a.flatMap(e=>{if(!e||"object"!=typeof e||Array.isArray(e))return[];const t=e,n="string"==typeof t.id?t.id.trim():"";if(!n)return[];const i="string"==typeof t.owned_by?t.owned_by.trim():"";return[{id:n,...i?{ownedBy:i}:{}}]}).sort((e,t)=>e.id.localeCompare(t.id))),latencyMs:Date.now()-i}}throw ia("MODEL_DISCOVERY_UNSUPPORTED","No compatible model-list endpoint was found for this endpoint.",502,r)}async function Xo(e,t){const n=Date.now(),i="codex"===t.app?await ea(e,Qo(t.endpoint,"responses"),{method:"POST",headers:{accept:"application/json",authorization:`Bearer ${t.key}`,"content-type":"application/json"},body:JSON.stringify({model:t.model,input:"Reply with OK.",max_output_tokens:32,stream:!1})}):await ea(e,function(e){const t=Zo(e),n=t.pathname.split("/").filter(Boolean).at(-1)||"";return Qo(t.toString(),/^v\d+$/.test(n)?"messages":"v1/messages")}(t.endpoint),{method:"POST",headers:{accept:"application/json","anthropic-version":"2023-06-01","content-type":"application/json","x-api-key":t.key},body:JSON.stringify({model:t.model,max_tokens:8,messages:[{role:"user",content:"Reply with OK."}]})});if(!i.ok)throw na("MODEL_TEST_FAILED",i.status);if((await ta(i,"MODEL_TEST_RESPONSE_INVALID")).error)throw ia("MODEL_TEST_RESPONSE_INVALID","The model endpoint returned an error payload.",502);return{success:!0,latencyMs:Date.now()-n}}function Qo(e,t){const n=Zo(e);return n.pathname=`${n.pathname.replace(/\/+$/,"")}/${t.replace(/^\/+/,"")}`,n.search="",n.hash="",n.toString()}function Zo(e){let t;try{t=new URL(e.trim())}catch{throw ia("MODEL_ENDPOINT_INVALID","The model endpoint must be a valid HTTP or HTTPS URL.",400)}if("http:"!==t.protocol&&"https:"!==t.protocol||t.username||t.password)throw ia("MODEL_ENDPOINT_INVALID","The model endpoint must be an HTTP or HTTPS URL without embedded credentials.",400);return t}async function ea(e,t,n){try{return await e(t,{...n,redirect:"error",signal:AbortSignal.timeout(15e3)})}catch(e){const t=e&&"object"==typeof e&&"name"in e&&"TimeoutError"===e.name;throw ia(t?"MODEL_ENDPOINT_TIMEOUT":"MODEL_ENDPOINT_UNREACHABLE",t?"The model endpoint timed out.":"The model endpoint could not be reached.",t?504:502)}}async function ta(e,t){const n=await e.text();if(n.length>1e6)throw ia(t,"The model endpoint response was too large.",502);try{const e=JSON.parse(n);if(!e||"object"!=typeof e||Array.isArray(e))throw new Error("not an object");return e}catch{throw ia(t,"The model endpoint returned invalid JSON.",502)}}function na(e,t){return ia(e,401===t||403===t?"The model endpoint rejected the API key.":"The model endpoint rejected the request.",502,t)}function ia(e,t,n,i){return Object.assign(new Error(t),{code:e,statusCode:n,...i?{details:{upstreamStatus:i}}:{}})}function ra(e,t){e.includes(t)||e.push(t)}function sa(e){const t=new Set;return e.filter(e=>!t.has(e.id)&&(t.add(e.id),!0))}const oa=d.z.object({endpoint:d.z.string().trim().url().max(2048),key:d.z.string().trim().min(1).max(4096).optional(),existingModelId:d.z.string().trim().min(1).max(120).optional()}).strict(),aa=oa.extend({model:d.z.string().trim().min(1).max(240),app:d.z.enum(["codex","claude"])}).strict(),ca=d.z.object({path:d.z.string().trim().min(1).max(2048),method:d.z.string().trim().min(1).max(20).default("GET"),headers:d.z.record(d.z.string(),d.z.string()).default({}),body:d.z.string().optional(),bodyBase64:d.z.string().optional()}).strict(),da=d.z.object({id:d.z.string().trim().min(1).max(120).optional(),name:d.z.string().trim().max(160),path:d.z.string().trim().min(1).max(4096),defaultImageSelection:mn.optional(),labels:d.z.record(d.z.string(),d.z.string()).default({})}).strict(),la=d.z.object({name:d.z.string().trim().max(160)}).strict(),ua=d.z.object({path:d.z.string().trim().min(1).max(4096).optional(),depth:d.z.coerce.number().int().min(0).max(1).default(0)}).strict(),ma=d.z.object({id:d.z.string().trim().min(1).max(120).optional(),name:d.z.string().trim().min(1).max(160).optional(),runtimeId:d.z.string().trim().min(1).max(120),imageSelection:mn.optional(),environmentSource:pn.optional(),projectId:d.z.string().trim().min(1).max(120).optional(),image:xi.optional(),source:si,sourceSnapshot:d.z.record(d.z.string(),d.z.unknown()).default({}),config:d.z.object({autoImportAgentConfigs:d.z.boolean().optional(),defaultCodexPermissionMode:Re.optional(),aiSessionHistoryLimit:d.z.number().int().min(1).max(Ze).optional(),aiSessionAttachmentRetentionDays:d.z.number().int().min(0).max(365).optional()}).strict().optional(),modelSelection:nr.shape.modelSelection}).strict().superRefine((e,t)=>{e.environmentSource&&e.imageSelection&&t.addIssue({code:"custom",path:["environmentSource"],message:"environmentSource and imageSelection are mutually exclusive."}),"template"===e.environmentSource?.type&&e.image&&t.addIssue({code:"custom",path:["image"],message:"Template environment source is resolved by the node-agent and cannot include an image snapshot."})}),pa=d.z.object({name:d.z.string().trim().min(1).max(160).optional(),config:d.z.object({autoImportAgentConfigs:d.z.boolean().optional(),defaultCodexPermissionMode:Re.optional(),aiSessionHistoryLimit:d.z.number().int().min(1).max(Ze).optional(),aiSessionAttachmentRetentionDays:d.z.number().int().min(0).max(365).optional()}).strict().optional(),modelSelection:nr.shape.modelSelection.optional()}).strict(),ha=d.z.object({id:d.z.string().trim().min(1).max(120).optional(),name:d.z.string().trim().min(1).max(160),type:d.z.enum(["docker","kubernetes","local"]),status:d.z.enum(["unknown","online","offline","degraded"]).default("unknown"),accessStrategy:d.z.enum(["node-proxy","direct-port","kubernetes-ingress","kubernetes-port-forward"]).optional(),capabilities:d.z.record(d.z.string(),d.z.unknown()).default({}),labels:d.z.record(d.z.string(),d.z.string()).default({})}).strict(),ga=ha.omit({id:!0}).partial().strict();function fa(e){const t=e.authorization;return"string"==typeof t&&t.startsWith("Bearer ")?t.slice(7).trim():void 0}class ya{operations=new Map;intents=new Map;intent(e){const t=this.intents.get(e);if(t)return t;const n={};return this.intents.set(e,n),n}invalidate(e){const t={};return this.intents.set(e,t),t}isIntentCurrent(e,t){return this.intents.get(e)===t}clearIntent(e){this.intents.delete(e)}async run(e,t){const n=this.operations.get(e)||Promise.resolve();let i;const r=new Promise(e=>{i=e});this.operations.set(e,r),await n;try{return await t()}finally{i(),this.operations.get(e)===r&&this.operations.delete(e)}}}const Ia=d.z.object({}).strict().default({});class Aa{state;images;options;inFlight=new Map;abortController=new AbortController;stopped=!1;constructor(e,t,n){this.state=e,this.images=t,this.options=n}retry(e){const t=this.state.requireInstance(e);if("docker"!==this.state.requireRuntime(t.runtimeId).type||!t.imageSnapshot)throw Object.assign(new Error(`Instance ${e} does not use a Docker image.`),{statusCode:400,code:"INSTANCE_IMAGE_PROVISIONING_UNSUPPORTED"});if("failed"!==t.status||"failed"!==t.imageProvisioning?.phase)throw Object.assign(new Error(`Instance ${e} does not have failed image provisioning to retry.`),{statusCode:409,code:"INSTANCE_IMAGE_PROVISIONING_NOT_FAILED"});const n=K();return this.state.controlledInstances.put(nr.parse({...t,status:"provisioning",health:"unknown",imageProvisioning:{phase:"checking-image",requestedReference:t.imageSnapshot.requestedReference,generation:(t.imageProvisioning?.generation||0)+1,startedAt:n,updatedAt:n},updatedAt:n}))}provision(e,t){if(this.stopped)return Promise.resolve();const n=e.imageProvisioning?.generation;if(void 0===n)return Promise.resolve();const i=`${e.id}:${n}`,r=this.inFlight.get(i);if(r)return r;const s=this.provisionGeneration(e,n,t).finally(()=>{this.inFlight.get(i)===s&&this.inFlight.delete(i)});return this.inFlight.set(i,s),s}async stop(){this.stopped=!0,this.abortController.abort(),await Promise.allSettled([...this.inFlight.values()])}async provisionGeneration(e,t,n){const i=this.currentGeneration(e.id,t,!0,e.createdAt);if(!i)return;let r,s=0,o=!1,a=Promise.resolve();try{const c=await this.images.ensure(i.imageSnapshot.requestedReference,n=>{a=a.then(async()=>{if(!r)try{await this.updatePhase(e.id,t,n,e.createdAt)}catch(e){r={error:e}}})},n=>{this.stopped||(o=!0,s=n.sequence,this.publishTerminalOutput(e,t,n))},this.abortController.signal);if(await a,r)throw r.error;if(this.stopped)return;o&&this.publishFinished(e,t,s+1,"succeeded");const d=async()=>{if(this.stopped)return;const i=this.currentGeneration(e.id,t,!0,e.createdAt);if(!i)return;const r=this.state.controlledInstances.put(nr.parse({...i,status:"provisioning"===i.status?"created":i.status,health:"unknown",imageSnapshot:{...i.imageSnapshot,requestedReference:c.requestedReference,resolvedDigest:c.resolvedDigest,resolvedReference:c.resolvedReference},imageProvisioning:{...i.imageProvisioning,phase:"ready",error:void 0,updatedAt:K()},updatedAt:K()}));this.options.sync(),this.options.diagnostic({instanceId:e.id,action:"image.provision",reference:c.requestedReference,digest:c.resolvedDigest,pulled:c.pulled},"node instance image provisioning completed"),"starting"===r.status&&await(n?.())};await(this.options.runInstanceOperation?.(e.id,d)??d())}catch(n){if(await a,r&&(n=r.error),this.stopped)return;o&&this.publishFinished(e,t,s+1,"failed");const i=n instanceof Error?n.message:String(n),c=async()=>{if(this.stopped)return;const n=this.currentGeneration(e.id,t,!1,e.createdAt);n?.imageProvisioning&&["provisioning","starting"].includes(n.status)&&(this.state.controlledInstances.put(nr.parse({...n,status:"failed",health:"failed",imageProvisioning:{...n.imageProvisioning,phase:"failed",error:i,updatedAt:K()},updatedAt:K()})),this.options.sync(),this.options.warn({instanceId:e.id,action:"image.provision",reference:n.imageProvisioning.requestedReference,error:i},"node instance image provisioning failed"))};await(this.options.runInstanceOperation?.(e.id,c)??c())}}currentGeneration(e,t,n=!0,i){const r=this.state.controlledInstances.get(e);if(!(!r||i&&r.createdAt!==i||r.imageProvisioning?.generation!==t||n&&!r.imageSnapshot))return r}async updatePhase(e,t,n,i){if(this.stopped)return;const r=async()=>{if(this.stopped)return;const r=this.currentGeneration(e,t,!0,i);r&&["provisioning","starting"].includes(r.status)&&(this.state.controlledInstances.put(nr.parse({...r,status:"starting"===r.status?"starting":"provisioning",imageProvisioning:{...r.imageProvisioning,phase:n,error:void 0,updatedAt:K()},updatedAt:K()})),this.options.sync())};await(this.options.runInstanceOperation?.(e,r)??r())}eventBase(e,t){return{instanceId:e.id,generation:t,requestedReference:e.imageProvisioning.requestedReference,observedAt:K()}}publishTerminalOutput(e,t,n){for(const[i,r]of function(e,t=6e4){const n=[];for(let i=0;i<e.length;i+=t)n.push(e.slice(i,i+t));return n}(n.data).entries())this.options.publish(Pi,{...this.eventBase(e,t),sequence:1e3*n.sequence+i,data:r,...n.replay?{replay:!0}:{}},e.id)}publishFinished(e,t,n,i){this.options.publish(Mi,{...this.eventBase(e,t),sequence:1e3*n,outcome:i},e.id)}}const ba=d.z.object({name:d.z.string().trim().min(1).max(160)}).strict();function wa(e,t,n){return{code:"object"==typeof e&&e&&"code"in e&&"string"==typeof e.code?e.code:t,message:e instanceof Error?e.message:String(e),phase:n}}class va{templateOperations=new ya;store;privateConfigs;docker;requireInstanceValue;requireRuntimeValue;runInstanceOperationValue;isImageReferencedValue;constructor(e,t,n,i,r,s,o=()=>!1){this.store=e,this.privateConfigs=t,this.docker=n,this.requireInstanceValue=i,this.requireRuntimeValue=r,this.runInstanceOperationValue=s,this.isImageReferencedValue=o}list(){return this.store.list()}require(e){const t=this.store.get(e);if(!t)throw Object.assign(new Error(`Environment template ${e} was not found.`),{statusCode:404,code:"ENVIRONMENT_TEMPLATE_NOT_FOUND"});return t}runTemplateOperation(e,t){return this.templateOperations.run(e,async()=>t())}async create(e,t){const n=ba.parse(t),i=this.requireInstanceValue(e),r=this.requireRuntimeValue(i.runtimeId);if("docker"!==r.type)throw Object.assign(new Error(`Runtime ${r.name} does not support environment templates.`),{statusCode:409,code:"ENVIRONMENT_TEMPLATE_RUNTIME_UNSUPPORTED"});if(!i.runtime.containerName)throw Object.assign(new Error(`Instance ${i.id} does not have a Docker container.`),{statusCode:409,code:"ENVIRONMENT_TEMPLATE_CONTAINER_NOT_FOUND"});const s=K(),o=ho("envtpl"),a=`task-handoff/environment-template:${o.toLowerCase().replace(/[^a-z0-9_.-]/g,"-")}`;return this.store.put(Cn.parse({id:o,name:n.name,sourceInstanceId:i.id,nodeId:i.nodeId,internalTag:a,status:"creating",createdAt:s,updatedAt:s})),this.runInstanceOperationValue(i.id,async()=>{let e,t=!1;try{const n=this.requireInstanceValue(i.id);if("docker"!==this.requireRuntimeValue(n.runtimeId).type||!n.runtime.containerName)throw Object.assign(new Error(`Instance ${i.id} is no longer a valid Docker template source.`),{code:"ENVIRONMENT_TEMPLATE_SOURCE_CHANGED"});const r=this.privateConfigs.get(i.id);if(!r)throw Object.assign(new Error(`Instance ${i.id} private configuration is missing.`),{code:"INSTANCE_PRIVATE_CONFIG_MISSING"});const s=[r.instanceCredential,...Object.values(r.environment)];await this.docker.inspectContainerConfigSecurity(n.runtime.containerName,s),e=await this.docker.commitEnvironmentTemplate(n.runtime.containerName,n.runtime.containerId,a),t=!0;const c=await this.docker.inspectEnvironmentTemplateImage(a);return await this.docker.inspectImageConfigSecurity(a,s),this.store.put(Cn.parse({...this.require(o),...c,status:"ready",error:void 0,updatedAt:K()}))}catch(n){return t&&(await this.docker.untagEnvironmentTemplate(a,e).catch(()=>!1),e&&await this.docker.garbageCollectEnvironmentTemplateImage(e).catch(()=>!1)),this.store.put(Cn.parse({...this.require(o),status:"failed",error:wa(n,"ENVIRONMENT_TEMPLATE_CREATE_FAILED","commit"),updatedAt:K()}))}})}async delete(e){return this.runTemplateOperation(e,async()=>{const t=this.require(e);this.store.put(Cn.parse({...t,status:"deleting",error:void 0,updatedAt:K()}));try{const n=t.internalTag?await this.docker.untagEnvironmentTemplate(t.internalTag,t.imageId):void 0,i=t.imageId||n;return i&&!this.isImageReferencedValue(i)&&await this.docker.garbageCollectEnvironmentTemplateImage(i),this.store.delete(e),{deleted:!0,templateId:e}}catch(e){throw this.store.put(Cn.parse({...t,status:"failed",error:wa(e,"ENVIRONMENT_TEMPLATE_DELETE_FAILED","delete"),updatedAt:K()})),e}})}async releaseUnusedImage(e){return!this.store.list().some(t=>t.imageId===e)&&!this.isImageReferencedValue(e)&&this.docker.garbageCollectEnvironmentTemplateImage(e)}}const Ea=new Set(["DELETE","GET","HEAD","PATCH","POST","PUT","OPTIONS"]);function Na(e){return"string"==typeof e&&Ea.has(e.toUpperCase())?e.toUpperCase():"GET"}const Sa=new Set(["content-encoding","content-length","transfer-encoding"]),za=67108864;function Ta(e){return Object.fromEntries([...e.entries()].filter(([e])=>!Sa.has(e.toLowerCase())))}function _a(e){return e.bodyBase64?Buffer.from(e.bodyBase64,"base64"):e.body}function Ca(){const e=Number(process.env.TASK_HANDOFF_INSTANCE_PROXY_MAX_RESPONSE_BYTES);return Number.isSafeInteger(e)&&e>0?e:67108864}const ka="x-task-handoff-trace-id";function Oa(e){return e.startsWith("/")?e:`/${e}`}function Ra(e,t){return e.code(502).send({error:{code:"INSTANCE_PROXY_RESPONSE_TOO_LARGE",message:`Instance response exceeds ${t} bytes.`}})}async function xa(e,t,n,i){try{return await e(t,n)}catch(e){if(n.signal?.aborted)throw e;throw i.diagnostic({instanceId:i.instanceId,action:"proxy.upstream.failed",method:i.method,path:i.path,error:e instanceof Error?e.message:String(e)},"node instance proxy upstream unavailable"),Object.assign(new Error(`Instance ${i.instanceId} web endpoint is not reachable.`),{statusCode:502,code:"INSTANCE_PROXY_UPSTREAM_UNREACHABLE",retryable:!0,cause:e})}}function Da(e,t){return Object.assign(new Error(`Instance ${e.id} has an invalid node-owned web endpoint: ${t}`),{statusCode:409,code:"NODE_INSTANCE_WEB_ENDPOINT_INVALID"})}function Pa(e,t){const n=t||("local"===e.runtime?.kind&&e.runtime.port?`http://127.0.0.1:${e.runtime.port}`:void 0);if(!n){const t=new Error(`Instance ${e.id} does not have a web endpoint.`);throw Object.assign(t,{statusCode:409,code:"NODE_INSTANCE_WEB_ENDPOINT_MISSING"}),t}let i;try{i=new URL(n)}catch{throw Da(e,"endpoint is not a URL")}if("http:"!==i.protocol||"127.0.0.1"!==i.hostname||!i.port||i.username||i.password||"/"!==i.pathname&&""!==i.pathname||i.search||i.hash)throw Da(e,"endpoint must be an origin-only http://127.0.0.1:<port> URL");return i.origin}const Ma=d.z.object({version:d.z.literal(1),externalListener:Ki}).strict();function La(e){return"all-ipv4"===e?"0.0.0.0":"127.0.0.1"}function ja(e){if(!e||"object"!=typeof e||Array.isArray(e))return e;const t=e,n=t.externalListener&&"object"==typeof t.externalListener&&!Array.isArray(t.externalListener)?t.externalListener:{},i=Object.keys(t).filter(e=>"version"!==e&&"externalListener"!==e),r=Object.keys(n).filter(e=>"bindScope"!==e&&"port"!==e);return(i.length||r.length)&&console.warn(JSON.stringify({message:"unknown stored node agent runtime setting fields were ignored",filePath:"runtime-settings.json",fields:[...i,...r.map(e=>`externalListener.${e}`)]})),{version:t.version,externalListener:{bindScope:n.bindScope,port:n.port}}}async function $a(e){const t=La(e.bindScope);return!await new Promise(t=>{const n=g.createConnection({host:"127.0.0.1",port:e.port}),i=e=>{n.removeAllListeners(),n.destroy(),t(e)};n.once("connect",()=>i(!0)),n.once("error",()=>i(!1)),n.setTimeout(250,()=>i(!1))})&&new Promise(n=>{const i=g.createServer();i.once("error",()=>n(!1)),i.listen({host:t,port:e.port,exclusive:!0},()=>i.close(()=>n(!0)))})}class Fa{app;state;settings;sockets=new Set;config;source;status="error";error;onActiveListener;updateQueue=Promise.resolve();constructor(e){this.app=e.app,this.state=e.state,this.settings=e.settings,this.config=e.config,this.source=e.source,this.onActiveListener=e.onActiveListener,this.app.server.on("connection",e=>{this.sockets.add(e),e.once("close",()=>this.sockets.delete(e))})}current(){return Gi.parse({...this.config,host:La(this.config.bindScope),status:this.status,source:this.source,...this.error?{error:this.error}:{}})}async start(){try{await this.listen(this.config),this.status="listening",this.error=void 0,this.state.setListenerPort(this.config.port)}catch(e){throw this.status="error",this.error=e instanceof Error?e.message:String(e),this.app.log.error({host:La(this.config.bindScope),port:this.config.port,error:this.error},"node agent TCP listener failed to start"),Object.assign(new Error(`Failed to bind node agent TCP listener at ${La(this.config.bindScope)}:${this.config.port}: ${this.error}`),{statusCode:409,code:"NODE_AGENT_LISTENER_BIND_FAILED"})}const e=this.current();return this.onActiveListener?.(e),e}update(e){const t=this.updateQueue.then(()=>this.updateOnce(e));return this.updateQueue=t.then(()=>{},()=>{}),t}async updateOnce(e){const t=Ji.parse(e);if(t.bindScope===this.config.bindScope&&t.port===this.config.port)return this.current();if(t.port!==this.config.port){const e=this.state.runningInstanceCount();if(e>0)throw Object.assign(new Error(`Cannot change the node agent port while ${e} controlled instance(s) are running.`),{statusCode:409,code:"NODE_AGENT_LISTENER_PORT_IN_USE_BY_INSTANCES",blockingInstanceCount:e})}const n=this.snapshot();await this.stop();try{await this.listen(t)}catch(e){throw await this.restore(n),Object.assign(new Error(`Failed to bind node agent TCP listener at ${La(t.bindScope)}:${t.port}: ${e instanceof Error?e.message:String(e)}`),{statusCode:409,code:"NODE_AGENT_LISTENER_BIND_FAILED"})}try{this.settings.put({version:1,externalListener:t})}catch(e){throw await this.stop(),await this.restore(n),Object.assign(new Error(`Failed to persist node agent TCP listener: ${e instanceof Error?e.message:String(e)}`),{statusCode:500,code:"NODE_AGENT_LISTENER_PERSIST_FAILED"})}this.config=t,this.source="persisted",this.status="listening",this.error=void 0,this.state.setListenerPort(t.port);const i=this.current();return this.onActiveListener?.(i),i}async shutdown(){await this.updateQueue,await this.stop()}snapshot(){return{config:this.config,source:this.source,status:this.status,error:this.error}}async restore(e){if(this.config=e.config,this.source=e.source,this.status=e.status,this.error=e.error,"listening"===e.status)try{await this.listen(e.config)}catch(e){this.status="error",this.error=`Failed to restore previous listener: ${e instanceof Error?e.message:String(e)}`,this.app.log.error({error:this.error},"node agent TCP listener rollback failed")}this.state.setListenerPort(e.config.port),"listening"===this.status&&this.onActiveListener?.(this.current())}async listen(e){await new Promise((t,n)=>{const i=e=>{this.app.server.off("listening",r),n(e)},r=()=>{this.app.server.off("error",i),t()};this.app.server.once("error",i),this.app.server.once("listening",r),this.app.server.listen({host:La(e.bindScope),port:e.port})})}async stop(){this.app.server.listening&&await new Promise((e,t)=>{this.app.server.close(n=>n?t(n):e());for(const e of this.sockets)e.destroy()})}}const Ua="TASK_HANDOFF_NODE_AGENT_V1",Va="/api/node-tunnel";function Ha(e=""){return u.createHash("sha256").update(e).digest("hex")}function qa(e,t){return u.createHmac("sha256",e).update(function(e){return[Ua,e.keyId,e.method.toUpperCase(),e.pathWithQuery,e.timestamp,e.nonce,e.bodySha256].join("\n")}(t)).digest("hex")}function Ba(e){const t=e.timestamp||(new Date).toISOString(),n=e.nonce||u.randomBytes(18).toString("base64url"),i=Ha(e.body||""),r=qa(e.secret,{keyId:e.keyId,method:e.method,pathWithQuery:e.pathWithQuery,timestamp:t,nonce:n,bodySha256:i});return{"x-taskhandoff-node-id":e.nodeId,"x-taskhandoff-key-id":e.keyId,"x-taskhandoff-timestamp":t,"x-taskhandoff-nonce":n,"x-taskhandoff-body-sha256":i,"x-taskhandoff-signature":r}}class Ka{usedNonces=new Map;identity;nodeId;overrideSecret;overrideKeyId;nowMs;constructor(e,t,n,i,r=Date.now){this.identity=e,this.nodeId=t,this.overrideSecret=n,this.overrideKeyId=i,this.nowMs=r}hasRemoteSecrets(){return this.identity.remoteSecrets(this.overrideSecret,this.overrideKeyId).length>0}verify(e){const t=function(e){const t=new Map;for(const[n,i]of Object.entries(e)){const e=Array.isArray(i)?i.join(","):"string"==typeof i?i:void 0===i?"":String(i);t.set(n.toLowerCase(),e)}return{nodeId:t.get("x-taskhandoff-node-id")||"",keyId:t.get("x-taskhandoff-key-id")||"",timestamp:t.get("x-taskhandoff-timestamp")||"",nonce:t.get("x-taskhandoff-nonce")||"",bodySha256:t.get("x-taskhandoff-body-sha256")||"",signature:t.get("x-taskhandoff-signature")||""}}(e.headers);if(!t.nodeId&&!t.signature)return!1;const n="DELETE"===e.method&&"/api/node-agent/pairing/current"===e.url.split("?")[0],i=this.identity.remoteSecrets(this.overrideSecret,this.overrideKeyId,n);if(!i.length)return!1;if(t.nodeId!==this.nodeId)throw Object.assign(new Error("Invalid node agent HMAC node id."),{statusCode:401,code:"NODE_AGENT_HMAC_NODE_MISMATCH"});if(!t.keyId)throw Object.assign(new Error("Node agent HMAC key id is missing."),{statusCode:401,code:"NODE_AGENT_HMAC_KEY_MISSING"});const r=i.filter(e=>t.keyId===e.keyId);if(!r.length)throw Object.assign(new Error("Invalid node agent HMAC key id."),{statusCode:401,code:"NODE_AGENT_HMAC_KEY_INVALID"});const 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=Ha(null==(c=e.body)?"":"string"==typeof c||Buffer.isBuffer(c)?c:JSON.stringify(c));var c;if(t.bodySha256!==a)throw Object.assign(new Error("Node agent HMAC body hash mismatch."),{statusCode:401,code:"NODE_AGENT_HMAC_BODY_HASH_INVALID"});if(!r.some(n=>function(e,t){const n=Buffer.from(e,"hex"),i=Buffer.from(t,"hex");return n.length===i.length&&u.timingSafeEqual(n,i)}(t.signature,qa(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 Ga=d.z.string().trim().min(1).max(160),Ja=d.z.string().datetime(),Wa=d.z.string().min(1).max(4096),Ya=d.z.string().trim().url().max(2048),Xa=d.z.object({id:Ga,keyId:Ga,name:d.z.string().trim().min(1).max(160).optional(),secret:Wa,pairedAt:Ja,revokedAt:Ja.optional(),updatedAt:Ja}).strip(),Qa=d.z.object({id:Ga,pairingKeyId:Ga,name:d.z.string().trim().min(1).max(160).optional(),url:Ya,enabled:d.z.boolean().default(!0),createdAt:Ja,updatedAt:Ja}).strip(),Za=d.z.object({controlPlaneName:d.z.string().trim().min(1).max(160).optional(),controlPlaneUrl:d.z.string().trim().max(2048).optional(),expiresInMs:d.z.number().int().positive().max(36e5).optional()}).strict(),ec=d.z.object({joinToken:d.z.string().trim().min(1).max(4096),controlPlaneId:d.z.string().trim().min(1).max(160).optional(),controlPlaneName:d.z.string().trim().min(1).max(160).optional()}).strict(),tc=d.z.object({controlPlaneUrl:d.z.string().trim().url().max(2048),joinToken:d.z.string().trim().min(1).max(4096),controlPlaneName:d.z.string().trim().min(1).max(160).optional(),activate:d.z.boolean().optional()}).strict(),nc=new Set(["nodeId","createdAt","updatedAt","pairingInvites","controlPlanePairings","controlPlaneConnections","remoteControlPlanes"]),ic=new Set(["id","keyId","name","secret","pairedAt","revokedAt","updatedAt"]),rc=new Set(["id","pairingKeyId","name","url","enabled","createdAt","updatedAt"]),sc=new Set(["id","keyId","name","url","secret","pairedAt","updatedAt","active"]);function oc(e,t){console.warn(JSON.stringify({message:e,...t}))}function ac(e,t){return Object.assign(new Error(e,void 0===t?void 0:{cause:t}),{code:"NODE_AGENT_IDENTITY_INVALID"})}function cc(e,t){return Object.keys(e).filter(e=>!t.has(e))}function dc(e,t,n){const i=Ja.safeParse(e);return i.success?i.data:(n("invalid node agent identity timestamp was replaced",{field:t}),K())}function lc(e,t){if(!e||"object"!=typeof e||Array.isArray(e))throw ac("Node agent identity must be a JSON object.");const n=e,i=Ga.safeParse(n.nodeId);if(!i.success)throw ac("Node agent identity has an invalid nodeId.",i.error);const r=i.data,s=cc(n,nc);s.length&&t("unknown node agent identity fields were ignored",{fields:s}),Array.isArray(n.pairingInvites)&&n.pairingInvites.length&&t("persisted node agent pairing invites were discarded",{count:n.pairingInvites.length});const o=Array.isArray(n.remoteControlPlanes)?n.remoteControlPlanes.flatMap(e=>{if(!e||"object"!=typeof e||Array.isArray(e))return[];const n=e,i=cc(n,sc);i.length&&t("unknown legacy node agent remote control-plane fields were ignored",{fields:i});const r=Xa.safeParse(n);if(!r.success)return t("invalid legacy node agent control-plane pairing was ignored",{issues:r.error.issues}),[];const s=n.url?Qa.safeParse({id:`connection_${r.data.keyId}`,pairingKeyId:r.data.keyId,name:n.name,url:n.url,enabled:!1!==n.active,createdAt:r.data.pairedAt,updatedAt:r.data.updatedAt}):void 0;return[{pairing:r.data,...s?.success?{connection:s.data}:{}}]}):[],a=(e,n,i,r)=>Array.isArray(e)?e.flatMap(e=>{if(!e||"object"!=typeof e||Array.isArray(e))return t(`invalid node agent ${r} was ignored`,{}),[];const s=cc(e,n);s.length&&t(`unknown node agent ${r} fields were ignored`,{fields:s});const o=i.safeParse(e);return o.success?[o.data]:(t(`invalid node agent ${r} was ignored`,{issues:o.error.issues}),[])}):[];return{nodeId:r,createdAt:dc(n.createdAt,"createdAt",t),updatedAt:dc(n.updatedAt,"updatedAt",t),controlPlanePairings:n.controlPlanePairings?a(n.controlPlanePairings,ic,Xa,"control-plane pairing"):o.map(e=>e.pairing),controlPlaneConnections:n.controlPlaneConnections?a(n.controlPlaneConnections,rc,Qa,"control-plane connection"):o.flatMap(e=>e.connection?[e.connection]:[])}}class uc{paths;logger;constructor(e,t={}){this.paths=e,this.logger=t.logger||oc}read(){let e,t;try{e=i.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{t=JSON.parse(e)}catch(e){throw ac(`Node agent identity contains invalid JSON: ${this.paths.identityPath}`,e)}return lc(t,this.logger)}init(){const e=this.read();if(!e)return;const t=JSON.parse(i.readFileSync(this.paths.identityPath,"utf8"));("pairingInvites"in t||"remoteControlPlanes"in t)&&this.write(e)}write(e){i.mkdirSync(r.dirname(this.paths.identityPath),{recursive:!0});const t=lc({...e,updatedAt:K()},this.logger);b.sync(this.paths.identityPath,`${JSON.stringify(t,null,2)}\n`,{encoding:"utf8",mode:384})}}class mc{values=new Map;put(e,t,n=Date.now()){this.prune(n),this.values.set(e,t)}take(e,t=Date.now()){this.prune(t);const n=this.values.get(e);return n&&this.values.delete(e),n}peek(e,t=Date.now()){return this.prune(t),this.values.get(e)}delete(e,t=Date.now()){this.prune(t);const n=this.values.get(e);return n&&this.values.delete(e),n}list(e=Date.now()){return this.prune(e),[...this.values.values()]}prune(e=Date.now()){for(const[t,n]of this.values)Date.parse(n.expiresAt)<=e&&this.values.delete(t)}}class pc{store;pairingInvites=new mc;controlPlaneConnectionOperations=new Map;constructor(e){this.store=new uc(e),this.store.init()}async runControlPlaneConnectionOperation(e,t){const n=e.replace(/\/$/,""),i=this.controlPlaneConnectionOperations.get(n)||Promise.resolve();let r;const s=new Promise(e=>{r=e});this.controlPlaneConnectionOperations.set(n,s),await i;try{return await t()}finally{r(),this.controlPlaneConnectionOperations.get(n)===s&&this.controlPlaneConnectionOperations.delete(n)}}resolveNodeId(e){if(e?.trim())return this.writeNodeId(e.trim()),e.trim();const t=this.store.read();if(t?.nodeId)return t.nodeId;const n=ho("node");return this.writeNodeId(n),n}createPairingInvite(e){const t=K(),n=new Date(Date.now()+(e.expiresInMs||6e5)).toISOString(),i=go(),r={tokenHash:Ha(i),createdAt:t,expiresAt:n,...e.controlPlaneName?{controlPlaneName:e.controlPlaneName}:{}};return this.pairingInvites.put(r.tokenHash,r),{...r,token:i}}completePairingInvite(e){const t=this.store.read()||this.newIdentity(),n=Ha(e.joinToken),i=this.pairingInvites.take(n);if(!i){const e=new Error("Node agent pairing invite is invalid or expired.");throw Object.assign(e,{statusCode:401,code:"NODE_AGENT_PAIRING_INVITE_INVALID"}),e}const r=K(),s={id:e.controlPlaneId||ho("cp"),keyId:ho("key"),...e.controlPlaneName||i.controlPlaneName?{name:e.controlPlaneName||i.controlPlaneName}:{},secret:go(),pairedAt:r,updatedAt:r};return this.store.write({...t,controlPlanePairings:[...(t.controlPlanePairings||[]).filter(e=>e.id!==s.id),s]}),s}stageControlPlaneConnection(e){const{pairing:t,connection:n}=this.createControlPlaneConnection(e),i=this.store.read()||this.newIdentity(),r=n.url.replace(/\/$/,""),s=(i.controlPlaneConnections||[]).filter(e=>e.id===n.id||e.url.replace(/\/$/,"")===r);return this.store.write({...i,controlPlanePairings:[...(i.controlPlanePairings||[]).filter(e=>e.keyId!==t.keyId),t],controlPlaneConnections:[...(i.controlPlaneConnections||[]).filter(e=>e.id!==n.id&&e.url.replace(/\/$/,"")!==r),n]}),{pairing:t,connection:n,replacedConnections:s}}commitControlPlaneConnection(e,t={}){const n=this.store.read()||this.newIdentity(),i={...e.pairing,...t.name?{name:t.name}:{}},r={...e.connection,...t.name?{name:t.name}:{}},s=new Set((n.controlPlaneConnections||[]).map(e=>e.pairingKeyId)),o=new Set(e.replacedConnections.map(e=>e.pairingKeyId));return this.store.write({...n,controlPlanePairings:[...(n.controlPlanePairings||[]).filter(e=>e.keyId!==i.keyId&&(!o.has(e.keyId)||s.has(e.keyId))),i],controlPlaneConnections:[...(n.controlPlaneConnections||[]).filter(e=>e.id!==r.id),r]}),{pairing:i,connection:r}}rollbackControlPlaneConnection(e){const t=this.store.read();if(!t)return;const n=new Set(e.replacedConnections.map(e=>e.id));this.store.write({...t,controlPlanePairings:(t.controlPlanePairings||[]).filter(t=>t.keyId!==e.pairing.keyId),controlPlaneConnections:[...(t.controlPlaneConnections||[]).filter(t=>t.id!==e.connection.id&&!n.has(t.id)),...e.replacedConnections]})}createControlPlaneConnection(e){const t=K(),n={id:ho("cp"),keyId:ho("key"),...e.name?{name:e.name}:{},secret:go(),pairedAt:t,updatedAt:t};return{pairing:n,connection:{id:ho("connection"),pairingKeyId:n.keyId,...e.name?{name:e.name}:{},url:e.url,enabled:!1!==e.enabled,createdAt:t,updatedAt:t}}}resolvedControlPlaneAccess(){const e=this.store.read(),t=new Map((e?.controlPlanePairings||[]).filter(e=>!e.revokedAt).map(e=>[e.keyId,e])),n=e?.controlPlaneConnections||[];return{hasPersistedAccess:n.length>0||t.size>0,connections:n.map(e=>({connection:e,pairing:t.get(e.pairingKeyId)}))}}listControlPlanePairings(e=""){return(this.store.read()?.controlPlanePairings||[]).filter(e=>!e.revokedAt).map(({secret:t,...n})=>({...n,current:Boolean(e&&n.keyId===e)})).sort((e,t)=>Number(t.current)-Number(e.current)||t.updatedAt.localeCompare(e.updatedAt))}listControlPlaneConnections(){return[...this.store.read()?.controlPlaneConnections||[]].sort((e,t)=>t.updatedAt.localeCompare(e.updatedAt))}deleteControlPlanePairing(e,t=""){if(t&&e===t){const e=new Error("Cannot delete the pairing used to authenticate the current request.");throw Object.assign(e,{statusCode:409,code:"NODE_AGENT_PAIRING_CURRENT_REQUEST"}),e}const n=this.store.read();if(!n)return!1;if((n.controlPlaneConnections||[]).some(t=>t.pairingKeyId===e))throw Object.assign(new Error("Cannot delete a pairing used by a configured control-plane connection."),{statusCode:409,code:"NODE_AGENT_PAIRING_IN_USE"});const i=(n.controlPlanePairings||[]).filter(t=>t.keyId!==e);return i.length!==(n.controlPlanePairings||[]).length&&(this.store.write({...n,controlPlanePairings:i}),!0)}revokeCurrentControlPlanePairing(e){if(!e)throw Object.assign(new Error("Current paired-HMAC authentication is required to revoke this pairing."),{statusCode:403,code:"NODE_AGENT_PAIRING_SELF_REVOKE_HMAC_REQUIRED"});const t=this.store.read(),n=t?.controlPlanePairings?.find(t=>t.keyId===e);if(!t||!n)throw Object.assign(new Error("The current control-plane pairing no longer exists."),{statusCode:404,code:"NODE_AGENT_PAIRING_NOT_FOUND"});if(n.revokedAt)return{keyId:e,revoked:!0,revokedAt:n.revokedAt};if((t.controlPlaneConnections||[]).some(t=>t.pairingKeyId===e))throw Object.assign(new Error("Cannot revoke a pairing used by a configured control-plane connection."),{statusCode:409,code:"NODE_AGENT_PAIRING_IN_USE"});const i=K();return this.store.write({...t,controlPlanePairings:t.controlPlanePairings.map(t=>t.keyId===e?{...t,revokedAt:i,updatedAt:i}:t)}),{keyId:e,revoked:!0,revokedAt:i}}deleteControlPlaneConnection(e){const t=this.store.read();if(!t)return!1;const n=(t.controlPlaneConnections||[]).filter(t=>t.id!==e);return n.length!==(t.controlPlaneConnections||[]).length&&(this.store.write({...t,controlPlaneConnections:n}),!0)}remoteSecrets(e,t,n=!1){return[...(this.store.read()?.controlPlanePairings||[]).filter(e=>n||!e.revokedAt).map(e=>({keyId:e.keyId,secret:e.secret})),...e&&t?[{keyId:t,secret:e}]:[]]}isRevokedPairing(e){return Boolean(this.store.read()?.controlPlanePairings?.some(t=>t.keyId===e&&t.revokedAt))}reverseTunnelSecret(e,t,n){if(t&&n)return{keyId:n,secret:t};const i=this.store.read(),r=(i?.controlPlanePairings||[]).filter(e=>!e.revokedAt);if(!r.length)return;if(e){const t=e.replace(/\/$/,""),n=(i?.controlPlaneConnections||[]).find(e=>e.url.replace(/\/$/,"")===t),s=n&&r.find(e=>e.keyId===n.pairingKeyId);if(s)return{keyId:s.keyId,secret:s.secret}}const s=[...r].sort((e,t)=>t.updatedAt.localeCompare(e.updatedAt))[0];return s?{keyId:s.keyId,secret:s.secret}:void 0}newIdentity(){return{nodeId:this.resolveNodeId(),createdAt:K(),updatedAt:K(),controlPlanePairings:[],controlPlaneConnections:[]}}writeNodeId(e){const t=this.store.read();this.store.write({...t||{createdAt:K()},nodeId:e,updatedAt:K(),controlPlanePairings:t?.controlPlanePairings||[],controlPlaneConnections:t?.controlPlaneConnections||[]})}}const hc=d.z.string().trim().min(1).max(160);const gc=ei.strict();function fc(e){const t=e.filter(e=>!["created","stopped","failed"].includes(e.status)),n=new Set(t.map(e=>e.id)),i=t.filter(e=>e.apps.runningCount>0||e.aiSessions.runningCount>0);return{runningInstanceCount:t.length,stoppedInstanceCount:e.length-t.length,activeInstanceCount:i.length,restartInstanceCount:t.length,runningInstanceIds:t.map(e=>e.id).sort(),stoppedInstanceIds:e.filter(e=>!n.has(e.id)).map(e=>e.id).sort(),activeInstanceIds:i.map(e=>e.id).sort()}}class yc{preflights=new Map;options;applying=!1;constructor(e){this.options=e}async check(e){const t=Xn.parse(e),n=fc(this.options.listInstances()),i=await To(this.options.runCommand,this.options.moduleDir),r=this.options.currentRuntimeVersion(),s=this.options.managedUpdateSupport?.(i)||{supported:!0};if(!s.supported)return Qn.parse({source:"npm",channel:t.channel,currentVersion:i.currentVersion||r,availableVersion:i.currentVersion||r||"unavailable",impact:n,updateAvailable:!1,supported:!1,reason:s.reason||"Managed updates are unavailable on this node.",checkedAt:(new Date).toISOString()});const o="@task-handoff/server"===i.packageName?[...new Set([...i.relatedCurrentVersions,r])]:i.relatedCurrentVersions,a=await async function(e){const t=e.packageName||"@task-handoff/node-agent",n=await async function(e,t,n){const i=function(e){return"stable"===e?"latest":e}(n),r=await e(So(),["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,t,e.channel);if(!n)return function(e){return Qn.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:K()})}({channel:e.channel,currentVersion:e.currentVersion,impact:e.impact});const i=No(e.currentVersion,n)||(e.relatedCurrentVersions||[]).some(e=>No(e,n)),r=i?await async function(e,t,n){const i=await e(So(),["view",`${t}@${n}`,"dist.integrity","--json"]),r=JSON.parse(i.stdout);if("string"!=typeof r||!/^sha(?:256|384|512)-[A-Za-z0-9+/=]+$/.test(r))throw Object.assign(new Error(`npm did not return immutable integrity metadata for ${t}@${n}.`),{statusCode:502,code:"NODE_UPDATE_PREFLIGHT_FAILED",retryable:!0});return r}(e.runCommand,t,n):void 0;return Qn.parse({source:"npm",channel:e.channel,currentVersion:e.currentVersion,availableVersion:n,...r?{artifactRef:`npm:${t}@${n}#${r}`}:{},runtimeArtifacts:e.runtimeArtifacts||[],impact:e.impact||{runningInstanceCount:0,stoppedInstanceCount:0,activeInstanceCount:0,restartInstanceCount:0,runningInstanceIds:[],stoppedInstanceIds:[],activeInstanceIds:[]},updateAvailable:i,checkedAt:K()})}({channel:t.channel,currentVersion:i.currentVersion||r,runCommand:this.options.runCommand,packageName:i.packageName,relatedCurrentVersions:o,impact:n});if(!a.updateAvailable)return a;const c={...a,runtimeArtifacts:await this.options.resolveRuntimeArtifacts(a.availableVersion),preflightToken:go()};return this.preflights.set(c.preflightToken,{result:c,expiresAt:Date.now()+6e5}),c}async apply(e){const t=gc.parse(e),n=this.preflights.get(t.preflightToken);(!n||n.expiresAt<=Date.now())&&await this.consumePreflight(t),this.applying&&this.throwAlreadyRunning(),this.applying=!0;try{const{check:e,selection:n}=await this.consumePreflight(t);if(this.options.jobs.list().some(e=>!["succeeded","degraded","failed"].includes(e.status))&&this.throwAlreadyRunning(),!e.supported)throw Object.assign(new Error(e.reason||"The requested update is not supported."),{statusCode:400,code:"UPDATE_UNSUPPORTED"});if(!e.updateAvailable)throw Object.assign(new Error(e.reason||"No update is available for the selected channel."),{statusCode:409,code:"UPDATE_NOT_AVAILABLE"});const s=this.options.jobs.create(this.options.nodeId,e),{worker:o,packaged:a,expectedWorker:c}=function(e,t=i.existsSync){const n=[r.resolve(e,"..","bin","task-handoff-node-update-worker"),r.resolve(e,"..","..","bin","task-handoff-node-update-worker")],s=n.find(t),o=r.resolve(e,"..","..","..","..","scripts","node-update-worker.cts");return s?{worker:s,packaged:!0,expectedWorker:n[0]}:t(o)?{worker:o,packaged:!1,expectedWorker:n[0]}:{worker:void 0,packaged:!1,expectedWorker:n[0]}}(this.options.moduleDir);if(!o)throw this.options.jobs.patch(s.id,{status:"failed",rollout:{...s.rollout,phase:"failed"},error:{code:"NODE_UPDATE_FAILED",message:`Update worker was not found: ${c}`,retryable:!1},completedAt:(new Date).toISOString()}),Object.assign(new Error(`Node agent update worker was not found: ${c}`),{statusCode:500,code:"UPDATE_WORKER_NOT_FOUND"});const d=process.env.TASK_HANDOFF_CONTROL_PLANE_HEALTH_URL?.trim();try{await this.options.runCommand("systemd-run",["--unit",`task-handoff-update-${s.id}`,"--collect","--property=Type=exec",...a?[o]:[process.execPath,o],"--job-file",this.options.jobs.records.filePath(s.id),"--target-version",s.toVersion,"--npm-command",So(),"--install-prefix",n.installPrefix,...process.env.TASK_HANDOFF_NODE_AGENT_IPC_PATH?.trim()?["--node-agent-ipc-path",process.env.TASK_HANDOFF_NODE_AGENT_IPC_PATH.trim()]:[],...d?["--control-plane-health-url",d]:[]])}catch(e){const t=e instanceof Error?e.message:String(e);throw this.options.jobs.patch(s.id,{status:"failed",rollout:{...s.rollout,phase:"failed"},error:{code:"NODE_UPDATE_FAILED",message:`Failed to launch the node update worker: ${t}`,retryable:!0},completedAt:(new Date).toISOString()}),Object.assign(new Error(`Failed to launch the node update worker: ${t}`),{statusCode:500,code:"NODE_UPDATE_WORKER_LAUNCH_FAILED",cause:e})}return s}finally{this.applying=!1}}async consumePreflight(e){const t=this.preflights.get(e.preflightToken);if(this.preflights.delete(e.preflightToken),!t||t.expiresAt<=Date.now())throw Object.assign(new Error("The update preflight is missing or expired. Check for updates again."),{statusCode:409,code:"UPDATE_PREFLIGHT_EXPIRED"});const n=t.result,i=await To(this.options.runCommand,this.options.moduleDir);n.channel===e.channel&&n.availableVersion===e.targetVersion&&n.currentVersion===(i.currentVersion||this.options.currentRuntimeVersion())&&!0===n.artifactRef?.startsWith(`npm:${i.packageName}@`)&&JSON.stringify(n.impact)===JSON.stringify(fc(this.options.listInstances()))||this.throwStale();const r=await this.options.resolveRuntimeArtifacts(n.availableVersion);return JSON.stringify(n.runtimeArtifacts)!==JSON.stringify(r)&&this.throwStale(),{check:n,selection:i}}throwStale(){throw Object.assign(new Error("The update target or affected instances changed after preflight. Check for updates again."),{statusCode:409,code:"UPDATE_PREFLIGHT_STALE"})}throwAlreadyRunning(){throw Object.assign(new Error("Another server update is already running on this node."),{statusCode:409,code:"SERVER_UPDATE_ALREADY_RUNNING"})}}const Ic=new Set(["provisioning","starting","registering","registered","running"]);function Ac(e){return Ic.has(e.status)&&!to(e)}function bc(e){return nr.parse({...e,health:"unknown",connectionStatus:"offline",agentStatus:"offline",targetStatus:"unknown",uiAccessStatus:"unknown",target:{...e.target,status:"unknown"},updatedAt:K()})}class wc{options;restoredInstances=new Set;restoreErrors=new Map;unexpectedExitRetries=new Map;suppressedInstances=new Set;pendingUnexpectedExits=new Map;activeRestores=new Map;timer;activeCycle;cycleRequested=!1;cycleRequestDelayMs;started=!1;stopped=!1;constructor(e){this.options=e}markRestored(e){const t=this.options.state.requireInstance(e);return!["failed","stopping","stopped"].includes(t.status)&&!to(t)&&(this.restoredInstances.add(e),this.restoreErrors.delete(e),!0)}allowRecovery(e){this.suppressedInstances.delete(e);const t=this.pendingUnexpectedExits.get(e);void 0!==t&&(this.pendingUnexpectedExits.delete(e),this.applyUnexpectedLocalExit(e,t))}completeSuppressedOperation(e){this.pendingUnexpectedExits.delete(e),this.restoredInstances.delete(e),this.restoreErrors.delete(e),this.unexpectedExitRetries.delete(e)}forgetInstance(e){this.restoredInstances.delete(e),this.restoreErrors.delete(e),this.unexpectedExitRetries.delete(e),this.suppressedInstances.delete(e),this.activeRestores.delete(e),this.pendingUnexpectedExits.delete(e)}async suppressRecovery(e){this.suppressedInstances.add(e),await(this.activeRestores.get(e)?.catch(()=>{}))}handleUnexpectedLocalExit(e,t){this.stopped||(this.suppressedInstances.has(e)?this.pendingUnexpectedExits.set(e,t):this.applyUnexpectedLocalExit(e,t))}applyUnexpectedLocalExit(e,t){const n=this.options.state.requireInstance(e);if("local"!==this.options.state.requireRuntime(n.runtimeId).type)return;this.restoredInstances.delete(e);const i=this.options.nowMs?.()??Date.now(),r=this.unexpectedExitRetries.get(e),s=this.options.crashStableWindowMs??3e4,o=r&&i-r.lastExitAt<s?r.attempt+1:1;this.unexpectedExitRetries.set(e,{attempt:o,lastExitAt:i});const a=this.options.retryBaseDelayMs??1e3,c=1===o?0:Math.min(this.options.retryMaxDelayMs??3e4,a*2**Math.min(o-2,10)),d=t instanceof Error?t.message:String(t);this.restoreErrors.set(e,{message:d,attempt:o,nextAttemptAt:i+c}),this.options.state.applyInstanceLifecycle(e,{type:"runtime-exited",error:t}),this.requestCycle(c)}async restoreManagedInstances(){if(this.stopped)return;const{state:e}=this.options;for(const t of e.listInstances()){if(this.stopped)return;"docker"===e.requireRuntime(t.runtimeId).type&&["provisioning","starting"].includes(t.status)&&"ready"!==t.imageProvisioning?.phase&&this.options.provisionImage(t)}const t=e.listInstances().filter(t=>{if(this.restoredInstances.has(t.id))return!1;if(this.suppressedInstances.has(t.id))return!1;const n=e.requireRuntime(t.runtimeId);if("local"===n.type){const e=this.restoreErrors.get(t.id);return(Ic.has(t.status)||"failed"===t.status)&&(!e||e.nextAttemptAt<=(this.options.nowMs?.()??Date.now()))}return"docker"===n.type&&Ac(t)});await Promise.all(t.map(async t=>{if(this.stopped)return;const n=async()=>{if(this.stopped)return;const n=e.listInstances().find(e=>e.id===t.id);if(!n)return;if(!this.isRestoreCandidate(n))return;const i=this.restoreErrors.get(n.id);try{const t=this.options.restoreInstance(n.id);this.activeRestores.set(n.id,t);try{await t}finally{this.activeRestores.get(n.id)===t&&this.activeRestores.delete(n.id)}if(this.stopped||this.suppressedInstances.has(n.id))return;if(await this.options.autoImport(e.requireInstance(n.id)),this.stopped||this.suppressedInstances.has(n.id))return;if(this.restoreErrors.get(n.id)!==i)return;if(!this.markRestored(n.id))throw new Error(`Restored instance ${n.id} did not reach a recoverable running state.`)}catch(t){if(this.stopped||this.suppressedInstances.has(n.id))return;"local"===e.requireRuntime(n.runtimeId).type&&e.applyInstanceLifecycle(n.id,{type:"start-failed",error:t});const i=t instanceof Error?t.message:String(t),r=this.restoreErrors.get(n.id),s=(r?.attempt??0)+1,o=this.options.retryBaseDelayMs??1e3,a=Math.min(this.options.retryMaxDelayMs??3e4,o*2**Math.min(s-1,10)),c=(this.options.nowMs?.()??Date.now())+a;this.restoreErrors.set(n.id,{message:i,attempt:s,nextAttemptAt:c}),r?.message===i&&r.attempt===s||this.options.warn({instanceId:n.id,action:"restore",runtimeId:n.runtimeId,error:i,attempt:s,nextAttemptAt:new Date(c).toISOString()},"node instance restore failed; recovery will retry")}};await(this.options.runInstanceOperation?.(t.id,n)??n())}))}isRestoreCandidate(e){if(this.restoredInstances.has(e.id)||this.suppressedInstances.has(e.id))return!1;const t=this.options.state.requireRuntime(e.runtimeId);if("local"===t.type){const t=this.restoreErrors.get(e.id);return(Ic.has(e.status)||"failed"===e.status)&&(!t||t.nextAttemptAt<=(this.options.nowMs?.()??Date.now()))}return"docker"===t.type&&Ac(e)}async recoverManagedInstances(){if(this.stopped)return;const{state:e,convergence:t}=this.options,n=e.listInstances().filter(e=>this.options.usesManagedArtifact(e)&&!t.isRunning(e.id)&&(this.restoredInstances.has(e.id)||"unknown"!==e.target.status)&&(!e.ready||"matched"!==e.runtimeVersion?.phase)&&!to(e)&&!["created","stopped","failed","provisioning","stopping"].includes(e.status));await Promise.all(n.map(async e=>{if(!this.stopped)try{await t.schedule(e.id)}catch(t){this.options.error({instanceId:e.id,error:t},"runtime convergence recovery failed")}}))}start(){this.started||this.stopped||(this.started=!0,this.runAndContinue())}async stop(){this.stopped=!0,this.timer&&clearTimeout(this.timer),this.timer=void 0;const e=this.options.stopImageProvisioning(),t=this.options.state.listInstances().map(e=>this.options.convergence.cancel(e.id));await Promise.all(t),await this.activeCycle,await e,await this.options.runtimeAdapters.stopAll();for(const e of this.options.state.listInstances())"local"===this.options.state.requireRuntime(e.runtimeId).type&&this.options.state.controlledInstances.put(bc(e))}async runCycle(){await this.restoreManagedInstances(),this.stopped||await this.recoverManagedInstances()}runAndContinue(){if(this.stopped)return;const e=this.runCycle().catch(e=>this.options.error({error:e},"node agent startup recovery cycle failed"));this.activeCycle=e,e.finally(()=>{this.activeCycle===e&&(this.activeCycle=void 0),this.cycleRequested?(this.cycleRequested=!1,this.cycleRequestDelayMs=void 0,this.scheduleNext()):this.scheduleNext()})}scheduleNext(){if(this.stopped)return;const e=this.options.nowMs?.()??Date.now(),t=new Map(this.options.state.listInstances().map(e=>[e.id,e])),n=[...this.restoreErrors.entries()].reduce((e,[n,i])=>{const r=t.get(n);return!r||this.restoredInstances.has(n)||this.suppressedInstances.has(n)||"local"!==this.options.state.requireRuntime(r.runtimeId).type?e:Ic.has(r.status)||"failed"===r.status?Math.min(e,i.nextAttemptAt):e},Number.POSITIVE_INFINITY),i=Math.min(this.options.intervalMs??1e4,Math.max(0,n-e));this.timer=setTimeout(()=>{this.timer=void 0,this.runAndContinue()},i),this.timer.unref?.()}requestCycle(e=0){if(this.started&&!this.stopped){if(this.activeCycle)return this.cycleRequested=!0,void(this.cycleRequestDelayMs=void 0===this.cycleRequestDelayMs?e:Math.min(this.cycleRequestDelayMs,e));this.timer&&clearTimeout(this.timer),this.timer=setTimeout(()=>{this.timer=void 0,this.runAndContinue()},e),this.timer.unref?.()}}}function vc(e){return e.readyState===(e.OPEN??1)}function Ec(e){const t=Buffer.isBuffer(e)?e.toString("utf8"):"string"==typeof e?e:"";if(Buffer.byteLength(t,"utf8")<=123)return t;let n="";for(const e of t){const t=`${n}${e}`;if(Buffer.byteLength(t,"utf8")>123)break;n=t}return n}function Nc(e){if("number"==typeof e&&Number.isInteger(e))return e>=3e3&&e<=4999||e>=1e3&&e<=1014&&1004!==e&&1005!==e&&1006!==e?e:void 0}function Sc(e,t,n){e.close(Nc(t),Ec(n)||void 0)}function zc(e,t,n,i){if(vc(e))for(const e of t.splice(0))if(i(e),!n(e))return}function Tc(e,t){const n=new URL(t.tunnelUrl);n.searchParams.set("nodeId",t.nodeId);const i=t.secret?Ba({nodeId:t.nodeId,keyId:t.keyId,secret:t.secret,method:"GET",pathWithQuery:`${n.pathname}${n.search}`}):{},r=new h(n,{headers:i}),s=new Map,o=new Map,a=new Map;let c;r.on("error",i=>{e.log.warn({nodeId:t.nodeId,tunnelUrl:`${n.origin}${n.pathname}`,error:i instanceof Error?i.message:String(i)},"node agent reverse tunnel connection failed")});const d=e=>{const n=e.startsWith("/")?e:`/${e}`,i="function"==typeof t.port?t.port():t.port,r=new URL(`/api/node-agent${n}`,`http://127.0.0.1:${i}`);return r.protocol="ws:",r},l=(e,n,i,r={})=>{const s=e.startsWith("/")?e:`/${e}`;return{...r,...t.secret&&t.keyId?Ba({nodeId:t.nodeId,keyId:t.keyId,secret:t.secret,method:n,pathWithQuery:`/api/node-agent${s}`,body:i}):t.token?{authorization:`Bearer ${t.token}`}:{}}},u=e=>t.secret?Ba({nodeId:t.nodeId,keyId:t.keyId,secret:t.secret,method:"GET",pathWithQuery:`${e.pathname}${e.search}`}):{},m=(e,t,n)=>{const i=s.get(e);s.delete(e),i?.upstream&&Sc(i.upstream,t,n),i?.tunnel&&Sc(i.tunnel,t,n)},p=(e,t,n=!1)=>new Promise((i,r)=>{e.send(t,{binary:n},e=>e?r(e):i())});r.on("open",()=>{r.send(JSON.stringify({type:"node-agent.identify",nodeId:t.nodeId,serverTime:(new Date).toISOString()})),c=e.nodeAgentEventForwarder?.addOutput(r,{legacyFallbackMs:1e3})}),r.on("close",()=>{for(const e of s.keys())m(e,1001,"Reverse tunnel disconnected.");for(const[e,t]of o)o.delete(e),t.controller.abort(),Sc(t.tunnel,1001,"Reverse tunnel disconnected.");for(const[e,t]of a)a.delete(e),t.abort();c?.(),c=void 0});return r.on("message",i=>{(async i=>{let c;try{c=JSON.parse(String(i))}catch{return void r.send(JSON.stringify({type:"node-agent.error",code:"INVALID_JSON"}))}const g=c&&"object"==typeof c?c:{};if("control-plane.event-subscribe"!==g.type){if("control-plane.http.open"===g.type){const i="string"==typeof g.streamId?g.streamId:"",s="string"==typeof g.route&&g.route.startsWith("/")?g.route:"/health",a=g.init&&"object"==typeof g.init?g.init:{},c=a.headers&&"object"==typeof a.headers?a.headers:{},d=Na(a.method);let m;try{m=tn(a.body)}catch(n){return e.log.warn({nodeId:t.nodeId,messageType:g.type,streamId:i,error:n instanceof Error?n.message:String(n)},"node agent reverse tunnel request body rejected"),void r.send(JSON.stringify({type:"node-agent.error",code:"NODE_TUNNEL_REQUEST_BODY_INVALID",streamId:i}))}const f=new AbortController,y=(e=>{const t=new URL(n);return t.pathname=`${t.pathname.replace(/\/$/,"")}/http-streams/${encodeURIComponent(e)}`,t})(i),I=new h(y,{headers:u(y)});return o.set(i,{tunnel:I,controller:f}),I.on("open",async()=>{try{const e=await fetch((e=>{const n=e.startsWith("/")?e:`/${e}`,i="function"==typeof t.port?t.port():t.port;return new URL(`/api/node-agent${n}`,`http://127.0.0.1:${i}`)})(s),{method:d,headers:l(s,d,m,c),body:Buffer.isBuffer(m)?new Uint8Array(m):m,signal:f.signal});if(await p(I,JSON.stringify({type:"node-agent.http.head",streamId:i,status:e.status,headers:Object.fromEntries(e.headers.entries())})),e.body){const t=e.body.getReader();for(;;){const{done:e,value:n}=await t.read();if(e)break;await p(I,Buffer.from(n),!0)}}await p(I,JSON.stringify({type:"node-agent.http.end",streamId:i})),I.close(1e3,"HTTP stream completed.")}catch(e){I.readyState===h.OPEN&&(await p(I,JSON.stringify({type:"node-agent.http.error",streamId:i,message:e instanceof Error?e.message:String(e)})).catch(()=>{}),I.close(1011,"HTTP stream failed."))}finally{o.delete(i)}}),I.on("close",()=>{f.abort(),o.delete(i)}),void I.on("error",()=>f.abort())}if("control-plane.http.cancel"===g.type){const e="string"==typeof g.streamId?g.streamId:"",t=o.get(e);if(!t)return;return o.delete(e),t.controller.abort(),void Sc(t.tunnel,1e3,"string"==typeof g.reason?g.reason:"HTTP stream canceled.")}if("control-plane.websocket.open"===g.type){const e="string"==typeof g.streamId?g.streamId:"",t="string"==typeof g.route?g.route:"",i=Array.isArray(g.protocols)?g.protocols.filter(e=>"string"==typeof e):void 0;try{const o=l(t,"GET",void 0),a=i?.length?new h(d(t),i,{headers:o}):new h(d(t),{headers:o}),c=(e=>{const t=new URL(n);return t.pathname=`${t.pathname.replace(/\/$/,"")}/streams/${encodeURIComponent(e)}`,t})(e),m=new h(c,{headers:u(c)});s.set(e,{upstream:a,tunnel:m,close:(e=1e3,t="")=>{Sc(a,e,t),Sc(m,e,t)}}),a.on("open",()=>{r.send(JSON.stringify({type:"node-agent.websocket.open",streamId:e,protocol:a.protocol}))}),function(e,t,n={}){const i=n.pendingFrameLimit??256,r=n.maxFrameBytes??8388608,s=n.maxTotalBytes??1073741824,o=n.maxBufferedBytes??16777216;let a=!1,c=vc(t);const d=[],l=[];let u,m=0,p=0,h=0;const g=e=>Buffer.isBuffer(e)||e instanceof ArrayBuffer||ArrayBuffer.isView(e)?e.byteLength:Buffer.byteLength("string"==typeof e?e:String(e),"utf8"),f=(i,o)=>{const a=g(o);return h+=a,n.onFrame?.(i,a),!(a>r||h>s)||(Sc(e,1009,"WebSocket bridge traffic limit exceeded."),Sc(t,1009,"WebSocket bridge traffic limit exceeded."),!1)},y=()=>{u&&(clearTimeout(u),u=void 0)},I=(n,i)=>{const r=i.bytes;if((n.bufferedAmount??0)+r>o)return Sc(e,1013,"WebSocket bridge consumer is too slow."),Sc(t,1013,"WebSocket bridge consumer is too slow."),!1;try{return function(e,t){e.send(t.data,{binary:t.isBinary})}(n,i),!0}catch{return Sc(e,1011,"WebSocket bridge send failed."),Sc(t,1011,"WebSocket bridge send failed."),!1}},A=(n,r,s)=>{if(r.length>=i)return Sc(e,1011,"WebSocket bridge pending frame limit exceeded."),void Sc(t,1011,"WebSocket bridge pending frame limit exceeded.");const a="upstream"===n?m:p;if((("upstream"===n?t:e).bufferedAmount??0)+a+s.bytes>o)return Sc(e,1013,"WebSocket bridge consumer is too slow."),void Sc(t,1013,"WebSocket bridge consumer is too slow.");r.push(s),"upstream"===n?m+=s.bytes:p+=s.bytes};n.upstreamOpenTimeoutMs&&!c&&(u=setTimeout(()=>{c||a||(Sc(e,1011,"Upstream websocket did not open."),Sc(t))},n.upstreamOpenTimeoutMs)),e.on("open",()=>zc(e,l,t=>I(e,t),e=>{p-=e.bytes})),t.on("open",()=>{y(),c=!0,n.onUpstreamOpen?.(),zc(t,d,e=>I(t,e),e=>{m-=e.bytes})}),e.on("message",(e,n=!1)=>{if(!f("client-to-upstream",e))return;const i={data:e,isBinary:Boolean(n),bytes:g(e)};vc(t)?I(t,i):A("upstream",d,i)}),t.on("message",(t,n=!1)=>{if(!f("upstream-to-client",t))return;const i={data:t,isBinary:Boolean(n),bytes:g(t)};vc(e)?I(e,i):A("client",l,i)}),t.on("close",(t,i)=>{y(),n.onUpstreamClose?.(t,i),(c||a||!n.onUpstreamCloseBeforeOpen?.())&&Sc(e,t,i)}),t.on("error",t=>{n.onUpstreamError?.(t),(c||a||!n.onUpstreamErrorBeforeOpen?.(t))&&Sc(e)}),e.on("close",(e,i)=>{y(),a=!0,n.onClientClose?.(e,i),Sc(t,e,i)}),e.on("error",e=>{y(),a=!0,n.onClientError?.(e),Sc(t,1011,"WebSocket bridge client failed.")})}(m,a,{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);const i=Nc(t),o=Ec(n);r.send(JSON.stringify({type:"node-agent.websocket.close",streamId:e,...void 0===i?{}:{code:i},...o?{reason:o}:{}}))},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"===g.type){const e="string"==typeof g.streamId?g.streamId:"";return void m(e,"number"==typeof g.code?g.code:1e3,"string"==typeof g.reason?g.reason:"")}if("control-plane.request.cancel"===g.type){const e="string"==typeof g.requestId?g.requestId:"";return a.get(e)?.abort(),void a.delete(e)}if("control-plane.request"===g.type){const n="string"==typeof g.requestId?g.requestId:"",i=g.init&&"object"==typeof g.init?g.init:{},s="string"==typeof g.route&&g.route.startsWith("/")?g.route:"/health",o=i.headers&&"object"==typeof i.headers?i.headers:{},c=Na(i.method);let d;try{d=tn(i.body)}catch(i){return e.log.warn({nodeId:t.nodeId,messageType:g.type,requestId:n,error:i instanceof Error?i.message:String(i)},"node agent reverse tunnel request body rejected"),void r.send(JSON.stringify({type:"node-agent.response",requestId:n,status:400,error:{code:"NODE_TUNNEL_REQUEST_BODY_INVALID",message:"Reverse tunnel request body does not match the negotiated protocol."}}))}const u=new AbortController;a.set(n,u);try{const t=await e.inject({method:c,url:`/api/node-agent${s}`,headers:l(s,c,d,o),payload:d,signal:u.signal});if(u.signal.aborted)return;r.send(JSON.stringify({type:"node-agent.response",requestId:n,status:t.statusCode,headers:t.headers,body:t.body}))}catch(e){if(u.signal.aborted)return;r.send(JSON.stringify({type:"node-agent.response",requestId:n,status:502,error:{code:"NODE_AGENT_REVERSE_INJECT_FAILED",message:e instanceof Error?e.message:String(e)}}))}finally{a.delete(n)}}}else e.nodeAgentEventForwarder?.setOutputSubscription?.(r,g.aiSessionTransient)})(i).catch(n=>{e.log.warn({nodeId:t.nodeId,error:n instanceof Error?n.message:String(n)},"node agent reverse tunnel message rejected");try{r.send(JSON.stringify({type:"node-agent.error",code:"INVALID_TUNNEL_MESSAGE"}))}catch{}})}),r}function _c(e,t){return Number.isFinite(e)&&Number(e)>0?Number(e):t}function Cc(e){if(!e.length)return;const t=[...e].sort((e,t)=>e-t);return t[Math.ceil(.95*t.length)-1]}function kc(e){return e.unref?.(),e}class Oc{connectTimeoutMs;handshakeTimeoutMs;heartbeatIntervalMs;heartbeatTimeoutMs;heartbeatMissThreshold;stableThresholdMs;now;setTimeoutFn;clearTimeoutFn;ping;onTimeout;onStable;onPhase;connectTimer;handshakeTimer;heartbeatTimer;stableTimer;awaitingPongSince;consecutiveHeartbeatMisses=0;stable=!1;stopped=!1;currentPhase="connecting";lastActivityAt;lastPongAt;pingRttMs;recentPingRttMs=[];constructor(e){this.connectTimeoutMs=_c(e.connectTimeoutMs,1e4),this.handshakeTimeoutMs=_c(e.handshakeTimeoutMs,1e4),this.heartbeatIntervalMs=_c(e.heartbeatIntervalMs,25e3),this.heartbeatTimeoutMs=_c(e.heartbeatTimeoutMs,15e3),this.heartbeatMissThreshold=Math.max(1,Math.floor(_c(e.heartbeatMissThreshold,2))),this.stableThresholdMs=_c(e.stableThresholdMs,6e4),this.now=e.now||Date.now,this.setTimeoutFn=e.setTimeoutFn||setTimeout,this.clearTimeoutFn=e.clearTimeoutFn||clearTimeout,this.ping=e.ping,this.onTimeout=e.onTimeout,this.onStable=e.onStable,this.onPhase=e.onPhase}get phase(){return this.currentPhase}start(){this.stopped=!1,this.setPhase("connecting"),this.clearTimer("connectTimer"),this.connectTimer=kc(this.setTimeoutFn(()=>this.timeout("connect"),this.connectTimeoutMs))}opened(){this.stopped||(this.clearTimer("connectTimer"),this.setPhase("handshaking"),this.handshakeTimer=kc(this.setTimeoutFn(()=>this.timeout("handshake"),this.handshakeTimeoutMs)),this.scheduleHeartbeat(this.heartbeatIntervalMs))}healthy(){this.stopped||(this.clearTimer("handshakeTimer"),this.activity(),this.setPhase("healthy"),this.stable||this.stableTimer||(this.stableTimer=kc(this.setTimeoutFn(()=>{this.stableTimer=void 0,this.stopped||"healthy"!==this.currentPhase||(this.stable=!0,this.onStable?.())},this.stableThresholdMs))))}activity(){this.stopped||(this.lastActivityAt=this.now(),this.awaitingPongSince=void 0,this.consecutiveHeartbeatMisses=0,"handshaking"!==this.currentPhase&&"healthy"!==this.currentPhase||this.scheduleHeartbeat(this.heartbeatIntervalMs))}pong(){if(this.stopped)return;const e=this.now();void 0!==this.awaitingPongSince&&(this.pingRttMs=Math.max(0,e-this.awaitingPongSince),this.recentPingRttMs.push(this.pingRttMs),this.recentPingRttMs.length>20&&this.recentPingRttMs.shift()),this.awaitingPongSince=void 0,this.consecutiveHeartbeatMisses=0,this.lastPongAt=e,this.lastActivityAt=e,this.scheduleHeartbeat(this.heartbeatIntervalMs)}close(){this.stopped||(this.stopped=!0,this.clearTimers(),this.awaitingPongSince=void 0,this.setPhase("closed"))}diagnostics(){return{phase:this.currentPhase,stable:this.stable,...void 0===this.pingRttMs?{}:{pingRttMs:this.pingRttMs},...this.recentPingRttMs.length?{pingRttP95Ms:Cc(this.recentPingRttMs)}:{},...void 0===this.lastActivityAt?{}:{lastActivityAt:new Date(this.lastActivityAt).toISOString()},...void 0===this.lastPongAt?{}:{lastPongAt:new Date(this.lastPongAt).toISOString()},...this.consecutiveHeartbeatMisses?{consecutiveHeartbeatMisses:this.consecutiveHeartbeatMisses}:{}}}scheduleHeartbeat(e){this.stopped||(this.clearTimer("heartbeatTimer"),this.heartbeatTimer=kc(this.setTimeoutFn(()=>{if(this.heartbeatTimer=void 0,!this.stopped){if(void 0!==this.awaitingPongSince){const e=Math.max(0,this.now()-this.awaitingPongSince);return e>=this.heartbeatTimeoutMs?(this.consecutiveHeartbeatMisses+=1,this.awaitingPongSince=void 0,this.consecutiveHeartbeatMisses>=this.heartbeatMissThreshold?void this.timeout("heartbeat"):void this.sendHeartbeatProbe()):void this.scheduleHeartbeat(this.heartbeatTimeoutMs-e)}this.sendHeartbeatProbe()}},e)))}sendHeartbeatProbe(){this.awaitingPongSince=this.now();try{this.ping()}catch{if(this.consecutiveHeartbeatMisses+=1,this.awaitingPongSince=void 0,this.consecutiveHeartbeatMisses>=this.heartbeatMissThreshold)return void this.timeout("heartbeat")}this.scheduleHeartbeat(this.heartbeatTimeoutMs)}timeout(e){this.stopped||(this.clearTimers(),this.setPhase("failed"),this.onTimeout(e))}setPhase(e){this.currentPhase!==e&&(this.currentPhase=e,this.onPhase?.(e))}clearTimers(){this.clearTimer("connectTimer"),this.clearTimer("handshakeTimer"),this.clearTimer("heartbeatTimer"),this.clearTimer("stableTimer")}clearTimer(e){const t=this[e];t&&this.clearTimeoutFn(t),this[e]=void 0}}function Rc(e){const t=new URL(Va,e);return t.protocol="https:"===t.protocol?"wss:":"ws:",t.toString()}const xc=new Set(["linux","darwin","win32","freebsd","openbsd","aix","sunos"]);function Dc(e){return xc.has(e)?e:"unknown"}function Pc(e){return!0===e.managedArtifacts}class Mc{managedArtifacts=!0;executor;runCommand;platform;arch;constructor(e,t,n,i){this.executor=e,this.runCommand=t,this.platform=n,this.arch=i}artifactTarget(e){return this.executor.inspectRuntimeTarget(e?.instance.runtime.containerName)}resolveInstanceWeb(e){return this.executor.resolveInstanceWeb(e)}async installRuntime(e,t){const n=e.instance.runtime.containerName;if(!n)throw Object.assign(new Error(`Instance ${e.instance.id} does not have a Docker container.`),{code:"INSTANCE_RUNTIME_INSTALL_FAILED"});await this.executor.installRuntimeReleaseWithRecovery({containerName:n,expectedContainerId:e.instance.runtime.containerId,artifactPath:t.archivePath,identity:t.identity})}async inspectRuntime(e,t){const n=e.instance.runtime.containerName;if(!n)return!1;const i=function(e,t){return e.packageName===t.packageName&&e.version===t.version&&e.platform===t.platform&&e.arch===t.arch&&e.formatVersion===t.formatVersion&&e.launcherAbi===t.launcherAbi&&e.entrypoint===t.entrypoint&&e.sha256===t.sha256}(await this.executor.inspectRuntimeVersion(n),t),r=e.instance.runtime.labels["task-handoff.bootstrap-backup"];return i&&r&&await this.executor.removeBootstrapBackup(r,e.instance.id),i}start(e){return this.executor.start(e)}stop(e){return this.executor.stop(e)}restart(e){return this.executor.restart(e,e.instance.runtime.containerId)}delete(e,t){return this.executor.delete(e,t)}async check(e){try{const t=(await this.runCommand("docker",["version","--format","{{.Server.Version}}"],{timeoutMs:5e3})).stdout.trim();return{status:"online",capabilities:{...e.capabilities,daemon:{status:"online",hostPlatform:Dc(this.platform),...t?{serverVersion:t}:{}}}}}catch(t){return{status:"offline",capabilities:{...e.capabilities,daemon:{status:"offline",hostPlatform:Dc(this.platform),error:t instanceof Error?t.message:String(t)}}}}}}class Lc{docker;local;constructor(e,t){this.docker=e,this.local=t}forRuntime(e){if("docker"===e.type)return this.docker;if("local"===e.type)return this.local;throw Object.assign(new Error(`Runtime type ${e.type} is not supported by this node agent.`),{statusCode:400,code:"NODE_RUNTIME_TYPE_UNSUPPORTED"})}managedAdapters(){return[this.docker,this.local].filter(Pc)}async stopAll(){await(this.local.stopAll?.())}}const jc="task-handoff.local-process-nonce",$c=1e3,Fc=1e4,Uc=2e3;function Vc(e,t){try{e?.(t)}catch{}}function Hc(e){return e.runtime.port?`http://127.0.0.1:${e.runtime.port}`:void 0}async function qc(e,t){try{const n=await fetch(`${e}/api/internal/node-agent/process-identity`,{headers:{authorization:`Bearer ${t}`},signal:AbortSignal.timeout($c)});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 Bc(e,t){if(z.processStartIdentity(e)!==t)return!1;try{process.kill(e,"SIGTERM")}catch{return!0}const n=Date.now()+Fc;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()+Uc;for(;Date.now()<i;){try{process.kill(e,0)}catch{return!0}await new Promise(e=>setTimeout(e,50))}return!1}function Kc(e,t){return Object.assign(new Error(t),{statusCode:503,code:"LOCAL_INSTANCE_STOP_UNCONFIRMED",instanceId:e.id})}async function Gc(e){return!await function(e){return new Promise(t=>{const n=g.createConnection({host:"127.0.0.1",port:e}),i=e=>{n.removeAllListeners(),n.destroy(),t(e)};n.once("connect",()=>i(!0)),n.once("error",()=>i(!1)),n.setTimeout(250,()=>i(!1))})}(e)&&new Promise(t=>{const n=g.createServer();n.once("error",()=>t(!1)),n.listen({host:"127.0.0.1",port:e,exclusive:!0},()=>n.close(()=>t(!0)))})}const Jc=Gc;function Wc(e,t){return null!==e.exitCode||null!==e.signalCode?Promise.resolve(!0):new Promise(n=>{const i=setTimeout(()=>{e.off("exit",r),n(null!==e.exitCode||null!==e.signalCode)},t);i.unref();const r=()=>{clearTimeout(i),n(!0)};e.once("exit",r)})}async function Yc(e,t=1e4,n=2e3,i){if(await Wc(e,t))return;Vc(i,{stage:"graceful-timeout",pid:e.pid,timeoutMs:t});let r=!1;if(null===e.exitCode&&null===e.signalCode&&(e.kill("SIGKILL"),r=!0,Vc(i,{stage:"force-signal-sent",pid:e.pid,signal:"SIGKILL"})),!await Wc(e,n))throw Vc(i,{stage:"force-exit-unconfirmed",pid:e.pid,signal:"SIGKILL",timeoutMs:n}),Object.assign(new Error(`Controlled instance process pid=${e.pid??"unknown"} did not exit after SIGKILL.`),{statusCode:503,code:"LOCAL_INSTANCE_PROCESS_EXIT_UNCONFIRMED",pid:e.pid});r&&Vc(i,{stage:"force-exit-confirmed",pid:e.pid,signal:"SIGKILL"})}class Xc{children=new Map;readyChildren=new WeakSet;expectedExits=new WeakSet;lifecycleReporters=new WeakMap;lockPath;onUnexpectedExit;onUnexpectedExitError;constructor(e,t,n){this.lockPath=e,this.onUnexpectedExit=t,this.onUnexpectedExitError=n}track(e,t,n){this.children.set(e,t),n&&this.lifecycleReporters.set(t,n),t.once("exit",(n,i)=>{if(this.release(e,t),this.readyChildren.has(t)&&!this.expectedExits.has(t)){const r={instanceId:e,pid:t.pid,code:n,signal:i},s=e=>{try{this.onUnexpectedExitError?.(e,r)}catch{}};try{Promise.resolve(this.onUnexpectedExit?.(r)).catch(s)}catch(e){s(e)}}})}markReady(e,t){return this.children.get(e)===t&&null===t.exitCode&&null===t.signalCode&&(this.readyChildren.add(t),!0)}release(e,t){this.children.get(e)===t&&this.children.delete(e)}async stop(e){const t=this.children.get(e.id);if(t){this.expectedExits.add(t);const n=this.lifecycleReporters.get(t);return t.killed||(t.kill("SIGTERM"),Vc(n,{stage:"graceful-signal-sent",pid:t.pid,signal:"SIGTERM"})),this.children.delete(e.id),void await Yc(t,Fc,Uc,n)}const n=await async function(e){const t=Hc(e),n=e.runtime.labels?.[jc];if(!t||!n||!e.registrationToken)return;const i=await qc(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($c)})).ok?i:void 0}catch{return}}(e);if(n){const t=Hc(e),i=Date.now()+Fc;for(;t&&Date.now()<i;){if(!await qc(t,e.registrationToken))return;await new Promise(e=>setTimeout(e,50))}const r=t?await qc(t,e.registrationToken):void 0;if(r&&r.instanceId===n.instanceId&&r.pid===n.pid&&r.processNonce===n.processNonce&&r.startIdentity===n.startIdentity&&r.startIdentity&&await Bc(r.pid,r.startIdentity))return;throw Kc(e,`Controlled instance ${e.id} accepted shutdown but its exit could not be confirmed.`)}const i=function(e=function(){const e="win32"===process.platform?l.tmpdir():"/tmp";return r.join(e,`task-handoff-local-controlled-instance-${function(){const e=process.getuid?.();return void 0!==e?String(e):l.userInfo().username.replace(/[^a-zA-Z0-9_.-]/g,"_")}()}.lock`)}()){return R(e)}(this.lockPath),s=await async function(e){const t=Hc(e);if(t)try{const[n,i]=await Promise.all([fetch(`${t}/api/instance/status`,{signal:AbortSignal.timeout($c)}),fetch(`${t}/api/diagnostics`,{signal:AbortSignal.timeout($c)})]);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=z.processStartIdentity(o);return a?{pid:o,startIdentity:a}:void 0}catch{return}}(e);if(s){if(await Bc(s.pid,s.startIdentity))return;throw Kc(e,`Legacy controlled instance ${e.id} did not exit after termination.`)}if(i?.instanceId===e.id&&P(i))throw Kc(e,`Local controlled instance ${e.id} is still owned by pid ${i.pid}, but its process identity could not be verified.`)}async waitUntilHealthy(e,t,n,i,r=function(e=process.env.TASK_HANDOFF_LOCAL_PROCESS_READY_TIMEOUT_MS){const t=Number(e);return Number.isFinite(t)&&t>0?t:3e4}()){const s=Date.now()+r;for(;Date.now()<s;){if(null!==n.exitCode||null!==n.signalCode)return!1;const r=await qc(e,i);if(r&&r.instanceId===t.instanceId&&r.pid===t.pid&&r.processNonce===t.processNonce&&r.startIdentity===t.startIdentity)return!0;await new Promise(e=>setTimeout(e,100))}return!1}async stopAll(){const e=Array.from(this.children.values());for(const t of e){this.expectedExits.add(t);const e=this.lifecycleReporters.get(t);t.killed||(t.kill("SIGTERM"),Vc(e,{stage:"graceful-signal-sent",pid:t.pid,signal:"SIGTERM"}))}this.children.clear(),await Promise.all(e.map(e=>Yc(e,Fc,Uc,this.lifecycleReporters.get(e))))}}async function Qc(e,t){try{const n=await e(t,["--version"]);return{available:!0,command:t,version:(n.stdout||n.stderr).split(/\r?\n/)[0]?.trim()||void 0}}catch{return{available:!1}}}class Zc{runCommand;paths;nodeAgentUrl;processSupervisor;async resolveInstanceWeb(e){const t=e.instance.runtime.port;if(!t)throw Object.assign(new Error(`Instance ${e.instance.id} does not have a node-owned local runtime port.`),{statusCode:409,code:"INSTANCE_RUNTIME_ENDPOINT_UNAVAILABLE"});return`http://127.0.0.1:${t}`}commandOverride;lockPath;constructor(e,t,n,i,r,s,o){this.runCommand=e,this.paths=t,this.nodeAgentUrl=n,this.commandOverride=i,this.lockPath=r,this.processSupervisor=new Xc(r,s,o)}async start(e){await this.processSupervisor.stop(e.instance);const t=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 r.resolve(e.source.path)}(e.instance),n=e.instance.runtime.port,s=!!n&&await Gc(n),o="allocate"===process.env.TASK_HANDOFF_LOCAL_INSTANCE_PORT_CONFLICT;if(n&&!s&&!o)throw Object.assign(new Error(`Local controlled instance port 127.0.0.1:${n} is already in use.`),{statusCode:409,code:"LOCAL_INSTANCE_PORT_IN_USE"});const a=n&&s?n: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 Jc(e))return e;throw Object.assign(new Error(`No free localhost port found in range ${t}-${Math.min(t+999,65535)}.`),{statusCode:503,code:"LOCAL_INSTANCE_PORT_UNAVAILABLE"})}(),c=r.join(this.paths.dataDir,"local-instances",e.instance.id),d=r.join(c,"logs");i.mkdirSync(d,{recursive:!0,mode:448}),i.chmodSync(c,448),i.chmodSync(d,448);const[l,...p]=function(e){if(e)return e;const t=r.resolve(process.cwd(),"bin","task-handoff.js");if(i.existsSync(t))return[process.execPath,t,"web"];throw Object.assign(new Error("The bundled controlled-instance command is unavailable."),{statusCode:500,code:"LOCAL_CONTROLLED_COMMAND_MISSING"})}(this.commandOverride),h=[...p,"--host","127.0.0.1","--port",String(a)],g=u.randomUUID(),f=r.join(d,"controlled-instance.out.log"),y=r.join(d,"controlled-instance.err.log");Fs(f),Fs(y);const I=i.openSync(f,"a",384),A=i.openSync(y,"a",384),b=m.spawn(l,h,{cwd:t,detached:!1,stdio:["ignore",I,A],env:{...process.env,TASK_HANDOFF_CONTROL_MODE:"controlled",TASK_HANDOFF_RUNTIME_KIND:"local",TASK_HANDOFF_CONTROLLED_INSTANCE_VERSION:Po(),...this.lockPath?{TASK_HANDOFF_LOCAL_CONTROLLED_INSTANCE_LOCK_PATH:this.lockPath}:{},TASK_HANDOFF_NODE_AGENT_URL:this.nodeAgentUrl(),TASK_HANDOFF_INSTANCE_ID:e.instance.id,TASK_HANDOFF_INSTANCE_NAME:e.instance.name,TASK_HANDOFF_REGISTRATION_TOKEN:e.instance.registrationToken||"",TASK_HANDOFF_PROJECT_ID:e.project.id,TASK_HANDOFF_NODE_ID:e.node.id,TASK_HANDOFF_RUNTIME_ID:e.runtime.id,TASK_HANDOFF_LOCAL_PROCESS_NONCE:g,TASK_HANDOFF_WORKSPACE:t,TASK_HANDOFF_WORKSPACE_MODE:"local-bind",TASK_HANDOFF_DATA_DIR:c,TASK_HANDOFF_LOG_DIR:d,TASK_HANDOFF_APP_SESSION_PERSIST:"1",TASK_HANDOFF_CODEX_APP_SERVER:process.env.TASK_HANDOFF_CODEX_APP_SERVER||"1",TASK_HANDOFF_WEB_PORT:String(a),TASK_HANDOFF_WEB_HOST:"127.0.0.1",...e.modelEnv||{}}});i.closeSync(I),i.closeSync(A);try{await function(e){return new Promise((t,n)=>{const i=()=>{e.off("error",r),t()},r=t=>{e.off("spawn",i),n(t)};e.once("spawn",i),e.once("error",r)})}(b)}catch(e){const n=e instanceof Error?e.message:String(e);try{i.appendFileSync(r.join(d,"controlled-instance.lifecycle.log"),`[${(new Date).toISOString()}] spawn failed command=${l} cwd=${t} error=${n}\n`)}catch{}throw Object.assign(new Error(`Controlled instance process could not start with command ${l} in ${t}: ${n}`),{statusCode:500,code:"LOCAL_INSTANCE_PROCESS_SPAWN_FAILED"})}const w=r.join(d,"controlled-instance.lifecycle.log");this.processSupervisor.track(e.instance.id,b,e=>{i.appendFileSync(w,`[${(new Date).toISOString()}] shutdown stage=${e.stage} pid=${e.pid??""} signal=${e.signal??""} timeoutMs=${e.timeoutMs??""}\n`)}),b.on("error",e=>{try{i.appendFileSync(w,`[${(new Date).toISOString()}] process error pid=${b.pid??""} error=${e.message}\n`)}catch{}}),b.once("exit",(e,t)=>{try{i.appendFileSync(w,`[${(new Date).toISOString()}] exited pid=${b.pid??""} code=${e??""} signal=${t??""}\n`)}catch{}});const v=`http://127.0.0.1:${a}`,E=b.pid?z.processStartIdentity(b.pid):void 0;if(!(b.pid&&e.instance.registrationToken&&await this.processSupervisor.waitUntilHealthy(v,{instanceId:e.instance.id,pid:b.pid,processNonce:g,startIdentity:E},b,e.instance.registrationToken)&&this.processSupervisor.markReady(e.instance.id,b)))throw this.processSupervisor.release(e.instance.id,b),null===b.exitCode&&null===b.signalCode&&b.kill("SIGTERM"),await Yc(b),Object.assign(new Error(`Controlled instance process did not become ready for instance ${e.instance.id} on ${v}.`),{statusCode:503,code:"LOCAL_INSTANCE_PROCESS_NOT_READY"});return{status:"registering",health:"unknown",connectionStatus:"online",agentStatus:"unknown",targetStatus:"unknown",uiAccessStatus:"unknown",target:{strategy:"direct-port",status:"unknown",web:v,api:`${v}/api`},workspace:{mode:"local-bind",status:"pending",path:t},runtime:{kind:"local",workspacePath:t,pid:b.pid,port:a,labels:{...e.instance.runtime.labels,"task-handoff.runtime-kind":"local",[jc]:g}}}}async stop(e){return await this.processSupervisor.stop(e.instance),{status:"stopped",health:"unknown",connectionStatus:"offline",agentStatus:"offline",targetStatus:"unknown",uiAccessStatus:"unknown",target:{...e.instance.target,status:"unknown"},runtime:e.instance.runtime}}async restart(e){return this.start(e)}async delete(e,t){return await this.stop(e),vn.parse({instanceId:e.instance.id,containerDeleted:!0,completed:!0,deletedVolumes:[],retainedVolumes:[],volumeResults:[]})}async check(e){const[t,n]=await Promise.all([Qc(this.runCommand,"codex"),Qc(this.runCommand,"claude")]);return{status:"online",capabilities:Go({...e.capabilities,apps:{terminal:!0,codex:t,claude:n}})}}async stopAll(){await this.processSupervisor.stopAll()}}const ed=["codex","claude"],td=5e3,nd=z.processStartIdentity(process.pid);function id(e){const t=process.env[e]?.trim();return t||void 0}function rd(e){const t=e.authorization;return"string"==typeof t&&t.startsWith("Bearer ")?t.slice(7).trim():void 0}function sd(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 od(e){return!e.ip&&!e.socket.remoteAddress&&!e.socket.remoteFamily}async function ad(e,t,n){const i=new AbortController,r=setTimeout(()=>i.abort(),2e3);try{return(await e(`${await n(t)}/api/health`,{signal:i.signal})).ok?"reachable":"endpoint-unreachable"}catch{return"endpoint-unreachable"}finally{clearTimeout(r)}}async function cd(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 dd(e,t,n,i,r){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 s=await r(t),o=Number(process.env.TASK_HANDOFF_CONFIG_AUTO_IMPORT_TIMEOUT_MS||td);for(const r of ed)try{const a=await cd(e,`${s}/api/config-sync/import/${encodeURIComponent(r)}`,{method:"POST"},Number.isFinite(o)&&o>0?o:td);if(!a.ok){i.warn({instanceId:t.id,action:n,preset:r,statusCode:a.status},"node instance config auto-import failed");continue}i.diagnostic({instanceId:t.id,action:n,preset:r},"node instance config auto-import completed")}catch(e){i.warn({instanceId:t.id,action:n,preset:r,error:e instanceof Error?e.message:String(e)},"node instance config auto-import failed")}}async function ld(e,t,n,i,r=async e=>Pa(e)){const s=t.requireInstance(n);if(t.instancePrivateConfigs.materialize(s.id,s.registrationToken,t.resolvedAssignedModelEnvironment(n)),"reachable"!==s.targetStatus)return!1;let o;try{o=await cd(e,`${await r(s)}/api/internal/model-environment`,{method:"PUT",headers:{"content-type":"application/json",authorization:`Bearer ${s.registrationToken}`},body:JSON.stringify(t.resolvedAssignedModelEnvironment(n))},td)}catch(e){return i?.({instanceId:n,targetWeb:s.target.web,error:e instanceof Error?e.message:String(e)},"node instance model environment live sync deferred"),!1}return!!o.ok||(i?.({instanceId:n,targetWeb:s.target.web,statusCode:o.status},"node instance model environment live sync deferred"),!1)}async function ud(e,t,n,i,r,s,o="request"){const a=e.requireInstance(i);if(a.imageProvisioning&&"ready"!==a.imageProvisioning.phase&&"docker"===e.requireRuntime(a.runtimeId).type)return r.diagnostic({instanceId:i,action:"start",reason:o,runtimeId:a.runtimeId,imageId:a.imageSelection?.imageId,imagePhase:a.imageProvisioning.phase},"node instance start queued until image provisioning completes"),e.controlledInstances.put(nr.parse({...a,status:"starting",updatedAt:K()}));r.diagnostic({instanceId:i,action:"start",reason:o,runtimeId:a.runtimeId,imageId:a.imageSelection?.imageId},"node instance start requested");const c=e.applyInstanceLifecycle(i,{type:"start-requested"}),d=t.forRuntime(e.requireRuntime(c.runtimeId)),l=await d.start(e.context(c)),u=l.target?.web?await ad(n,nr.parse({...c,...l,target:{...c.target,...l.target},workspace:l.workspace?{...c.workspace,error:void 0,...l.workspace}:c.workspace,runtime:l.runtime?{...c.runtime,...l.runtime}:c.runtime,updatedAt:K()}),s):"unknown",m=e.applyInstanceLifecycle(i,{type:"runtime-lifecycle-completed",baseline:c,observation:{...l,target:l.target?{...l.target,status:u}:void 0,workspace:l.workspace?{error:void 0,...l.workspace}:void 0,targetStatus:u,uiAccessStatus:u}});return r.diagnostic({instanceId:i,action:"start",reason:o,status:m.status,connectionStatus:m.connectionStatus,targetStatus:m.targetStatus,targetWeb:m.target.web,containerName:m.runtime.containerName},"node instance start completed"),m}async function md(e={}){const t=e.token||process.env.TASK_HANDOFF_NODE_AGENT_TOKEN,n=Number(e.port||process.env.TASK_HANDOFF_NODE_AGENT_PORT||"8091"),s=`http://127.0.0.1:${n}`,l=e.containerUrl||process.env.TASK_HANDOFF_NODE_AGENT_CONTAINER_URL,u=js(e.dataDir),m=e.remoteSecret||process.env.TASK_HANDOFF_NODE_AGENT_REMOTE_SECRET,p=e.remoteKeyId||process.env.TASK_HANDOFF_NODE_AGENT_REMOTE_KEY_ID,g=new pc(u),y=g.resolveNodeId(e.nodeId||process.env.TASK_HANDOFF_NODE_ID),I=e.connectionMode||("local-ipc"===process.env.TASK_HANDOFF_NODE_AGENT_CONNECTION_MODE?"local-ipc":"local-loopback"),A=e.ipcPath||process.env.TASK_HANDOFF_NODE_AGENT_IPC_PATH||Vs(u.dataDir),b="local-ipc"===I?`ipc://${encodeURIComponent(A)}`:s,w=e.platform||process.platform,E=e.arch||process.arch,N=new Wo(u,y,s,l,n,w);N.node.connectionMode=I,N.node.controlEndpoint=b,N.node.endpoint=b,N.init();const S=e.dockerCommandRunner||Ir,z=new br(S,e.dockerTerminalCommandRunner),T=new Or(S,{publishHost:"127.0.0.1",imageService:z});let _;const C=new Lc(new Mc(T,S,w,E),new Zc(e.dockerCommandRunner||Ir,u,()=>N.localNodeAgentUrl,function(){const e=process.env.TASK_HANDOFF_LOCAL_CONTROLLED_COMMAND_ARGV?.trim();if(!e){const e=process.env.TASK_HANDOFF_LOCAL_CONTROLLED_COMMAND?.trim();return e?e.split(/\s+/):void 0}let t;try{t=JSON.parse(e)}catch{throw Object.assign(new Error("TASK_HANDOFF_LOCAL_CONTROLLED_COMMAND_ARGV must be valid JSON."),{code:"LOCAL_CONTROLLED_COMMAND_INVALID"})}if(!Array.isArray(t)||!t.length||t.some(e=>"string"!=typeof e||!e))throw Object.assign(new Error("TASK_HANDOFF_LOCAL_CONTROLLED_COMMAND_ARGV must be a non-empty string array."),{code:"LOCAL_CONTROLLED_COMMAND_INVALID"});return t}(),e.localControlledInstanceLockPath||process.env.TASK_HANDOFF_LOCAL_CONTROLLED_INSTANCE_LOCK_PATH,e=>_.handleUnexpectedLocalExit(e.instanceId,new Error(`Local controlled instance exited unexpectedly (pid=${e.pid??"unknown"}, code=${e.code??"none"}, signal=${e.signal??"none"}).`)),(e,t)=>H.log.error({error:e,instanceId:t.instanceId,pid:t.pid},"local controlled instance exit recovery failed"))),k=async e=>Pa(e,await C.forRuntime(N.requireRuntime(e.runtimeId)).resolveInstanceWeb(N.context(e))),O=e.updateCommandRunner||e.dockerCommandRunner||Ir,R=e.fetchImpl||fetch,x=new Map,D=async e=>{const t=N.requireInstance(e);if(!Wt(t.capabilities).features.aiSessionPersistenceSettings||"reachable"!==t.targetStatus||!t.registrationToken)return!1;const n=!0===t.capabilities.features.aiSessionConversationAttachments?.retentionSettings,i=`${t.processIncarnationId||"unknown"}:${t.config.aiSessionHistoryLimit}:${n?t.config.aiSessionAttachmentRetentionDays:"unsupported"}`;if(x.get(e)===i)return!0;let r;try{r=await cd(R,`${await k(t)}/api/internal/ai-session-persistence-settings`,{method:"PUT",headers:{"content-type":"application/json",authorization:`Bearer ${t.registrationToken}`},body:JSON.stringify({historyLimit:t.config.aiSessionHistoryLimit,...n?{attachmentRetentionDays:t.config.aiSessionAttachmentRetentionDays}:{}})},td)}catch(t){return ie.warn({instanceId:e,error:t instanceof Error?t.message:String(t)},"node instance AI session persistence settings live sync deferred"),!1}return r.ok?(x.set(e,i),!0):(ie.warn({instanceId:e,statusCode:r.status},"node instance AI session persistence settings live sync deferred"),!1)},P=new Ys({cacheDir:r.join(u.dataDir,"runtime-artifacts"),fetchImpl:R}),M=e.resolveRuntimeArtifactRelease||((e,t,n)=>Xs(e,t,n,R)),L=async(t,n,i)=>{const r=await n.artifactTarget(i);if(e.resolveRuntimeArtifact)return e.resolveRuntimeArtifact(t,r.platform,r.arch);const s=await M(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 P.resolve(s.identity,s.source)},j=e=>C.forRuntime(N.requireRuntime(e.runtimeId)),$=e=>{const t=j(e);return Pc(t)?t:void 0},F=e=>{const t=$(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})},U=e=>Boolean($(e)),V=(e,t)=>{const n=N.context(e);return L(t,F(e),n)},H=a({logger:e.logger??!0}),q=new Us(u,{logger:(e,t)=>H.log.warn(t,e)}),B=()=>N.listInstances().map(e=>e.id),G=()=>{try{q.run(B())}catch(e){H.log.warn({error:e},"node-agent persistence maintenance failed")}};G();const J=setInterval(()=>{G()},216e5);J.unref();const W=setInterval(()=>{(()=>{try{q.capNodeAgentLogs(),q.capActiveInstanceLogs(B())}catch(e){H.log.warn({error:e},"node-agent open log maintenance failed")}})()},6e4);W.unref();const Y={requests:0,active:0,completed:0,aborted:0,limitRejected:0,responseBytes:0,totalDurationMs:0,maxResponseBytes:Ca()};H.decorate("nodeAgentState",N),await H.register(c);const X=new hs(N,t,{logger:H.log,safetyIntervalMs:Number(process.env.TASK_HANDOFF_EVENT_CONNECTION_SAFETY_INTERVAL_MS)||void 0}),Q=new Qs(N.controlledInstances,Po,{isInstalled:async(e,t)=>{const n=await V(e,t),i=await F(e).inspectRuntime(N.context(e),n.identity);if(i&&e.runtime.labels["task-handoff.bootstrap-backup"]){const t=N.requireInstance(e.id),n={...t.runtime.labels};delete n["task-handoff.bootstrap-backup"],N.controlledInstances.put(nr.parse({...t,runtime:{...t.runtime,labels:n},updatedAt:K()}))}return i},beginDrain:async e=>{try{const t=await async function(e,t,n=async e=>Pa(e)){const i=await n(t);if(t.registrationToken&&(await cd(e,`${i}/api/internal/node-agent/drain`,{method:"POST",headers:{authorization:`Bearer ${t.registrationToken}`}},1e4)).ok)return{requested:t.apps.runningCount,failures:[]};const r=await cd(e,`${i}/api/apps/sessions`,{method:"GET",headers:{"cache-control":"no-cache"}},5e3);if(!r.ok)throw new Error(`Could not list app sessions for runtime drain (HTTP ${r.status}).`);const s=function(e){if(!e||"object"!=typeof e||Array.isArray(e))return[];const t=e.data;if(Array.isArray(t))return t;if(!t||"object"!=typeof t||Array.isArray(t))return[];const n=t.snapshot,i=(n&&"object"==typeof n&&!Array.isArray(n)?n:t).sessions;return Array.isArray(i)?i:[]}(await r.json()).flatMap(e=>{if(!e||"object"!=typeof e||Array.isArray(e))return[];const t=e;return"running"===t.status&&"string"==typeof t.id&&t.id?[t.id]:[]}),o=await Promise.all(s.map(async t=>{try{const n=await cd(e,`${i}/api/apps/sessions/${encodeURIComponent(t)}/stop`,{method:"POST"},5e3);return n.ok?void 0:{sessionId:t,error:`HTTP ${n.status}`}}catch(e){return{sessionId:t,error:e instanceof Error?e.message:String(e)}}}));return{requested:s.length,failures:o.filter(e=>Boolean(e))}}(R,e,k);t.failures.length?H.log.warn({instanceId:e.id,requested:t.requested,failures:t.failures},"runtime convergence could not stop every app session"):H.log.info({instanceId:e.id,requested:t.requested},"runtime convergence requested app session drain")}catch(t){H.log.warn({instanceId:e.id,error:t instanceof Error?t.message:String(t)},"runtime convergence could not request app session drain")}},endDrain:async e=>{try{await async function(e,t,n=async e=>Pa(e)){return!!t.registrationToken&&(await cd(e,`${await n(t)}/api/internal/node-agent/resume`,{method:"POST",headers:{authorization:`Bearer ${t.registrationToken}`}},5e3)).ok}(R,e,k)&&H.log.info({instanceId:e.id},"runtime convergence released app session drain")}catch(t){H.log.warn({instanceId:e.id,error:t instanceof Error?t.message:String(t)},"runtime convergence could not release app session drain")}},install:async(e,t)=>{const n=F(e);await n.installRuntime(N.context(e),await V(e,t))},restart:async e=>{const t=j(e),n=N.applyInstanceLifecycle(e.id,{type:"convergence-restart-requested"}),i=await t.restart(N.context(n)),r=nr.parse({...n,...i,target:i.target?{...n.target,...i.target}:n.target,runtime:i.runtime?{...n.runtime,...i.runtime}:n.runtime,updatedAt:K()}),s=await ad(R,r,k);N.applyInstanceLifecycle(e.id,{type:"runtime-lifecycle-completed",baseline:n,observation:{...i,target:i.target?{...i.target,status:s}:void 0,targetStatus:s,uiAccessStatus:s}})},onForcedDrain:e=>H.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});N.controlledInstances.setOnStored(e=>{X.publishInstanceLifecycle(e),N.updateJobs.reconcileRollouts(N.listInstances(),Po())}),X.start(),H.decorate("nodeAgentEventForwarder",X);const Z=new ws(S,()=>N.listInstances().filter(e=>"docker"===N.requireRuntime(e.runtimeId).type),e=>X.publish("instance.metrics.snapshot",e,{instanceId:e.instanceId}));Z.start(),H.decorate("nodeAgentRuntimeMetrics",Z);const ee=(de=process.env.TASK_HANDOFF_DIAGNOSTIC_LOGS,["1","true","yes","on"].includes(String(de||"").trim().toLowerCase())),te=new Ka(g,y,m,p),ne=(e,t)=>{ee&&H.log.info(e,t)},ie={diagnostic:ne,warn:(e,t)=>H.log.warn(e,t)},re=new ya,se=new va(N.environmentTemplates,N.instancePrivateConfigs,T,e=>N.requireInstance(e),e=>N.requireRuntime(e),(e,t)=>re.run(e,t),e=>N.listInstances().some(t=>t.environmentTemplateOrigin?.imageId===e)),oe=async(e,t,n=()=>!0)=>{try{if(!n())return N.requireInstance(e);let i=N.requireInstance(e);"failed"===i.runtimeVersion?.phase&&U(i)&&(i=N.controlledInstances.put(nr.parse({...i,ready:!1,runtimeVersion:Lo(Zs(i)),updatedAt:K()})));const r=N.requireRuntime(i.runtimeId);await ud(N,C,R,e,ie,k);const s=N.requireInstance(e);if("docker"===r.type&&s.imageProvisioning&&"ready"!==s.imageProvisioning.phase)return X.syncNow(),s;if(!n())return N.requireInstance(e);_.markRestored(e);let o=N.requireInstance(e);if(U(o)){try{o=await Q.schedule(e,{startRequested:!0})}catch(n){o=N.requireInstance(e),ie.warn({instanceId:e,action:"runtime.converge",reason:t,error:n instanceof Error?n.message:String(n)},"node instance runtime convergence failed after start")}"matched"!==o.runtimeVersion?.phase&&o.runtimeVersion?.error&&ie.warn({instanceId:e,action:"runtime.converge",reason:t,error:o.runtimeVersion.error},"node instance started with pending runtime convergence")}return n()?(await dd(R,o,"start",ie,k),X.syncNow(),o):N.requireInstance(e)}catch(n){throw N.applyInstanceLifecycle(e,{type:"start-failed",error:n}),X.syncNow(),ie.warn({instanceId:e,action:"start",reason:t,error:n instanceof Error?n.message:String(n)},"node instance start failed"),n}},ae=new Aa(N,z,{sync:()=>X.syncNow(),diagnostic:ie.diagnostic,warn:ie.warn,publish:(e,t,n)=>X.publish(e,t,{instanceId:n}),runInstanceOperation:(e,t)=>re.run(e,t)}),ce=e=>{const t=re.intent(e.id);ae.provision(e,async()=>{await oe(e.id,"image-ready",()=>re.isIntentCurrent(e.id,t)).catch(()=>{})})};var de;_=new wc({state:N,runtimeAdapters:C,convergence:Q,restoreInstance:e=>ud(N,C,R,e,ie,k,"restore"),autoImport:e=>dd(R,e,"start",ie,k),provisionImage:ce,stopImageProvisioning:()=>ae.stop(),usesManagedArtifact:U,warn:ie.warn,error:(e,t)=>H.log.error(e,t),runInstanceOperation:(e,t)=>re.run(e,t)});const le=new yc({nodeId:y,jobs:N.updateJobs,runCommand:O,currentRuntimeVersion:Po,listInstances:()=>N.listInstances(),resolveRuntimeArtifacts:async e=>(await(async e=>{const t=new Map;for(const e of C.managedAdapters()){const n=await e.artifactTarget();t.set(`${n.platform}-${n.arch}`,{adapter:e})}for(const e of N.listInstances()){const n=$(e);if(!n)continue;const i=N.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})=>L(e,t,n)))).sort((e,t)=>`${e.identity.platform}/${e.identity.arch}`.localeCompare(`${t.identity.platform}/${t.identity.arch}`))})(e)).map(e=>e.identity),moduleDir:("undefined"==typeof document?require("url").pathToFileURL(__filename).href:v&&"SCRIPT"===v.tagName.toUpperCase()&&v.src||new URL("cli.js",document.baseURI).href)?r.dirname(o.fileURLToPath("undefined"==typeof document?require("url").pathToFileURL(__filename).href:v&&"SCRIPT"===v.tagName.toUpperCase()&&v.src||new URL("cli.js",document.baseURI).href)):__dirname,managedUpdateSupport:e.managedUpdateSupport||(t=>"linux"!==(e.platform||process.platform)?{supported:!1,reason:"Managed server updates require Linux and systemd."}:"function"==typeof process.getuid&&0!==process.getuid()?{supported:!1,reason:"Managed server updates require the node agent to run as root."}:i.existsSync("/run/systemd/system")?"@task-handoff/server"!==t.packageName||process.env.TASK_HANDOFF_CONTROL_PLANE_HEALTH_URL?.trim()?process.env.TASK_HANDOFF_NODE_AGENT_IPC_PATH?.trim()?{supported:!0}:{supported:!1,reason:"Managed server updates require the node-agent IPC readiness endpoint."}:{supported:!1,reason:"Managed server updates require a local control-plane health URL."}:{supported:!1,reason:"Managed server updates require an active systemd host."})});return H.setErrorHandler((e,t,n)=>{const i=function(e){if(e instanceof d.z.ZodError)return{statusCode:400,code:"VALIDATION_ERROR",message:e.issues.map(e=>`${e.path.join(".")||"body"}: ${e.message}`).join("; "),details:{issues:e.issues.map(e=>({path:e.path.map(String),code:e.code,message:e.message}))}};const t=e&&"object"==typeof e?e:{};return{statusCode:"number"==typeof t.statusCode?t.statusCode:500,code:"string"==typeof t.code?t.code:"NODE_AGENT_ERROR",message:e instanceof Error?e.message:String(e),...t.details&&"object"==typeof t.details&&!Array.isArray(t.details)?{details:t.details}:{},..."boolean"==typeof t.retryable?{retryable:t.retryable}:{}}}(e);(ee||i.statusCode>=500)&&(i.statusCode>=500?H.log.error.bind(H.log):H.log.warn.bind(H.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}:{}}})}),H.addHook("preHandler",async e=>{const n=te.verify(e);if(n){if(g.isRevokedPairing(n)&&"/api/node-agent/pairing/current"!==e.url.split("?")[0]){const e=new Error("The node agent pairing used for this request has been revoked.");throw Object.assign(e,{statusCode:401,code:"NODE_AGENT_HMAC_KEY_REVOKED"}),e}e.nodeAgentAuthKeyId=n}else if(od(e)){if(t&&rd(e.headers)!==t){const e=new Error("Invalid node agent token.");throw Object.assign(e,{statusCode:401,code:"NODE_AGENT_UNAUTHORIZED"}),e}}else if("/api/node-agent/pairing/complete"!==e.url.split("?")[0]&&!function(e){const t=e.split("?")[0];return/^\/api\/node-agent\/instances\/[^/]+\/(register|heartbeat)$/.test(t)}(e.url)){if(te.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 sd(e.ip)||sd(e.socket.remoteAddress)||!e.ip&&!e.socket.remoteAddress&&!e.socket.remoteFamily}(e)){const e=new Error("Local node agent access is only accepted from loopback or local IPC connections.");throw Object.assign(e,{statusCode:401,code:"NODE_AGENT_LOCAL_TOKEN_REQUIRES_LOOPBACK"}),e}if(t&&rd(e.headers)!==t){const e=new Error("Invalid node agent token.");throw Object.assign(e,{statusCode:401,code:"NODE_AGENT_UNAUTHORIZED"}),e}}}),H.addHook("onClose",async()=>{clearInterval(J),clearInterval(W),Z.stop(),X.stop(),await _.stop()}),H.decorate("nodeAgentRestoreManagedInstances",()=>_.restoreManagedInstances()),H.decorate("nodeAgentRecoverManagedInstances",()=>_.recoverManagedInstances()),H.decorate("nodeAgentStartRecoverySupervisor",()=>_.start()),H.get("/api/node-agent/health",async()=>{return{data:{ok:!0,role:"node-agent",process:{pid:process.pid,...nd?{startIdentity:nd}:{}},listener:{host:"127.0.0.1",port:N.currentListenerPort},nodeId:y,platform:Dc(w),arch:process.arch,protocolVersion:Ft,capabilities:{modelEndpointProbe:!0,aiSessionHistoryLimit:!0,aiSessionAttachmentRetention:!0,folderPlaces:!0,localFolderNameUpdate:!0},build:(e="node-agent",{component:e,packageName:"@task-handoff/node-agent",packageVersion:Po(),protocolVersion:Ft,buildId:id("TASK_HANDOFF_BUILD_ID"),builtAt:id("TASK_HANDOFF_BUILT_AT"),gitCommit:id("TASK_HANDOFF_GIT_COMMIT"),imageRef:id("TASK_HANDOFF_IMAGE_REF"),imageDigest:id("TASK_HANDOFF_IMAGE_DIGEST")}),instanceProxy:{...Y},serverTime:(new Date).toISOString()}};var e}),function(e,t){e.get("/api/node-agent/settings/external-listener",async e=>({data:t(e).current()})),e.patch("/api/node-agent/settings/external-listener",async e=>({data:await t(e).update(e.body)}))}(H,e=>{if(!od(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(!H.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 H.nodeAgentListenerManager}),function(e,t,n){e.get("/api/node-agent/updates/jobs",async()=>({data:n.list()})),e.post("/api/node-agent/updates/check",async e=>({data:await t.check(e.body)})),e.post("/api/node-agent/updates/apply",async(e,n)=>n.code(202).send({data:await t.apply(e.body)}))}(H,le,N.updateJobs),function(e,t){const{identity:n,nodeId:i,fetchImpl:r}=t;e.post("/api/node-agent/pairing/invites",async(e,t)=>{const r=n.createPairingInvite(Za.parse(e.body||{}));return t.code(201).send({data:{nodeId:i,joinToken:r.token,expiresAt:r.expiresAt}})}),e.post("/api/node-agent/pairing/complete",async(e,t)=>{const r=n.completePairingInvite(ec.parse(e.body));return t.code(201).send({data:{nodeId:i,keyId:r.keyId,secret:r.secret,pairedAt:r.pairedAt}})}),e.get("/api/node-agent/control-plane-pairings",async e=>({data:n.listControlPlanePairings(e.nodeAgentAuthKeyId)})),e.delete("/api/node-agent/control-plane-pairings/:keyId",async e=>{const t=hc.parse(e.params.keyId);return{data:{deleted:n.deleteControlPlanePairing(t,e.nodeAgentAuthKeyId)}}}),e.delete("/api/node-agent/pairing/current",async e=>({data:n.revokeCurrentControlPlanePairing(e.nodeAgentAuthKeyId||"")})),e.get("/api/node-agent/control-plane-connections",async()=>({data:n.listControlPlaneConnections().map(e=>({...e,...t.reverseTunnels()?.state(e.id)||{status:e.enabled?"connecting":"disabled"}}))})),e.delete("/api/node-agent/control-plane-connections/:connectionId",async e=>{const i=hc.parse(e.params.connectionId),r=n.deleteControlPlaneConnection(i);return r&&t.reverseTunnels()?.connectConfigured(),{data:{deleted:r}}}),e.post("/api/node-agent/control-plane-connections",async(e,s)=>{const o=tc.parse(e.body),a=function(e){const t=new URL(e);if("http:"!==t.protocol&&"https:"!==t.protocol){const e=new Error("Control-plane URL must use http or https.");throw Object.assign(e,{statusCode:400,code:"NODE_AGENT_REMOTE_CONTROL_PLANE_URL_INVALID"}),e}return t.toString().replace(/\/$/,"")}(o.controlPlaneUrl);return n.runControlPlaneConnectionOperation(a,async()=>{const e=n.stageControlPlaneConnection({url:a,...o.controlPlaneName?{name:o.controlPlaneName}:{},enabled:!1!==o.activate});let c;try{c=await async function(e,t,n){const i=await e(new URL("/api/node-join/complete",t).toString(),{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(n)}),r=await i.json().catch(()=>({}));if(!i.ok){const e=new Error(r.error?.message||`Control-plane node join failed with HTTP ${i.status}.`);throw Object.assign(e,{statusCode:i.status,code:r.error?.code||"NODE_AGENT_REMOTE_JOIN_FAILED"}),e}return r.data||{}}(r,a,{joinToken:o.joinToken,nodeId:i,nodeName:t.nodeName(),keyId:e.pairing.keyId,secret:e.pairing.secret,pairedAt:e.pairing.pairedAt})}catch(t){throw n.rollbackControlPlaneConnection(e),t}const d=n.commitControlPlaneConnection(e,{name:o.controlPlaneName||("string"==typeof c.name&&c.name?c.name:void 0)});let l,u=d.connection.enabled?"saved":"disabled";const m=t.reverseTunnels();if(m)try{m.connectConfigured(),d.connection.enabled&&(u="connecting")}catch(e){u="failed",l=e instanceof Error?e.message:String(e)}return s.code(201).send({data:{pairing:n.listControlPlanePairings().find(e=>e.keyId===d.pairing.keyId),connection:d.connection,tunnel:{status:u,...l?{error:l}:{}}}})})})}(H,{identity:g,nodeId:y,nodeName:()=>N.node.name,fetchImpl:R,reverseTunnels:()=>H.nodeAgentReverseTunnels}),function(e,t){e.get("/api/node-agent/runtimes",async()=>({data:t.listRuntimes()})),e.post("/api/node-agent/runtimes",async(e,n)=>n.code(201).send({data:t.createRuntime(ha.parse(e.body))})),e.patch("/api/node-agent/runtimes/:id",async e=>({data:t.updateRuntime(e.params.id,ga.parse(e.body))})),e.delete("/api/node-agent/runtimes/:id",async e=>({data:{deleted:t.deleteRuntime(e.params.id)}})),e.post("/api/node-agent/runtimes/:id/check",async e=>({data:await t.checkRuntime(e.params.id)})),e.get("/api/node-agent/local-folders",async()=>({data:t.listLocalFolders()})),e.get("/api/node-agent/folders/places",async()=>({data:t.listFolderPlaces()})),e.get("/api/node-agent/folders/tree",async e=>({data:t.listFolderTree(ua.parse(e.query))})),e.post("/api/node-agent/local-folders",async(e,n)=>n.code(201).send({data:t.createLocalFolder(da.parse(e.body))})),e.patch("/api/node-agent/local-folders/:id",async e=>({data:t.updateLocalFolder(e.params.id,la.parse(e.body))})),e.delete("/api/node-agent/local-folders/:id",async e=>({data:{deleted:t.deleteLocalFolder(e.params.id)}}))}(H,{listRuntimes:()=>N.nodeRuntimes.list(),createRuntime:e=>N.createRuntime(e),updateRuntime:(e,t)=>N.updateRuntime(e,t),deleteRuntime:e=>N.deleteRuntime(e),checkRuntime:async e=>{const t=N.requireRuntime(e);return N.checkRuntime(e,C.forRuntime(t))},listLocalFolders:()=>N.localFolders.list(),listFolderPlaces:Ds,listFolderTree:Ms,createLocalFolder:e=>N.createLocalFolder(e),updateLocalFolder:(e,t)=>N.updateLocalFolder(e,t),deleteLocalFolder:e=>N.localFolders.delete(e)}),function(e,t,n,i){e.get("/api/node-agent/models",async()=>({data:t.list()})),e.post("/api/node-agent/models",async(e,n)=>n.code(201).send({data:t.create(yi.parse(e.body))})),e.post("/api/node-agent/models/discover",async e=>{const n=oa.parse(e.body);return{data:await Yo(i,{...n,key:t.resolveProbeKey(n.existingModelId,n.key)})}}),e.post("/api/node-agent/models/test",async e=>{const n=aa.parse(e.body);return{data:await Xo(i,{...n,key:t.resolveProbeKey(n.existingModelId,n.key)})}}),e.put("/api/node-agent/models/:id/deploy",async e=>{const n=e.params.id,i=Ai.parse(e.body);if(i.id!==n)throw Object.assign(new Error(`Model payload id ${i.id} does not match route id ${n}.`),{statusCode:400,code:"NODE_MODEL_ID_MISMATCH"});return{data:t.deploy(i)}}),e.patch("/api/node-agent/models/:id",async e=>({data:t.update(e.params.id,Ii.parse(e.body))})),e.delete("/api/node-agent/models/:id",async e=>({data:{deleted:t.delete(e.params.id)}})),e.put("/api/node-agent/instances/:id/model-assignment",async e=>{const i=e.params.id,r=t.assign(i,bi.parse(e.body));return await n(i),{data:r}})}(H,N.modelRegistry,e=>ld(R,N,e,ie.warn,k),R),function(e,t){e.get("/api/node-agent/environment-templates",async()=>({data:t.list()})),e.get("/api/node-agent/environment-templates/:id",async e=>({data:Cn.parse(t.require(e.params.id))})),e.post("/api/node-agent/instances/:id/environment-templates",async(e,n)=>{const i=await t.create(e.params.id,e.body);return n.code(201).send({data:i})}),e.delete("/api/node-agent/environment-templates/:id",async e=>({data:await t.delete(e.params.id)}))}(H,se),function(e,t){e.get("/api/node-agent/instances",async()=>({data:t.list()})),e.post("/api/node-agent/instances",async(e,n)=>{const i=await t.create(ma.parse(e.body));return t.afterCreate(i),n.code(201).send({data:i})}),e.post("/api/node-agent/instances/:id/image-provisioning/retry",async e=>{const n=t.retryImageProvisioning(e.params.id);return t.afterImageRetry(n),{data:n}}),e.patch("/api/node-agent/instances/:id",async e=>{const n=t.update(e.params.id,pa.parse(e.body));return await t.afterUpdate(n),{data:n}}),e.post("/api/node-agent/instances/:id/register",async(e,n)=>{const i=e.params.id,r=t.sanitizeReport(i,"register",e.body),s=t.register(i,lr.parse(r),fa(e.headers));return t.afterReport(s,"register"),n.code(201).send({data:s})}),e.post("/api/node-agent/instances/:id/heartbeat",async e=>{const n=e.params.id,i=t.sanitizeReport(n,"heartbeat",e.body),r=t.heartbeat(n,ur.parse(i),fa(e.headers));return t.afterReport(r,"heartbeat"),{data:r}})}(H,{list:()=>N.listInstances(),create:e=>"template"===e.environmentSource?.type?se.runTemplateOperation(e.environmentSource.environmentTemplateId,()=>N.createInstance(e)):N.createInstance(e),retryImageProvisioning:e=>ae.retry(e),update:(e,t)=>{const n=N.requireInstance(e);return N.controlledInstances.put(nr.parse({...n,...t,...t.config?{config:{...n.config,...t.config}}:{},updatedAt:K()}))},register:(e,t,n)=>N.registerInstance(e,t,n),heartbeat:(e,t,n)=>N.heartbeatInstance(e,t,n),sanitizeReport:(e,t,n)=>{const i=n&&"object"==typeof n&&!Array.isArray(n)?n.protocolVersion:void 0;if("string"!=typeof i||i===Ft)return n;const r=({field:n,action:r})=>H.log.warn({instanceId:e,report:t,protocolVersion:i,expectedProtocolVersion:Ft,field:n,action:r},"cross-version controlled instance report sanitized");return"register"===t?function(e,t){if(!e||"object"!=typeof e||Array.isArray(e))return e;const n=e,i=["instanceId","projectId","source","nodeId","runtimeId","imageSelection","instanceVersion","protocolVersion","build","controlMode","capabilities","appInventory","target","workspace","registrationToken","processIncarnationId"],r=new Set([...i,"imageId"]);for(const e of Object.keys(n))r.has(e)||t?.({field:e,action:"ignored"});return Object.prototype.hasOwnProperty.call(n,"imageId")&&t?.({field:"imageId",action:"migrated"}),{...dr(n,i),imageSelection:Nn(n.imageSelection,n.imageId)}}(n,r):function(e,t){if(!e||"object"!=typeof e||Array.isArray(e))return e;const n=["status","health","protocolVersion","build","capabilities","appInventory","apps","aiSessions","triggers","workspace","target","processIncarnationId"],i=new Set(n);for(const n of Object.keys(e))i.has(n)||t?.({field:n,action:"ignored"});return dr(e,n)}(n,r)},afterCreate:e=>{X.syncNow(),e.imageProvisioning&&ce(e)},afterImageRetry:e=>{X.syncNow(),ce(e)},afterUpdate:async e=>{X.syncNow(),await D(e.id)},afterReport:(e,t)=>{X.syncNow(),D(e.id),"register"===t?ne({instanceId:e.id,action:t,protocolVersion:e.protocolVersion,build:e.build,targetStatus:e.targetStatus,targetStrategy:e.target.strategy},"node instance registered"):ne({instanceId:e.id,action:t,status:e.status,health:e.health,protocolVersion:e.protocolVersion,build:e.build,targetStatus:e.targetStatus,apps:e.apps.runningCount},"node instance heartbeat accepted"),!U(e)||e.ready&&"matched"===e.runtimeVersion?.phase||Q.schedule(e.id).catch(n=>H.log.error({instanceId:e.id,error:n},`runtime convergence after ${t} failed`))}}),H.get("/api/node-agent/events",{websocket:!0},(e,t)=>{const n=e;n.send(JSON.stringify({type:"node-agent.events.connected",nodeId:y,serverTime:(new Date).toISOString()}));const i=t.query,r=X.addOutput(n,{expectsTransientSubscription:"1"===i.aiSessionTransient});n.on("message",e=>{try{const t=JSON.parse(String(e));"subscribe"===t.type&&void 0!==t.aiSessionTransient&&X.setOutputSubscription(n,t.aiSessionTransient)}catch{}}),n.on("close",r),n.on("error",r)}),H.get("/api/node-agent/docker/images",async()=>({data:await Hr(e.dockerCommandRunner)})),H.get("/api/node-agent/instances/:id/metrics",async e=>{const t=e.params.id,n=N.requireInstance(t);if("docker"!==N.requireRuntime(n.runtimeId).type){const e=new Error(`Runtime type ${N.requireRuntime(n.runtimeId).type} does not provide resource metrics.`);throw Object.assign(e,{statusCode:409,code:"INSTANCE_METRICS_UNSUPPORTED"}),e}return{data:await Z.snapshot(t)}}),function(e,t,n,i,r,s=new ya){const o=e=>s.intent(e),a=e=>Promise.resolve(i.cancel(e)).then(()=>({ok:!0}),e=>({ok:!1,error:e})),c=(e,t)=>{if(!s.isIntentCurrent(e,t))throw Object.assign(new Error(`Instance operation for ${e} was superseded by stop or delete.`),{statusCode:409,code:"INSTANCE_OPERATION_SUPERSEDED"})};e.post("/api/node-agent/instances/:id/start",async e=>{Ia.parse(e.body);const t=e.params.id,n=o(t);return s.run(t,async()=>(c(t,n),r.allowRecovery(t),{data:await r.start(t,()=>s.isIntentCurrent(t,n))}))}),e.post("/api/node-agent/instances/:id/runtime/reconcile",async e=>{const n=e.params.id;Ia.parse(e.body);const a=o(n);return s.run(n,async()=>{c(n,a);const e=t.requireInstance(n);t.putInstance(nr.parse({...e,ready:!1,runtimeVersion:Lo(Zs(e)),updatedAt:K()})),c(n,a);const s=await i.schedule(n,{startRequested:!["created","stopped"].includes(e.status),resumeCancelled:!0});return c(n,a),r.sync(),{data:s}})}),e.post("/api/node-agent/instances/:id/stop",async e=>{const i=e.params.id;t.requireInstance(i),s.invalidate(i);const o=a(i);return s.run(i,async()=>{const e=t.requireInstance(i);t.applyLifecycle(i,{type:"stop-requested"});try{await r.suppressRecovery(i);const e=await o;if("error"in e)throw e.error;const s=t.requireInstance(i);r.diagnostic({instanceId:i,action:"stop",runtimeId:s.runtimeId,containerName:s.runtime.containerName},"node instance stop requested"),await n.forRuntime(t.requireRuntime(s.runtimeId)).stop(t.context(s))}catch(n){try{t.applyLifecycle(i,{type:"stop-failed",baseline:e}),r.sync()}finally{r.allowRecovery(i)}throw n}const s=t.applyLifecycle(i,{type:"stop-completed"});return r.completeSuppressedRecovery(i),r.sync(),r.diagnostic({instanceId:i,action:"stop",status:s.status,connectionStatus:s.connectionStatus,containerName:s.runtime.containerName},"node instance stop completed"),{data:s}})}),e.post("/api/node-agent/instances/:id/restart",async e=>{const a=e.params.id;Ia.parse(e.body);const d=o(a);return s.run(a,async()=>{c(a,d),r.allowRecovery(a);let e=t.requireInstance(a);if(r.isManaged(e)&&(!e.ready||"matched"!==e.runtimeVersion?.phase)){"failed"===e.runtimeVersion?.phase&&(e=t.putInstance(nr.parse({...e,runtimeVersion:Lo(Zs(e)),updatedAt:K()}))),c(a,d);const n=await i.schedule(a,{startRequested:!0});return c(a,d),r.sync(),{data:n}}r.diagnostic({instanceId:a,action:"restart",runtimeId:e.runtimeId,imageId:e.imageSelection?.imageId,containerName:e.runtime.containerName},"node instance restart requested");const s=await n.forRuntime(t.requireRuntime(e.runtimeId)).restart(t.context(e));let o=t.applyLifecycle(a,{type:"runtime-lifecycle-completed",baseline:e,observation:{...s,target:s.target?{...e.target,...s.target}:void 0}});r.markRestarted(a),c(a,d);const l=nr.parse({...o,updatedAt:K()}),u=await r.probe(l);return c(a,d),o=t.applyLifecycle(a,{type:"runtime-lifecycle-completed",baseline:o,observation:{target:{...o.target,status:u},targetStatus:u,uiAccessStatus:u}}),await r.autoImport(o),r.sync(),r.diagnostic({instanceId:a,action:"restart",status:o.status,connectionStatus:o.connectionStatus,targetStatus:o.targetStatus,targetWeb:o.target.web,containerName:o.runtime.containerName},"node instance restart completed"),{data:o}})}),e.post("/api/node-agent/instances/:id/delete",async e=>{const i=e.params.id,o=bn.parse(e.body);t.requireInstance(i),s.invalidate(i);const c=a(i);return s.run(i,async()=>{const e=t.requireInstance(i);"deleting"!==e.status&&t.applyLifecycle(i,{type:"stop-requested"});try{await r.suppressRecovery(i);const e=await c;if("error"in e)throw e.error;const a=t.requireInstance(i);t.putInstance(nr.parse({...a,status:"deleting",ready:!1,updatedAt:K()})),r.diagnostic({instanceId:i,action:"delete",runtimeId:a.runtimeId,containerName:a.runtime.containerName},"node instance delete requested");const d=await n.forRuntime(t.requireRuntime(a.runtimeId)).delete(t.context(a,{}),o);if(!d.completed)return r.diagnostic({instanceId:i,action:"delete",volumeResults:d.volumeResults},"node instance delete requires retry"),r.sync(),{data:d};r.diagnostic({instanceId:i,action:"delete"},"node instance delete completed");const l=t.deleteInstance(i);return l&&(r.forgetRecovery(i),s.clearIntent(i)),r.deleteMetadata(i),l&&r.retireInstanceData(i),l&&a.environmentTemplateOrigin?.imageId&&r.releaseEnvironmentImage&&await r.releaseEnvironmentImage(a.environmentTemplateOrigin.imageId).catch(e=>{r.diagnostic({instanceId:i,action:"release-environment-image",error:e instanceof Error?e.message:String(e)},"environment image cleanup deferred after instance deletion")}),r.sync(),{data:d}}catch(n){try{t.putInstance(nr.parse({...e,updatedAt:K()})),r.sync()}finally{r.allowRecovery(i)}throw n}})})}(H,{requireInstance:e=>N.requireInstance(e),requireRuntime:e=>N.requireRuntime(e),putInstance:e=>N.controlledInstances.put(e),deleteInstance:e=>N.controlledInstances.delete(e),applyLifecycle:(e,t)=>N.applyInstanceLifecycle(e,t),context:(e,t)=>N.context(e,t)},C,Q,{start:(e,t)=>oe(e,"request",t),sync:()=>X.syncNow(),isManaged:U,probe:e=>ad(R,e,k),autoImport:e=>dd(R,e,"restart",ie,k),markRestarted:e=>_.markRestored(e),allowRecovery:e=>_.allowRecovery(e),suppressRecovery:e=>_.suppressRecovery(e),forgetRecovery:e=>_.forgetInstance(e),completeSuppressedRecovery:e=>_.completeSuppressedOperation(e),deleteMetadata:e=>{x.delete(e),N.modelRegistry.deleteInstanceMetadata(e),N.instancePrivateConfigs.delete(e)},retireInstanceData:e=>{q.retire(e)},releaseEnvironmentImage:e=>se.releaseUnusedImage(e),diagnostic:ne},re),function(e,t){const{fetchImpl:n,metrics:i,diagnostic:r}=t;e.post("/api/node-agent/instances/:id/proxy",async(e,i)=>{const s=performance.now(),o=e.params.id,a=ca.parse(e.body),c=await t.instanceBase(o),d=Oa(a.path);"POST"===a.method&&"/api/apps/sessions"===d&&await t.syncModelEnvironment(o),r({instanceId:o,action:"proxy",method:a.method,path:d,instanceBase:c},"node instance proxy requested");const l=await xa(n,`${c}${d}`,{method:a.method,headers:{...a.headers},body:_a(a)},{instanceId:o,method:a.method,path:d,diagnostic:r}),u=l.headers.get("content-type")||"application/octet-stream",m=await l.text(),p=performance.now()-s,h=l.headers.get(ka)||a.headers[ka],g=function(...e){return e.map(e=>String(e||"").trim()).filter(Boolean).join(", ")}(l.headers.get("server-timing"),function(e,t){return`node_proxy;dur=${(Number.isFinite(t)?Math.max(0,t):0).toFixed(1)}`}(0,p));i.header("server-timing",g),h&&i.header(ka,h),r({instanceId:o,action:"proxy",method:a.method,path:d,statusCode:l.status,contentType:u,durationMs:p,traceId:h},"node instance proxy completed"),i.code(l.status).type(u).send(m)}),e.post("/api/node-agent/instances/:id/proxy/stream",{bodyLimit:za},async(e,s)=>{const o=Date.now();i.requests+=1,i.active+=1;const a=new AbortController;let c=0,d=!1,l=!1;const u=e=>{l||(l=!0,i.active-=1,i.totalDurationMs+=Date.now()-o,i.responseBytes+=c,i[e]+=1)},m=()=>{a.abort(),d&&u("aborted")};e.raw.once("aborted",m),s.raw.once("close",m);try{const o=e.params.id,l=ca.parse(e.body),m=await t.instanceBase(o),p=Oa(l.path);r({instanceId:o,action:"proxy.stream",method:l.method,path:p,instanceBase:m},"node instance streaming proxy requested");const h=await xa(n,`${m}${p}`,{method:l.method,headers:{...l.headers},body:_a(l),signal:a.signal},{instanceId:o,method:l.method,path:p,diagnostic:r}),g=Number(h.headers.get("content-length"));if(Number.isFinite(g)&&g>i.maxResponseBytes)return i.limitRejected+=1,a.abort(),Ra(s,i.maxResponseBytes);s.code(h.status);for(const[e,t]of Object.entries(Ta(h.headers)))s.header(e,t);if(!h.body||"HEAD"===l.method)return u("completed"),s.send();const y=new f.Transform({transform(e,t,n){if(c+=e.length,c>i.maxResponseBytes)return i.limitRejected+=1,a.abort(),void n(Object.assign(new Error("Instance proxy response limit exceeded."),{code:"INSTANCE_PROXY_RESPONSE_TOO_LARGE"}));n(null,e)}});return d=!0,y.once("end",()=>u("completed")),y.once("error",()=>u("aborted")),s.send(f.Readable.fromWeb(h.body).pipe(y))}catch(e){throw u("aborted"),e}finally{e.raw.off("aborted",m),d||u("completed")}}),e.post("/api/node-agent/instances/:id/proxy/raw",{bodyLimit:za},async(e,s)=>{const o=e.params.id,a=ca.parse(e.body),c=await t.instanceBase(o),d=Oa(a.path);r({instanceId:o,action:"proxy.raw",method:a.method,path:d,instanceBase:c},"node instance raw proxy requested");const l=await xa(n,`${c}${d}`,{method:a.method,headers:{...a.headers},body:_a(a)},{instanceId:o,method:a.method,path:d,diagnostic:r}),u=Number(l.headers.get("content-length"));if(Number.isFinite(u)&&u>i.maxResponseBytes)return i.limitRejected+=1,await(l.body?.cancel("Instance proxy response limit exceeded.").catch(()=>{})),Ra(s,i.maxResponseBytes);let m;try{m=await async function(e,t){if(!e.body)return Buffer.alloc(0);const n=[];let i=0;const r=e.body.getReader();for(;;){const{done:e,value: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)}(l,i.maxResponseBytes)}catch(e){if(!(e instanceof Error)||"INSTANCE_PROXY_RESPONSE_TOO_LARGE"!==e.code)throw e;return i.limitRejected+=1,Ra(s,i.maxResponseBytes)}return r({instanceId:o,action:"proxy.raw",method:a.method,path:d,statusCode:l.status,byteLength:m.length},"node instance raw proxy completed"),{data:{status:l.status,headers:Ta(l.headers),bodyBase64:m.toString("base64")}}}),e.get("/api/node-agent/instances/:id/proxy/ws/*",{websocket:!0},async(e,n)=>{const i=n.params.id,s=n.params["*"]||"",o=n.url.indexOf("?"),a=o>=0?n.url.slice(o):"";let c;try{const o=await t.instanceBase(i),d=new URL(`/${s}${a}`,`${o}/`);d.protocol="https:"===d.protocol?"wss:":"ws:";const l=function(e){const t=Object.entries(e).find(([e])=>"sec-websocket-protocol"===e.toLowerCase()),n=t?.[1],i=(Array.isArray(n)?n.join(","):"string"==typeof n?n:"").split(",").map(e=>e.trim()).filter(Boolean);return i.length?i:void 0}(n.headers);r({instanceId:i,action:"proxy.ws",path:`/${s}${a}`,upstreamUrl:d.toString(),protocols:l||[]},"node instance websocket proxy opening"),c=l?new h(d,l):new h(d),c.on("open",()=>{r({instanceId:i,action:"proxy.ws",path:`/${s}${a}`},"node instance websocket proxy opened"),e.on("message",(e,t)=>c?.readyState===h.OPEN&&c.send(function(e,t){return t?e:e.toString()}(e,t))),e.on("close",()=>c?.close()),e.on("error",()=>c?.close())}),c.on("message",(t,n)=>e.readyState===h.OPEN&&e.send(n?t:t.toString())),c.on("close",()=>{r({instanceId:i,action:"proxy.ws",path:`/${s}${a}`},"node instance websocket proxy closed"),e.close()}),c.on("error",t=>{r({instanceId:i,action:"proxy.ws",path:`/${s}${a}`,error:t instanceof Error?t.message:String(t)},"node instance websocket proxy failed"),e.close(1011,"Instance websocket proxy failed.")})}catch(t){r({instanceId:i,action:"proxy.ws",path:`/${s}${a}`,error:t instanceof Error?t.message:String(t)},"node instance websocket endpoint unavailable"),c?.close(),e.close(1011,"Instance websocket endpoint is not reachable.")}})}(H,{fetchImpl:R,metrics:Y,instanceBase:e=>k(N.requireInstance(e)),syncModelEnvironment:e=>ld(R,N,e,ie.warn,k),diagnostic:ne}),H}async function pd(e){const t=js(e.dataDir),n=function(e,t={}){return function(e,t={}){i.mkdirSync(r.dirname(e),{recursive:!0});const n=z.processStartIdentity(process.pid),s={pid:process.pid,hostname:l.hostname(),command:process.argv.join(" "),acquiredAt:(new Date).toISOString(),token:u.randomUUID(),...void 0!==t.component?{component:t.component}:{},...n?{startIdentity:n}:{},...void 0!==t.dataDir?{dataDir:t.dataDir}:{},...void 0!==t.host?{host:t.host}:{},...void 0!==t.port?{port:t.port}:{},...void 0!==t.instanceId?{instanceId:t.instanceId}:{}};for(let n=0;n<5;n+=1)try{return i.mkdirSync(e),i.writeFileSync(C(e),`${JSON.stringify({token:s.token,pid:s.pid,startIdentity:s.startIdentity,startedAt:(new Date).toISOString()})}\n`,{encoding:"utf8",mode:384,flag:"wx"}),M(e,s),{lockPath:e,owner:s,updateDetails:t=>L(e,s,t),release(){const t=x(e);t?.token===s.token&&i.rmSync(e,{recursive:!0,force:!0})}}}catch(r){if("EEXIST"!==r.code)throw r;const s=x(e);if(P(s))throw new T(e,s,t.error);if(!s&&($(e)||V(e)<(t.incompleteLockStaleMs??2e3))){if(n+1<5){U();continue}throw new T(e,void 0,t.error)}const o=u.randomUUID();if(!H(e,o)){if(n+1<5){U();continue}throw new T(e,x(e),t.error)}const a=x(e);if(P(a))throw F(k(e)),new T(e,a,t.error);if(s?.token&&a?.token!==s.token){F(k(e));continue}if(!B(e,o))continue;i.rmSync(e,{recursive:!0,force:!0})}const o=x(e);throw new T(e,o,t.error)}(e,{...t,component:"node-agent",error:{label:"Node agent",code:"NODE_AGENT_ALREADY_RUNNING"}})}(function(){const e=process.env.TASK_HANDOFF_NODE_AGENT_LOCK_PATH?.trim();return e?r.resolve(e):r.join(l.tmpdir(),`task-handoff-node-agent-${process.getuid?.()??"user"}.lock`)}(),{dataDir:t.dataDir});try{const c=(o=e.host,a=e.port,Ki.parse({bindScope:"0.0.0.0"===o.trim()?"all-ipv4":"loopback",port:a})),d=i.existsSync(t.settingsPath),l=function(e,t){return new yo(e.settingsPath,()=>({version:1,externalListener:t}),{schema:Ma,sanitize:ja})}(t,c);let u=l.get().externalListener;if("allocate"===process.env.TASK_HANDOFF_NODE_AGENT_PORT_CONFLICT){const e=await async function(e,t=20){for(let n=0;n<t&&e.port+n<=65535;n+=1){const t={...e,port:e.port+n};if(await $a(t))return t}throw Object.assign(new Error(`No available node-agent port found starting at ${e.port}.`),{statusCode:503,code:"NODE_AGENT_LISTENER_PORT_UNAVAILABLE"})}(u);e.port!==u.port&&(l.put({version:1,externalListener:e}),u=e)}const m=e=>{if(!n.updateDetails({dataDir:t.dataDir,host:e.host,port:e.port,instanceId:void 0}))throw new Error("Node agent singleton ownership changed while publishing listener state.")},p={...e,port:u.port},h=await md(p),g=h.nodeAgentState;if(!g)throw new Error("Node agent state was not initialized.");const f=new pc(t).resolveNodeId(e.nodeId||process.env.TASK_HANDOFF_NODE_ID),y=function(e,t,n,i){const r=t.token||process.env.TASK_HANDOFF_NODE_AGENT_TOKEN,s=new pc(n),o=new Map;let a=!1;const c=(t,n)=>{if(a||n.retry.pending||o.get(t)!==n)return;const r=n.retry.schedule(()=>{a||o.get(t)!==n||n.socket||d(t,n)});r&&(n.status="reconnecting",n.nextRetryAt=new Date(Date.now()+r.delay).toISOString(),e.log.info({nodeId:i,tunnelUrl:new URL(n.config.tunnelUrl).origin,attempt:r.attempt,delay:r.delay},"node agent reverse tunnel reconnect scheduled"))},d=(n,s)=>{let d;s.status=s.lastDisconnectedAt?"reconnecting":"connecting",s.error=void 0,s.failureReason=void 0,s.nextRetryAt=void 0;try{d=Tc(e,{...s.config,nodeId:i,port:()=>e.nodeAgentState.currentListenerPort,token:r})}catch(e){return s.status="failed",s.lastDisconnectedAt=(new Date).toISOString(),s.error=e instanceof Error?e.message:String(e),void c(n,s)}s.socket=d;const l=new Oc({connectTimeoutMs:t.connectTimeoutMs,handshakeTimeoutMs:t.handshakeTimeoutMs,heartbeatIntervalMs:t.heartbeatIntervalMs,heartbeatTimeoutMs:t.heartbeatTimeoutMs,heartbeatMissThreshold:t.heartbeatMissThreshold,stableThresholdMs:t.stableThresholdMs,ping:()=>d.ping(),onTimeout:e=>{o.get(n)===s&&s.socket===d&&(s.status="failed",s.failureReason=`Reverse tunnel ${e} timeout.`,s.error=s.failureReason,d.terminate())},onStable:()=>s.retry.reset()});return s.supervisor=l,l.start(),d.on("open",()=>{o.get(n)===s&&s.socket===d&&(s.status="connecting",l.opened())}),d.on("message",t=>{if(o.get(n)!==s||s.socket!==d)return;if(l.activity(),"connected"===s.status)return;let r;try{r=JSON.parse(String(t))}catch{return}const a=r&&"object"==typeof r?r.type:void 0;"control-plane.hello"!==a&&"control-plane.identified"!==a||(l.activity(),l.healthy(),s.status="connected",s.lastConnectedAt=(new Date).toISOString(),s.nextRetryAt=void 0,s.error=void 0,e.log.info({nodeId:i,tunnelUrl:new URL(s.config.tunnelUrl).origin},"node agent reverse tunnel connected"))}),d.on("pong",()=>l.pong()),d.on("close",(t,r)=>{if(o.get(n)!==s||s.socket!==d)return;l.close(),s.socket=void 0,s.lastDisconnectedAt=(new Date).toISOString();const u=`WebSocket closed${t?` (${t})`:""}${r?`: ${Buffer.isBuffer(r)?r.toString("utf8"):String(r)}`:""}`;s.error=s.failureReason||u,a||(e.log.warn({nodeId:i,tunnelUrl:new URL(s.config.tunnelUrl).origin,code:t,reason:Buffer.isBuffer(r)?r.toString("utf8"):String(r||""),error:s.error,closeOrigin:s.failureReason?"supervisor":"transport"},"node agent reverse tunnel disconnected"),c(n,s))}),d.on("error",e=>{o.get(n)===s&&s.socket===d&&(s.status="failed",s.failureReason=e instanceof Error?e.message:String(e),s.error=s.failureReason,d.terminate())}),d},l=(e,t)=>{const n=o.get(e);n?.retry.cancel(),n?.supervisor?.close();const i={config:t,retry:new ms,status:"connecting"};return o.set(e,i),n?.socket?.close(1e3,"Reverse tunnel reconnecting."),d(e,i)},u=(e,t)=>e.tunnelUrl===t.tunnelUrl&&e.keyId===t.keyId&&e.secret===t.secret;return{connectConfigured:()=>{a=!1;const n=new Map,r=s.resolvedControlPlaneAccess(),c=new Set;for(const{connection:t,pairing:s}of r.connections){if(!t.enabled)continue;if(!s){e.log.warn({nodeId:i,connectionId:t.id,pairingKeyId:t.pairingKeyId},"node agent control-plane connection has no pairing");continue}const r=Rc(t.url);n.set(t.id,{tunnelUrl:r,keyId:s.keyId,secret:s.secret}),c.add(r)}const d=function(e){const t=e.controlPlaneTunnelUrl||process.env.TASK_HANDOFF_CONTROL_PLANE_TUNNEL_URL;return t?new URL(t).toString():void 0}(t);if(d&&!c.has(d)){const e=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);n.set(`explicit:${d}`,{tunnelUrl:d,keyId:e?.keyId,secret:e?.secret}),c.add(d)}const m=r.hasPersistedAccess?void 0:function(){const e=process.env.TASK_HANDOFF_CONTROL_PLANE_URL;if(!e)return;const t=new URL(Va,e);return t.protocol="https:"===t.protocol?"wss:":"ws:",t.toString()}();if(m&&!c.has(m)){const e=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);n.set(`bootstrap:${m}`,{tunnelUrl:m,keyId:e?.keyId,secret:e?.secret})}(e=>{for(const[t,n]of o)e.has(t)||(n.retry.cancel(),n.supervisor?.close(),o.delete(t),n.socket?.close(1e3,"Reverse tunnel configuration removed."));for(const[t,n]of e){const e=o.get(t);e&&u(e.config,n)||l(t,n)}})(n)},state:e=>{const t=o.get(e);if(!t)return;const n=t.supervisor?.diagnostics();return{status:t.status,...void 0===n?.pingRttMs?{}:{pingRttMs:n.pingRttMs},...void 0===n?.pingRttP95Ms?{}:{pingRttP95Ms:n.pingRttP95Ms},consecutiveReconnects:t.retry.attempts,...t.lastConnectedAt?{lastConnectedAt:t.lastConnectedAt}:{},...t.lastDisconnectedAt?{lastDisconnectedAt:t.lastDisconnectedAt}:{},...t.nextRetryAt?{nextRetryAt:t.nextRetryAt}:{},...t.error?{error:t.error}:{}}},closeAll:()=>{a=!0;for(const e of o.values())e.retry.cancel(),e.supervisor?.close(),e.socket?.close(1001,"Node agent shutting down.");o.clear()}}}({log:h.log,inject:e=>h.inject(e),nodeAgentEventForwarder:h.nodeAgentEventForwarder,nodeAgentState:g},p,t,f);h.decorate("nodeAgentReverseTunnels",y);const I=new Fa({app:h,state:g,settings:l,config:u,source:d?"persisted":"bootstrap",onActiveListener:m});let A;h.decorate("nodeAgentListenerManager",I),function(e){let t=!1;const n=async n=>{if(!t){t=!0,y.closeAll(),A?.close();try{await e.close()}finally{process.exitCode=n?0:process.exitCode}}},i=()=>{n("SIGINT")},r=()=>{n("SIGTERM")};process.once("SIGINT",i),process.once("SIGTERM",r),e.addHook("onClose",async()=>{process.off("SIGINT",i),process.off("SIGTERM",r)})}(h),h.addHook("onClose",async()=>{A?.close(),n.release()});try{await h.ready();const n=e.ipcPath||process.env.TASK_HANDOFF_NODE_AGENT_IPC_PATH||Vs(t.dataDir);A=await async function(e,t){!function(e,t=process.platform){if("win32"!==t){i.mkdirSync(r.dirname(e),{recursive:!0,mode:448});try{i.chmodSync(r.dirname(e),448)}catch{}try{i.unlinkSync(e)}catch(e){if("ENOENT"!==e.code)throw e}}}(t);const n=s.createServer((t,n)=>{e.server.emit("request",t,n)});return n.on("upgrade",(t,n,i)=>{e.server.emit("upgrade",t,n,i)}),await new Promise((e,i)=>{n.once("error",i),n.listen(t,()=>{n.off("error",i),e()})}),n}(h,n),await I.start(),y.connectConfigured(),h.nodeAgentStartRecoverySupervisor?.()}catch(e){throw await h.close(),e}}catch(e){throw n.release(),e}var o,a}function hd(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 gd(e){if("local-ipc"!==e&&"local-loopback"!==e)throw new Error("Connection mode must be local-ipc or local-loopback.");return e}function fd(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 e=new n.Command;e.name("task-handoff-node-agent").description("Run a TaskHandoff node agent.").version(S("@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",hd,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",gd).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 pd({host:e.host,port:e.port,dataDir:e.dataDir,token:e.token,connectionMode:e.connectionMode,ipcPath:e.ipcPath,controlPlaneTunnelUrl:e.controlPlaneTunnelUrl})}),e.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",fd).option("--json","Print raw JSON output").action(async t=>{const n=e.opts(),i=t.ipcPath||n.ipcPath||process.env.TASK_HANDOFF_NODE_AGENT_IPC_PATH,r=t.dataDir||n.dataDir||process.env.TASK_HANDOFF_NODE_AGENT_DATA_DIR,o=t.endpoint?void 0:i||Vs(r||Ls()),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",r="string"==typeof n.body||n.body instanceof Buffer?n.body:void 0===n.body||null===n.body?void 0:String(n.body),o=new Headers(n.headers||{});return void 0===r||o.has("content-length")||o.set("content-length",String(Buffer.byteLength(r))),new Promise((a,c)=>{const d=s.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?f.Readable.toWeb(e):null,{status:t,headers:e.headers}))});d.on("error",c);const l=()=>d.destroy(new DOMException("The operation was aborted.","AbortError"));n.signal?.aborted?l():n.signal?.addEventListener("abort",l,{once:!0}),d.once("close",()=>n.signal?.removeEventListener("abort",l)),void 0!==r&&d.write(r),d.end()})}(e.ipcPath,"/pairing/invites",{method:"POST",headers:t,body:n}),r=await i.json().catch(()=>({}));if(!i.ok)throw new Error(r.error?.message||`Node agent pairing invite failed with HTTP ${i.status}`);const o="string"==typeof r.data?.joinToken?r.data.joinToken:"";if(!o)throw new Error("Node agent pairing invite response did not include a join token.");return{nodeId:"string"==typeof r.data?.nodeId?r.data.nodeId:"",joinToken:o,expiresAt:"string"==typeof r.data?.expiresAt?r.data.expiresAt:""}}({endpoint:t.endpoint,ipcPath:o,token:t.token,expiresInMs:t.expiresInMs});t.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 e.parseAsync(process.argv)})().catch(e=>{console.error(e instanceof Error?e.message:String(e)),process.exitCode=1});