@task-handoff/node-agent 0.0.24 → 0.0.25-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/dist/cli.js +1 -1
  2. package/dist/git-provisioning-helper.js +1 -0
  3. package/dist/node-update-worker.js +1 -1
  4. package/docker/entrypoint.sh +8 -0
  5. package/docker/git-provision.sh +126 -0
  6. package/docker/git-provisioning-helper.js +1 -0
  7. package/node_modules/node-pty/LICENSE +69 -0
  8. package/node_modules/node-pty/lib/conpty_console_list_agent.js +16 -0
  9. package/node_modules/node-pty/lib/conpty_console_list_agent.js.map +1 -0
  10. package/node_modules/node-pty/lib/eventEmitter2.js +47 -0
  11. package/node_modules/node-pty/lib/eventEmitter2.js.map +1 -0
  12. package/node_modules/node-pty/lib/eventEmitter2.test.js +30 -0
  13. package/node_modules/node-pty/lib/eventEmitter2.test.js.map +1 -0
  14. package/node_modules/node-pty/lib/index.js +52 -0
  15. package/node_modules/node-pty/lib/index.js.map +1 -0
  16. package/node_modules/node-pty/lib/interfaces.js +7 -0
  17. package/node_modules/node-pty/lib/interfaces.js.map +1 -0
  18. package/node_modules/node-pty/lib/shared/conout.js +11 -0
  19. package/node_modules/node-pty/lib/shared/conout.js.map +1 -0
  20. package/node_modules/node-pty/lib/terminal.js +190 -0
  21. package/node_modules/node-pty/lib/terminal.js.map +1 -0
  22. package/node_modules/node-pty/lib/terminal.test.js +139 -0
  23. package/node_modules/node-pty/lib/terminal.test.js.map +1 -0
  24. package/node_modules/node-pty/lib/testUtils.test.js +28 -0
  25. package/node_modules/node-pty/lib/testUtils.test.js.map +1 -0
  26. package/node_modules/node-pty/lib/types.js +7 -0
  27. package/node_modules/node-pty/lib/types.js.map +1 -0
  28. package/node_modules/node-pty/lib/unixTerminal.js +346 -0
  29. package/node_modules/node-pty/lib/unixTerminal.js.map +1 -0
  30. package/node_modules/node-pty/lib/unixTerminal.test.js +351 -0
  31. package/node_modules/node-pty/lib/unixTerminal.test.js.map +1 -0
  32. package/node_modules/node-pty/lib/utils.js +39 -0
  33. package/node_modules/node-pty/lib/utils.js.map +1 -0
  34. package/node_modules/node-pty/lib/windowsConoutConnection.js +125 -0
  35. package/node_modules/node-pty/lib/windowsConoutConnection.js.map +1 -0
  36. package/node_modules/node-pty/lib/windowsPtyAgent.js +320 -0
  37. package/node_modules/node-pty/lib/windowsPtyAgent.js.map +1 -0
  38. package/node_modules/node-pty/lib/windowsPtyAgent.test.js +90 -0
  39. package/node_modules/node-pty/lib/windowsPtyAgent.test.js.map +1 -0
  40. package/node_modules/node-pty/lib/windowsTerminal.js +199 -0
  41. package/node_modules/node-pty/lib/windowsTerminal.js.map +1 -0
  42. package/node_modules/node-pty/lib/windowsTerminal.test.js +219 -0
  43. package/node_modules/node-pty/lib/windowsTerminal.test.js.map +1 -0
  44. package/node_modules/node-pty/lib/worker/conoutSocketWorker.js +22 -0
  45. package/node_modules/node-pty/lib/worker/conoutSocketWorker.js.map +1 -0
  46. package/node_modules/node-pty/package.json +6 -0
  47. package/node_modules/node-pty/prebuilds/linux-arm64/pty.node +0 -0
  48. package/node_modules/node-pty/prebuilds/linux-x64/pty.node +0 -0
  49. package/package.json +4 -1
  50. package/runtime-artifacts/{controlled-instance-runtime-0.0.24-linux-universal.manifest.json → controlled-instance-runtime-0.0.25-alpha.2-linux-universal.manifest.json} +2 -2
  51. package/runtime-artifacts/controlled-instance-runtime-0.0.25-alpha.2-linux-universal.tar.gz +0 -0
  52. package/runtime-artifacts/controlled-instance-runtime-0.0.25-alpha.2-linux-universal.tar.gz.sha256 +1 -0
  53. package/runtime-artifacts/controlled-instance-runtime-0.0.24-linux-universal.tar.gz +0 -0
  54. package/runtime-artifacts/controlled-instance-runtime-0.0.24-linux-universal.tar.gz.sha256 +0 -1
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 k(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 C(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=C;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=k(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(),ke=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:ke,cwdFolderId:a.z.string().trim().min(1).max(120).optional(),clientRequestId:a.z.string().trim().min(1).max(160)}).strict();const Ce=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:Ce.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","revoked"]),yt=a.z.object({id:lt,targetNodeId:lt,status:ft,createdBy:lt,expiresAt:ut,revokedAt:ut.optional(),createdAt:ut,updatedAt:ut}).strict();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,status:It,revision:a.z.number().int().positive(),lastError:gt.optional(),revokedAt:ut.optional(),createdAt:ut,updatedAt:ut}).strict();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-18",zt=new Set(["2026-08-01","2026-08-16","2026-08-17",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 kt(){return{features:{appRuntime:!1,tty:!1,gui:!1,browser:!1,screenshots:!1,logs:!1,aiSessionWorkspaceSelection:!1,aiSessionPersistenceSettings:!1,aiSessionTimeline:{sessionReadAgents:[],turnReadAgents:[],liveItemAgents:[]}}}}const Ct=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:Ct.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=Ct.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 kn=a.z.enum(["stable","beta","alpha"]),Cn=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:kn.default("stable")}).strict(),Mn=a.z.object({source:a.z.literal("npm"),channel:kn,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(Cn).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:kn,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(Cn).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:kn,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(),ki=a.z.object({modelEndpointProbe:a.z.boolean().optional(),aiSessionHistoryLimit:a.z.boolean().optional(),folderPlaces: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:ki.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 Ci=a.z.object({bindScope:a.z.enum(["loopback","all-ipv4"]),port:a.z.number().int().min(1).max(65535)}).strict(),Oi=Ci.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=Ci;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"]),pingRttMs:a.z.number().nonnegative().optional(),pingRttP95Ms:a.z.number().nonnegative().optional(),consecutiveReconnects:a.z.number().int().nonnegative().optional(),nextRetryAt:Pt.optional(),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({kind:a.z.enum(["home","root"]),name:a.z.string().trim().min(1),path:a.z.string().trim().min(1).max(4096)}).passthrough(),a.z.object({status:a.z.number().int().min(100).max(599).optional(),headers:a.z.record(a.z.string(),a.z.string()).optional(),bodyBase64:a.z.string().optional()}).passthrough();const 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(kt),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(kt),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){Cr(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",kr(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",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:""})),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){Cr(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(Cn,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 kr(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 Cr(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();function Br(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 Kr{retryNumber=0;random;constructor(e=Math.random){this.random=e}get attempts(){return this.retryNumber}next(){return this.retryNumber+=1,{attempt:this.retryNumber,delay:Br(this.retryNumber,this.random)}}reset(){this.retryNumber=0}}class Gr{backoff;timer;constructor(e=Math.random){this.backoff=new Kr(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 Jr extends Gr{}function Wr(e,t=6e4){const n=[];for(let i=0;i<e.length;i+=t)n.push(e.slice(i,i+t));return n}class Yr{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;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 m(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()}addOutput(e){this.outputs.add(e),e.on("close",()=>this.outputs.delete(e)),e.on("error",()=>this.outputs.delete(e));for(const t of this.state.listInstances()){const n=Xr(t);n?this.sendForwarded(e,this.createEvent(Fi,n,{instanceId:t.id})):this.logger?.warn?.({instanceId:t.id},"instance.lifecycle.snapshot.invalid")}for(const[t,n]of this.imagePullTerminalByInstance)Wr(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(Qr(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=es(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 Jr,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.");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)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&&es(t);if(!n||!this.outputs.size)return;const i=this.retries.get(e)??{timer:new Jr};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!==J)return;if("ai-session.message-delta"===t.type)return;const n=Zr(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=Zr(t.payload),i=this.lastAppSessionEventByInstance.get(e);i?.streamId===n.streamId&&void 0!==i.revision&&void 0!==n.revision&&n.revision>i.revision+1&&this.logger?.warn?.({instanceId:e,traceId:n.traceId,streamId:n.streamId,previousRevision:i.revision,revision:n.revision},"app-session.event.forward.gap"),this.lastAppSessionEventByInstance.set(e,{streamId:n.streamId??i?.streamId,revision:n.revision??i?.revision}),this.logger?.info?.({instanceId:e,traceId:n.traceId,eventType:t.type,streamId:n.streamId,revision:n.revision},"app-session.event.forward.message")}}function Xr(e){const t=Ui.safeParse(Qr(e));return t.success?t.data:void 0}function Qr(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 Zr(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 es(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 ts=new Set(["provisioning","starting","registering","registered","running","unhealthy"]),ns=JSON.stringify({id:"{{.ID}}",name:"{{.Name}}",cpu:"{{.CPUPerc}}",memory:"{{.MemUsage}}",memoryPercent:"{{.MemPerc}}",network:"{{.NetIO}}",blockIo:"{{.BlockIO}}",pids:"{{.PIDs}}"});class is{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(!ts.has(t.status))return ds(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=rs(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,rs(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=>ts.has(e.status)&&(e.runtime.containerId||e.runtime.containerName));for(const t of e.filter(e=>ts.has(e.status)&&!e.runtime.containerId&&!e.runtime.containerName))this.update(ls(t.id));for(const t of e.filter(e=>!ts.has(e.status)))this.update(ds(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",ns,...n],{timeoutMs:5e3});this.applyDockerOutput(t,e.stdout,i)}catch(e){if(1===t.length)return void this.update(us(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",ns,t],{timeoutMs:5e3});this.applyDockerOutput([e],n.stdout,i)}catch(t){this.update(us(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=cs(e.id),s=cs(e.name),o=r||s;if(!o)continue;const a=ss(cs(e.memory)),c=ss(cs(e.network)),d=ss(cs(e.blockIo)),l=_i.parse({instanceId:o,runtimeKind:"docker",state:"available",sampledAt:t,cpu:os(e.cpu,"usagePercent"),memory:a?{usageBytes:a[0],...void 0!==a[1]?{limitBytes:a[1]}:{},...os(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:as(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}:us(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 rs(e){return[e.status,e.runtime.containerId||"",e.runtime.containerName||""].join("\0")}function ss(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 os(e,t){const n=Number(cs(e).replace(/%$/,""));return Number.isFinite(n)&&n>=0?{[t]:n}:void 0}function as(e){const t=Number(cs(e));return Number.isFinite(t)&&t>=0?t:void 0}function cs(e){return"string"==typeof e||"number"==typeof e?String(e).trim():""}function ds(e){return{instanceId:e,runtimeKind:"docker",state:"stopped",sampledAt:(new Date).toISOString()}}function ls(e){return{instanceId:e,runtimeKind:"docker",state:"pending",sampledAt:(new Date).toISOString()}}function us(e,t,n){return{instanceId:e,runtimeKind:"docker",state:"unavailable",sampledAt:t,error:n.slice(0,2048)}}function ms(e,t,n){return Object.assign(new Error(e),{statusCode:t,code:n})}function ps(e){const i=n.resolve(e);let r;try{r=t.statSync(i)}catch(e){const t=e&&"object"==typeof e?e.code:void 0;if("ENOENT"===t||"ENOTDIR"===t)throw ms(`Folder ${i} was not found.`,404,"NODE_FOLDER_PATH_NOT_FOUND");throw ms(`Folder ${i} is not accessible.`,403,"NODE_FOLDER_PATH_UNREADABLE")}if(!r.isDirectory())throw ms(`Path ${i} is not a folder.`,400,"NODE_FOLDER_PATH_NOT_DIRECTORY");try{t.accessSync(i,t.constants.R_OK|t.constants.X_OK)}catch{throw ms(`Folder ${i} is not accessible.`,403,"NODE_FOLDER_PATH_UNREADABLE")}return i}function hs(e){try{return t.statSync(e).isDirectory()}catch{return!1}}function gs(){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(hs)}function fs(){const e=n.resolve(c.homedir()),t=gs().map(e=>n.resolve(e));return[...hs(e)?[{kind:"home",name:n.basename(e)||e,path:e}]:[],...t.map(e=>({kind:"root",name:e,path:e}))]}function ys(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()&&hs(n.join(s,e.name))).sort((e,t)=>e.name.localeCompare(t.name)).slice(0,80).flatMap(e=>{const t=ys(n.join(s,e.name),i-1);return t?[t]:[]}):[];return{name:o,path:s,children:c}}function Is(e){return(e.path?[ps(e.path)]:gs()).flatMap(t=>{const n=ys(t,e.depth);return n?[n]:[]})}function As(){return process.env.TASK_HANDOFF_NODE_AGENT_DATA_DIR||n.join(c.homedir(),".config","task-handoff","node-agent")}function bs(e=As()){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 ws(e,t){const i=n.extname(e);return`${i?e.slice(0,-i.length):e}.${t}${i}`}function vs(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(ws(e,n),{force:!0});for(let i=n-1;i>=1;i-=1){const n=ws(e,i);t.existsSync(n)&&t.renameSync(n,ws(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(ws(e,1),r,{mode:384})}return t.truncateSync(e,0),t.chmodSync(e,384),!0}class Es{logsDir;localInstancesRoot;localInstancesTrashRoot;options;constructor(e,t={}){this.options=t,this.logsDir=e.logsDir,this.localInstancesRoot=n.join(e.dataDir,"local-instances"),this.localInstancesTrashRoot=n.join(e.dataDir,"local-instances-trash")}run(e){this.capNodeAgentLogs();const n=new Set(e);if(t.existsSync(this.localInstancesRoot)){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)}capNodeAgentLogs(){const e=[];for(const t of["node-agent.out.log","node-agent.err.log"]){const i=n.join(this.logsDir,t);try{vs(i)&&e.push(i)}catch(e){this.options.logger?.("node-agent log rotation failed",{filePath:i,error:e instanceof Error?e.message:String(e)})}}return e}capControlledInstanceLogs(e){const t=n.resolve(this.localInstancesRoot,e);if(n.dirname(t)!==n.resolve(this.localInstancesRoot))return[];const i=n.join(t,"logs"),r=[];for(const t of["controlled-instance.out.log","controlled-instance.err.log"]){const s=n.join(i,t);try{vs(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 Ns(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 Ss="runtime-manifest.json";class zs 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 Ts(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===Ss)continue;const o=n.join(e,...r.split("/"));if(s.isDirectory()){i.push(...await Ts(e,r));continue}if(s.isSymbolicLink()){const t=await g.readlink(o);if(n.isAbsolute(t))throw new zs("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 zs("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload symlink escapes the artifact: ${r}`);if(!await g.lstat(s).catch(()=>{}))throw new zs("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 zs("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 _s(e){const n=(await Ts(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 ks(e){for(const[t,n]of[["version",e.version],["platform",e.platform],["arch",e.arch]])if(!/^[0-9A-Za-z._-]+$/.test(n))throw new zs("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Invalid runtime artifact ${t}: ${n}`);return`${e.version}-${e.platform}-${e.arch}`}function Cs(e,t){return`${ks(e)}-${e.sha256}-${t}`}async function Os(e){const n=d.createHash("sha256");for await(const i of t.createReadStream(e))n.update(i);return n.digest("hex")}class Rs{#e;#t;#n=new Map;constructor(e){this.#e=e.cacheDir,this.#t=e.fetchImpl??fetch}resolve(e,t){const n=Cn.parse(e);if(!/^[a-f0-9]{64}$/.test(t.archiveSha256))throw new zs("INSTANCE_RUNTIME_ARTIFACT_INVALID","Runtime archive SHA-256 is invalid.");if((t.archiveUrl?1:0)+(t.archivePath?1:0)!=1)throw new zs("INSTANCE_RUNTIME_ARTIFACT_INVALID","Runtime artifact source must specify exactly one archive location.");const i=Cs(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 zs("INSTANCE_RUNTIME_ARTIFACT_INVALID","Runtime archive SHA-256 is invalid.");const r=Cs(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 zs("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 Os(a)!==i.archiveSha256)throw new zs("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 zs)throw e;throw new zs("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 Os(e)===n&&(await this.#s(e,t),!0)}catch{return!1}}async#s(e,t){const i=n.join(this.#e,"validation",`${ks(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 zs("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 zs("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime archive contains unsupported entry type ${r??"unknown"}: ${e}`);return!0}})}catch(e){throw new zs("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,Ss),"utf8"))}catch(e){throw new zs("INSTANCE_RUNTIME_ARTIFACT_INVALID","Runtime artifact manifest is missing or invalid JSON.",{cause:e})}const i=Yi(Cn,t);if(!i.success)throw new zs("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 zs("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 zs("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Unsupported runtime artifact format ${r.formatVersion}.`);if(i?.platform&&"universal"!==r.platform&&r.platform!==i.platform)throw new zs("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 zs("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 zs("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 zs("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 zs("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 zs("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime entrypoint is missing: ${s}`);const a=await _s(e);if(a!==r.sha256)throw new zs("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 xs(e,t,i,r=fetch){if("linux"!==t||!["x64","arm64"].includes(i))throw new zs("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(Cn,JSON.parse(r));if(!o.success||o.data.version!==e||"linux"!==o.data.platform||"universal"!==o.data.arch)throw new zs("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 zs("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 zs)throw t;throw new zs("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 zs("INSTANCE_RUNTIME_ARTIFACT_UNAVAILABLE",`Could not read release metadata for controlled-instance ${e}.`,{cause:t,retryable:!0})});if(!u.ok||!m.ok)throw new zs("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 zs("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Release manifest for controlled-instance ${e} is not valid JSON.`,{cause:t})}const h=Yi(Cn,p);if(!h.success)throw new zs("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 zs("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 zs("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Release checksum for controlled-instance ${e} is invalid.`);return{identity:h.data,source:{archiveUrl:d,archiveSha256:f}}}class Ds{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=Vs(i.retryBaseDelayMs??1e3,"retryBaseDelayMs"),this.retryMaxDelayMs=Vs(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||Ls(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=Ps(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()},!Ls(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?js(t,n):$s("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)),Ls(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),Ms(n)){const t=await this.waitUntil(e,this.drainTimeoutMs,e=>!Ms(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)||Ls(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=>Ps(e)===i);if(this.cancelled.has(e))return this.storePhase(this.requireInstance(e),"pending");if(!r)throw $s("INSTANCE_RUNTIME_VERIFICATION_FAILED",`Instance ${e} did not register controlled-instance ${i} after restart.`,i,Ps(this.requireInstance(e)),!0);const s=this.requireInstance(e);if(this.hooks.isInstalled&&!await this.hooks.isInstalled(s,i))throw $s("INSTANCE_RUNTIME_VERIFICATION_FAILED",`Instance ${e} reported controlled-instance ${i}, but its active runtime release is missing.`,i,Ps(s),!0);return this.storeState(s,{desiredVersion:i,actualVersion:i,phase:"matched",attempt:s.runtimeVersion?.attempt||1,matchedAt:this.timestamp()},!Ls(s)&&"failed"!==s.health)}catch(t){if(this.cancelled.has(e))return this.storePhase(this.requireInstance(e),"pending");r=Fs(t,i,Ps(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?Us(i,Ps(n),this.maxAttempts,r):r);n=this.storeState(n,{desiredVersion:i,...Ps(n)?{actualVersion:Ps(n)}:{},phase:"pending",attempt:s,lastAttemptAt:this.timestamp(),error:r}),await this.delay(this.retryDelayMs(s))}return this.storeBatchFailure(n,i,Us(i,Ps(n),this.maxAttempts,n.runtimeVersion?.error))}finally{a&&await(this.hooks.endDrain?.(this.requireInstance(e)))}}storeBatchFailure(e,t,n){const i=Ps(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=Ps(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:js(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 Ps(e){return e?.build?.packageVersion||e?.instanceVersion}function Ms(e){return e.apps.runningCount>0||e.aiSessions.runningCount>0}function Ls(e){return["created","stopped","failed"].includes(e.status)}function js(e,t){return $s("INSTANCE_RUNTIME_VERSION_MISMATCH",`Expected controlled-instance ${e}, received ${t||"an unknown version"}.`,e,t,!0)}function $s(e,t,n,i,r){return{code:e,message:t,expectedVersion:n,...i?{actualVersion:i}:{},retryable:r}}function Fs(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 $s(r.data,i.message,t,n,"boolean"!=typeof i.retryable||i.retryable)}return $s("INSTANCE_RUNTIME_INSTALL_FAILED",e instanceof Error?e.message:String(e),t,n,!0)}function Us(e,t,n,i){const r=i?.message?` Last error: ${i.message}`:"";return $s(i?.code||"INSTANCE_RUNTIME_INSTALL_FAILED",`Runtime convergence paused after ${n} attempts and will retry.${r}`,e,t,!0)}function Vs(e,t){if(!Number.isFinite(e)||e<0)throw new TypeError(`${t} must be a nonnegative finite number.`);return e}function Hs(e,n=448){t.mkdirSync(e,{recursive:!0,mode:n}),t.chmodSync(e,n)}function qs(e,i,r={}){const s=r.directoryMode??448,o=r.fileMode??384;Hs(n.dirname(e),s),I.sync(e,`${JSON.stringify(i,null,2)}\n`,{encoding:"utf8",mode:o}),t.chmodSync(e,o)}function Bs(e,t){console.warn(JSON.stringify({message:e,...t}))}function Ks(e){return e&&"object"==typeof e&&"issues"in e?{issues:e.issues}:{error:e instanceof Error?e.message:String(e)}}function Gs(e,n){const i=n.logger||Bs;let r;try{r=JSON.parse(t.readFileSync(e,"utf8"))}catch(t){return void i("stored JSON could not be read",{filePath:e,...Ks(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 Js(e){return`${e}_${d.randomUUID().replace(/-/g,"").slice(0,20)}`}function Ws(){return d.randomBytes(24).toString("base64url")}class Ys{directory;options;permissionsInitialized=!1;constructor(e,t={}){this.directory=e,this.options=t}init(){if(this.permissionsInitialized&&t.existsSync(this.directory))return;Hs(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=Gs(n.join(this.directory,e),this.options);return t?[t]:[]})}get(e){this.init();const n=this.filePath(e);return t.existsSync(n)?Gs(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 qs(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 Xs{filePathValue;defaults;options;constructor(e,t,n={}){this.filePathValue=e,this.defaults=t,this.options=n}init(){Hs(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)?Gs(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 qs(this.filePathValue,n,this.options),n}}const Qs=a.z.record(a.z.string(),a.z.string()),Zs=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 eo{directory;constructor(e){this.directory=e}get(e){try{return Qs.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=Qs.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 to{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 no{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 io(){return(new Date).toISOString()}class ro{models;assignments;legacyEnvironments;nodeId;instances;constructor(e,t,n){this.nodeId=t,this.instances=n,this.models=new to(e.nodeModelsDir,t),this.assignments=new no(e.modelAssignmentsDir),this.legacyEnvironments=new eo(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=io(),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:io()}),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:io()});this.assignments.put(r);try{return{assignment:r,instance:this.instances.put($i.parse({...n,modelSelection:t.modelSelection,updatedAt:io()}))}}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=>!Zs.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=io();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 so(){return(new Date).toISOString()}function oo(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 ao(){return process.env.TASK_HANDOFF_NPM_COMMAND||"npm"}function co(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 lo(e){const t=(await e(ao(),["root","--global"])).stdout.trim();if(!t)throw new Error("npm did not return its global module root.");const n=co(t,"@task-handoff/server"),i=co(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 uo(e){if(!e||"object"!=typeof e||Array.isArray(e))return e;const t=e,n="string"==typeof t.updatedAt?t.updatedAt:so(),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=Cn.strip().safeParse(e);return t.success?[t.data]:[]}):[],rollout:f.success?f.data:g,...u?{error:u}:{},...r?{completedAt:t.completedAt||n}:{}}}class mo{records;constructor(e){this.records=new Ys(e.updatesDir,{schema:Ln,sanitize:uo})}init(){this.records.init()}list(){return this.records.list().sort((e,t)=>t.createdAt.localeCompare(e.createdAt))}create(e,t){const n=so();return this.records.put(Ln.parse({id:Js("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:so()}))}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:so()});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:so()}:{}})}}run(e,t){(async()=>{this.patch(e.id,{status:"updating-node",rollout:{...e.rollout,phase:"updating-node"},startedAt:so(),error:void 0});try{await t(e),this.patch(e.id,{status:"succeeded",completedAt:so()})}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:so()})}})()}}function po(){return(new Date).toISOString()}class ho{records;constructor(e){this.records=new Ys(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:po()}))}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 go=a.z.record(a.z.string().regex(/^[A-Za-z_][A-Za-z0-9_]*$/),a.z.string()),fo=a.z.object({version:a.z.literal(1),instanceId:a.z.string().trim().min(1).max(120),instanceCredential:a.z.string().trim().min(1).max(240),environment:go,updatedAt:a.z.string().datetime()}).strict();class yo{directory;constructor(e){this.directory=e.instancePrivateConfigsDir}init(){t.mkdirSync(this.directory,{recursive:!0,mode:448}),t.chmodSync(this.directory,448);for(const e of t.readdirSync(this.directory).filter(e=>e.endsWith(".json")))t.chmodSync(n.join(this.directory,e),384)}filePath(e){return n.join(this.directory,`${e}.json`)}get(e){const n=this.filePath(e);if(!t.existsSync(n))return;const i=JSON.parse(t.readFileSync(n,"utf8")),r=i&&"object"==typeof i&&!Array.isArray(i)?i:{},s=fo.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=fo.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 Io=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 Ao(){return Io()}function bo(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 wo(e){const t=Ao();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:bo(t,e)}}function vo(e,t,n=!0){if(!n)return wo(t);const i=Ao(),r=e.runtimeVersion;if(!r||r.desiredVersion!==i)return wo(t);const s="INSTANCE_RUNTIME_VERSION_MISMATCH"!==r.error?.code?r.error:t===i?void 0:bo(i,t);return Rn.parse({...r,desiredVersion:i,...t?{actualVersion:t}:{actualVersion:void 0},..."pending"===r.phase?{error:s||(t!==i?bo(i,t):void 0)}:{}})}const Eo="runtime_local_host",No="task-handoff.node-agent.builtin";function So(){return(new Date).toISOString()}function zo(e){const t={...e};return delete t[No],t}function To(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 _o(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:To(t),labels:{},createdAt:e.createdAt,updatedAt:e.updatedAt})}function ko(e,t){throw Object.assign(new Error(t),{statusCode:403,code:e})}function Co(e,t){e!==St&&console.warn(JSON.stringify({message:"protocol version mismatch",peer:t,expectedProtocolVersion:St,actualProtocolVersion:e||"missing",errorCode:"PROTOCOL_VERSION_MISMATCH"}))}function Oo(e){return"none"!==e.capabilities.artifactKind}function Ro(e={}){return{...e,requiresImage:!1,supportsControlledInstanceApi:!0,supportsContainerLifecycle:!1,supportsAppSessions:!0,supportsHostSessions:!0,artifactKind:"none",isolation:"none"}}class xo extends Ys{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 Do{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 Ys(e.localFoldersDir,{schema:Vn,sanitize:dn}),this.nodeRuntimes=new Ys(e.nodeRuntimesDir,{schema:Ti}),this.instancePrivateConfigs=new yo(e),this.controlledInstances=new xo(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 ho(e),this.modelRegistry=new ro(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 mo(e),this.listenerPort=r,this.platform=s,this.containerUrlOverride=i;const o=So();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(),Ao(),{processStarted:!0}),!this.nodeRuntimes.get("runtime_local_docker")){const e=So();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(Eo),t=So();this.nodeRuntimes.put(Ti.parse({id:Eo,nodeId:this.nodeId,name:"Local Runtime",type:"local",status:e?.status||"unknown",accessStrategy:"node-proxy",capabilities:Ro(e?.capabilities),labels:{...e?.labels,[No]:"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:So()}));for(const e of this.localFolders.list())e.nodeId!==this.nodeId&&this.localFolders.put(Vn.parse({...e,nodeId:this.nodeId,updatedAt:So()}));this.normalizeInstanceRuntimeVersions()}normalizeInstanceRuntimeVersions(){for(const e of this.controlledInstances.list()){const t=wo(e.build?.packageVersion||e.instanceVersion),n=Oo(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:So()}))}}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=So()}runningInstanceCount(){const e=new Set(["created","stopped","failed"]);return this.listInstances().filter(t=>!e.has(t.status)).length}createLocalFolder(e){const t=So(),n=Vn.parse({...e,path:ps(e.path),id:e.id||Js("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=So(),n=Ti.parse({...e,id:e.id||Js("runtime"),nodeId:this.nodeId,accessStrategy:e.accessStrategy||(i=e.type,"docker"===i?"direct-port":"node-proxy"),capabilities:e.capabilities||{},labels:zo(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[No]){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?zo(t.labels):n.labels,createdAt:n.createdAt,updatedAt:So()});return this.nodeRuntimes.put(i)}deleteRuntime(e){if("true"===this.requireRuntime(e).labels[No]){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:So()});return this.nodeRuntimes.put(t)}):this.nodeRuntimes.put(Ti.parse({...n,status:"unknown",updatedAt:So()}))}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=So(),r=e.id||Js("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:wo(),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:Ws(),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=So(),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;Co(i.protocolVersion,`Instance ${e}`);const o=i.build?.packageVersion||i.instanceVersion,a=Oo(this.requireRuntime(s.runtimeId)),c=vo(s,o,a),d=$i.parse({...s,status:"registered",health:o===Ao()?"ok":"degraded",ready:!a&&o===Ao(),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.`),Co(r.protocolVersion,`Instance ${e}`);const s=So(),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=vo(i,r.build?.packageVersion||i.build?.packageVersion||i.instanceVersion,Oo(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&&ko("INSTANCE_ID_MISMATCH",`Instance ${t.instanceId} cannot register as ${e.id}.`),t.nodeId&&t.nodeId!==this.nodeId&&ko("INSTANCE_NODE_MISMATCH",`Instance ${e.id} belongs to node ${this.nodeId}.`),t.runtimeId&&t.runtimeId!==e.runtimeId&&ko("INSTANCE_RUNTIME_MISMATCH",`Instance ${e.id} belongs to runtime ${e.runtimeId}.`),t.imageSelection&&t.imageSelection.imageId!==e.imageSelection?.imageId&&ko("INSTANCE_IMAGE_MISMATCH",`Instance ${e.id} belongs to image ${e.imageSelection?.imageId}.`)}validateInstanceToken(e,t){e.registrationToken&&t===e.registrationToken||ko("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:_o(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 Po(e,t){const n=function(e){const t=jo(e),n=[],i=t.pathname.split("/").filter(Boolean).at(-1)||"";return Ho(n,Lo(t.toString(),/^v\d+$/.test(i)?"models":"v1/models")),Ho(n,new URL("/v1/models",t.origin).toString()),Ho(n,new URL("/models",t.origin).toString()),n}(t.endpoint),i=Date.now();let r;for(const s of n){const n=await $o(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 Uo("MODEL_DISCOVERY_FAILED",n.status);const o=await Fo(n,"MODEL_DISCOVERY_RESPONSE_INVALID"),a=Array.isArray(o.data)?o.data:void 0;if(!a)throw Vo("MODEL_DISCOVERY_RESPONSE_INVALID","The model endpoint returned an invalid model list.",502);return{models:qo(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 Vo("MODEL_DISCOVERY_UNSUPPORTED","No compatible model-list endpoint was found for this endpoint.",502,r)}async function Mo(e,t){const n=Date.now(),i="codex"===t.app?await $o(e,Lo(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 $o(e,function(e){const t=jo(e),n=t.pathname.split("/").filter(Boolean).at(-1)||"";return Lo(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 Uo("MODEL_TEST_FAILED",i.status);if((await Fo(i,"MODEL_TEST_RESPONSE_INVALID")).error)throw Vo("MODEL_TEST_RESPONSE_INVALID","The model endpoint returned an error payload.",502);return{success:!0,latencyMs:Date.now()-n}}function Lo(e,t){const n=jo(e);return n.pathname=`${n.pathname.replace(/\/+$/,"")}/${t.replace(/^\/+/,"")}`,n.search="",n.hash="",n.toString()}function jo(e){let t;try{t=new URL(e.trim())}catch{throw Vo("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 Vo("MODEL_ENDPOINT_INVALID","The model endpoint must be an HTTP or HTTPS URL without embedded credentials.",400);return t}async function $o(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 Vo(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 Fo(e,t){const n=await e.text();if(n.length>1e6)throw Vo(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 Vo(t,"The model endpoint returned invalid JSON.",502)}}function Uo(e,t){return Vo(e,401===t||403===t?"The model endpoint rejected the API key.":"The model endpoint rejected the request.",502,t)}function Vo(e,t,n,i){return Object.assign(new Error(t),{code:e,statusCode:n,...i?{details:{upstreamStatus:i}}:{}})}function Ho(e,t){e.includes(t)||e.push(t)}function qo(e){const t=new Set;return e.filter(e=>!t.has(e.id)&&(t.add(e.id),!0))}const Bo=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(),Ko=Bo.extend({model:a.z.string().trim().min(1).max(240),app:a.z.enum(["codex","claude"])}).strict(),Go=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(),Jo=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(),Wo=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(),Yo=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."})}),Xo=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(),Qo=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(),Zo=Qo.omit({id:!0}).partial().strict();function ea(e){const t=e.authorization;return"string"==typeof t&&t.startsWith("Bearer ")?t.slice(7).trim():void 0}class ta{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 na=a.z.object({}).strict().default({});function ia(){return(new Date).toISOString()}function ra(){return(new Date).toISOString()}class sa{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=ra();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:ra()},updatedAt:ra()}));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:ra()},updatedAt:ra()})),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:ra()},updatedAt:ra()})),this.options.sync())};await(this.options.runInstanceOperation?.(e,r)??r())}eventBase(e,t){return{instanceId:e.id,generation:t,requestedReference:e.imageProvisioning.requestedReference,observedAt:ra()}}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 oa=a.z.object({name:a.z.string().trim().min(1).max(160)}).strict();function aa(){return(new Date).toISOString()}function ca(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 da{templateOperations=new ta;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=oa.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=aa(),o=Js("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:aa()}))}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:ca(n,"ENVIRONMENT_TEMPLATE_CREATE_FAILED","commit"),updatedAt:aa()}))}})}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:aa()}));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:ca(e,"ENVIRONMENT_TEMPLATE_DELETE_FAILED","delete"),updatedAt:aa()})),e}})}async releaseUnusedImage(e){return!this.store.list().some(t=>t.imageId===e)&&!this.isImageReferencedValue(e)&&this.docker.garbageCollectEnvironmentTemplateImage(e)}}const la=new Set(["DELETE","GET","HEAD","PATCH","POST","PUT","OPTIONS"]);function ua(e){return"string"==typeof e&&la.has(e.toUpperCase())?e.toUpperCase():"GET"}const ma=new Set(["content-encoding","content-length","transfer-encoding"]),pa=67108864;function ha(e){return Object.fromEntries([...e.entries()].filter(([e])=>!ma.has(e.toLowerCase())))}function ga(e){return e.bodyBase64?Buffer.from(e.bodyBase64,"base64"):e.body}function fa(){const e=Number(process.env.TASK_HANDOFF_INSTANCE_PROXY_MAX_RESPONSE_BYTES);return Number.isSafeInteger(e)&&e>0?e:67108864}function ya(e){return e.startsWith("/")?e:`/${e}`}function Ia(e,t){return e.code(502).send({error:{code:"INSTANCE_PROXY_RESPONSE_TOO_LARGE",message:`Instance response exceeds ${t} bytes.`}})}const Aa=a.z.object({version:a.z.literal(1),externalListener:Ci}).strict();function ba(e){return"all-ipv4"===e?"0.0.0.0":"127.0.0.1"}function wa(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 va(e){const t=ba(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 Ea{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:ba(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:ba(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 ${ba(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 ${ba(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:ba(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 Na="TASK_HANDOFF_NODE_AGENT_V1",Sa="/api/node-tunnel";function za(e=""){return d.createHash("sha256").update(e).digest("hex")}function Ta(e,t){return d.createHmac("sha256",e).update(function(e){return[Na,e.keyId,e.method.toUpperCase(),e.pathWithQuery,e.timestamp,e.nonce,e.bodySha256].join("\n")}(t)).digest("hex")}function _a(e){const t=e.timestamp||(new Date).toISOString(),n=e.nonce||d.randomBytes(18).toString("base64url"),i=za(e.body||""),r=Ta(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=za(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,Ta(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 Ca=a.z.string().trim().min(1).max(160),Oa=a.z.string().datetime(),Ra=a.z.string().min(1).max(4096),xa=a.z.string().trim().url().max(2048),Da=a.z.object({id:Ca,keyId:Ca,name:a.z.string().trim().min(1).max(160).optional(),secret:Ra,pairedAt:Oa,revokedAt:Oa.optional(),updatedAt:Oa}).strip(),Pa=a.z.object({id:Ca,pairingKeyId:Ca,name:a.z.string().trim().min(1).max(160).optional(),url:xa,enabled:a.z.boolean().default(!0),createdAt:Oa,updatedAt:Oa}).strip(),Ma=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(),La=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(),ja=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 $a(){return(new Date).toISOString()}const Fa=new Set(["nodeId","createdAt","updatedAt","pairingInvites","controlPlanePairings","controlPlaneConnections","remoteControlPlanes"]),Ua=new Set(["id","keyId","name","secret","pairedAt","revokedAt","updatedAt"]),Va=new Set(["id","pairingKeyId","name","url","enabled","createdAt","updatedAt"]),Ha=new Set(["id","keyId","name","url","secret","pairedAt","updatedAt","active"]);function qa(e,t){console.warn(JSON.stringify({message:e,...t}))}function Ba(e,t){return Object.assign(new Error(e,void 0===t?void 0:{cause:t}),{code:"NODE_AGENT_IDENTITY_INVALID"})}function Ka(e,t){return Object.keys(e).filter(e=>!t.has(e))}function Ga(e,t,n){const i=Oa.safeParse(e);return i.success?i.data:(n("invalid node agent identity timestamp was replaced",{field:t}),$a())}function Ja(e,t){if(!e||"object"!=typeof e||Array.isArray(e))throw Ba("Node agent identity must be a JSON object.");const n=e,i=Ca.safeParse(n.nodeId);if(!i.success)throw Ba("Node agent identity has an invalid nodeId.",i.error);const r=i.data,s=Ka(n,Fa);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=Ka(n,Ha);i.length&&t("unknown legacy node agent remote control-plane fields were ignored",{fields:i});const r=Da.safeParse(n);if(!r.success)return t("invalid legacy node agent control-plane pairing was ignored",{issues:r.error.issues}),[];const s=n.url?Pa.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=Ka(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:Ga(n.createdAt,"createdAt",t),updatedAt:Ga(n.updatedAt,"updatedAt",t),controlPlanePairings:n.controlPlanePairings?a(n.controlPlanePairings,Ua,Da,"control-plane pairing"):o.map(e=>e.pairing),controlPlaneConnections:n.controlPlaneConnections?a(n.controlPlaneConnections,Va,Pa,"control-plane connection"):o.flatMap(e=>e.connection?[e.connection]:[])}}class Wa{paths;logger;constructor(e,t={}){this.paths=e,this.logger=t.logger||qa}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 Ba(`Node agent identity contains invalid JSON: ${this.paths.identityPath}`,e)}return Ja(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=Ja({...e,updatedAt:$a()},this.logger);I.sync(this.paths.identityPath,`${JSON.stringify(i,null,2)}\n`,{encoding:"utf8",mode:384})}}class Ya{values=new Map;put(e,t,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)}}function Xa(){return(new Date).toISOString()}class Qa{store;pairingInvites=new Ya;controlPlaneConnectionOperations=new Map;constructor(e){this.store=new Wa(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=Js("node");return this.writeNodeId(n),n}createPairingInvite(e){const t=Xa(),n=new Date(Date.now()+(e.expiresInMs||6e5)).toISOString(),i=Ws(),r={tokenHash:za(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=za(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=Xa(),s={id:e.controlPlaneId||Js("cp"),keyId:Js("key"),...e.controlPlaneName||i.controlPlaneName?{name:e.controlPlaneName||i.controlPlaneName}:{},secret:Ws(),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=Xa(),n={id:Js("cp"),keyId:Js("key"),...e.name?{name:e.name}:{},secret:Ws(),pairedAt:t,updatedAt:t};return{pairing:n,connection:{id:Js("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=Xa();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:Xa(),updatedAt:Xa(),controlPlanePairings:[],controlPlaneConnections:[]}}writeNodeId(e){const t=this.store.read();this.store.write({...t||{createdAt:Xa()},nodeId:e,updatedAt:Xa(),controlPlanePairings:t?.controlPlanePairings||[],controlPlaneConnections:t?.controlPlaneConnections||[]})}}const Za=a.z.string().trim().min(1).max(160);const ec=jn.strict();function tc(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 nc{preflights=new Map;options;constructor(e){this.options=e}async check(e){const t=Pn.parse(e),n=tc(this.options.listInstances()),i=await lo(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(ao(),["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:so()})}({channel:e.channel,currentVersion:e.currentVersion,impact:e.impact});const i=oo(e.currentVersion,n)||(e.relatedCurrentVersions||[]).some(e=>oo(e,n)),r=i?await async function(e,t,n){const i=await e(ao(),["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:so()})}({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:Ws()};return this.preflights.set(a.preflightToken,{result:a,expiresAt:Date.now()+6e5}),a}async apply(e){const i=ec.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",ao(),...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 lo(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(tc(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 ic=new Set(["provisioning","starting","registering","registered","running"]);function rc(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 sc{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(ic.has(t.status)||"failed"===t.status)&&(!e||e.nextAttemptAt<=(this.options.nowMs?.()??Date.now()))}return"docker"===n.type&&(ic.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(ic.has(e.status)||"failed"===e.status)&&(!t||t.nextAttemptAt<=(this.options.nowMs?.()??Date.now()))}return"docker"===t.type&&(ic.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(rc(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 oc(e){return e.readyState===(e.OPEN??1)}function ac(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 cc(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 dc(e,t,n){e.close(cc(t),ac(n)||void 0)}function lc(e,t,n,i){if(oc(e))for(const e of t.splice(0))if(i(e),!n(e))return}function uc(e,t){const n=new URL(t.tunnelUrl);n.searchParams.set("nodeId",t.nodeId);const i=t.secret?_a({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?_a({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?_a({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&&dc(i.upstream,t,n),i?.tunnel&&dc(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(),dc(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=ua(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 dc(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="")=>{dc(a,e,t),dc(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=oc(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)||(dc(e,1009,"WebSocket bridge traffic limit exceeded."),dc(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 dc(e,1013,"WebSocket bridge consumer is too slow."),dc(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 dc(e,1011,"WebSocket bridge send failed."),dc(t,1011,"WebSocket bridge send failed."),!1}},A=(n,r,s)=>{if(r.length>=i)return dc(e,1011,"WebSocket bridge pending frame limit exceeded."),void dc(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 dc(e,1013,"WebSocket bridge consumer is too slow."),void dc(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||(dc(e,1011,"Upstream websocket did not open."),dc(t))},n.upstreamOpenTimeoutMs)),e.on("open",()=>lc(e,l,t=>I(e,t),e=>{p-=e.bytes})),t.on("open",()=>{y(),c=!0,n.onUpstreamOpen?.(),lc(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)};oc(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)};oc(e)?I(e,i):A("client",l,i)}),t.on("close",(t,i)=>{y(),n.onUpstreamClose?.(t,i),(c||a||!n.onUpstreamCloseBeforeOpen?.())&&dc(e,t,i)}),t.on("error",t=>{n.onUpstreamError?.(t),(c||a||!n.onUpstreamErrorBeforeOpen?.(t))&&dc(e)}),e.on("close",(e,i)=>{y(),a=!0,n.onClientClose?.(e,i),dc(t,e,i)}),e.on("error",e=>{y(),a=!0,n.onClientError?.(e),dc(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=cc(t),o=ac(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=ua(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 mc(e,t){return Number.isFinite(e)&&Number(e)>0?Number(e):t}function pc(e){if(!e.length)return;const t=[...e].sort((e,t)=>e-t);return t[Math.ceil(.95*t.length)-1]}function hc(e){return e.unref?.(),e}class gc{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;pingRttMs;recentPingRttMs=[];constructor(e){this.connectTimeoutMs=mc(e.connectTimeoutMs,1e4),this.handshakeTimeoutMs=mc(e.handshakeTimeoutMs,1e4),this.heartbeatIntervalMs=mc(e.heartbeatIntervalMs,25e3),this.heartbeatTimeoutMs=mc(e.heartbeatTimeoutMs,1e4),this.stableThresholdMs=mc(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=hc(this.setTimeoutFn(()=>this.timeout("connect"),this.connectTimeoutMs))}opened(){this.stopped||(this.clearTimer("connectTimer"),this.setPhase("handshaking"),this.handshakeTimer=hc(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=hc(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();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.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:pc(this.recentPingRttMs)}:{},...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=hc(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 fc(e){const t=new URL(Sa,e);return t.protocol="https:"===t.protocol?"wss:":"ws:",t.toString()}const yc=new Set(["linux","darwin","win32","freebsd","openbsd","aix","sunos"]);function Ic(e){return yc.has(e)?e:"unknown"}function Ac(e){return!0===e.managedArtifacts}class bc{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:Ic(this.platform),...t?{serverVersion:t}:{}}}}}catch(t){return{status:"offline",capabilities:{...e.capabilities,daemon:{status:"offline",hostPlatform:Ic(this.platform),error:t instanceof Error?t.message:String(t)}}}}}}class wc{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(Ac)}async stopAll(){await(this.local.stopAll?.())}}const vc="task-handoff.local-process-nonce",Ec=1e3,Nc=1e4,Sc=2e3;function zc(e,t){try{e?.(t)}catch{}}function Tc(e){return e.runtime.port?`http://127.0.0.1:${e.runtime.port}`:e.target.web}async function _c(e,t){try{const n=await fetch(`${e}/api/internal/node-agent/process-identity`,{headers:{authorization:`Bearer ${t}`},signal:AbortSignal.timeout(Ec)});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 kc(e,t){if(k(e)!==t)return!1;try{process.kill(e,"SIGTERM")}catch{return!0}const n=Date.now()+Nc;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()+Sc;for(;Date.now()<i;){try{process.kill(e,0)}catch{return!0}await new Promise(e=>setTimeout(e,50))}return!1}function Cc(e,t){return Object.assign(new Error(t),{statusCode:503,code:"LOCAL_INSTANCE_STOP_UNCONFIRMED",instanceId:e.id})}async function Oc(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 Rc=Oc;function xc(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 Dc(e,t=1e4,n=2e3,i){if(await xc(e,t))return;zc(i,{stage:"graceful-timeout",pid:e.pid,timeoutMs:t});let r=!1;if(null===e.exitCode&&null===e.signalCode&&(e.kill("SIGKILL"),r=!0,zc(i,{stage:"force-signal-sent",pid:e.pid,signal:"SIGKILL"})),!await xc(e,n))throw zc(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&&zc(i,{stage:"force-exit-confirmed",pid:e.pid,signal:"SIGKILL"})}class Pc{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"),zc(n,{stage:"graceful-signal-sent",pid:t.pid,signal:"SIGTERM"})),this.children.delete(e.id),void await Dc(t,Nc,Sc,n)}const i=await async function(e){const t=Tc(e),n=e.runtime.labels?.[vc];if(!t||!n||!e.registrationToken)return;const i=await _c(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(Ec)})).ok?i:void 0}catch{return}}(e);if(i){const t=Tc(e),n=Date.now()+Nc;for(;t&&Date.now()<n;){if(!await _c(t,e.registrationToken))return;await new Promise(e=>setTimeout(e,50))}const r=t?await _c(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 kc(r.pid,r.startIdentity))return;throw Cc(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 C(e)}(this.lockPath),s=await async function(e){const t=Tc(e);if(t)try{const[n,i]=await Promise.all([fetch(`${t}/api/instance/status`,{signal:AbortSignal.timeout(Ec)}),fetch(`${t}/api/diagnostics`,{signal:AbortSignal.timeout(Ec)})]);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=k(o);return a?{pid:o,startIdentity:a}:void 0}catch{return}}(e);if(s){if(await kc(s.pid,s.startIdentity))return;throw Cc(e,`Legacy controlled instance ${e.id} did not exit after termination.`)}if(r?.instanceId===e.id&&x(r))throw Cc(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 _c(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"),zc(e,{stage:"graceful-signal-sent",pid:t.pid,signal:"SIGTERM"}))}this.children.clear(),await Promise.all(e.map(e=>Dc(e,Nc,Sc,this.lifecycleReporters.get(e))))}}async function Mc(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 Lc{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 Pc(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 Oc(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 Rc(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");vs(f),vs(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:Ao(),...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?k(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 Dc(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",[vc]: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([Mc(this.runCommand,"codex"),Mc(this.runCommand,"claude")]);return{status:"online",capabilities:Ro({...e.capabilities,apps:{terminal:!0,codex:t,claude:n}})}}async stopAll(){await this.processSupervisor.stopAll()}}const jc=["codex","claude"],$c=5e3,Fc=k(process.pid);function Uc(e){const t=process.env[e]?.trim();return t||void 0}function Vc(e){const t=e.authorization;return"string"==typeof t&&t.startsWith("Bearer ")?t.slice(7).trim():void 0}function Hc(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 qc(e){return!e.ip&&!e.socket.remoteAddress&&!e.socket.remoteFamily}function Bc(){return(new Date).toISOString()}async function Kc(e,t){if(!t.target.web)return"unknown";const n=new AbortController,i=setTimeout(()=>n.abort(),2e3);try{return(await e(`${Yc(t)}/api/health`,{signal:n.signal})).ok?"reachable":"endpoint-unreachable"}catch{return"endpoint-unreachable"}finally{clearTimeout(i)}}async function Gc(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 Jc(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=Yc(t),s=Number(process.env.TASK_HANDOFF_CONFIG_AUTO_IMPORT_TIMEOUT_MS||$c);for(const o of jc)try{const a=await Gc(e,`${r}/api/config-sync/import/${encodeURIComponent(o)}`,{method:"POST"},Number.isFinite(s)&&s>0?s:$c);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 Wc(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 Gc(e,`${Yc(r)}/api/internal/model-environment`,{method:"PUT",headers:{"content-type":"application/json",authorization:`Bearer ${r.registrationToken}`},body:JSON.stringify(t.resolvedAssignedModelEnvironment(n))},$c)}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 Yc(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 Xc(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:Bc()}));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 Kc(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:Bc()})),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=bs(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 Qa(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||Ns(l.dataDir),A="local-ipc"===y?`ipc://${encodeURIComponent(I)}`:c,w=e.platform||process.platform,v=e.arch||process.arch,E=new Do(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 wc(new bc(z,N,w,v),new Lc(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"))),k=e.updateCommandRunner||e.dockerCommandRunner||tr,C=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 Gc(C,`${Yc(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})},$c)}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 Rs({cacheDir:n.join(l.dataDir,"runtime-artifacts"),fetchImpl:C}),D=e.resolveRuntimeArtifactRelease||((e,t,n)=>xs(e,t,n,C)),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 Ac(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 Es(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.capNodeAgentLogs(),V.capActiveInstanceLogs(H())}catch(e){U.log.warn({error:e},"node-agent open log maintenance failed")}})()},6e4);K.unref();const G={requests:0,active:0,completed:0,aborted:0,limitRejected:0,responseBytes:0,totalDurationMs:0,maxResponseBytes:fa()};U.decorate("nodeAgentState",E),await U.register(o);const J=new Yr(E,t,{logger:U.log,safetyIntervalMs:Number(process.env.TASK_HANDOFF_EVENT_CONNECTION_SAFETY_INTERVAL_MS)||void 0}),W=new Ds(E.controlledInstances,Ao,{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:Bc()}))}return i},beginDrain:async e=>{try{const t=await async function(e,t){const n=Yc(t);if(t.registrationToken&&(await Gc(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 Gc(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 Gc(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))}}(C,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 Gc(e,`${Yc(t)}/api/internal/node-agent/resume`,{method:"POST",headers:{authorization:`Bearer ${t.registrationToken}`}},5e3)).ok}(C,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(),Ao())}),J.start(),U.decorate("nodeAgentEventForwarder",J);const Y=new is(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 ka(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 ta,ne=new da(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:wo(Ps(i)),updatedAt:Bc()})));const r=E.requireRuntime(i.runtimeId);await Xc(E,_,C,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 Jc(C,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 sa(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 sc({state:E,runtimeAdapters:_,convergence:W,restoreInstance:e=>Xc(E,_,C,e,ee,"restore"),autoImport:e=>Jc(C,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 nc({nodeId:f,jobs:E.updateJobs,runCommand:k,currentRuntimeVersion:Ao,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(qc(e)){if(t&&Vc(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 Hc(e.ip)||Hc(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&&Vc(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,...Fc?{startIdentity:Fc}:{}},listener:{host:"127.0.0.1",port:E.currentListenerPort},nodeId:f,platform:Ic(w),arch:process.arch,protocolVersion:St,capabilities:{modelEndpointProbe:!0,aiSessionHistoryLimit:!0,folderPlaces:!0},build:(e="node-agent",{component:e,packageName:"@task-handoff/node-agent",packageVersion:Ao(),protocolVersion:St,buildId:Uc("TASK_HANDOFF_BUILD_ID"),builtAt:Uc("TASK_HANDOFF_BUILT_AT"),gitCommit:Uc("TASK_HANDOFF_GIT_COMMIT"),imageRef:Uc("TASK_HANDOFF_IMAGE_REF"),imageDigest:Uc("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(!qc(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(Ma.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(La.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=Za.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=Za.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=ja.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:C,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(Qo.parse(e.body))})),e.patch("/api/node-agent/runtimes/:id",async e=>({data:t.updateRuntime(e.params.id,Zo.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(Wo.parse(e.query))})),e.post("/api/node-agent/local-folders",async(e,n)=>n.code(201).send({data:t.createLocalFolder(Jo.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(),listFolderPlaces:fs,listFolderTree:Is,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=Bo.parse(e.body);return{data:await Po(i,{...n,key:t.resolveProbeKey(n.existingModelId,n.key)})}}),e.post("/api/node-agent/models/test",async e=>{const n=Ko.parse(e.body);return{data:await Mo(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=>Wc(C,E,e,ee.warn),C),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(Yo.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,Xo.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),ea(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),ea(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:Bc()}))},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 ta){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=>{na.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;na.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:wo(Ps(e)),updatedAt:ia()})),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;na.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:wo(Ps(e)),updatedAt:ia()}))),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:ia()}),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:ia()})),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:ia()})),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=>Kc(C,e),autoImport:e=>Jc(C,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=Go.parse(e.body),a=t.instanceBase(s),c=ya(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:ga(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:pa},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=Go.parse(e.body),m=t.instanceBase(o),p=ya(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:ga(l),signal:a.signal}),f=Number(g.headers.get("content-length"));if(Number.isFinite(f)&&f>i.maxResponseBytes)return i.limitRejected+=1,a.abort(),Ia(s,i.maxResponseBytes);s.code(g.status);for(const[e,t]of Object.entries(ha(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:pa},async(e,s)=>{const o=e.params.id,a=Go.parse(e.body),c=t.instanceBase(o),d=ya(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:ga(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(()=>{})),Ia(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,Ia(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:ha(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:C,metrics:G,instanceBase:e=>Yc(E.requireInstance(e)),syncModelEnvironment:e=>Wc(C,E,e,ee.warn),diagnostic:Z}),U}async function Zc(e){const r=bs(e.dataDir),s=function(e,i={}){return function(e,i={}){t.mkdirSync(n.dirname(e),{recursive:!0});const r=k(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,Ci.parse({bindScope:"0.0.0.0"===o.trim()?"all-ipv4":"loopback",port:a})),d=t.existsSync(r.settingsPath),l=function(e,t){return new Xs(e.settingsPath,()=>({version:1,externalListener:t}),{schema:Aa,sanitize:wa})}(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 va(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 Qa(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 Qa(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=uc(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 gc({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 Jr,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=fc(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(Sa,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,r,f);h.decorate("nodeAgentReverseTunnels",y);const I=new Ea({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||Ns(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 ed(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 td(e){if("local-ipc"!==e&&"local-loopback"!==e)throw new Error("Connection mode must be local-ipc or local-loopback.");return e}function nd(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",ed,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",td).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 Zc({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",nd).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||Ns(s||As()),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=require("commander"),t=require("node:fs"),n=require("node:path"),i=require("node:http"),s=require("node:url"),r=require("fastify"),o=require("@fastify/websocket"),a=require("zod"),c=require("node:os"),d=require("node:crypto"),l=require("node:child_process"),u=require("node-pty"),p=require("ws"),m=require("node:net"),h=require("node:stream"),g=require("node:fs/promises"),f=require("node:stream/promises"),y=require("tar"),I=require("write-file-atomic"),A=require("semver"),b=require("node:readline/promises"),v=require("node:process"),w="undefined"!=typeof document?document.currentScript:null;function S(e,n){try{const i=JSON.parse(t.readFileSync(e,"utf8"));if(n&&i.name!==n)return;return"string"==typeof i.version&&i.version.trim()?i.version.trim():void 0}catch{return}}function E(e){if(e)try{return n.dirname(t.realpathSync(e))}catch{return}}function N(e,t=process.env,i=e){const s=t.TASK_HANDOFF_VERSION?.trim();if(s)return s;const r=i.split("/").at(-1),o=process.argv[1]?n.resolve(process.argv[1]):void 0,a=o?n.dirname(o):void 0,c=[E(o),a,process.cwd()].filter(e=>Boolean(e));for(const t of new Set(c)){let i=t;for(;;){const t=S(n.join(i,"package.json"),e);if(t)return t;const s=n.dirname(i);if(s===i)break;i=s}}let d;for(const e of new Set(c)){let t=e;for(;;){if(r){const e=S(n.join(t,"packages",r,"package.json"),i);if(e)return e}d||=S(n.join(t,"package.json"));const e=n.dirname(t);if(e===t)break;t=e}}return d||"unknown"}const z={perMessageDeflate:{threshold:256,serverNoContextTakeover:!0,clientNoContextTakeover:!0,concurrencyLimit:4,zlibDeflateOptions:{level:1}}};function T(e){return e.readyState===(e.OPEN??1)}function _(e){const t=Buffer.isBuffer(e)?e.toString("utf8"):"string"==typeof e?e:"";if(Buffer.byteLength(t,"utf8")<=123)return t;let n="";for(const e of t){const t=`${n}${e}`;if(Buffer.byteLength(t,"utf8")>123)break;n=t}return n}function k(e){if("number"==typeof e&&Number.isInteger(e))return e>=3e3&&e<=4999||e>=1e3&&e<=1014&&1004!==e&&1005!==e&&1006!==e?e:void 0}function C(e,t,n){e.close(k(t),_(n)||void 0)}function O(e,t,n,i){if(T(e))for(const e of t.splice(0))if(i(e),!n(e))return}var R,x,P=function(){if(x)return R;x=1;const e=t,{spawnSync:n}=l;return R={processStartIdentity:function(t,i=process.platform){if(Number.isInteger(t)&&!(t<=0)){if("linux"===i)try{const n=e.readFileSync(`/proc/${t}/stat`,"utf8"),i=n.lastIndexOf(")");if(i<0)return;const s=n.slice(i+2).trim().split(/\s+/)[19];return s?`linux:${s}`:void 0}catch{return}if(["darwin","freebsd","openbsd","aix","sunos"].includes(i)){const e=n("ps",["-o","lstart=","-p",String(t)],{encoding:"utf8",timeout:1e3}),s=0===e.status?e.stdout.trim().replace(/\s+/g," "):"";return s?`${i}:${s}`:void 0}if("win32"===i){const e=n("powershell.exe",["-NoProfile","-NonInteractive","-Command",`(Get-Process -Id ${t} -ErrorAction Stop).StartTime.ToUniversalTime().Ticks`],{encoding:"utf8",timeout:2e3}),i=0===e.status?e.stdout.trim():"";return/^\d+$/.test(i)?`win32:${i}`:void 0}}}}}();class D 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 M(e){return n.join(e,"owner.json")}function j(e){return n.join(e,"initializing.json")}function L(e){return n.join(e,"recovering.json")}function F(e){return Number.isInteger(e)&&Number(e)>0}function $(e){try{const n=JSON.parse(t.readFileSync(M(e),"utf8"));if(F(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(!(F(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 U=$;function V(e){if(!F(e))return!1;try{return process.kill(Number(e),0),!0}catch(e){return"EPERM"===e.code}}function H(e){if(!e||!V(e.pid))return!1;if(!e.startIdentity)return!0;const t=P.processStartIdentity(e.pid);return void 0===t||t===e.startIdentity}function B(e,i){const s=n.join(e,`.owner-${i.token}.tmp`);t.writeFileSync(s,`${JSON.stringify(i,null,2)}\n`,{encoding:"utf8",mode:384,flag:"wx"});const r=K(e);if(r?.token!==i.token)throw W(s),new Error(`Process lock initialization was superseded: ${e}`);t.renameSync(s,M(e)),W(j(e))}function q(e,i,s){const r=U(e);if(r?.token!==i.token)return!1;const o={...i};for(const[e,t]of Object.entries(s))void 0===t?delete o[e]:Object.assign(o,{[e]:t});const a=n.join(e,`.owner-update-${i.token}-${d.randomUUID()}.tmp`);try{if(t.writeFileSync(a,`${JSON.stringify(o,null,2)}\n`,{encoding:"utf8",mode:384,flag:"wx"}),U(e)?.token!==i.token)return!1;t.renameSync(a,M(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{W(a)}}function K(e){try{return JSON.parse(t.readFileSync(j(e),"utf8"))}catch{return}}function G(e){const t=K(e);return F(t?.pid)&&H({pid:t.pid,startIdentity:t.startIdentity})}function W(e){try{t.unlinkSync(e)}catch(e){if("ENOENT"!==e.code)throw e}}function J(){Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,20)}function Y(e){try{const n=K(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 X(e,i){try{return t.writeFileSync(L(e),`${JSON.stringify({token:i,pid:process.pid,startedAt:(new Date).toISOString()})}\n`,{encoding:"utf8",mode:384,flag:"wx"}),!0}catch(s){if("EEXIST"===s.code)return!!function(e){const i=L(e),s=Q(i),r=Date.parse(s?.startedAt||"");if(V(s?.pid)||Number.isFinite(r)&&Date.now()-r<2e3)return!1;const o=n.join(e,`.recovering-${d.randomUUID()}.stale`);try{t.renameSync(i,o)}catch(e){if(["ENOENT","EEXIST"].includes(e.code||""))return!1;throw e}const a=Q(o);if(a?.token===s?.token)return W(o),!0;try{t.linkSync(o,i)}catch(e){if("EEXIST"!==e.code)throw e}finally{W(o)}return!1}(e)&&X(e,i);if("ENOENT"===s.code)return!1;throw s}}function Q(e){try{return JSON.parse(t.readFileSync(e,"utf8"))}catch{return}}function Z(e,t){return Q(L(e))?.token===t}function ee(){return(new Date).toISOString()}const te=6048e5;function ne(e,t){const i=n.resolve(e),s=n.resolve(i,t);if(n.dirname(s)!==i||n.basename(s)!==t)throw new Error(`Retention entry is not a direct child of its managed root: ${t}`);return s}function ie(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 se=20971520,re=512e3,oe=re,ae=se,ce=41943040,de="ai.sessions",le="ai-session.snapshot",ue="ai-session.patch",pe="ai-session.removed",me="ai-session.message-delta",he="ai-session.timeline-item",ge=a.z.string().trim().min(1).max(80),fe=a.z.enum(["app-session","ai-session"]),ye=a.z.enum(["image","file"]),Ie={scopeType:a.z.enum(["session","create-request"]),scopeId:a.z.string().trim().min(1).max(160),kind:ye,name:a.z.string().trim().min(1).max(240),mime:a.z.string().trim().min(1).max(120)};a.z.object({...Ie,size:a.z.coerce.number().int().positive().max(se)}).strict();const Ae=a.z.string().regex(/^cia_[a-f0-9]{24}$/);a.z.object({attachmentId:Ae,...Ie,size:a.z.number().int().positive().max(se)}).strict(),a.z.object({offset:a.z.coerce.number().int().nonnegative()}).strict(),a.z.object({attachmentId:Ae,offset:a.z.number().int().nonnegative()}),a.z.object({id:Ae,kind:ye,name:a.z.string().trim().min(1).max(240),mime:a.z.string().trim().min(1).max(120),size:a.z.number().int().positive().max(se),expiresAt:a.z.string().datetime()});const be=a.z.object({id:a.z.string().trim().min(1).max(120),kind:ye,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)}),ve=a.z.enum(["available","expired","missing"]),we=be.extend({contentState:ve.default("available")}).strict(),Se=a.z.object({id:a.z.string().trim().min(1).max(240),text:a.z.string(),attachments:a.z.array(we).max(6).default([])}).strict(),Ee=a.z.enum(["running","waiting","idle","failed"]);a.z.object({instanceId:a.z.string().trim().min(1).max(160),sessionId:a.z.string().trim().min(1).max(120),unread:a.z.boolean(),sessionUpdatedAt:a.z.string().datetime(),updatedAt:a.z.string().datetime()}).strict();const Ne=a.z.enum(["thinking","tool","editing","approval","responding","unknown"]),ze=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(),Te=a.z.enum(["running","completed","failed","waiting"]),_e=a.z.object({id:a.z.string().trim().min(1).max(240),turnId:a.z.string().trim().min(1).max(240)}).strict(),ke=_e.extend({type:a.z.literal("user-message"),text:a.z.string(),attachments:a.z.array(we).max(6).optional()}).strict(),Ce=_e.extend({type:a.z.literal("ai-message"),text:a.z.string()}).strict(),Oe=_e.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:Te.optional(),summary:a.z.string().max(4e3).optional(),input:a.z.string().max(1e5).optional(),output:a.z.string().max(1e6).optional(),paths:a.z.array(a.z.string().trim().min(1).max(4096)).max(500).optional(),exitCode:a.z.number().int().optional(),durationMs:a.z.number().int().nonnegative().optional()}).strict(),Re=a.z.discriminatedUnion("type",[ke,Ce,Oe]);a.z.object({sessionId:a.z.string().trim().min(1).max(120),providerSessionId:a.z.string().trim().min(1).max(240),items:a.z.array(Re),generatedAt:a.z.string().datetime()}).strict(),a.z.object({sessionId:a.z.string().trim().min(1).max(120),turnId:a.z.string().trim().min(1).max(240),items:a.z.array(Re),generatedAt:a.z.string().datetime()}).strict();const xe=a.z.enum(["pending-init","running","interrupted","completed","errored","shutdown","not-found"]),Pe=a.z.enum(["started","interacted","interrupted"]),De=a.z.object({threadId:a.z.string().trim().min(1).max(240),path:a.z.string().trim().max(4096).optional(),status:xe,activity:Pe.optional(),message:a.z.string().trim().max(1e3).optional(),updatedAt:a.z.string().datetime()}).strict(),Me=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}),je=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(),Le=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(),Fe=a.z.union([be.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?se:re;(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.`})}),be.extend({source:a.z.object({type:a.z.literal("runtime-path"),path:a.z.string().trim().min(1).max(4096)}).strict()}).strict()]),$e=be.extend({sourceType:a.z.enum(["inline","runtime-path"])}).strict(),Ue=a.z.union([a.z.object({id:a.z.string().trim().min(1).max(120),kind:ye.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:ye,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()]),Ve=a.z.enum(["auto","queue","steer","immediate"]),He=a.z.enum(["ask","auto-review","full-access"]),Be=a.z.enum(["review","rename","goal","compact"]);a.z.object({command:Be,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:Be,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 qe=a.z.object({name:a.z.string().trim().min(1).max(240),path:a.z.string().trim().min(1).max(4096)}),Ke=a.z.discriminatedUnion("kind",[qe.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(),qe.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(),qe.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()]),Ge=a.z.array(Ke).max(20).default([]),We=a.z.enum(["plugin","skill","file","directory","app"]),Je=a.z.object({kind:We,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."})}),Ye=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(Je).max(1e3).default([]),diagnostics:a.z.array(Ye).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(Je.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 Xe=a.z.object({message:a.z.string().trim().min(1).max(2e4),mode:Ve.optional(),permissionMode:He.optional()}),Qe=Xe.extend({attachments:a.z.array(Fe).max(6).default([]),references:Ge}).strict().superRefine((e,t)=>{e.attachments.reduce((e,t)=>e+("inline"===t.source.type?t.size:0),0)>ce&&t.addIssue({code:a.z.ZodIssueCode.custom,path:["attachments"],message:"Inline attachments must be 41943040 bytes or less in total."})}),Ze=Xe.extend({attachments:a.z.array(Ue).max(6).default([]),references:Ge}).strict(),et=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();Qe.extend({agent:ge,cwd:et,cwdFolderId:a.z.string().trim().min(1).max(120).optional(),clientRequestId:a.z.string().trim().min(1).max(160)}).strict();const tt=a.z.object({mode:a.z.enum(["current-folder","worktree"]),branch:a.z.string().trim().min(1).max(1024)}).strict();Ze.extend({agent:ge,cwdFolderId:a.z.string().trim().min(1).max(120).optional(),gitSelection:tt.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 nt=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:nt.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:fe}).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:fe}).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 it=a.z.object({id:a.z.string().trim().min(1).max(120),messageId:a.z.string().trim().min(1).max(240).optional(),message:a.z.string().trim().min(1).max(2e4),attachments:a.z.array($e).max(6).default([]),references:Ge,permissionMode:He.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(),st=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(it).max(100).default([])}).strict().default({revision:0,pendingCount:0,items:[]}),rt=a.z.enum(["control","realtime","adapter-snapshot","transcript-tail","transcript-scan","process-scan","app-session"]),ot=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(),at=a.z.object({id:a.z.string().trim().min(1).max(240),providerTurnId:a.z.string().trim().max(240).optional(),source:rt.optional(),userPrompt:a.z.string().trim().optional(),userMessages:a.z.array(Se).max(100).optional(),status:a.z.enum(["queued","running","waiting","completed","failed"]).default("running"),phase:Ne.optional(),summary:a.z.string().trim().max(1e3).optional(),lastMessage:a.z.string().trim().optional(),lastMessageItemId:a.z.string().trim().max(240).optional(),contextCompactions:a.z.array(ot).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(),ct=at.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(),dt=a.z.object({id:a.z.string().trim().min(1).max(120),agent:ge,creationSource:fe.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:Le.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:je.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(at).max(50).optional(),status:Ee.default("running"),phase:Ne.default("unknown"),summary:a.z.string().trim().max(1e3).optional(),lastMessage:a.z.string().trim().optional(),lastMessageItemId:a.z.string().trim().max(240).optional(),currentTool:ze.optional(),toolCallsSinceLastMessage:a.z.number().int().min(0).default(0),subAgents:a.z.array(De).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:Me,queue:st}).strict();dt.pick({id:!0,appBindingKeys:!0,cwd:!0,error:!0,providerMeta:!0,queue:!0,subAgents:!0}).strict();const lt=at.pick({id:!0,providerTurnId:!0,status:!0,phase:!0,revision:!0,startedAt:!0,updatedAt:!0,completedAt:!0}).extend({bodyRevision:a.z.string().trim().min(1).max(64)}).strict();a.z.object({sessionId:a.z.string().trim().min(1).max(120),revision:a.z.string().trim().min(1).max(64),turns:a.z.array(lt).max(50)}).strict(),a.z.object({sessionId:a.z.string().trim().min(1).max(120),revision:a.z.string().trim().min(1).max(64),turn:at}).strict();const ut=a.z.object({session:dt,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(),pt=ut.omit({session:!0}).extend({sessionId:a.z.string().trim().min(1).max(120),messageId:a.z.string().trim().min(1).max(240).optional()}).strict();a.z.union([pt,ut.transform(function(e){const t=e.session.turns?.at(-1),n=(e.queueId?e.session.queue?.items.find(t=>t.id===e.queueId)?.messageId:void 0)||("send"===e.action||"queue"===e.action||"steer"===e.action?t?.userMessages?.at(-1)?.id:void 0);return pt.parse({sessionId:e.session.id,provider:e.provider,action:e.action,...e.decision?{decision:e.decision}:{},...e.turnId||e.session.activeTurnId||t?.id?{turnId:e.turnId||e.session.activeTurnId||t?.id}:{},...e.providerTurnId||t?.providerTurnId?{providerTurnId:e.providerTurnId||t?.providerTurnId}:{},...e.queueId?{queueId:e.queueId}:{},...n?{messageId:n}:{}})})]);const mt=500,ht=a.z.object({id:a.z.string().trim().min(1).max(120),agent:ge,creationSource:fe,providerSessionId:a.z.string().trim().min(1).max(240),lineage:Le.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(ht).max(mt).default([])}).strict(),a.z.object({items:a.z.array(ht).max(mt).default([])}).strict(),a.z.object({item:ht,turns:a.z.array(ct).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:fe}).strict();const gt=at.omit({userMessages:!0}),ft=dt.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:a.z.array(gt).max(50).optional(),detailRevision:a.z.string().trim().min(1).max(64).optional(),turnsRevision:a.z.string().trim().min(1).max(64).optional(),turnCount:a.z.number().int().min(0).optional(),subAgentCount:a.z.number().int().min(0).optional(),lastUserMessageAt:a.z.string().datetime().optional()}).strict(),yt=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(ft).default([]),updatedAt:a.z.string().datetime()}).strict(),It=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:yt}).strict();yt.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 At=a.z.enum(["provider-event","app-session-created","app-session-updated","app-session-deleted","discovery-scan","control-action","heartbeat-sync","startup"]),bt=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:At}).strict(),vt=a.z.object({meta:bt,snapshot:yt}).strict(),wt=a.z.object({meta:bt,upserted:a.z.array(ft).default([]),removed:a.z.array(a.z.string().trim().min(1).max(120)).default([])}).strict(),St=a.z.object({meta:bt,sessionIds:a.z.array(a.z.string().trim().min(1).max(120)).default([]),expiresAt:a.z.string().datetime()}).strict(),Et=a.z.object({instanceId:a.z.string().trim().min(1).max(160),nodeId:a.z.string().trim().min(1).max(160).optional(),sessionId:a.z.string().trim().min(1).max(120),providerSessionId:a.z.string().trim().min(1).max(240).optional(),turnId:a.z.string().trim().min(1).max(240),itemId:a.z.string().trim().min(1).max(240),delta:a.z.string().min(1),generatedAt:a.z.string().datetime()}).strict(),Nt=Et.omit({instanceId:!0,nodeId:!0,providerSessionId:!0}).strict();a.z.object({instanceId:a.z.string().trim().min(1).max(160),nodeId:a.z.string().trim().min(1).max(160).optional(),sessionId:a.z.string().trim().min(1).max(120),providerSessionId:a.z.string().trim().min(1).max(240),item:Re,generatedAt:a.z.string().datetime()}).strict(),a.z.object({streamId:a.z.string().trim().min(1).max(240),instanceId:a.z.string().trim().min(1).max(160),sinceRevision:a.z.number().int().min(0),latestRevision:a.z.number().int().min(0),earliestRetainedRevision:a.z.number().int().min(0),syncRequired:a.z.boolean().default(!1),events:a.z.array(a.z.discriminatedUnion("type",[a.z.object({type:a.z.literal(le),payload:vt}).strict(),a.z.object({type:a.z.literal(ue),payload:wt}).strict(),a.z.object({type:a.z.literal(pe),payload:St}).strict()])).default([])}).strict();const zt=a.z.object({source:rt,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(),Tt=zt.extend({type:a.z.literal("snapshot"),agent:a.z.string().trim().min(1).max(80),creationSource:fe.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:Le.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:je.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(at).max(50).optional(),status:Ee.optional(),phase:Ne.optional(),summary:a.z.string().trim().max(1e3).optional(),lastMessage:a.z.string().trim().optional(),lastMessageItemId:a.z.string().trim().max(240).optional(),error:a.z.string().trim().max(4e3).optional(),currentTool:ze.optional(),toolCallsSinceLastMessage:a.z.number().int().min(0).optional(),subAgents:a.z.array(De).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(),_t=zt.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(),userMessage:Se.optional(),text:a.z.string().optional(),itemId:a.z.string().trim().max(240).optional(),status:Ee.optional(),phase:Ne.optional(),summary:a.z.string().trim().max(1e3).optional(),error:a.z.string().trim().max(4e3).optional(),currentTool:ze.nullable().optional(),toolCallsSinceLastMessage:a.z.number().int().min(0).optional(),subAgents:a.z.array(De).max(50).optional(),contextCompaction:ot.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"}),"send-ack"!==e.kind&&"user-message"!==e.kind&&void 0!==e.userMessage&&t.addIssue({code:"custom",path:["userMessage"],message:"userMessage is only valid for send-ack and user-message events"}),"sub-agent-activity"===e.kind?e.subAgents||t.addIssue({code:"custom",path:["subAgents"],message:"sub-agent-activity events require subAgents"}):void 0!==e.subAgents&&t.addIssue({code:"custom",path:["subAgents"],message:"subAgents is only valid for sub-agent-activity events"}),"tool-activity"!==e.kind)return void 0!==e.currentTool&&t.addIssue({code:"custom",path:["currentTool"],message:"currentTool is only valid for tool-activity events"}),void(void 0!==e.toolCallsSinceLastMessage&&t.addIssue({code:"custom",path:["toolCallsSinceLastMessage"],message:"toolCallsSinceLastMessage is only valid for tool-activity events"}));"currentTool"in e||t.addIssue({code:"custom",path:["currentTool"],message:"tool-activity events require currentTool"}),void 0===e.toolCallsSinceLastMessage&&t.addIssue({code:"custom",path:["toolCallsSinceLastMessage"],message:"tool-activity events require toolCallsSinceLastMessage"})});a.z.discriminatedUnion("type",[Tt,_t]);const kt=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()]),Ct=a.z.union([kt,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()]),Ot=a.z.object({promptTemplate:a.z.string().trim().min(1).max(2e4)}).strict(),Rt=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(),xt=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:Ct,action:Ot,policy:Rt.default({maxConcurrentRuns:1,whenBusy:"skip"}),createdAt:a.z.string().datetime(),updatedAt:a.z.string().datetime()}).strict(),Pt=a.z.object({type:a.z.literal("ai-session"),aiSessionId:a.z.string().trim().min(1).max(160)}).strict(),Dt=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:Pt,localName:a.z.string().trim().min(1).max(160).optional(),createdAt:a.z.string().datetime(),updatedAt:a.z.string().datetime()}).strict(),Mt=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(),jt=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:Pt,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(xt).default([]),deployments:a.z.array(Dt).default([]),runtime:a.z.array(Mt).default([]),recentRuns:a.z.array(jt).default([])}).strict();const Lt=a.z.object({instanceId:a.z.string().trim().min(1).max(160),instanceName:a.z.string().trim().min(1).max(160),deployment:Dt,runtime:Mt.optional()}).strip(),Ft=jt.extend({instanceName:a.z.string().trim().min(1).max(160).optional()}).strip(),$t=a.z.object({configHash:a.z.string().trim().min(8).max(80),config:xt,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(Lt),recentRuns:a.z.array(Ft)}).strip();a.z.object({updatedAt:a.z.string().datetime(),triggers:a.z.array($t)}).strip(),a.z.object({name:xt.shape.name,description:xt.shape.description,source:Ct,action:Ot,policy:Rt.partial().optional()}).strict(),a.z.object({scope:a.z.enum(["node","instance"]),nodeId:a.z.string().trim().min(1).max(160).optional(),instanceId:a.z.string().trim().min(1).max(160).optional(),code:a.z.string().trim().min(1).max(160),message:a.z.string().trim().min(1).max(4e3)}).strip();const Ut=a.z.string().regex(/^\d{4}-\d{2}-\d{2}$/,"Proxy protocol version must use YYYY-MM-DD format."),Vt=a.z.string().trim().min(1).max(160).regex(/^[a-zA-Z0-9][a-zA-Z0-9_.:-]*$/),Ht=a.z.string().datetime(),Bt=a.z.string().trim().min(32).max(4096),qt=a.z.string().trim().max(2048).transform((e,t)=>{try{return function(e){const t=new URL(e.trim());if("https:"!==t.protocol||t.username||t.password||"/"!==t.pathname||t.search||t.hash)throw new Error("Proxy origin must be an HTTPS origin without credentials, path, query, or fragment.");return t.origin}(e)}catch(e){return t.addIssue({code:"custom",message:e instanceof Error?e.message:String(e)}),a.z.NEVER}});a.z.string().trim().min(1).max(4096).transform((e,t)=>{try{return function(e){const t=e.trim();if(!t.startsWith("/")||t.startsWith("//")||t.includes("\\")||/%25/i.test(t))throw new Error("Proxy route must be a single-encoded node-agent relative route.");const n=t.split("?",1)[0];let i,s;try{i=n.split("/").map(e=>decodeURIComponent(e))}catch{throw new Error("Proxy route contains invalid percent encoding.")}if(i.some(e=>".."===e||"."===e))throw new Error("Proxy route cannot traverse outside the node-agent API.");try{s=new URL(t,"https://node-agent.invalid")}catch{throw new Error("Proxy route is invalid.")}if("https://node-agent.invalid"!==s.origin||s.username||s.password)throw new Error("Proxy route cannot select an absolute upstream URL.");return`${s.pathname}${s.search}`}(e)}catch(e){return t.addIssue({code:"custom",message:e instanceof Error?e.message:String(e)}),a.z.NEVER}});const Kt=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:Kt,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(),Wt=a.z.enum(["active","revoked"]),Jt=a.z.object({id:Vt,targetNodeId:Vt,status:Wt,createdBy:Vt,expiresAt:Ht,revokedAt:Ht.optional(),createdAt:Ht,updatedAt:Ht}).strict();a.z.object({targetNodeId:Vt,expiresInSeconds:a.z.number().int().min(60).max(3600).default(600)}).strict(),a.z.object({invite:Jt,token:a.z.string().trim().min(24).max(512),proxyOrigin:qt,protocolVersion:Ut}).strict();const Yt=a.z.enum(["active","revoked"]),Xt=a.z.object({id:Vt,claimId:Vt,sourceControlPlaneId:Vt,targetNodeId:Vt,bindingKeyId:Vt,status:Yt,revision:a.z.number().int().positive(),lastError:Gt.optional(),revokedAt:Ht.optional(),createdAt:Ht,updatedAt:Ht}).strict();a.z.object({protocolVersion:Ut,inviteToken:a.z.string().trim().min(24).max(512).optional(),claimId:Vt,sourceControlPlaneId:Vt,targetNodeId:Vt.optional(),bindingKeyId:Vt,credential:Bt}).strict(),a.z.object({sourceControlPlaneId:Vt,bindingKeyId:Vt,credential:Bt}).strict();const Qt=a.z.object({id:Vt,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:Ht.optional(),capabilities:a.z.record(a.z.string(),a.z.unknown()).default({})}).strict(),Zt=a.z.object({protocolVersion:Ut,binding:Xt,streamId:Vt,revision:a.z.number().int().nonnegative(),observedAt:Ht,target:Qt}).strict(),en=a.z.object({type:a.z.literal("control-plane-proxy.event"),protocolVersion:Ut,streamId:Vt,bindingId:Vt,sourceControlPlaneId:Vt,targetNodeId:Vt,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:Qt,event:a.z.object({type:a.z.string().trim().min(1).max(240),topic:a.z.string().trim().min(1).max(240),createdAt:Ht}).strict()}).strict(),tn=a.z.object({type:a.z.literal("control-plane-proxy.events.ready"),protocolVersion:Ut,streamId:Vt,bindingId:Vt,sourceControlPlaneId:Vt,targetNodeId:Vt,latestRevision:a.z.number().int().nonnegative(),earliestRetainedRevision:a.z.number().int().nonnegative()}).strict(),nn=a.z.object({type:a.z.literal("control-plane-proxy.snapshot-required"),protocolVersion:Ut,streamId:Vt,bindingId:Vt,sourceControlPlaneId:Vt,targetNodeId:Vt,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",[en,tn,nn]),a.z.object({protocolVersion:Ut,binding:Xt,target:Zt.shape.target}).strict(),a.z.object({id:Vt,claimId:Vt,proxyOrigin:qt,requestedName:a.z.string().trim().min(1).max(160).optional(),sourceControlPlaneId:Vt,targetNodeId:Vt.optional(),bindingKeyId:Vt,credential:Bt,status:a.z.enum(["pending","compensation-required"]),createdAt:Ht,updatedAt:Ht,expiresAt:Ht}).strict().omit({credential:!0}),a.z.object({id:Vt,nodeId:Vt,proxyOrigin:qt,proxyBindingId:Vt,targetNodeId:Vt,sourceControlPlaneId:Vt,bindingKeyId:Vt,credential:Bt,createdAt:Ht,updatedAt:Ht}).strict();const sn=a.z.string().trim().min(1).max(120),rn=a.z.object({agent:sn,actions:a.z.object({create:a.z.boolean().default(!1),send:a.z.boolean().default(!1),queue:a.z.boolean().default(!1),steer:a.z.boolean().default(!1),interrupt:a.z.boolean().default(!1),archive:a.z.boolean().default(!1),delete:a.z.boolean().default(!1),fork:a.z.boolean().default(!1),approvalDecisions:a.z.array(a.z.enum(["allow","deny","skip"])).max(3).default([])}).passthrough(),timeline:a.z.object({sessionRead:a.z.boolean().default(!1),turnRead:a.z.boolean().default(!1),liveItems:a.z.boolean().default(!1)}).passthrough()}).passthrough(),on=a.z.array(rn).max(100).default([]),an="2026-08-23",cn=new Set(["2026-08-01","2026-08-16","2026-08-17","2026-08-20",an]),dn=a.z.string().regex(/^\d{4}-\d{2}-\d{2}$/,"Protocol version must use YYYY-MM-DD format."),ln=a.z.string().trim().min(1).max(120);function un(){return{features:{appRuntime:!1,tty:!1,gui:!1,browser:!1,screenshots:!1,logs:!1,aiSessionWorkspaceSelection:!1,aiSessionPersistenceSettings:!1,gitCliCredentialBroker:!1,gitCredentialProxy:!1,aiSessionTimeline:{sessionReadAgents:[],turnReadAgents:[],liveItemAgents:[]},aiSessionConversationAttachments:{metadataAgents:[],contentAgents:[],uploadAgents:[],retentionSettings:!1,fileSizeLimitSettings:!1},aiSessionProviders:[]}}}const pn=a.z.object({sessionReadAgents:a.z.array(ln).max(100).default([]),turnReadAgents:a.z.array(ln).max(100).default([]),liveItemAgents:a.z.array(ln).max(100).default([])}).passthrough(),mn=a.z.object({metadataAgents:a.z.array(ln).max(100).default([]),contentAgents:a.z.array(ln).max(100).default([]),uploadAgents:a.z.array(ln).max(100).default([]),retentionSettings:a.z.boolean().default(!1),fileSizeLimitSettings:a.z.boolean().default(!1)}).passthrough(),hn=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),gitCliCredentialBroker:a.z.boolean().optional(),gitCredentialProxy:a.z.boolean().optional(),aiSessionTimeline:pn.default(function(){return{sessionReadAgents:[],turnReadAgents:[],liveItemAgents:[]}}),aiSessionConversationAttachments:mn.optional(),aiSessionProviders:on.optional()}).passthrough(),gn=a.z.object({features:hn.default(function(){return{appRuntime:!1,tty:!1,gui:!1,browser:!1,screenshots:!1,logs:!1,aiSessionWorkspaceSelection:!1,aiSessionPersistenceSettings:!1,gitCliCredentialBroker:!1,gitCredentialProxy:!1,aiSessionTimeline:{sessionReadAgents:[],turnReadAgents:[],liveItemAgents:[]},aiSessionConversationAttachments:{metadataAgents:[],contentAgents:[],uploadAgents:[],retentionSettings:!1,fileSizeLimitSettings:!1},aiSessionProviders:[]}})}).passthrough();function fn(e){const t={features:{appRuntime:!1,tty:!1,gui:!1,browser:!1,screenshots:!1,logs:!1,aiSessionWorkspaceSelection:!1,aiSessionPersistenceSettings:!1,gitCliCredentialBroker:!1,gitCredentialProxy:!1,aiSessionTimeline:{sessionReadAgents:[],turnReadAgents:[],liveItemAgents:[]},aiSessionConversationAttachments:{metadataAgents:[],contentAgents:[],uploadAgents:[],retentionSettings:!1,fileSizeLimitSettings:!1},aiSessionProviders:[]}};if(!e||"object"!=typeof e||Array.isArray(e))return t;const n=e,i=n.features;if(!i||"object"!=typeof i||Array.isArray(i))return t;const s=i,r={appRuntime:!1,tty:!1,gui:!1,browser:!1,screenshots:!1,logs:!1,aiSessionWorkspaceSelection:!1,aiSessionPersistenceSettings:!1,gitCliCredentialBroker:!1,gitCredentialProxy:!1,aiSessionTimeline:{sessionReadAgents:[],turnReadAgents:[],liveItemAgents:[]},aiSessionConversationAttachments:{metadataAgents:[],contentAgents:[],uploadAgents:[],retentionSettings:!1,fileSizeLimitSettings:!1},aiSessionProviders:[]};for(const e of["appRuntime","tty","gui","browser","screenshots","logs","aiSessionWorkspaceSelection","aiSessionPersistenceSettings","gitCliCredentialBroker","gitCredentialProxy"]){const t=a.z.boolean().safeParse(s[e]);t.success&&(r[e]=t.data)}const o=pn.safeParse(s.aiSessionTimeline);o.success&&(r.aiSessionTimeline=o.data);const c=mn.safeParse(s.aiSessionConversationAttachments);c.success&&(r.aiSessionConversationAttachments=c.data);const d=on.safeParse(s.aiSessionProviders);return d.success&&(r.aiSessionProviders=d.data),gn.parse({...n,features:{...s,...r}})}function yn(e){return fn(e).features.aiSessionConversationAttachments}const In=a.z.string().trim().min(1).max(120).regex(/^[a-zA-Z0-9][a-zA-Z0-9_.:-]*$/),An=a.z.string().datetime(),bn=a.z.record(a.z.string(),a.z.string()).default({}),vn=a.z.record(a.z.string(),a.z.string()).default({}),wn=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 Sn(e){if(null==e)return;const t=wn.parse(e);return"utf8"===t.encoding?t.data:Buffer.from(t.data,"base64")}const En=/^[A-Za-z0-9_][A-Za-z0-9_.-]{0,127}$/,Nn=/^sha256:([a-fA-F0-9]{64})$/,zn=/^(?:localhost|[a-z0-9](?:[a-z0-9.-]*[a-z0-9])?)(?::[1-9][0-9]{0,4})?$/,Tn=/^[a-z0-9]+(?:(?:[._]|__|-+)[a-z0-9]+)*$/;function _n(e){const t=e.trim();if(!t||t.length>512||t.includes("://")||/\s/.test(t))throw new Error("Docker image reference must not contain a URL scheme or whitespace.");const n=t.indexOf("@");if(-1!==n&&n!==t.lastIndexOf("@"))throw new Error("Docker image reference contains more than one digest separator.");const i=-1===n?void 0:t.slice(n+1),s=-1===n?t:t.slice(0,n),r=i?Nn.exec(i):void 0;if(i&&!r)throw new Error("Docker image digest must use sha256 followed by 64 hexadecimal characters.");const o=s.lastIndexOf("/"),a=s.lastIndexOf(":"),c=a>o,d=c?s.slice(a+1):void 0,l=c?s.slice(0,a):s;if(d&&!En.test(d))throw new Error("Docker image tag is invalid.");if(!d&&!r)throw new Error("Docker image reference must include an explicit tag or sha256 digest.");const u=l.split("/");if(!u.length||u.some(e=>!e))throw new Error("Docker image repository path is invalid.");const p=u.length>1&&(u[0].includes(".")||u[0].includes(":")||"localhost"===u[0]),m=p?u.slice(1):u;if(p&&!zn.test(u[0].toLowerCase()))throw new Error("Docker image registry host or port is invalid.");if(!m.length||m.some(e=>!Tn.test(e)))throw new Error("Docker image repository names must be lowercase and use valid separators.");const h=u.map((e,t)=>p&&0===t?e.toLowerCase():e).join("/"),g=r?`sha256:${r[1].toLowerCase()}`:void 0;return`${h}${d?`:${d}`:""}${g?`@${g}`:""}`}function kn(e){const t=_n(e),n=t.indexOf("@"),i=-1===n?void 0:t.slice(n+1),s=-1===n?t:t.slice(0,n),r=s.lastIndexOf("/"),o=s.lastIndexOf(":"),a=o>r;return{reference:t,repository:a?s.slice(0,o):s,tag:a?s.slice(o+1):void 0,digest:i}}const Cn=a.z.string().trim().min(1).max(512).transform((e,t)=>{try{return _n(e)}catch(e){return t.addIssue({code:"custom",message:e instanceof Error?e.message:String(e)}),a.z.NEVER}}),On=a.z.string().trim().transform((e,t)=>{const n=Nn.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)}),Rn=a.z.object({codexModelHash:In.nullable().optional(),claudeModelHash:In.nullable().optional(),opencodeModelHash:In.nullable().optional()}).strict().default({}),xn=a.z.object({imageId:In,tag:a.z.string().trim().min(1).max(128).regex(En).optional()}).strict(),Pn=a.z.discriminatedUnion("type",[a.z.object({type:a.z.literal("image"),imageSelection:xn}).strict(),a.z.object({type:a.z.literal("template"),environmentTemplateId:In}).strict()]),Dn=a.z.enum(["creating","ready","failed","deleting"]),Mn=a.z.enum(["linux","darwin","win32","freebsd","openbsd","aix","sunos","unknown"]),jn=a.z.enum(["x64","arm64","arm","ia32","ppc64","s390x","riscv64","unknown"]),Ln=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(),Fn=a.z.object({templateId:In,nodeId:In,imageId:On,name:a.z.string().trim().min(1).max(160),platform:Mn,architecture:jn}).strict(),$n=a.z.enum(["data","agent-home","workspace"]),Un=a.z.object({deleteVolumes:a.z.boolean()}).strict(),Vn=a.z.object({role:$n,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(),Hn=a.z.object({instanceId:In,containerDeleted:a.z.boolean(),completed:a.z.boolean(),deletedVolumes:a.z.array(Vn),retainedVolumes:a.z.array(Vn),volumeResults:a.z.array(Vn)}).strict(),Bn={img_default:"market_taskhandoff_browser",img_codex:"market_taskhandoff_codex",img_ai:"market_taskhandoff_ai"};function qn(e,t){if(e&&"object"==typeof e&&!Array.isArray(e)){const t=e;return{imageId:"string"==typeof t.imageId&&Bn[t.imageId]||t.imageId,..."string"==typeof t.tag?{tag:t.tag}:{}}}if("string"==typeof t)return{imageId:Bn[t]||t}}function Kn(e){if(!e||"object"!=typeof e||Array.isArray(e))return e;const t=e,{defaultImageId:n,...i}=t;return{...i,defaultImageSelection:qn(t.defaultImageSelection,n)}}const Gn=a.z.object({id:In,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(),Wn=a.z.object({code:a.z.enum(["APP_CATALOG_INVALID"]),message:a.z.string().trim().min(1).max(500)}).strict(),Jn=a.z.object({items:a.z.array(Gn).max(256),observedAt:An,issues:a.z.array(Wn).max(32).default([])}).strict(),Yn=a.z.object({id:In,name:a.z.string().trim().min(1).max(160),sourceInstanceId:In,nodeId:In,imageId:On.optional(),internalTag:a.z.string().trim().min(1).max(512).optional(),platform:Mn.optional(),architecture:jn.optional(),sizeBytes:a.z.number().int().nonnegative().optional(),status:Dn,error:Ln.optional(),createdAt:An,updatedAt:An}).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."})}),Xn=a.z.enum(["apt","dnf","brew","npm"]),Qn=a.z.enum(["user","passwordless-sudo","root"]),Zn=a.z.object({platform:Mn,arch:jn,installers:a.z.array(Xn).max(8),privilege:Qn,installerAccess:a.z.object({npmGlobalWritable:a.z.boolean().optional()}).strict().optional()}).strict(),ei=a.z.enum(["installed","not-installed","broken","unsupported"]),ti=a.z.enum(["recipe","bundled","external","none"]),ni=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(),ii=a.z.object({id:In,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:ei,managementSource:ti,version:a.z.string().trim().max(120).optional(),canInstall:a.z.boolean(),canUninstall:a.z.boolean(),installReason:ni.optional(),uninstallReason:ni.optional(),activeJobId:In.optional()}).strict(),si=a.z.enum(["install","uninstall"]),ri=a.z.enum(["queued","running","succeeded","failed","cancelled","interrupted"]),oi=a.z.object({current:a.z.number().finite().nonnegative().optional(),total:a.z.number().finite().positive().optional(),unit:a.z.string().trim().min(1).max(40).optional()}).strict().refine(e=>void 0===e.total||void 0===e.current||e.current<=e.total,{message:"Progress current must not exceed total.",path:["current"]}),ai=a.z.object({executable:a.z.string().trim().min(1).max(4096),args:a.z.array(a.z.string().max(4096)).max(128)}).strict(),ci=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(In).max(64).optional()}).strict(),di=a.z.object({id:In,requestId:In.optional(),appId:In,operation:si,state:ri,phase:a.z.string().trim().min(1).max(120).optional(),progress:oi.optional(),command:ai.optional(),logTail:a.z.string().max(32768).optional(),logTruncated:a.z.boolean().optional(),error:ci.optional(),requestedAt:An,startedAt:An.optional(),finishedAt:An.optional(),updatedAt:An}).strict(),li=a.z.object({streamId:In,sequence:a.z.number().int().nonnegative(),capabilities:Zn,apps:a.z.array(ii).max(256),activeJobs:a.z.array(di).max(256),recentJobs:a.z.array(di).max(256),observedAt:An}).strict();a.z.object({requestId:In.optional()}).strict(),a.z.object({job:di}).strict(),a.z.object({type:a.z.literal("app-management"),streamId:In,sequence:a.z.number().int().nonnegative(),observedAt:An,job:di.optional(),snapshot:li.optional()}).strict().refine(e=>void 0!==e.job||void 0!==e.snapshot,{message:"An app management event requires a job or snapshot."});const ui=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:dn.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:dn,build:ui.extend({component:a.z.literal("control-plane"),packageVersion:a.z.string().trim().min(1).max(80)}).loose(),serverTime:An}).loose()}).loose();const pi=a.z.enum(["stable","beta","alpha"]),mi=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(),hi=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(),gi=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:An.optional(),matchedAt:An.optional(),error:hi.optional()}).strict(),fi=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(In).max(1024).default([]),stoppedInstanceIds:a.z.array(In).max(1024).default([]),activeInstanceIds:a.z.array(In).max(1024).default([])}).strict(),yi=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(In).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(),Ii=a.z.object({channel:pi.default("stable")}).strict(),Ai=a.z.object({source:a.z.literal("npm"),channel:pi,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(mi).default([]),impact:fi,updateAvailable:a.z.boolean(),supported:a.z.boolean().default(!0),reason:a.z.string().trim().max(2048).optional(),checkedAt:An,preflightToken:a.z.string().trim().min(16).max(240).optional()}).strict(),bi=a.z.object({id:In,nodeId:In,source:a.z.literal("npm"),channel:pi,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(mi).default([]),impact:fi,rollout:yi,status:a.z.enum(["queued","updating-node","restarting-node","converging-instances","succeeded","degraded","failed"]),error:hi.optional(),startedAt:An.optional(),completedAt:An.optional(),createdAt:An,updatedAt:An}).strict(),vi=a.z.object({channel:pi,targetVersion:a.z.string().trim().min(1).max(240),preflightToken:a.z.string().trim().min(16).max(240)}).strict(),wi=a.z.object({type:a.z.enum(["branch","tag"]),name:a.z.string().trim().min(1).max(240)}).strict(),Si=a.z.object({type:a.z.literal("commit"),commit:a.z.string().trim().regex(/^[0-9a-fA-F]{4,64}$/,"commit must be a hexadecimal Git object id")}).strict(),Ei=a.z.discriminatedUnion("type",[wi,Si]),Ni=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(),zi=a.z.object({depth:a.z.number().int().positive().max(1e5).optional(),submodules:a.z.boolean().default(!1),lfs:a.z.boolean().default(!1),subdirectory:a.z.string().trim().max(240).refine(e=>!e.startsWith("/")&&!e.split("/").some(e=>".."===e),"subdirectory must be a relative path within the repository").transform(e=>e.split("/").filter(e=>e&&"."!==e).join("/")).default("")}).strict();a.z.object({id:In,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:Ei.default({type:"branch",name:"main"}),auth:Ni.default({type:"none"}),clone:zi.default({submodules:!1,lfs:!1,subdirectory:""}),defaultImageSelection:xn.optional(),labels:bn,createdAt:An,updatedAt:An}).strict();const Ti=a.z.object({id:In,nodeId:In,name:a.z.string().trim().min(1).max(160),path:a.z.string().trim().min(1).max(4096),defaultImageSelection:xn.optional(),labels:bn,createdAt:An,updatedAt:An}).strict(),_i=a.z.discriminatedUnion("type",[a.z.object({type:a.z.literal("git-repository"),repositoryId:In.optional(),url:a.z.string().trim().min(1).max(2048),provider:a.z.string().trim().max(80).optional(),ref:Ei.default({type:"branch",name:"main"}),auth:Ni.default({type:"none"}),clone:zi.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:Ei.default({type:"branch",name:"main"}),auth:Ni.default({type:"none"}),clone:zi.default({submodules:!1,lfs:!1,subdirectory:""})}).strict(),a.z.object({type:a.z.literal("local-folder"),localFolderId:In.optional(),path:a.z.string().trim().min(1).max(4096),ownerNodeId:In.optional()}).strict()]),ki=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(),Ci=a.z.enum(["codex","claude","opencode"]),Oi=a.z.object({id:In,name:a.z.string().trim().min(1).max(160),source:_i,defaultImageSelection:xn.optional(),defaultNodeId:In.optional(),workspacePolicy:ki,labels:bn,createdAt:An,updatedAt:An}).strict(),Ri=a.z.object({id:In,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:Ci,enabled:a.z.boolean().default(!0),order:a.z.number().int().min(0).max(1e6).default(0),labels:bn,createdAt:An,updatedAt:An}).strict(),xi=Ri,Pi=Ri.omit({key:!0}).extend({keyPreview:a.z.string().trim().min(1).max(160),keySet:a.z.boolean()}).strict(),Di=Pi.extend({referenceCount:a.z.number().int().min(0)}).strict(),Mi=a.z.object({instanceId:In,codexModelHash:In.optional(),claudeModelHash:In.optional(),opencodeModelHash:In.optional(),updatedAt:An}).strict(),ji=a.z.discriminatedUnion("type",[a.z.object({type:a.z.literal("control-plane"),name:Ri.shape.name,enabled:Ri.shape.enabled,order:Ri.shape.order}).strict(),a.z.object({type:a.z.literal("node"),nodeId:In,name:Ri.shape.name,enabled:Ri.shape.enabled,order:Ri.shape.order,referenceCount:a.z.number().int().min(0)}).strict()]),Li=a.z.object({id:In,model:Pi,locations:a.z.array(ji).min(1),referenceCount:a.z.number().int().min(0).default(0)}).strict(),Fi=a.z.object({nodeId:In,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(Li),nodeDiagnostics:a.z.array(Fi).default([]),updatedAt:An}).strict();const $i=Ri.omit({id:!0,createdAt:!0,updatedAt:!0}).strict(),Ui=$i.partial().strict(),Vi=Ri,Hi=a.z.object({modelSelection:Rn,codexModelHash:In.optional(),claudeModelHash:In.optional(),opencodeModelHash:In.optional()}).strict();function Bi(e){const t={app:Ci.parse(e.app),endpoint:Ri.shape.endpoint.parse(e.endpoint),key:Ri.shape.key.parse(e.key),model:Ri.shape.model.parse(e.model)};return`mdl_${d.createHash("sha256").update(JSON.stringify(t)).digest("hex")}`}const qi=a.z.enum(["market","custom"]),Ki=a.z.enum(["active","deprecated","yanked"]),Gi=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:On.optional()}).strict()]),Wi=a.z.array(a.z.string().trim().min(1).max(80)).default([]),Ji=a.z.array(a.z.string().trim().min(1).max(120)).default([]),Yi=a.z.record(a.z.string().trim().min(2).max(35),a.z.string().trim().min(1).max(4096)),Xi=a.z.object({os:a.z.string().trim().min(1).max(40),architecture:a.z.string().trim().min(1).max(40),digest:On.optional(),downloadSizeBytes:a.z.number().int().positive().optional(),unpackedSizeBytes:a.z.number().int().positive().optional()}).strict(),Qi=a.z.object({name:a.z.string().trim().min(1).max(128).regex(En),version:a.z.string().trim().min(1).max(160).optional(),reference:Cn,manifestDigest:On.optional(),publishedAt:An.optional(),platforms:a.z.array(Xi).default([]),status:Ki.default("active")}).strict(),Zi=a.z.object({id:In,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:Yi.optional(),cover:Gi.optional(),repository:a.z.string().trim().min(1).max(512),defaultTag:a.z.string().trim().min(1).max(128).regex(En),tags:a.z.array(Qi).min(1),capabilities:Wi,optionalApps:Ji,defaultEnv:vn,labels:bn,status:Ki.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:dn,catalogId:In,revision:a.z.string().trim().min(1).max(240),source:a.z.enum(["embedded","remote","cache"]),generatedAt:An,expiresAt:An.optional(),items:a.z.array(Zi)}).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:An,error:a.z.string().trim().max(4096).optional()}).strict(),a.z.object({id:In,origin:a.z.literal("custom"),name:a.z.string().trim().min(1).max(160),description:a.z.string().trim().max(4096).optional(),localizedDescriptions:Yi.optional(),cover:Gi.optional(),reference:Cn,repository:a.z.string().trim().min(1).max(512),tag:a.z.string().trim().min(1).max(128).regex(En).optional(),pullPolicy:a.z.literal("if-not-present").default("if-not-present"),capabilities:Wi,optionalApps:Ji,defaultEnv:vn,labels:bn,createdAt:An,updatedAt:An}).strict();const es=a.z.object({name:a.z.string().trim().min(1).max(128).regex(En),version:a.z.string().trim().min(1).max(160).optional(),reference:Cn,manifestDigest:On.optional(),status:Ki}).strict(),ts=a.z.object({id:In,origin:qi,name:a.z.string().trim().min(1).max(160),description:a.z.string().trim().max(4096).optional(),localizedDescriptions:Yi.optional(),cover:Gi,repository:a.z.string().trim().min(1).max(512),tag:a.z.string().trim().min(1).max(128).regex(En).optional(),availableTags:a.z.array(es),reference:Cn,digest:On.optional(),downloadSizeBytes:a.z.number().int().positive().optional(),unpackedSizeBytes:a.z.number().int().positive().optional(),capabilities:Wi,optionalApps:Ji,defaultEnv:vn,labels:bn,readOnly:a.z.boolean(),lifecycleStatus:Ki.optional(),market:a.z.object({catalogId:In,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(),ns=a.z.object({id:In,origin:qi,name:a.z.string().trim().min(1).max(160),description:a.z.string().trim().max(4096).optional(),localizedDescriptions:Yi.optional(),cover:Gi.optional(),repository:a.z.string().trim().min(1).max(512),tag:a.z.string().trim().min(1).max(128).regex(En).optional(),requestedReference:Cn,resolvedDigest:On.optional(),resolvedReference:Cn.optional(),downloadSizeBytes:a.z.number().int().positive().optional(),pullPolicy:a.z.literal("if-not-present").default("if-not-present"),capabilities:Wi,optionalApps:Ji,defaultEnv:vn,labels:bn,market:a.z.object({catalogId:In,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:An,updatedAt:An}).strict(),is=a.z.object({phase:a.z.enum(["checking-image","pulling-image","resolving-image","ready","failed"]),requestedReference:Cn,generation:a.z.number().int().nonnegative().default(0),error:a.z.string().trim().max(4096).optional(),startedAt:An,updatedAt:An}).strict(),ss="image.pull.terminal.output",rs="image.pull.terminal.finished",os=a.z.object({instanceId:In,generation:a.z.number().int().nonnegative(),requestedReference:Cn,sequence:a.z.number().int().nonnegative(),observedAt:An}).strict(),as=os.extend({data:a.z.string().min(1).max(65536),replay:a.z.boolean().optional()}).strict(),cs=os.extend({outcome:a.z.enum(["succeeded","failed"])}).strict();os.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 ds=a.z.discriminatedUnion("kind",[a.z.object({kind:a.z.literal("direct")}).strict(),a.z.object({kind:a.z.literal("control-plane-proxy"),proxyId:In,proxyBindingId:In,targetNodeId:In}).strict()]),ls=a.z.object({pingRttMs:a.z.number().nonnegative().optional(),pingRttP95Ms:a.z.number().nonnegative().optional(),consecutiveReconnects:a.z.number().int().nonnegative(),nextRetryAt:An.optional()}).strict();a.z.object({nodeId:In,inviteId:In.optional()}).strict(),a.z.discriminatedUnion("status",[a.z.object({id:In,status:a.z.literal("pending")}).strict(),a.z.object({id:In,status:a.z.literal("completed"),nodeId:In}).strict()]);const us=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:An.optional(),target:Qt.optional(),lastError:Gt.optional(),updatedAt:An}).strict(),ps=a.z.object({id:In,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:ds.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:In.optional(),secret:a.z.string().trim().max(4096).optional(),pairedAt:An.optional(),pairing:a.z.object({status:a.z.enum(["pending","paired","expired"]).default("pending"),joinToken:a.z.string().trim().max(4096).optional(),expiresAt:An.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:us.optional(),appInventory:Jn.optional(),labels:bn,lastSeenAt:An.optional(),createdAt:An,updatedAt:An}).strict().superRefine((e,t)=>{"control-plane-proxy"===e.connectionPath.kind&&"control-plane-proxy"!==e.connectionMode&&t.addIssue({code:"custom",path:["connectionPath"],message:"Control-plane proxy paths require control-plane-proxy connection mode."}),"control-plane-proxy"===e.connectionMode&&"control-plane-proxy"!==e.connectionPath.kind&&t.addIssue({code:"custom",path:["connectionPath"],message:"Control-plane proxy nodes require a control-plane-proxy connection path."})});a.z.object({nodeId:In,status:a.z.enum(["unknown","online","offline","degraded"]),health:a.z.enum(["unknown","ok","degraded","failed"]),lastSeenAt:An.nullable(),connectionPhase:a.z.enum(["connecting","handshaking","healthy","reconnecting","suspect","offline"]).nullable(),connectionDiagnostics:ls.nullable(),proxyState:us.nullable()}).strict();const ms=a.z.object({id:In,nodeId:In,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:bn,createdAt:An,updatedAt:An}).strict(),hs=a.z.object({instanceId:In,runtimeKind:a.z.literal("docker"),state:a.z.enum(["pending","available","stopped","unavailable"]),sampledAt:An,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(),gs=a.z.object({registry:a.z.boolean().default(!1),runtimeBroker:a.z.boolean().default(!1),workspaceProvisioning:a.z.object({docker:a.z.boolean().default(!1),kubernetes:a.z.boolean().default(!1),local:a.z.boolean().default(!1)}).strip().default({docker:!1,kubernetes:!1,local:!1})}).strip(),fs=a.z.object({modelEndpointProbe:a.z.boolean().optional(),aiSessionHistoryLimit:a.z.boolean().optional(),aiSessionAttachmentRetention:a.z.boolean().optional(),aiSessionFileAttachmentLimit:a.z.boolean().optional(),folderPlaces:a.z.boolean().optional(),localFolderNameUpdate:a.z.boolean().optional(),managedGitCredentials:gs.optional()}).strip(),ys=a.z.object({status:a.z.enum(["healthy","congested","recovering"]),activeOutputs:a.z.number().int().nonnegative(),bufferedBytes:a.z.number().int().nonnegative(),peakBufferedBytes:a.z.number().int().nonnegative(),coalescedEvents:a.z.number().int().nonnegative(),oversizedEvents:a.z.number().int().nonnegative().optional(),peakEventBytes:a.z.number().int().nonnegative().optional(),congestedSince:An.optional(),lastCongestedAt:An.optional()}).strip();a.z.object({ok:a.z.boolean().optional(),role:a.z.string().optional(),nodeId:In.optional(),platform:Mn.optional(),arch:jn.optional(),protocolVersion:dn.optional(),capabilities:fs.optional(),build:ui.strip().optional(),process:a.z.object({pid:a.z.number().int().positive(),startIdentity:a.z.string().trim().min(1).optional()}).strip().optional(),listener:a.z.object({host:a.z.string().trim().min(1),port:a.z.number().int().min(1).max(65535)}).strip().optional(),instanceProxy:a.z.object({requests:a.z.number().int().nonnegative(),active:a.z.number().int().nonnegative(),completed:a.z.number().int().nonnegative(),aborted:a.z.number().int().nonnegative(),limitRejected:a.z.number().int().nonnegative(),responseBytes:a.z.number().nonnegative(),totalDurationMs:a.z.number().nonnegative(),maxResponseBytes:a.z.number().int().nonnegative()}).partial().strip().optional(),eventTransport:ys.optional(),serverTime:An.optional()}).strip();const Is=a.z.object({bindScope:a.z.enum(["loopback","all-ipv4"]),port:a.z.number().int().min(1).max(65535)}).strict(),As=Is.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(),bs=Is;a.z.object({nodeId:In,joinToken:a.z.string().trim().min(1),expiresAt:An}).passthrough(),a.z.object({nodeId:In,keyId:In,secret:a.z.string().regex(/^[A-Za-z0-9_-]{32,128}$/),pairedAt:An}).strict();const vs=a.z.object({id:In,keyId:In,name:a.z.string().trim().min(1).max(160).optional(),pairedAt:An,updatedAt:An,current:a.z.boolean()}).passthrough();a.z.object({keyId:In,revoked:a.z.literal(!0),revokedAt:An}).strict(),a.z.object({id:In,pairingKeyId:In,url:a.z.string().trim().min(1).max(2048),name:a.z.string().trim().min(1).max(160).optional(),enabled:a.z.boolean(),createdAt:An,updatedAt:An,status:a.z.enum(["disabled","connecting","connected","reconnecting","failed"]),pingRttMs:a.z.number().nonnegative().optional(),pingRttP95Ms:a.z.number().nonnegative().optional(),consecutiveReconnects:a.z.number().int().nonnegative().optional(),nextRetryAt:An.optional(),lastConnectedAt:An.optional(),lastDisconnectedAt:An.optional(),error:a.z.string().optional()}).passthrough(),a.z.object({pairing:vs,connection:a.z.object({id:In,pairingKeyId:In,url:a.z.string().trim().min(1).max(2048),name:a.z.string().trim().min(1).max(160).optional(),enabled:a.z.boolean(),createdAt:An,updatedAt:An}).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 ws=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:ts,status:a.z.enum(["available","pull-required","unknown"]),localImage:ws.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 Ss=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(Ss)}).passthrough());a.z.object({kind:a.z.enum(["home","root"]),name:a.z.string().trim().min(1),path:a.z.string().trim().min(1).max(4096)}).passthrough(),a.z.object({status:a.z.number().int().min(100).max(599).optional(),headers:a.z.record(a.z.string(),a.z.string()).optional(),bodyBase64:a.z.string().optional()}).passthrough();const Es=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(),Ns=a.z.object({...Es.shape}).strict(),zs=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"}),Ts=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(),_s=a.z.object({id:In,name:a.z.string().trim().min(1).max(160),projectId:In.optional(),source:_i,sourceSnapshot:a.z.record(a.z.string(),a.z.unknown()).default({}),modelSelection:Rn,nodeId:In,runtimeId:In,imageSelection:xn.optional(),environmentSource:Pn.optional(),environmentTemplateOrigin:Fn.optional(),imageSnapshot:ns.optional(),imageProvisioning:is.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:dn.optional(),instanceVersion:a.z.string().trim().max(80).optional(),build:ui.optional(),runtimeVersion:gi.optional(),ready:a.z.boolean().default(!1),capabilities:gn.default(un),appInventory:Jn.optional(),config:a.z.object({autoImportAgentConfigs:a.z.boolean().default(!0),defaultCodexPermissionMode:He.default("ask"),aiSessionHistoryLimit:a.z.number().int().min(1).max(mt).default(50),aiSessionAttachmentRetentionDays:a.z.number().int().min(0).max(365).default(30),aiSessionMaxFileAttachmentBytes:a.z.number().int().positive().max(ae).default(oe)}).strict().default({autoImportAgentConfigs:!0,defaultCodexPermissionMode:"ask",aiSessionHistoryLimit:50,aiSessionAttachmentRetentionDays:30,aiSessionMaxFileAttachmentBytes:oe}),workspace:Ts.default({status:"unknown"}),target:Es.default({strategy:"direct-port",status:"unknown"}),access:zs,apps:a.z.object({runningCount:a.z.number().int().min(0).default(0),problemCount:a.z.number().int().min(0).default(0),updatedAt:An.optional(),revision:a.z.number().int().min(0).optional()}).strict().default({runningCount:0,problemCount:0}),aiSessions:yt.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:xt,deployments:a.z.array(Dt).default([]),runtime:a.z.array(Mt).default([])}).strict()).default([]),recentRuns:a.z.array(jt).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:An.optional(),createdAt:An,updatedAt:An}).strict(),ks=a.z.union([_s.transform(e=>({instance:e,gitWorkspaceProvisioningOperationId:void 0})),a.z.object({instance:_s,gitWorkspaceProvisioningOperationId:In.optional()}).strict()]);a.z.preprocess(e=>{if(!e||"object"!=typeof e||Array.isArray(e))return e;const t=e;return t.instance&&"object"==typeof t.instance&&!Array.isArray(t.instance)?{instance:xs(t.instance),..."string"==typeof t.gitWorkspaceProvisioningOperationId?{gitWorkspaceProvisioningOperationId:t.gitWorkspaceProvisioningOperationId}:{}}:xs(t)},ks);const Cs="instance.lifecycle.snapshot",Os=a.z.object({instanceId:_s.shape.id,revision:a.z.number().int().min(0),updatedAt:An,status:_s.shape.status.unwrap(),health:_s.shape.health.unwrap(),connectionStatus:_s.shape.connectionStatus.unwrap(),accessStatus:a.z.enum(["reachable","endpoint-unreachable"]),imageProvisioning:is.optional(),workspace:Ts,runtime:_s.shape.runtime.unwrap(),runtimeVersion:gi.optional(),ready:a.z.boolean(),lastHeartbeatAt:An.optional()}).strict();function Rs(e,t){return _s.safeParse(xs(e,t))}function xs(e,t){if(!e||"object"!=typeof e||Array.isArray(e))return e;const n=e,i=new Set(Object.keys(_s.shape)),s={};for(const[e,r]of Object.entries(n))i.has(e)?s[e]=r:t?.({instanceId:"string"==typeof n.id?n.id:void 0,field:e});if(n.capabilities&&"object"==typeof n.capabilities&&!Array.isArray(n.capabilities)){const e={...n.capabilities};Object.prototype.hasOwnProperty.call(e,"apps")&&(t?.({instanceId:"string"==typeof n.id?n.id:void 0,field:"capabilities.apps"}),delete e.apps),s.capabilities=fn(e)}else s.capabilities=fn(void 0);s.appInventory=function(e,t,n){if(!e||"object"!=typeof e||Array.isArray(e))return;const i=e;Object.keys(i).some(e=>!["observedAt","items","issues"].includes(e))&&t?.({instanceId:n,field:"appInventory"});const s={observedAt:i.observedAt,items:Array.isArray(i.items)?i.items.map(e=>{e&&"object"==typeof e&&!Array.isArray(e)&&Object.keys(e).some(e=>!["id","name","kind","source","availability","capabilities","diagnosticCode"].includes(e))&&t?.({instanceId:n,field:"appInventory.items"});const i=Ms(e,["id","name","kind","source","availability","diagnosticCode"]);return!i||"object"!=typeof i||Array.isArray(i)?i:{...i,capabilities:Ms(e.capabilities,["automation","supportsCwdSelection"])}}):i.items,issues:Array.isArray(i.issues)?i.issues.map(e=>Ms(e,["code","message"])):i.issues},r=Jn.safeParse(s);return r.success?r.data:void 0}(n.appInventory,t,"string"==typeof n.id?n.id:void 0),s.source=function(e,t,n){if(!e||"object"!=typeof e||Array.isArray(e))return e;const i=e,s=i.type,r=_i.options.find(e=>e.shape.type.value===s);if(!r)return e;const o="local-folder"===s?["type","localFolderId","path","ownerNodeId"]:"git-template"===s?["type","url","templateId","ref","auth","clone"]:["type","repositoryId","url","provider","ref","auth","clone"],a=Ms(i,o);if("local-folder"!==s){const e=function(e,t,n){const i=e&&"object"==typeof e&&!Array.isArray(e)?e:void 0,s=Ei.safeParse(Ms(i,["type","name","commit"]));if(s.success)return s.data;const r="string"==typeof i?.commit?i.commit.trim():"",o="string"==typeof i?.name?i.name.trim():"",a=r?Ei.safeParse({type:"commit",commit:r}):o?Ei.safeParse({type:"tag"===i?.type?"tag":"branch",name:o}):Ei.safeParse({type:"branch",name:"main"});return a.success?(t?.({instanceId:n,field:"source.ref"}),a.data):void 0}(i.ref,t,n),s=Ps(Ni,Ms(i.auth,["type","secretId"]),"source.auth",t,n),r=Ps(zi,Ms(i.clone,["depth","submodules","lfs","subdirectory"]),"source.clone",t,n);e?a.ref=e:delete a.ref,s?a.auth=s:delete a.auth,r?a.clone=r:delete a.clone}const c=Ps(r,a,"source",t,n);return c?(Object.keys(i).some(e=>!o.includes(e))&&t?.({instanceId:n,field:"source"}),c):a}(n.source,t,"string"==typeof n.id?n.id:void 0),s.sourceSnapshot=n.sourceSnapshot&&"object"==typeof n.sourceSnapshot&&!Array.isArray(n.sourceSnapshot)?n.sourceSnapshot:{},s.build=Ps(ui,n.build,"build",t,"string"==typeof n.id?n.id:void 0),s.aiSessions=function(e,t,n){if(!e||"object"!=typeof e||Array.isArray(e))return;const i=e,s=Array.isArray(i.sessions)?i.sessions.flatMap((e,i)=>{const s=Ps(ft,e,`aiSessions.sessions.${i}`,t,n);return s?[s]:[]}):[],r={runningCount:"number"==typeof i.runningCount&&Number.isInteger(i.runningCount)&&i.runningCount>=0?i.runningCount:0,waitingCount:"number"==typeof i.waitingCount&&Number.isInteger(i.waitingCount)&&i.waitingCount>=0?i.waitingCount:0,staleCount:"number"==typeof i.staleCount&&Number.isInteger(i.staleCount)&&i.staleCount>=0?i.staleCount:0,sessions:s,updatedAt:An.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"}),yt.parse(r)}(n.aiSessions,t,"string"==typeof n.id?n.id:void 0),s.triggers=function(e,t,n){if(!e||"object"!=typeof e||Array.isArray(e))return;const i=e;Object.keys(i).some(e=>!["enabledCount","runningCount","errorCount","configs","recentRuns"].includes(e))&&t?.({instanceId:n,field:"triggers"});const s=(e,i,s)=>Array.isArray(e)?e.flatMap((e,r)=>{const o=Ps(i,e,`${s}.${r}`,t,n);return o?[o]:[]}):[],r=Array.isArray(i.configs)?i.configs.flatMap((e,i)=>{if(!e||"object"!=typeof e||Array.isArray(e))return[];const r=e;Object.keys(r).some(e=>!["configHash","config","deployments","runtime"].includes(e))&&t?.({instanceId:n,field:`triggers.configs.${i}`});const o=function(e,t,n,i){if(!e||"object"!=typeof e||Array.isArray(e))return;const s=e,r=Ms(s,["configHash","name","description","createdAt","updatedAt"]);if(s.source&&"object"==typeof s.source&&!Array.isArray(s.source)){const e=s.source,t="schedule"===e.type?"interval"===e.scheduleKind?["type","scheduleKind","intervalMs"]:"daily"===e.scheduleKind?["type","scheduleKind","timeOfDay","timezone"]:["type","scheduleKind","weekdays","timeOfDay","timezone"]:"file-change"===e.type?["type","roots","globs","ignore","debounceMs"]:["type","agent","statuses","phases"];r.source=Ms(e,t)}return r.action=Ms(s.action,["promptTemplate"]),r.policy=Ms(s.policy,["cooldownMs","maxConcurrentRuns","whenBusy"]),Ps(xt,r,t,n,i)}(r.config,`triggers.configs.${i}.config`,t,n);return"string"==typeof r.configHash&&o?[{configHash:r.configHash,config:o,deployments:s(r.deployments,Dt,`triggers.configs.${i}.deployments`),runtime:s(r.runtime,Mt,`triggers.configs.${i}.runtime`)}]:[]}):[];return{enabledCount:"number"==typeof i.enabledCount&&Number.isInteger(i.enabledCount)&&i.enabledCount>=0?i.enabledCount:0,runningCount:"number"==typeof i.runningCount&&Number.isInteger(i.runningCount)&&i.runningCount>=0?i.runningCount:0,errorCount:"number"==typeof i.errorCount&&Number.isInteger(i.errorCount)&&i.errorCount>=0?i.errorCount:0,configs:r,recentRuns:s(i.recentRuns,jt,"triggers.recentRuns")}}(n.triggers,t,"string"==typeof n.id?n.id:void 0),s.apps=Ps(_s.shape.apps.unwrap(),Ms(n.apps,["runningCount","problemCount","updatedAt","revision"]),"apps",t,"string"==typeof n.id?n.id:void 0)||{runningCount:0,problemCount:0},s.config=Ps(_s.shape.config.unwrap(),Ms(n.config,["autoImportAgentConfigs","defaultCodexPermissionMode","aiSessionHistoryLimit","aiSessionAttachmentRetentionDays","aiSessionMaxFileAttachmentBytes"]),"config",t,"string"==typeof n.id?n.id:void 0)||{autoImportAgentConfigs:!0,defaultCodexPermissionMode:"ask",aiSessionHistoryLimit:50,aiSessionAttachmentRetentionDays:30,aiSessionMaxFileAttachmentBytes:oe},s.modelSelection=Ps(Rn.unwrap(),Ms(n.modelSelection,["codexModelHash","claudeModelHash","opencodeModelHash"]),"modelSelection",t,"string"==typeof n.id?n.id:void 0)||{},s.imageSnapshot=function(e,t,n,i){if(!e||"object"!=typeof e||Array.isArray(e))return e;const s=e,r=function(e){if(!e||"object"!=typeof e||Array.isArray(e))return e;const t=e,n=new Set(["id","origin","name","description","localizedDescriptions","cover","reference","repository","tag","image","registry","pullPolicy","capabilities","optionalApps","defaultEnv","labels","createdAt","updatedAt"]);for(const e of Object.keys(t))n.has(e);"string"==typeof t.id&&t.id;const i="string"==typeof t.image?t.image:void 0;Object.prototype.hasOwnProperty.call(t,"registry");let s,r="string"==typeof t.reference?t.reference:i;if(r)try{r=_n(r)}catch{if(!r.includes("@")&&r.lastIndexOf(":")<=r.lastIndexOf("/"))try{r=_n(`${r}:latest`)}catch{}}try{s=r?kn(r):void 0}catch{}return{id:t.id,origin:"custom",name:t.name,description:t.description,localizedDescriptions:t.localizedDescriptions,cover:Ms(t.cover,["kind","key","url","mediaType","digest"]),reference:s?.reference??r,repository:s?.repository??t.repository,tag:s?.tag??t.tag,pullPolicy:t.pullPolicy??"if-not-present",capabilities:t.capabilities,optionalApps:t.optionalApps,defaultEnv:t.defaultEnv,labels:t.labels,createdAt:t.createdAt,updatedAt:t.updatedAt}}(s),{reference:o,...a}=r,c=s.requestedReference??o;let d;try{d="string"==typeof c?kn(c):void 0}catch{}const l={img_default:"market_taskhandoff_browser",img_codex:"market_taskhandoff_codex",img_ai:"market_taskhandoff_ai"},u="string"==typeof s.id?s.id:"string"==typeof t?t:void 0,p="market"===s.origin||u&&l[u]?"market":"custom";return void 0===s.image&&void 0===s.reference||n?.({instanceId:i,field:"imageSnapshot.reference"}),{...a,id:u&&l[u]?l[u]:u,origin:p,repository:d?.repository??s.repository,tag:d?.tag??s.tag,requestedReference:d?.reference??c,resolvedDigest:s.resolvedDigest,resolvedReference:s.resolvedReference,downloadSizeBytes:s.downloadSizeBytes,market:"market"===p?Ms(s.market,["catalogId","catalogRevision","publisher","version"])??{catalogId:"task_handoff_embedded",catalogRevision:"legacy",publisher:"task-handoff"}:void 0}}(n.imageSnapshot,n.imageId,t,"string"==typeof n.id?n.id:void 0);const r="string"==typeof n.imageId?{img_default:"market_taskhandoff_browser",img_codex:"market_taskhandoff_codex",img_ai:"market_taskhandoff_ai"}[n.imageId]||n.imageId:void 0,o=Ms(n.imageSelection,["imageId","tag"]);s.imageSelection=o||(r?{imageId:r,tag:s.imageSnapshot?.tag}:void 0),s.imageProvisioning=Ps(is,Ms(n.imageProvisioning,["phase","requestedReference","generation","error","startedAt","updatedAt"]),"imageProvisioning",t,"string"==typeof n.id?n.id:void 0),s.runtimeVersion=function(e,t,n){if(!e||"object"!=typeof e||Array.isArray(e))return;const i=e,s=e=>{if("string"!=typeof e)return;const t=e.trim();return t&&t.length<=80?t:void 0},r=s(i.desiredVersion);if(!r)return void t?.({instanceId:n,field:"runtimeVersion.desiredVersion"});const o=new Set(gi.shape.phase.options),a="string"==typeof i.phase?i.phase:"pending",c=o.has(a)?a:{idle:"pending",queued:"pending",checking:"pending",downloading:"installing",updating:"installing",completed:"matched",succeeded:"matched",ready:"matched",error:"failed"}[a]||"pending";let d;if(c!==a&&t?.({instanceId:n,field:"runtimeVersion.phase"}),i.error&&"object"==typeof i.error&&!Array.isArray(i.error)){const e=i.error,r="string"==typeof e.message?e.message.trim().slice(0,4096):"";if(r){const i=new Set(hi.shape.code.options),o="string"==typeof e.code&&i.has(e.code)?e.code:"INSTANCE_RUNTIME_INSTALL_FAILED";o!==e.code&&t?.({instanceId:n,field:"runtimeVersion.error.code"});const a=s(e.expectedVersion),c=s(e.actualVersion);d={code:o,message:r,...a?{expectedVersion:a}:{},...c?{actualVersion:c}:{},retryable:!0===e.retryable}}else t?.({instanceId:n,field:"runtimeVersion.error"})}"string"==typeof i.error&&i.error.trim()&&(d={code:"INSTANCE_RUNTIME_INSTALL_FAILED",message:i.error.trim().slice(0,4096),expectedVersion:r,...s(i.actualVersion)?{actualVersion:s(i.actualVersion)}:{},retryable:!1});const l=s(i.actualVersion),u=An.safeParse(i.lastAttemptAt),p=An.safeParse(i.matchedAt);return void 0===i.lastAttemptAt||u.success||t?.({instanceId:n,field:"runtimeVersion.lastAttemptAt"}),void 0===i.matchedAt||p.success||t?.({instanceId:n,field:"runtimeVersion.matchedAt"}),{desiredVersion:r,...l?{actualVersion:l}:{},phase:c,attempt:"number"==typeof i.attempt&&Number.isInteger(i.attempt)&&i.attempt>=0?i.attempt:0,...u.success?{lastAttemptAt:u.data}:{},...p.success?{matchedAt:p.data}:{},...d?{error:d}:{}}}(n.runtimeVersion,t,"string"==typeof n.id?n.id:void 0),s.workspace=Ps(Ts,n.workspace,"workspace",t,"string"==typeof n.id?n.id:void 0)||{status:"unknown"},s.environmentSource=Ps(Pn,n.environmentSource,"environmentSource",t,"string"==typeof n.id?n.id:void 0),s.environmentTemplateOrigin=Ps(Fn,n.environmentTemplateOrigin,"environmentTemplateOrigin",t,"string"==typeof n.id?n.id:void 0),s.runtime=Ps(_s.shape.runtime.unwrap(),n.runtime,"runtime",t,"string"==typeof n.id?n.id:void 0)||{labels:{}},s.target=Ps(Es,Ms(n.target??n.endpoints,["strategy","web","api","vnc","tty","logs","status"]),"target",t,"string"==typeof n.id?n.id:void 0)||{strategy:"direct-port",status:"unknown"},s.access=Ps(zs,Ms(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(_s.shape))Object.prototype.hasOwnProperty.call(s,e)&&!i.safeParse(s[e]).success&&i.safeParse(void 0).success&&(delete s[e],t?.({instanceId:"string"==typeof n.id?n.id:void 0,field:e}));return s}function Ps(e,t,n,i,s){if(!t||"object"!=typeof t||Array.isArray(t))return;let r=structuredClone(t),o=!1;for(let t=0;t<20;t+=1){const t=e.safeParse(r);if(t.success)return o&&i?.({instanceId:s,field:n}),t.data;let a=!1;for(const e of t.error.issues){if("unrecognized_keys"!==e.code)continue;const t=Ds(r,e.path);if(t&&"object"==typeof t&&!Array.isArray(t))for(const n of e.keys)Object.prototype.hasOwnProperty.call(t,n)&&(delete t[n],a=!0,o=!0)}if(!a){const o=structuredClone(r);let a=!1;for(const e of t.error.issues){if(!e.path.length||"string"!=typeof e.path.at(-1))continue;const t=Ds(o,e.path.slice(0,-1)),n=e.path.at(-1);t&&"object"==typeof t&&!Array.isArray(t)&&Object.prototype.hasOwnProperty.call(t,n)&&(delete t[n],a=!0)}if(a){const t=e.safeParse(o);if(t.success)return i?.({instanceId:s,field:n}),t.data}break}}i?.({instanceId:s,field:n})}function Ds(e,t){let n=e;for(const e of t){if(!n||"object"!=typeof n)return;n=n[e]}return n}function Ms(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 js=a.z.object({instanceId:In.optional(),projectId:In.optional(),source:_i.optional(),nodeId:In.optional(),runtimeId:In.optional(),imageSelection:xn.optional(),instanceVersion:a.z.string().trim().max(80).optional(),protocolVersion:dn,build:ui.optional(),controlMode:a.z.enum(["standalone","controlled"]).default("controlled"),capabilities:gn.default(un),appInventory:Jn.optional(),target:Ns.optional(),workspace:Ts.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)=>{cn.has(e.protocolVersion)&&!e.appInventory&&t.addIssue({code:"custom",path:["appInventory"],message:"Current protocol register payload requires appInventory."})}),Ls=a.z.object({status:_s.shape.status.optional(),health:_s.shape.health.optional(),protocolVersion:dn,build:ui.optional(),capabilities:_s.shape.capabilities.optional(),appInventory:Jn.optional(),apps:_s.shape.apps.optional(),aiSessions:_s.shape.aiSessions.optional(),triggers:_s.shape.triggers.optional(),workspace:Ts.optional(),target:Ns.optional(),processIncarnationId:a.z.string().trim().min(1).max(120).optional()}).strict().superRefine((e,t)=>{cn.has(e.protocolVersion)&&!e.appInventory&&t.addIssue({code:"custom",path:["appInventory"],message:"Current protocol heartbeat payload requires appInventory."})}),Fs=a.z.enum(["web","telegram","wechat","dingding","lark"]);function $s(e,t){let n=Bs(t);for(let t=0;t<100;t+=1){const t=e.safeParse(n);if(t.success)return t;const i=Us(t.error.issues);let s=!1;for(const e of i){const t=Hs(n,e.path);if(t&&"object"==typeof t&&!Array.isArray(t))for(const n of e.keys)Object.prototype.hasOwnProperty.call(t,n)&&(delete t[n],s=!0)}if(!s)return t}return e.safeParse(n)}function Us(e,t=[]){const n=[];for(const i of e){if("unrecognized_keys"===i.code){n.push({code:"unrecognized_keys",keys:i.keys,path:[...t,...i.path]});continue}if("invalid_union"!==i.code||!Array.isArray(i.errors))continue;const e=i.errors.filter(e=>Array.isArray(e));if(!e.length)continue;const s=e.reduce((e,t)=>Vs(t)<Vs(e)?t:e);n.push(...Us(s,[...t,...i.path]))}return n}function Vs(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(Vs)):1)},0)}function Hs(e,t){let n=e;for(const e of t){if(!n||"object"!=typeof n)return;n=n[e]}return n}function Bs(e){return Array.isArray(e)?e.map(Bs):e&&"object"==typeof e?Object.getPrototypeOf(e)!==Object.prototype&&null!==Object.getPrototypeOf(e)?e:Object.fromEntries(Object.entries(e).map(([e,t])=>[e,Bs(t)])):e}function qs(e,t,n={}){return new Promise((i,s)=>{if(n.signal?.aborted)return void s(Object.assign(new Error(`${e} was aborted.`),{code:"RUNTIME_COMMAND_ABORTED"}));const r=l.spawn(e,t,{stdio:["ignore","pipe","pipe"]}),o=[],a=[];let c=!1;const d=n.timeoutMs?setTimeout(()=>{c=!0,r.kill("SIGKILL")},n.timeoutMs):void 0;let u=!1;const p=()=>{u=!0,r.kill("SIGKILL")},m=()=>{d&&clearTimeout(d),n.signal?.removeEventListener("abort",p)};n.signal?.addEventListener("abort",p,{once:!0}),d?.unref?.(),r.stdout.on("data",e=>o.push(Buffer.from(e))),r.stderr.on("data",e=>a.push(Buffer.from(e))),r.on("error",e=>{m(),s(e)}),r.on("close",t=>{m();const r={stdout:Buffer.concat(o).toString("utf8").trim(),stderr:Buffer.concat(a).toString("utf8").trim()};if(c){const t=new Error(`${e} timed out after ${n.timeoutMs}ms`);return Object.assign(t,{statusCode:504,code:"RUNTIME_COMMAND_TIMEOUT",details:r}),void s(t)}if(u)return void s(Object.assign(new Error(`${e} was aborted.`),{code:"RUNTIME_COMMAND_ABORTED",details:r}));if(0===t)return void i(r);const d=new Error(r.stderr||`${e} exited with code ${t}`);Object.assign(d,{statusCode:502,code:"RUNTIME_EXECUTOR_FAILED",details:r}),s(d)})})}a.z.object({id:In,channel:Fs,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:An,updatedAt:An}).strict(),a.z.object({id:In,channel:Fs,bridgeId:In.optional(),chatSessionId:a.z.string().trim().min(1).max(240),userId:a.z.string().trim().max(240).optional(),activeProjectId:In.optional(),activeInstanceId:In.optional(),activeAiSessionId:a.z.string().trim().min(1).max(120).optional(),lastUsedAt:An,createdAt:An,updatedAt:An}).strict(),a.z.object({source:a.z.object({type:a.z.literal("chat-gateway").default("chat-gateway"),channel:Fs,bridgeId:In.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(Fe).max(6).default([])}).strict().superRefine((e,t)=>{e.attachments.reduce((e,t)=>e+("inline"===t.source.type?t.size:0),0)>ce&&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:In,aiSessionId:a.z.string().trim().min(1).max(120)}).strict().optional()}).strict(),a.z.object({id:In,instanceId:In,projectId:In.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:An}).strict();const Ks=(e,t,n={})=>new Promise((i,s)=>{if(n.signal?.aborted)return void s(Object.assign(new Error(`${e} was aborted.`),{code:"RUNTIME_COMMAND_ABORTED"}));const r=[];let o,a=!1,c=!1;try{o=u.spawn(e,t,{name:"xterm-256color",cols:n.cols||120,rows:n.rows||40,cwd:process.cwd(),env:process.env})}catch(e){return void s(e)}const d=n.timeoutMs?setTimeout(()=>{a=!0,o.kill("SIGKILL")},n.timeoutMs):void 0,l=()=>{c=!0;try{o.kill("SIGKILL")}catch{}};n.signal?.addEventListener("abort",l,{once:!0}),d?.unref?.(),o.onData(e=>{r.push(e),n.onData?.(e)}),o.onExit(({exitCode:t})=>{d&&clearTimeout(d),n.signal?.removeEventListener("abort",l);const o={stdout:r.join(""),stderr:""};a?s(Object.assign(new Error(`${e} timed out after ${n.timeoutMs}ms`),{statusCode:504,code:"RUNTIME_COMMAND_TIMEOUT",details:o})):c?s(Object.assign(new Error(`${e} was aborted.`),{code:"RUNTIME_COMMAND_ABORTED",details:o})):0!==t?s(Object.assign(new Error(o.stdout.replace(/\u001b\[[0-?]*[ -/]*[@-~]/g,"").split(/\r?\n/).map(e=>e.trim()).filter(Boolean).at(-1)||`${e} exited with code ${t}`),{statusCode:502,code:"RUNTIME_EXECUTOR_FAILED",details:o})):i(o)})});class Gs{inFlight=new Map;runCommand;runTerminalCommand;constructor(e=qs,t){this.runCommand=e,this.runTerminalCommand=t||function(e){return e===qs?Ks:async(t,n,i={})=>{const s=await e(t,n,{timeoutMs:i.timeoutMs,signal:i.signal});return s.stdout&&i.onData?.(s.stdout),s.stderr&&i.onData?.(s.stderr),s}}(e)}ensure(e,t,n,i){const s=_n(e),r=this.inFlight.get(s);if(r)return t&&(r.phaseListeners.add(t),r.phase&&t(r.phase)),n&&(r.terminalListeners.add(n),r.terminalTail&&n({sequence:r.terminalSequence,data:r.terminalTail,replay:!0})),this.bindAbort(r,i),r.promise;const o=new Set,a=new Set;t&&o.add(t),n&&a.add(n);const c={promise:Promise.resolve(void 0),controller:new AbortController,abortDisposers:new Set,phaseListeners:o,terminalListeners:a,terminalSequence:0,terminalTail:""};return this.bindAbort(c,i),c.promise=this.ensureOnce(s,e=>{c.phase=e,o.forEach(t=>t(e))},e=>{c.terminalSequence+=1,c.terminalTail=`${c.terminalTail}${e}`.slice(-262144);const t={sequence:c.terminalSequence,data:e};a.forEach(e=>e(t))},c.controller.signal).finally(()=>{this.inFlight.delete(s);for(const e of c.abortDisposers)e();c.abortDisposers.clear()}),this.inFlight.set(s,c),c.promise}bindAbort(e,t){if(!t)return;if(t.aborted)return void e.controller.abort();const n=()=>e.controller.abort();t.addEventListener("abort",n,{once:!0}),e.abortDisposers.add(()=>t.removeEventListener("abort",n))}async ensureOnce(e,t,n,i){t("checking-image");let s=await this.inspect(e,i).catch(e=>{if(i.aborted)throw e}),r=!1;s||(t("pulling-image"),await this.runTerminalCommand("docker",["pull",e],{cols:120,rows:40,signal:i,onData:n}),r=!0,s=await this.inspect(e,i)),t("resolving-image");const o=(a=s,Array.isArray(a.RepoDigests)?a.RepoDigests.filter(e=>"string"==typeof e):[]).find(e=>/@sha256:[a-fA-F0-9]{64}$/.test(e));var a;const c=o?.split("@").at(-1)?.toLowerCase();return{requestedReference:e,...c?{resolvedDigest:c}:{},resolvedReference:o||e,pulled:r}}async inspect(e,t){const n=await this.runCommand("docker",["image","inspect",e,"--format","{{json .}}"],{signal:t});return JSON.parse(n.stdout.trim()||"{}")}}function Ws(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 Js="/run/task-handoff/bootstrap",Ys=`${Js}/entrypoint.sh`,Xs="/bin/bash",Qs=`${Js}/runtime-installer.mjs`,Zs="/opt/task-handoff/instance-runtime";function er(e,t){return{role:"runtime",name:`${Ir(e)}-runtime`,mountPath:Zs,labels:{"task-handoff.owner":"task-handoff","task-handoff.instance-id":e,"task-handoff.node-id":t,"task-handoff.volume-role":"runtime"}}}function tr(e){return function(e,t,n){const i=Ir(e);return[{role:"data",suffix:"data",mountPath:"/data"},{role:"agent-home",suffix:"agent-home",mountPath:"/home/agent"},..."local-folder"===n.type?[]:[{role:"workspace",suffix:"workspace",mountPath:"/workspace"}]].map(({role:n,suffix:s,mountPath:r})=>({role:n,name:`${i}-${s}`,mountPath:r,labels:{"task-handoff.owner":"task-handoff","task-handoff.instance-id":e,"task-handoff.node-id":t,"task-handoff.volume-role":n}}))}(e.instance.id,e.node?.id||"node_unset",e.project.source)}const nr=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 ir(e,t=[]){const n=e&&"object"==typeof e&&!Array.isArray(e)?e:{},i=n.Config&&"object"==typeof n.Config&&!Array.isArray(n.Config)?n.Config:n,s=new Set;for(const e of Array.isArray(i.Env)?i.Env:[]){if("string"!=typeof e)continue;const n=e.indexOf("="),i=-1===n?e:e.slice(0,n),r=-1===n?"":e.slice(n+1);nr.has(i)&&s.add(`Config.Env.${i}`),t.some(e=>e&&r.includes(e))&&s.add(`Config.Env.${i||"unknown"}`)}if(i.Labels&&"object"==typeof i.Labels&&!Array.isArray(i.Labels))for(const[e,n]of Object.entries(i.Labels))(nr.has(e)||"string"==typeof n&&t.some(e=>e&&n.includes(e)))&&s.add(`Config.Labels.${e}`);if(s.size)throw Object.assign(new Error(`Docker configuration contains instance-private values in ${[...s].sort().join(", ")}.`),{statusCode:409,code:"ENVIRONMENT_TEMPLATE_SECRET_IN_DOCKER_CONFIG",findings:[...s].sort()})}class sr{runCommand;publishHost;images;launcherAssetsDir;portResolutionRetryDelaysMs;constructor(e=qs,t={}){this.runCommand=e,this.images=t.imageService||new Gs(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){vr(e);const t=e.instance.runtime.containerName||Ir(e.instance.id),i=await this.inspectContainerForStart(t);if(i){fr(t,i.id,e.instance.runtime.containerId,"before start","RUNTIME_EXECUTOR_FAILED");const s=i.labels["task-handoff.instance-id"];if(s!==e.instance.id)throw pr("RUNTIME_EXECUTOR_FAILED",`Docker container ${t} belongs to ${s||"an unknown instance"}, not ${e.instance.id}.`);const r=i.mounts.find(e=>"bind"===e.type&&e.destination===Js);if("1"!==i.labels["task-handoff.bootstrap-abi"]||i.entrypoint[0]!==Xs||i.command[0]!==Ys||!r?.source||n.resolve(r.source)!==n.resolve(this.launcherAssetsDir)){const n=new Set(tr(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 pr("RUNTIME_EXECUTOR_FAILED",`Could not start Docker container ${t}.`,e)}return this.resumedContainerResult(e,t,i.id)}if(e.instance.environmentTemplateOrigin){const t=await this.inspectEnvironmentTemplateImage(e.instance.environmentTemplateOrigin.imageId);if(t.imageId!==e.instance.environmentTemplateOrigin.imageId||t.platform!==e.instance.environmentTemplateOrigin.platform||t.architecture!==e.instance.environmentTemplateOrigin.architecture)throw Object.assign(new Error(`Environment template image identity or platform changed for instance ${e.instance.id}.`),{statusCode:409,code:"ENVIRONMENT_TEMPLATE_IMAGE_IDENTITY_MISMATCH"})}else await this.images.ensure(e.image.resolvedReference||e.image.requestedReference);let s;await this.createPersistentVolumes(e),"local-folder"!==e.project.source.type&&await this.provisionGitWorkspace(e);try{s=await this.runCommand("docker",br(e,t,{publishHost:this.publishHost,launcherAssetsDir:this.launcherAssetsDir}))}catch(e){throw pr("RUNTIME_EXECUTOR_FAILED",`Could not create Docker container ${t}.`,e)}return e.completeGitWorkspaceProvisioning?.(),this.bootstrapResult(e,t,s.stdout||void 0)}async provisionGitWorkspace(e){const i=e.gitWorkspaceProvisioning;if(!i)throw pr("GIT_WORKSPACE_PROVISIONING_MISSING",`Git workspace provisioning input is missing for ${e.instance.id}.`);const s=`${Ir(e.instance.id)}-git-provision`,r=t.mkdtempSync(n.join(c.tmpdir(),"task-handoff-git-auth-"));t.chmodSync(r,448);try{await this.runCommand("docker",["rm","-f",s],{timeoutMs:3e4}).catch(()=>({stdout:"",stderr:""})),this.materializeGitProvisioningAuth(r,i);const t=function(e,t,i,s={}){const r=e.gitWorkspaceProvisioning;if(!r||"local-folder"===e.project.source.type)throw Object.assign(new Error("Git provisioning requires a Git source and operation input."),{code:"GIT_WORKSPACE_PROVISIONING_INVALID",statusCode:400});const o=n.resolve(s.launcherAssetsDir||lr()),a=tr(e).find(e=>"workspace"===e.role);if(!a)throw Object.assign(new Error("Git workspace volume was not found."),{code:"GIT_WORKSPACE_VOLUME_MISSING",statusCode:409});const c=["run","--rm","--name",t,"--label","task-handoff.role=git-provisioning","--label",`task-handoff.instance-id=${e.instance.id}`,"--user","0:0","--network","bridge","--security-opt","no-new-privileges","--cap-drop","ALL","--cap-add","CHOWN","--cap-add","SETUID","--cap-add","SETGID","--cap-add","DAC_OVERRIDE","--mount",`type=volume,src=${a.name},dst=/workspace`,"--mount",`type=bind,src=${o},dst=${Js},readonly`,"--tmpfs","/run/task-handoff/git-runtime:rw,nosuid,nodev,exec,mode=0700"];r.credentials.length&&c.push("--mount",`type=bind,src=${n.resolve(i)},dst=/run/task-handoff/git-auth,readonly`);const d=(e,t)=>c.push("-e",`${e}=${t}`);return d("TASK_HANDOFF_GIT_URL",r.remoteUrl),d("TASK_HANDOFF_INSTANCE_ID",e.instance.id),"commit"===r.ref.type?d("TASK_HANDOFF_GIT_COMMIT",r.ref.commit):d("TASK_HANDOFF_GIT_REF",r.ref.name),r.clone.depth&&d("TASK_HANDOFF_GIT_DEPTH",String(r.clone.depth)),d("TASK_HANDOFF_GIT_SUBMODULES",r.clone.submodules?"true":"false"),d("TASK_HANDOFF_GIT_LFS",r.clone.lfs?"true":"false"),r.clone.subdirectory&&d("TASK_HANDOFF_WORKSPACE_SUBDIRECTORY",r.clone.subdirectory),c.push("--entrypoint","/bin/bash",e.instance.environmentTemplateOrigin?.imageId||e.image.resolvedReference||e.image.requestedReference,`${Js}/git-provision.sh`),c}(e,s,r,{launcherAssetsDir:this.launcherAssetsDir});await this.runCommand("docker",t,{timeoutMs:9e5,signal:e.signal})}catch(t){throw function(e,t){const n=t&&"object"==typeof t?t:void 0,i="string"==typeof n?.code?n.code:"";if("RUNTIME_COMMAND_TIMEOUT"===i)return pr("GIT_WORKSPACE_PROVISIONING_TIMEOUT",`Git workspace provisioning timed out for ${e}.`);if("RUNTIME_COMMAND_ABORTED"===i)return pr("GIT_WORKSPACE_PROVISIONING_CANCELLED",`Git workspace provisioning was cancelled for ${e}.`);const s=hr(t)||"",r=s.match(/TASK_HANDOFF_GIT_PROVISIONING_ERROR=([A-Z_]+)/)?.[1];return pr(`GIT_WORKSPACE_PROVISIONING_${r&&mr.has(r)?r:"FAILED"}`,`Could not provision Git workspace for ${e}.`)}(e.instance.id,t)}finally{await this.runCommand("docker",["rm","-f",s],{timeoutMs:3e4}).catch(()=>({stdout:"",stderr:""})),t.rmSync(r,{recursive:!0,force:!0})}}materializeGitProvisioningAuth(e,i){const s=(e,i,s)=>{const r=n.join(e,i);t.writeFileSync(r,s,{encoding:"utf8",mode:384}),t.chmodSync(r,384)};i.credentials.forEach((i,r)=>{const o=n.join(e,`credential-${r}`);if(t.mkdirSync(o,{recursive:!0,mode:448}),t.chmodSync(o,448),s(o,"scope.json",JSON.stringify(i.payload.credential.scope)),"https-token"===i.payload.secret.kind)return s(o,"username",i.payload.secret.username),void s(o,"token",i.payload.secret.token);s(o,"private-key",i.payload.secret.privateKey),s(o,"known_hosts",i.payload.secret.pinnedKnownHosts),i.payload.secret.passphrase&&s(o,"passphrase",i.payload.secret.passphrase),s(o,"ssh-askpass.sh",`#!/usr/bin/env bash\ncat /run/task-handoff/git-runtime/credential-${r}/passphrase 2>/dev/null || true\n`)})}async recreateWithAuthoritativeBootstrap(e,t,n){const i=`${t}-pre-bootstrap-${n.id.slice(0,12)}`;n.running&&await this.runCommand("docker",["stop",t]);try{await this.runCommand("docker",["rename",t,i])}catch(e){throw n.running&&await this.runCommand("docker",["start",t]).catch(()=>({stdout:"",stderr:""})),pr("RUNTIME_EXECUTOR_FAILED",`Could not preserve Docker container ${t} before bootstrap migration.`,e)}try{const s=await this.runCommand("docker",br(e,t,{publishHost:this.publishHost,launcherAssetsDir:this.launcherAssetsDir,imageReference:n.image}));return this.bootstrapResult(e,t,s.stdout||void 0,i)}catch(e){throw await this.runCommand("docker",["rm","-f",t]).catch(()=>({stdout:"",stderr:""})),await this.runCommand("docker",["rename",i,t]).catch(()=>({stdout:"",stderr:""})),n.running&&await this.runCommand("docker",["start",t]).catch(()=>({stdout:"",stderr:""})),pr("RUNTIME_EXECUTOR_FAILED",`Could not recreate Docker container ${t} with the node-agent bootstrap.`,e)}}async inspectContainerConfigSecurity(e,t){ir(await this.runCommand("docker",["inspect","--format","{{json .}}",e]).then(e=>JSON.parse(e.stdout||"{}")).catch(t=>{throw pr("ENVIRONMENT_TEMPLATE_CONTAINER_INSPECT_FAILED",`Could not inspect Docker container ${e}.`,t)}),t)}async inspectImageConfigSecurity(e,t){ir(await this.runCommand("docker",["image","inspect","--format","{{json .}}",e]).then(e=>JSON.parse(e.stdout||"{}")).catch(e=>{throw pr("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 pr("ENVIRONMENT_TEMPLATE_CONTAINER_NOT_FOUND",`Docker container ${e} does not exist.`);fr(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 pr("ENVIRONMENT_TEMPLATE_COMMIT_FAILED",`Could not save Docker container ${e} as an environment template.`,t)}}async inspectEnvironmentTemplateImage(e){try{const t=await this.runCommand("docker",["image","inspect","--format","{{json .}}",e]),n=JSON.parse(t.stdout||"{}"),i="string"==typeof n.Id?n.Id:"",s=cr(n.Os),r=dr(n.Architecture),o="number"==typeof n.Size?n.Size:Number.NaN;if(!/^sha256:[a-f0-9]{64}$/.test(i)||!s||!r||!Number.isSafeInteger(o)||o<0)throw new Error("Docker image inspection did not return a valid immutable identity.");return{imageId:i,platform:s,architecture:r,sizeBytes:o}}catch(e){throw pr("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,ur(n)]),await this.runCommand("docker",["image","rm",e]),n}catch(e){const t=hr(e)?.toLowerCase()||"";if(t.includes("no such image")||t.includes("no such object"))return;throw pr("ENVIRONMENT_TEMPLATE_UNTAG_FAILED","Could not remove the environment template tag.",e)}}async garbageCollectEnvironmentTemplateImage(e){try{try{await this.runCommand("docker",["image","rm",ur(e)])}catch(e){const t=hr(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=hr(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 pr("ENVIRONMENT_TEMPLATE_GC_FAILED","Could not garbage collect the environment template image.",e)}}async createPersistentVolumes(e,t=new Set){const n=er(e.instance.id,e.node?.id||"node_unset");for(const i of[...tr(e),n])await this.createVolume(i),await this.validateOwnedVolume(e.instance.id,i,t.has(i.name))}async createRuntimeVolume(e){await this.createVolume(er(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 pr("INSTANCE_VOLUME_CREATE_FAILED",`Could not create managed volume ${e.name}.`,t)}}async validatePersistentVolumes(e,t){for(const n of tr(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=er(e.instance.id,e.node?.id||"node_unset");await this.validateOwnedVolume(e.instance.id,i);const s=t.find(e=>"volume"===e.type&&e.destination===i.mountPath);if(!s||s.name!==i.name)throw Object.assign(new Error(`Docker container runtime mount does not match ${i.name}.`),{statusCode:409,code:"INSTANCE_VOLUME_MOUNT_IDENTITY_MISMATCH"});if("local-folder"===e.project.source.type){const i=t.find(t=>t.destination===(e.project.workspacePolicy.path||"/workspace"));if(!i||"bind"!==i.type||n.resolve(i.source||"")!==n.resolve(e.project.source.path))throw Object.assign(new Error(`Docker container workspace bind does not match local folder ${e.project.source.path}.`),{statusCode:409,code:"INSTANCE_WORKSPACE_MOUNT_IDENTITY_MISMATCH"})}}async validateOwnedVolume(e,t,n=!1){let i;try{i=await this.runCommand("docker",["volume","inspect","--format","{{json .}}",t.name])}catch(e){throw pr("INSTANCE_VOLUME_INSPECT_FAILED",`Could not inspect managed volume ${t.name}.`,e)}try{const s=JSON.parse(i.stdout||"{}"),r=s.Labels&&"object"==typeof s.Labels&&!Array.isArray(s.Labels)?s.Labels:{},o=s.Name===t.name&&"task-handoff"===r["task-handoff.owner"]&&r["task-handoff.instance-id"]===e&&r["task-handoff.volume-role"]===t.role,a=n&&s.Name===t.name&&0===Object.keys(r).length;if(!o&&!a)throw new Error("volume name or ownership labels do not match")}catch(n){throw Object.assign(new Error(`Managed volume ${t.name} identity does not match instance ${e}.`,{cause:n}),{statusCode:409,code:"INSTANCE_VOLUME_IDENTITY_MISMATCH"})}}async runningResult(e,t,n){const i=await this.publishedEndpoint(t),s=e.node?.id||"node_unset",r=e.runtime?.id||"runtime_local_docker";return{status:"registering",health:"unknown",connectionStatus:"online",agentStatus:"unknown",targetStatus:"unknown",uiAccessStatus:"unknown",target:{strategy:"direct-port",status:"reachable",...i},workspace:{mode:e.project.workspacePolicy.mode,status:"pending",path:e.project.workspacePolicy.path},runtime:{...e.instance.runtime,kind:"docker",containerName:t,...n?{containerId:n}:{},labels:{...e.instance.runtime.labels,"task-handoff.instance-id":e.instance.id,"task-handoff.project-id":e.project.id,"task-handoff.node-id":s,"task-handoff.runtime-id":r,"task-handoff.image-id":e.image.id}}}}async resumedContainerResult(e,t,n){const i=this.bootstrapResult(e,t,n);return{...i,target:{...i.target,...await this.publishedEndpoint(t)}}}async publishedEndpoint(e){const t=`http://127.0.0.1:${await this.containerPort(e,"8080/tcp")}`;return{web:t,api:`${t}/api`}}async resolveInstanceWeb(e){const t=e.instance.runtime.containerName||Ir(e.instance.id),n=await this.inspectContainerId(t);if(!n)throw pr("INSTANCE_RUNTIME_ENDPOINT_UNAVAILABLE",`Docker container ${t} does not exist.`);return fr(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||Ir(e.instance.id);try{await this.runCommand("docker",["stop",t])}catch(e){if(!gr(e))throw pr("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){vr(e);const n=e.instance.runtime.containerName||Ir(e.instance.id),i=await this.inspectContainerId(n);if(!i)throw pr("INSTANCE_RUNTIME_RESTART_FAILED",`Docker container ${n} does not exist.`);fr(n,i,t,"before restart","INSTANCE_RUNTIME_RESTART_FAILED"),await this.runCommand("docker",["restart",n]);const s=await this.inspectContainerId(n);if(!s||s!==i)throw pr("INSTANCE_RUNTIME_RESTART_FAILED",`Docker container identity changed while restarting ${n}.`);return fr(n,s,t,"after restart","INSTANCE_RUNTIME_RESTART_FAILED"),this.runningResult(e,n,s)}async delete(e,t){const n=e.instance.runtime.containerName||Ir(e.instance.id),i=await this.inspectContainerForStart(n),s=new Set;if(i){fr(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 pr("RUNTIME_EXECUTOR_FAILED",`Docker container ${n} belongs to ${t||"an unknown instance"}, not ${e.instance.id}.`);for(const t of tr(e))i.mounts.some(e=>"volume"===e.type&&e.name===t.name&&e.destination===t.mountPath)&&s.add(t.name);try{await this.runCommand("docker",["rm","-f",i.id])}catch(e){if(!gr(e))throw pr("RUNTIME_EXECUTOR_FAILED",`Could not delete Docker container ${n}.`,e)}}const r=[];for(const n of tr(e))if(t.deleteVolumes)try{const t=await this.inspectVolumeForDelete(n.name);if(!t){r.push({role:n.role,name:n.name,mountPath:n.mountPath,status:"missing"});continue}const i=t.name===n.name&&"task-handoff"===t.labels["task-handoff.owner"]&&t.labels["task-handoff.instance-id"]===e.instance.id&&t.labels["task-handoff.volume-role"]===n.role,o=s.has(n.name)&&t.name===n.name&&0===Object.keys(t.labels).length;if(!i&&!o)throw Object.assign(new Error(`Managed volume ${n.name} ownership does not match instance ${e.instance.id}.`),{code:"INSTANCE_VOLUME_IDENTITY_MISMATCH"});await this.runCommand("docker",["volume","rm",n.name]),r.push({role:n.role,name:n.name,mountPath:n.mountPath,status:"deleted"})}catch(e){r.push({role:n.role,name:n.name,mountPath:n.mountPath,status:"failed",error:{code:"object"==typeof e&&e&&"code"in e&&"string"==typeof e.code?e.code:"INSTANCE_VOLUME_DELETE_FAILED",message:e instanceof Error?e.message:String(e)}})}else r.push({role:n.role,name:n.name,mountPath:n.mountPath,status:"retained"});return await this.deleteRuntimeVolume(e),Hn.parse({instanceId:e.instance.id,containerDeleted:!0,completed:r.every(e=>"failed"!==e.status),deletedVolumes:r.filter(e=>"deleted"===e.status||"missing"===e.status),retainedVolumes:r.filter(e=>"retained"===e.status),volumeResults:r})}async deleteRuntimeVolume(e){const t=er(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 pr("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 pr("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=hr(e)?.toLowerCase()||"";return t.includes("no such volume")||t.includes("no such object")}(t))return;throw pr("INSTANCE_VOLUME_INSPECT_FAILED",`Could not inspect managed volume ${e}.`,t)}}async installRuntime(e){const t=await this.installRuntimeRelease(e);fr(e.containerName,t,e.expectedContainerId,"before runtime restart","INSTANCE_RUNTIME_RESTART_FAILED");try{await this.runCommand("docker",["restart",t])}catch(t){throw pr("INSTANCE_RUNTIME_RESTART_FAILED",`Could not restart Docker container ${e.containerName}.`,t)}const n=await this.inspectContainerId(e.containerName);if(!n||n!==t)throw pr("INSTANCE_RUNTIME_RESTART_FAILED",`Docker container identity changed while updating ${e.containerName}.`);return fr(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 pr("INSTANCE_RUNTIME_INSTALL_FAILED",`Docker container ${e.containerName} does not exist.`);fr(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",Qs,"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 pr("INSTANCE_RUNTIME_INSTALL_FAILED",`Could not install controlled-instance ${e.identity.version} in ${e.containerName}.`,t)}finally{await this.runCommand("docker",["exec","--user","0",t,"rm","-f",n]).catch(()=>({stdout:"",stderr:""}))}const s=await this.inspectContainerId(e.containerName);if(!s||s!==t)throw pr("INSTANCE_RUNTIME_INSTALL_FAILED",`Docker container identity changed while installing ${e.containerName}.`);return fr(e.containerName,s,e.expectedContainerId,"after runtime install","INSTANCE_RUNTIME_INSTALL_FAILED"),t}async inspectRuntimeVersion(e){const t=await this.inspectContainerId(e);if(!t)return{};const n=await this.runCommand("docker",["exec","--user","agent",e,"node",Qs,"verify-active"]).catch(()=>{});if(!n?.stdout)return{containerId:t};try{const e=$s(mi,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 pr("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 pr("INSTANCE_BASE_RUNTIME_INCOMPATIBLE","Could not inspect the Docker runtime target.",e)});t||=e.OSType,n||=e.Architecture}const i=cr(t),s=dr(n);if(!i||!s)throw pr("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Docker reported an unsupported runtime target ${String(t||"unknown")}/${String(n||"unknown")}.`);return{platform:i,arch:s,launcherAbi:1}}async installRuntimeReleaseWithRecovery(e){const t=e.containerName,i=await this.inspectContainerForStart(t);if(!i)throw pr("INSTANCE_RUNTIME_INSTALL_FAILED",`Docker container ${t} does not exist.`);if(fr(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 pr("INSTANCE_RUNTIME_INSTALL_FAILED",`Docker container ${t} does not expose its immutable image identity.`);const s="/run/task-handoff/runtime-rescue-artifact.tar.gz",r=[`test -r ${Ys}`,`test -r ${Js}/instance-launcher.sh`,`test -r ${Qs}`,`install -d -o root -g root -m 0755 ${Zs} ${Zs}/releases ${Zs}/staging ${Zs}/incoming`,`chown -R root:root ${Zs}`,`chmod -R go-w ${Zs}`,`node ${Qs} install --artifact "$1" --version "$2" --sha256 "$3" --platform "$4" --arch "$5" --launcher-abi "$6"`].join("; ");try{await this.runCommand("docker",["run","--rm","--user","0:0","--volumes-from",i.id,"--mount",`type=bind,source=${n.resolve(e.artifactPath)},target=${s},readonly`,"--entrypoint",Xs,i.image,"-ceu",r,"task-handoff-runtime-rescue",s,e.identity.version,e.identity.sha256,e.identity.platform,e.identity.arch,String(e.identity.launcherAbi)])}catch(n){throw pr("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 pr("INSTANCE_RUNTIME_INSTALL_FAILED",`Docker container ${t} disappeared during runtime install recovery.`);if(fr(t,o.id,i.id,"after runtime install recovery","INSTANCE_RUNTIME_INSTALL_FAILED"),o.running)throw pr("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 pr("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Docker container ${e} does not exist.`);fr(e,n,t,"before runtime launcher install","INSTANCE_BASE_RUNTIME_INCOMPATIBLE");try{await this.runCommand("docker",["exec","--user","0",n,"bash","-ceu",`test -r ${Ys}; test -r ${Js}/instance-launcher.sh; test -r ${Qs}; 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 pr("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Could not install the runtime launcher in ${e}.`,t)}const i=await this.inspectContainerId(e);if(i!==n)throw pr("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Docker container identity changed while installing the runtime launcher in ${e}.`);fr(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(gr(t))return;throw pr("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(gr(t))return;throw pr("RUNTIME_EXECUTOR_FAILED",`Could not inspect Docker container ${e}.`,t)}try{const e=JSON.parse(t.stdout||"{}");if("string"!=typeof e.Id||!e.Id)throw new Error("Docker inspect did not return a container id.");const n=e.Config?.Labels&&"object"==typeof e.Config.Labels&&!Array.isArray(e.Config.Labels)?Object.fromEntries(Object.entries(e.Config.Labels).filter(e=>"string"==typeof e[1])):{},i=Array.isArray(e.Mounts)?e.Mounts.flatMap(e=>{if(!e||"object"!=typeof e||Array.isArray(e))return[];const t=e,n="volume"===t.Type||"bind"===t.Type?t.Type:void 0,i="string"==typeof t.Destination?t.Destination:void 0;return n&&i?[{type:n,destination:i,name:"string"==typeof t.Name?t.Name:void 0,source:"string"==typeof t.Source?t.Source:void 0}]:[]}):[],s=Array.isArray(e.Config?.Entrypoint)?e.Config.Entrypoint.filter(e=>"string"==typeof e):"string"==typeof e.Config?.Entrypoint?[e.Config.Entrypoint]:[],r=Array.isArray(e.Config?.Cmd)?e.Config.Cmd.filter(e=>"string"==typeof e):"string"==typeof e.Config?.Cmd?[e.Config.Cmd]:[];return{id:e.Id,image:"string"==typeof e.Image?e.Image:void 0,running:!0===e.State?.Running,entrypoint:s,command:r,labels:n,mounts:i}}catch(t){throw pr("RUNTIME_EXECUTOR_FAILED",`Docker returned invalid inspection data for ${e}.`,t)}}async containerPort(e,t){let n,i=!1;for(const s of this.portResolutionRetryDelaysMs){s>0&&await ar(s);try{const n=rr((await this.runCommand("docker",["port",e,t])).stdout);if(n)return n}catch(e){n=e}try{const n=or((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 pr("RUNTIME_EXECUTOR_FAILED",`Docker container ${e} does not publish ${t}.`);throw pr("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 or(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 ar(e){return new Promise(t=>setTimeout(t,e))}function cr(e){return"linux"===e||"darwin"===e?e:"windows"===e||"win32"===e?"win32":void 0}function dr(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:w&&"SCRIPT"===w.tagName.toUpperCase()&&w.src||new URL("cli.js",document.baseURI).href)?n.dirname(s.fileURLToPath("undefined"==typeof document?require("url").pathToFileURL(__filename).href:w&&"SCRIPT"===w.tagName.toUpperCase()&&w.src||new URL("cli.js",document.baseURI).href)):__dirname,i=[n.resolve(e,"../../../../../docker"),n.resolve(e,"../docker"),n.resolve(e,"../../docker")];return i.find(e=>t.existsSync(n.join(e,"runtime-installer.mjs")))||i[0]}function ur(e){return`task-handoff/environment-image:${e.replace(/^sha256:/,"")}`}function pr(e,t,n){const i=hr(n),s=new Error(i?`${t} Cause: ${i}`:t,void 0===n?void 0:{cause:n});return Object.assign(s,{statusCode:502,code:e}),s}const mr=new Set(["AUTHENTICATION_REJECTED","CLONE_FAILED","CREDENTIAL_AMBIGUOUS","CREDENTIAL_MISSING","HOST_KEY_REQUIRED","LFS_FAILED","REF_NOT_FOUND","REMOTE_UNSUPPORTED","SSH_AGENT_UNAVAILABLE","SUBDIRECTORY_NOT_FOUND","WORKSPACE_NOT_EMPTY","WORKSPACE_OWNERSHIP_MISMATCH"]);function hr(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 gr(e){const t=hr(e)?.toLowerCase()||"";return t.includes("no such container")||t.includes("no such object")}function fr(e,t,n,i,s){if(n&&t!==n)throw pr(s,`Docker container ${e} identity mismatch ${i}: expected ${n}, got ${t}.`)}async function yr(e=qs){return async function(e=qs){return(await e("docker",["images","--digests","--format","{{json .}}"])).stdout.split(/\r?\n/).map(e=>e.trim()).filter(Boolean).map(e=>{const t=JSON.parse(e),n=t.Repository||"<none>",i=t.Tag||"<none>",s=t.ID||t.IDShort||"",r="<none>"!==n&&"<none>"!==i?`${n}:${i}`:s,o="<none>"!==n&&t.Digest&&"<none>"!==t.Digest?[`${n}@${t.Digest}`]:[];return{repository:n,tag:i,id:s,createdSince:t.CreatedSince,size:t.Size,sizeBytes:Ws(t.Size),reference:r,repoDigests:o}}).filter(e=>Boolean(e.reference))}(e)}function Ir(e){return`task-handoff-${e.replace(/[^a-zA-Z0-9_.-]/g,"-")}`}function Ar(e,t,n){e.push("-e",`${t}=${n}`)}function br(e,t,i={}){const s=i.publishHost||"127.0.0.1",r=n.resolve(i.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",`${s}::8080`];if(!e.privateConfigPath)throw Object.assign(new Error(`Instance ${e.instance.id} private config was not materialized.`),{statusCode:409,code:"INSTANCE_PRIVATE_CONFIG_MISSING"});c.push("--mount",`type=bind,src=${e.privateConfigPath},dst=/run/task-handoff/instance-private-config.json,readonly`,"--mount",`type=bind,src=${r},dst=${Js},readonly`,"--entrypoint",Xs);for(const t of tr(e))c.push("--mount",`type=volume,src=${t.name},dst=${t.mountPath}`);const d=er(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:`${Js}/instance-launcher.sh`,...e.image.tag?{TASK_HANDOFF_IMAGE_TAG:e.image.tag}:{},TASK_HANDOFF_CHAT_BRIDGES:"none",TASK_HANDOFF_WORKSPACE:e.project.workspacePolicy.path||"/workspace",TASK_HANDOFF_WORKSPACE_MODE:e.project.workspacePolicy.mode,..."local-folder"===e.project.source.type?{}:{TASK_HANDOFF_SKIP_WORKSPACE_BOOTSTRAP:"true"}};for(const[e,t]of Object.entries(l))Ar(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"}`):(Ar(c,"TASK_HANDOFF_PROJECT_SOURCE",JSON.stringify(e.project.source)),Ar(c,"TASK_HANDOFF_WORKSPACE_POLICY",JSON.stringify(e.project.workspacePolicy)),Ar(c,"TASK_HANDOFF_GIT_URL",e.project.source.url),"commit"===e.project.source.ref.type?Ar(c,"TASK_HANDOFF_GIT_COMMIT",e.project.source.ref.commit):Ar(c,"TASK_HANDOFF_GIT_REF",e.project.source.ref.name),e.project.source.clone?.depth&&Ar(c,"TASK_HANDOFF_GIT_DEPTH",String(e.project.source.clone.depth)),Ar(c,"TASK_HANDOFF_GIT_SUBMODULES",e.project.source.clone?.submodules?"true":"false"),Ar(c,"TASK_HANDOFF_GIT_LFS",e.project.source.clone?.lfs?"true":"false"),e.project.source.clone?.subdirectory&&Ar(c,"TASK_HANDOFF_WORKSPACE_SUBDIRECTORY",e.project.source.clone.subdirectory));for(const[t,n]of Object.entries(e.image.defaultEnv))Ar(c,t,n);return c.push(i.imageReference||e.instance.environmentTemplateOrigin?.imageId||e.image.resolvedReference||e.image.requestedReference,Ys,"task-handoff","web"),c}function vr(e){if("local-folder"===e.project.source.type&&e.project.source.ownerNodeId&&e.project.source.ownerNodeId!==e.node.id){const e=new Error("Local folder projects can only start on the node that owns the folder.");throw Object.assign(e,{statusCode:400,code:"LOCAL_FOLDER_REQUIRES_OWNER_NODE"}),e}if(!e.image.requestedReference?.trim()){const e=new Error("Image profile must reference a registered image.");throw Object.assign(e,{statusCode:400,code:"IMAGE_PROFILE_INVALID"}),e}}const wr="app.sessions";a.z.object({type:a.z.literal("snapshot"),data:a.z.string(),pendingEscape:a.z.string(),cols:a.z.number().int().positive(),rows:a.z.number().int().positive()}).passthrough();const Sr="app-session.snapshot",Er="app-session.patch",Nr="app-session.removed",zr=a.z.enum(["created","starting","running","stopping","stopped","exited","failed","closed","terminated","unknown"]),Tr=a.z.enum(["tty","vnc","web"]);a.z.object({mode:Tr,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 _r=new Set(["stopped","failed","exited","closed","terminated"]),kr=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(),Cr=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:zr.default("unknown"),bindings:a.z.array(kr).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()})),Or=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(Cr).default([]),updatedAt:a.z.string().datetime()}).strict(),Rr=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:Or}).strict();Or.pick({runningCount:!0,problemCount:!0,updatedAt:!0}).extend({revision:a.z.number().int().min(0).optional()});const xr=a.z.enum(["app-session-created","app-session-updated","app-session-deleted","app-session-recovered","control-action","heartbeat-sync","startup"]),Pr=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:xr}).strict(),Dr=a.z.object({meta:Pr,snapshot:Or}).strict(),Mr=a.z.object({meta:Pr,session:Cr}).strict(),jr=a.z.object({meta:Pr,sessionId:a.z.string().trim().min(1).max(160),tombstone:Cr.optional(),expiresAt:a.z.string().datetime().optional()}).strict();function Lr(e,t=(new Date).toISOString()){const n=e.map(e=>function(e){const t=$r("string"==typeof e.status?e.status:void 0),n="string"==typeof e.id?e.id:"",i=function(e){const t=qr(e.workspace),n=qr(e.tty),i=qr(e.launch),s=qr(e.ai),r=qr(s.claude),o=Kr(t.cwd)||Kr(n.cwd)||Kr(r.cwd)||Kr(i.cwd);return o?{cwd:o}:void 0}(e),{workspace:s,...r}=e;return Cr.parse({...r,status:t,bindings:Br([...(o=e.bindings,Array.isArray(o)?o.flatMap(e=>{const t=kr.safeParse(e);return t.success?[t.data]:[]}):[]),...n?[{type:"app-session",id:n}]:[],...Hr(e)]),...i?{workspace:i}:{}});var o}(e));return Or.parse({runningCount:n.filter(e=>"running"===e.status).length,problemCount:n.filter(e=>"failed"===e.status).length,sessions:n,updatedAt:t})}function Fr(e,t=(new Date).toISOString()){return Lr(e.filter(e=>Ur("string"==typeof e.status?e.status:void 0)),t)}function $r(e){const t=(e||"unknown").trim().toLowerCase();return"ended"===t?"closed":"terminating"===t?"stopping":zr.options.includes(t)?t:"unknown"}function Ur(e){return!_r.has($r(e))}function Vr(e){return"app-session"===e.type?`app:${e.id}`:"provider-session"===e.type?`provider:${e.agent||""}:${e.id}`:`adapter:${e.adapter||""}:${e.key||e.id}`}function Hr(e){const t=qr(e.ai),n=qr(t.claude),i=qr(t.appServer),s=qr(e.launch),r=[],o=Kr(qr(s.aiSessionResume).providerSessionId),a="codex"===e.appId||"claude"===e.appId||"opencode"===e.appId?e.appId:void 0;a&&o&&r.push({type:"provider-session",agent:a,id:o});const c=Kr(n.short);c&&r.push({type:"adapter-key",adapter:"claude",agent:"claude",id:`short:${c}`,key:`short:${c}`});const d=Kr(n.providerSessionId);d&&r.push({type:"provider-session",agent:"claude",id:d});const l=Array.isArray(t.threadIds)?t.threadIds.filter(e=>"string"==typeof e&&Boolean(e.trim())):[],u=Kr(t.activeThreadId);for(const e of[...new Set([u,...l].filter(Boolean))])r.push({type:"provider-session",agent:"codex",id:e});const p=Kr(i.socketPath);return p&&r.push({type:"adapter-key",adapter:"codex-app-server",agent:"codex",id:`socket:${p}`,key:`socket:${p}`}),r}function Br(e){const t=new Map;for(const n of e)t.set(Vr(n),n);return[...t.values()]}function qr(e){return e&&"object"==typeof e&&!Array.isArray(e)?e:{}}function Kr(e){return"string"==typeof e&&e.trim()?e.trim():""}a.z.object({streamId:a.z.string().trim().min(1).max(240),instanceId:a.z.string().trim().min(1).max(160),sinceRevision:a.z.number().int().min(0),latestRevision:a.z.number().int().min(0),earliestRetainedRevision:a.z.number().int().min(0),syncRequired:a.z.boolean().default(!1),events:a.z.array(a.z.discriminatedUnion("type",[a.z.object({type:a.z.literal(Sr),payload:Dr}).strict(),a.z.object({type:a.z.literal(Er),payload:Mr}).strict(),a.z.object({type:a.z.literal(Nr),payload:jr}).strict()])).default([])}).strict();const Gr="2026-08-25";function Wr(e){return e.startsWith("ai-session.")||e.startsWith("ai.session.")?"ai.sessions":e.startsWith("app-session.")?"app.sessions":e.startsWith("app.management")?"apps":e.startsWith("trigger.")?"triggers":e.startsWith("instance.")?"instances":e.startsWith("node.")?"nodes":e.startsWith("project.")?"projects":e.startsWith("model.")?"models":e.startsWith("image.")?"images":e.startsWith("market.")?"market":"system"}a.z.object({v:a.z.literal(1),type:a.z.literal("ping"),sentAt:a.z.string().datetime()}).strict(),a.z.object({v:a.z.literal(1),type:a.z.literal("pong"),sentAt:a.z.string().datetime(),receivedAt:a.z.string().datetime()}).strict();const Jr=a.z.object({replaySince:a.z.string().datetime().optional(),messageDeltas:a.z.object({allInstances:a.z.boolean().default(!1),instanceIds:a.z.array(a.z.string().trim().min(1).max(160)).max(1e3).default([])}).default({allInstances:!1,instanceIds:[]}),timelineAllSessions:a.z.boolean().default(!1),timelineSessions:a.z.array(a.z.object({instanceId:a.z.string().trim().min(1).max(160),sessionId:a.z.string().trim().min(1).max(120)})).max(1e3).default([])}),Yr=a.z.enum(["ai.sessions","app.sessions"]),Xr=a.z.object({topic:Yr,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(Xr)}).strict();function Zr(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 eo{retryNumber=0;random;constructor(e=Math.random){this.random=e}get attempts(){return this.retryNumber}next(){return this.retryNumber+=1,{attempt:this.retryNumber,delay:Zr(this.retryNumber,this.random)}}reset(){this.retryNumber=0}}class to{backoff;timer;constructor(e=Math.random){this.backoff=new eo(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 no extends to{}function io(e,t=6e4){const n=[];for(let i=0;i<e.length;i+=t)n.push(e.slice(i,i+t));return n}const so=262144,ro=262144;class oo{sockets=new Map;socketUrls=new Map;retries=new Map;outputs=new Set;outputSubscriptions=new Map;outputEnvelopeVersions=new Map;outputDiagnostics=new Map;aiSessionProjectionByInstance=new Map;appSessionProjectionByInstance=new Map;sessionStreamsHelloByInstance=new Map;sessionAuthorityReplayedOutputs=new Set;pendingAiSessionAuthorityByOutput=new Map;pendingAiSessionAuthorityFlush=new Map;eventTransportCongestion;imagePullTerminalByInstance=new Map;state;token;logger;safetyIntervalMs;lastAiSessionEventByInstance=new Map;lastAppSessionEventByInstance=new Map;timer;reconnectAttempts=0;safetyReconciliations=0;localSequence=0;outputSequence=0;createSocket;setIntervalFn;clearIntervalFn;setTimeoutFn;clearTimeoutFn;constructor(e,t,n={}){var i;this.state=e,this.token=t,this.logger=n.logger,this.safetyIntervalMs=(i=n.safetyIntervalMs,Math.min(6e4,Math.max(3e4,i??45e3))),this.createSocket=n.createSocket||((e,t)=>new p(e,t)),this.setIntervalFn=n.setIntervalFn||setInterval,this.clearIntervalFn=n.clearIntervalFn||clearInterval,this.setTimeoutFn=n.setTimeoutFn||setTimeout,this.clearTimeoutFn=n.clearTimeoutFn||clearTimeout}start(){this.sync(),this.timer=this.setIntervalFn(()=>{this.safetyReconciliations+=1,this.sync()},this.safetyIntervalMs)}stop(){this.timer&&(this.clearIntervalFn(this.timer),this.timer=void 0);for(const e of this.sockets.values())e.close();this.sockets.clear(),this.socketUrls.clear();for(const e of this.retries.values())e.timer.cancel();this.retries.clear(),this.outputs.clear(),this.outputSubscriptions.clear(),this.outputEnvelopeVersions.clear(),this.outputDiagnostics.clear();for(const e of this.pendingAiSessionAuthorityFlush.values())this.clearTimeoutFn(e);this.pendingAiSessionAuthorityFlush.clear(),this.pendingAiSessionAuthorityByOutput.clear(),this.aiSessionProjectionByInstance.clear(),this.appSessionProjectionByInstance.clear(),this.sessionStreamsHelloByInstance.clear(),this.sessionAuthorityReplayedOutputs.clear()}addOutput(e,t={}){let n;this.outputs.add(e),this.outputDiagnostics.set(e,{outputId:"event_output_"+ ++this.outputSequence,kind:t.expectsTransientSubscription?"events-websocket":void 0!==t.legacyFallbackMs?"reverse-tunnel":"legacy"}),this.outputSubscriptions.set(e,t.expectsTransientSubscription?Jr.parse({}):void 0),this.outputEnvelopeVersions.set(e,1),t.expectsTransientSubscription||void 0===t.legacyFallbackMs||(n=this.setTimeoutFn(()=>{n=void 0,this.outputs.has(e)&&void 0===this.outputSubscriptions.get(e)&&(this.replaySessionAuthority(e),this.syncNow())},t.legacyFallbackMs));let i=!1;const s=()=>{if(i)return;i=!0,this.outputs.delete(e),this.outputSubscriptions.delete(e),this.outputEnvelopeVersions.delete(e),this.outputDiagnostics.delete(e),this.sessionAuthorityReplayedOutputs.delete(e);const t=this.pendingAiSessionAuthorityFlush.get(e);t&&this.clearTimeoutFn(t),this.pendingAiSessionAuthorityFlush.delete(e),this.pendingAiSessionAuthorityByOutput.delete(e),this.refreshEventTransportRecovery(),n&&clearTimeout(n),this.syncNow()};e.on("close",s),e.on("error",s);for(const t of this.state.listInstances()){const n=ao(t);n?this.sendForwarded(e,this.createEvent(Cs,n,{instanceId:t.id})):this.logger?.warn?.({instanceId:t.id},"instance.lifecycle.snapshot.invalid")}for(const[t,n]of this.imagePullTerminalByInstance)io(n.tail).forEach((i,s)=>this.sendForwarded(e,this.createEvent(ss,{...n.output,sequence:n.output.sequence+s,data:i,...0===s?{replay:!0}:{}},{instanceId:t}))),n.finished&&this.sendForwarded(e,this.createEvent(rs,n.finished,{instanceId:t}));return(t.expectsTransientSubscription||void 0===t.legacyFallbackMs)&&(this.replaySessionAuthority(e),this.syncNow()),s}setOutputSubscription(e,t,n){if(!this.outputs.has(e))return!1;const i=Jr.safeParse(t);if(!i.success)return!1;this.outputSubscriptions.set(e,i.data),this.outputEnvelopeVersions.set(e,n===Gr?Gr:1),this.replaySessionAuthority(e),this.syncNow();for(const[e,t]of this.sockets)this.sendInstanceSubscription(e,t);return!0}publish(e,t,n={}){this.rememberImagePullTerminal(e,t);const i=this.createEvent(e,t,n);for(const e of this.outputs)this.sendForwarded(e,i)}rememberImagePullTerminal(e,t){if(e===ss){const e=$s(as,t);if(!e.success)return;const n=e.data,i=this.imagePullTerminalByInstance.get(n.instanceId);if(i&&n.generation<i.output.generation)return;const s=i?.output.generation===n.generation,r=n.replay||!s?n.data:`${i.tail}${n.data}`.slice(-262144);return void this.imagePullTerminalByInstance.set(n.instanceId,{output:n,tail:r})}if(e===rs){const e=$s(cs,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(Cs,function(e){return Os.parse(co(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:Wr(e),createdAt:(new Date).toISOString(),payload:t,scope:n}}sendForwarded(e,t){const n=t.type===me?Et.safeParse(t.payload):void 0,i=this.outputEnvelopeVersions.get(e)===Gr?function(e,t,n={}){const i=e.scope?n.publicScope&&e.scope.instanceId?{instanceId:e.scope.instanceId}:e.scope:void 0;return{v:Gr,id:e.id,type:e.type,createdAt:e.createdAt,payload:void 0===n.payload?e.payload:n.payload,...e.topic!==Wr(e.type)?{topic:e.topic}:{},...e.replay?{replay:!0}:{},...i&&Object.keys(i).length?{scope:i}:{}}}(t,0,{...n?.success?{payload:(s=n.data,Nt.parse({sessionId:s.sessionId,turnId:s.turnId,itemId:s.itemId,delta:s.delta,generatedAt:s.generatedAt}))}:{}}):t;var s;const r=JSON.stringify({type:"node-agent.event.forwarded",event:i});this.sendOutput(e,r,t)}sendOutput(e,t,n){const i=Buffer.byteLength(t,"utf8"),s=n?.topic===wr?"app-session":n?.topic===de?"ai-session":void 0,r=s?{...this.outputDiagnostics.get(e),instanceId:n.scope?.instanceId,eventType:n.type,...lo(n.payload)}:void 0;if(e.readyState!==p.OPEN)return r&&this.logger?.warn?.({...r,readyState:e.readyState,outcome:"not-open"},`${s}.event.output.rejected`),!1;if(n&&this.shouldCoalesceAiSessionAuthority(e,n)&&this.deferAiSessionAuthority(e,n))return!0;if(n&&po(n)&&i>ro){if(n.type!==le&&this.deferAiSessionAuthority(e,n))return!0;this.observeEventTransportCongestion(e,!1,i),r&&this.logger?.warn?.({...r,bufferedAmount:e.bufferedAmount,bytes:i,maxBytes:ro,outcome:"payload-too-large"},`${s}.event.output.rejected`);try{e.close(1009,"AI Session authority event exceeds the transport limit.")}catch{}return!1}if(e.bufferedAmount+i>16777216){this.observeEventTransportCongestion(e,!1),r&&this.logger?.warn?.({...r,bufferedAmount:e.bufferedAmount,outcome:"backpressure"},`${s}.event.output.rejected`);try{e.close(1013,"Event consumer is too slow.")}catch{}return!1}try{return e.send(t),r&&this.logger?.info?.({...r,bufferedAmount:e.bufferedAmount,bytes:i,outcome:"queued"},`${s}.event.output.queued`),!0}catch(t){r&&this.logger?.warn?.({...r,error:t instanceof Error?t.message:String(t),outcome:"send-failed"},`${s}.event.output.rejected`);try{e.close(1011,"Event delivery failed.")}catch{}return!1}}shouldCoalesceAiSessionAuthority(e,t){if(!po(t))return!1;const n=t.scope?.instanceId;return!!n&&(!!this.pendingAiSessionAuthorityByOutput.get(e)?.has(n)||e.bufferedAmount>=so)}deferAiSessionAuthority(e,t){const n=t.scope?.instanceId,i=n?this.aiSessionProjectionByInstance.get(n):void 0;if(!n||!i)return!1;const s=function(e,t){const n=uo(e);return n?n.payload.meta.streamId!==t.streamId||n.payload.meta.revision!==t.revision?void 0:vt.parse({meta:n.payload.meta,snapshot:t.snapshot}):void 0}(t,i);if(!s)return!1;const r=this.pendingAiSessionAuthorityByOutput.get(e)||new Map;return r.set(n,{...t,type:le,topic:de,payload:s}),this.pendingAiSessionAuthorityByOutput.set(e,r),this.observeEventTransportCongestion(e,!0),this.logger?.info?.({...this.outputDiagnostics.get(e),instanceId:n,eventType:t.type,...lo(s),bufferedAmount:e.bufferedAmount,outcome:"coalesced-latest"},"ai-session.event.output.coalesced"),this.scheduleAiSessionAuthorityFlush(e),!0}scheduleAiSessionAuthorityFlush(e){if(this.pendingAiSessionAuthorityFlush.has(e))return;const t=this.setTimeoutFn(()=>{this.pendingAiSessionAuthorityFlush.delete(e),this.flushAiSessionAuthority(e)},25);t.unref?.(),this.pendingAiSessionAuthorityFlush.set(e,t)}flushAiSessionAuthority(e){const t=this.pendingAiSessionAuthorityByOutput.get(e);if(!t?.size)return void this.pendingAiSessionAuthorityByOutput.delete(e);if(e.readyState!==p.OPEN)return void this.pendingAiSessionAuthorityByOutput.delete(e);const[n,i]=t.entries().next().value;e.bufferedAmount>=so?this.scheduleAiSessionAuthorityFlush(e):(t.delete(n),t.size||this.pendingAiSessionAuthorityByOutput.delete(e),this.sendForwarded(e,i),this.refreshEventTransportRecovery(),t.size&&this.scheduleAiSessionAuthorityFlush(e))}observeEventTransportCongestion(e,t,n=0){const i=(new Date).toISOString(),s=Math.max(0,Math.floor(e.bufferedAmount)),r=this.eventTransportCongestion;this.eventTransportCongestion={congestedSince:r?.recoveredAt?i:r?.congestedSince||i,lastCongestedAt:i,peakBufferedBytes:Math.max(r?.recoveredAt?0:r?.peakBufferedBytes||0,s),coalescedEvents:(r?.recoveredAt?0:r?.coalescedEvents||0)+(t?1:0),oversizedEvents:(r?.recoveredAt?0:r?.oversizedEvents||0)+(n>0?1:0),peakEventBytes:Math.max(r?.recoveredAt?0:r?.peakEventBytes||0,n)}}eventTransportIsCongested(){return!![...this.pendingAiSessionAuthorityByOutput.values()].some(e=>e.size>0)||[...this.outputs].some(e=>e.readyState===p.OPEN&&e.bufferedAmount>=so)}refreshEventTransportRecovery(){const e=this.eventTransportCongestion;!e||e.recoveredAt||this.eventTransportIsCongested()||(e.recoveredAt=(new Date).toISOString())}eventTransportHealth(){this.refreshEventTransportRecovery();const e=[...this.outputs].filter(e=>e.readyState===p.OPEN),t=e.reduce((e,t)=>Math.max(e,Math.max(0,Math.floor(t.bufferedAmount))),0),n=this.eventTransportIsCongested();let i=this.eventTransportCongestion;return i?.recoveredAt&&Date.now()-Date.parse(i.recoveredAt)>3e5&&(this.eventTransportCongestion=void 0,i=void 0),{status:n?"congested":i?"recovering":"healthy",activeOutputs:e.length,bufferedBytes:t,peakBufferedBytes:i?.peakBufferedBytes||t,coalescedEvents:i?.coalescedEvents||0,oversizedEvents:i?.oversizedEvents||0,peakEventBytes:i?.peakEventBytes||0,...n&&i?{congestedSince:i.congestedSince}:{},...i?{lastCongestedAt:i.lastCongestedAt}:{}}}syncNow(){this.sync()}diagnostics(){const e=[...this.outputSubscriptions.values()];return{reconnectAttempts:this.reconnectAttempts,safetyReconciliations:this.safetyReconciliations,activeConnections:this.sockets.size,pendingRetries:[...this.retries.values()].filter(e=>e.timer.pending).length,safetyIntervalMs:this.safetyIntervalMs,eventTransport:this.eventTransportHealth(),transientDemand:{legacyOutputs:e.filter(e=>void 0===e).length,scopedOutputs:e.filter(e=>void 0!==e).length,messageDeltaAllInstances:e.some(e=>e?.messageDeltas.allInstances),messageDeltaInstanceCount:new Set(e.flatMap(e=>e?.messageDeltas.instanceIds||[])).size,timelineAllSessions:e.some(e=>e?.timelineAllSessions),timelineSessionCount:new Set(e.flatMap(e=>e?.timelineSessions.map(e=>JSON.stringify([e.instanceId,e.sessionId]))||[])).size}}}sync(){const e=new Set(this.state.listInstances().map(e=>e.id));for(const t of this.aiSessionProjectionByInstance.keys())e.has(t)||this.aiSessionProjectionByInstance.delete(t);for(const t of this.appSessionProjectionByInstance.keys())e.has(t)||this.appSessionProjectionByInstance.delete(t);for(const t of this.sessionStreamsHelloByInstance.keys())e.has(t)||this.sessionStreamsHelloByInstance.delete(t);for(const t of this.imagePullTerminalByInstance.keys())e.has(t)||this.imagePullTerminalByInstance.delete(t);if(!this.outputs.size){for(const e of this.sockets.values())e.close();this.sockets.clear(),this.socketUrls.clear();for(const e of this.retries.values())e.timer.cancel();return void this.retries.clear()}const t=new Set;for(const e of this.state.listInstances()){const n=mo(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 no,url:t}),i.readyState===p.OPEN&&(this.sendInstanceSubscription(e,i),this.logger?.info?.({instanceId:e,url:t},"ai-session.event.forward.connect"),this.logger?.info?.({instanceId:e,url:t},"app-session.event.forward.connect"))}),i.on("message",t=>{const n=function(e,t){try{const n=function(e,t={}){if(!e||"object"!=typeof e||Array.isArray(e))return;const n=e,i="string"==typeof n.type?n.type:"";if(!i)return;const s=n.scope&&"object"==typeof n.scope&&!Array.isArray(n.scope)?n.scope:{};return{v:1,id:"string"==typeof n.id?n.id:`event_${Date.now().toString(36)}`,seq:"number"==typeof n.seq&&Number.isFinite(n.seq)?n.seq:0,type:i,topic:"string"==typeof n.topic?n.topic:Wr(i),createdAt:"string"==typeof n.createdAt?n.createdAt:(new Date).toISOString(),payload:"payload"in n?n.payload:{},...!0===n.replay?{replay:!0}:{},scope:{...t,...s}}}(JSON.parse(String(e)),{instanceId:t});if(!n||"events.connected"===n.type)return;if(n.type===me){const e=function(e,t){const n=Nt.safeParse(e);return n.success?Et.parse({instanceId:t,...n.data}):Et.parse(e)}(n.payload,t);return{...n,payload:e,scope:{...n.scope,instanceId:t}}}return{...n,scope:{...n.scope,instanceId:t}}}catch{return}}(t,e);if(n){if("streams.hello"===n.type){const t=$s(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.");this.retries.get(e)?.timer.reset(),this.sessionStreamsHelloByInstance.set(e,t.data);const s=JSON.stringify({type:"node-agent.streams.hello",instanceId:e,payload:t.data});for(const e of this.outputs)this.sendOutput(e,s);return}this.recordAiSessionEvent(e,n),this.recordAppSessionEvent(e,n);for(const e of this.outputs)this.outputAccepts(e,n)&&this.sendForwarded(e,n)}}),i.on("close",()=>{this.sockets.get(e)===i&&(this.sockets.delete(e),this.socketUrls.delete(e),this.scheduleReconnect(e))}),i.on("error",()=>{this.logger?.warn?.({instanceId:e,url:t},"ai-session.event.forward.error"),this.logger?.warn?.({instanceId:e,url:t},"app-session.event.forward.error"),i.close()})}sendInstanceSubscription(e,t){if(t.readyState!==p.OPEN)return;const n=[...this.outputs].map(e=>this.outputSubscriptions.get(e));if(n.some(e=>void 0===e))return void t.send(JSON.stringify({v:1,type:"subscribe",eventEnvelopeVersion:Gr,topics:[de,"app.sessions","apps","instances"]}));const i=n.some(t=>t.messageDeltas.allInstances||t.messageDeltas.instanceIds.includes(e)),s=n.some(e=>e.timelineAllSessions),r=[...new Set(n.flatMap(t=>t.timelineSessions.filter(t=>t.instanceId===e).map(e=>e.sessionId)))],o=n.map(e=>e.replaySince).filter(e=>Boolean(e)).sort()[0];t.send(JSON.stringify({v:1,type:"subscribe",eventEnvelopeVersion:Gr,topics:[le,ue,pe,...i?[me]:[],...s||r.length?[he]:[],"app.sessions","apps","instances"],aiSessionTransient:{...o?{replaySince:o}:{},messageDeltas:{allInstances:i,instanceIds:[]},timelineAllSessions:s,timelineSessions:r.map(t=>({instanceId:e,sessionId:t}))}}))}outputAccepts(e,t){const n=this.outputSubscriptions.get(e);return!n||function(e,t){if(!e)return!0;if("ai-session.message-delta"!==t.type&&"ai-session.timeline-item"!==t.type)return!0;const n=t.payload&&"object"==typeof t.payload&&!Array.isArray(t.payload)?t.payload:{},i=String(n.instanceId||t.scope?.instanceId||"");return"ai-session.message-delta"===t.type?e.messageDeltas.allInstances||e.messageDeltas.instanceIds.includes(i):e.timelineAllSessions||e.timelineSessions.some(e=>e.instanceId===i&&e.sessionId===n.sessionId)}(n,t)}scheduleReconnect(e){const t=this.state.listInstances().find(t=>t.id===e),n=t&&mo(t);if(!n||!this.outputs.size)return;const i=this.retries.get(e)??{timer:new no};if(i.timer.pending)return;i.url=n;const s=i.timer.schedule(()=>{this.sockets.has(e)||this.connect(e,n)},{setTimeoutFn:this.setTimeoutFn});s&&(this.reconnectAttempts+=1,this.logger?.info?.({instanceId:e,url:n,attempt:s.attempt,delay:s.delay,reconnectAttempts:this.reconnectAttempts},"session-stream.connection.reconnect-scheduled")),this.retries.set(e,i)}recordAiSessionEvent(e,t){if(t.topic!==de)return;if(t.type===me||t.type===he)return;const n=uo(t);if(n){const t=function(e,t){const{meta:n}=t.payload;if(t.type===le)return e?.streamId===n.streamId&&n.revision===e.revision?{kind:"duplicate",projection:e}:e?.streamId===n.streamId&&n.revision<e.revision?{kind:"stale",projection:e}:{kind:"applied",projection:It.parse({streamId:n.streamId,revision:n.revision,lastEventAt:n.generatedAt,snapshot:t.payload.snapshot})};if(!e||e.streamId!==n.streamId)return{kind:"snapshot-required",projection:e,streamId:n.streamId};if(n.revision===e.revision)return{kind:"duplicate",projection:e};if(n.revision<e.revision)return{kind:"stale",projection:e};if(n.revision!==e.revision+1||n.previousRevision!==e.revision)return{kind:"gap",projection:e,expectedRevision:e.revision+1,receivedRevision:n.revision};const i=new Map(e.snapshot.sessions.map(e=>[e.id,e]));if(t.type===ue){for(const e of t.payload.upserted)i.set(e.id,e);for(const e of t.payload.removed)i.delete(e)}else for(const e of t.payload.sessionIds)i.delete(e);const s=[...i.values()],r=yt.parse({runningCount:s.filter(e=>"running"===e.status).length,waitingCount:s.filter(e=>"waiting"===e.status).length,staleCount:e.snapshot.staleCount,sessions:s,updatedAt:n.generatedAt});return{kind:"applied",projection:It.parse({streamId:n.streamId,revision:n.revision,lastEventAt:n.generatedAt,snapshot:r})}}(this.aiSessionProjectionByInstance.get(e),n);"applied"!==t.kind&&"duplicate"!==t.kind&&"stale"!==t.kind||this.aiSessionProjectionByInstance.set(e,t.projection)}const i=lo(t.payload),s=this.lastAiSessionEventByInstance.get(e);s?.streamId===i.streamId&&void 0!==s.revision&&void 0!==i.revision&&i.revision>s.revision+1&&this.logger?.warn?.({instanceId:e,traceId:i.traceId,streamId:i.streamId,previousRevision:s.revision,revision:i.revision},"ai-session.event.forward.gap"),this.lastAiSessionEventByInstance.set(e,{streamId:i.streamId??s?.streamId,revision:i.revision??s?.revision}),this.logger?.info?.({instanceId:e,traceId:i.traceId,eventType:t.type,streamId:i.streamId,revision:i.revision},"ai-session.event.forward.message")}recordAppSessionEvent(e,t){if(t.topic!==wr)return;const n=function(e){const t=e.type===Sr?Dr:e.type===Er?Mr:e.type===Nr?jr:void 0;if(!t)return;const n=$s(t,e.payload);return n.success?{type:e.type,payload:n.data}:void 0}(t);if(n){const t=function(e,t){const{meta:n}=t.payload;if(t.type===Sr)return e?.streamId===n.streamId&&n.revision===e.revision?{kind:"duplicate",projection:e}:e?.streamId===n.streamId&&n.revision<e.revision?{kind:"stale",projection:e}:{kind:"applied",projection:Rr.parse({streamId:n.streamId,revision:n.revision,lastEventAt:n.generatedAt,snapshot:Fr(t.payload.snapshot.sessions,t.payload.snapshot.updatedAt)})};if(!e||e.streamId!==n.streamId)return{kind:"snapshot-required",projection:e,streamId:n.streamId};if(n.revision===e.revision)return{kind:"duplicate",projection:e};if(n.revision<e.revision)return{kind:"stale",projection:e};if(n.revision!==e.revision+1||n.previousRevision!==e.revision)return{kind:"gap",projection:e,expectedRevision:e.revision+1,receivedRevision:n.revision};const i=[...e.snapshot.sessions];if(t.type===Er){const e=i.findIndex(e=>e.id===t.payload.session.id);Ur(t.payload.session.status)?e<0?i.push(t.payload.session):i[e]=t.payload.session:e>=0&&i.splice(e,1)}else{const e=i.findIndex(e=>e.id===t.payload.sessionId);e>=0&&i.splice(e,1)}const s=Lr(i,n.generatedAt);return{kind:"applied",projection:Rr.parse({streamId:n.streamId,revision:n.revision,lastEventAt:n.generatedAt,snapshot:s})}}(this.appSessionProjectionByInstance.get(e),n);"applied"!==t.kind&&"duplicate"!==t.kind&&"stale"!==t.kind||this.appSessionProjectionByInstance.set(e,t.projection)}const i=lo(t.payload),s=this.lastAppSessionEventByInstance.get(e);s?.streamId===i.streamId&&void 0!==s.revision&&void 0!==i.revision&&i.revision>s.revision+1&&this.logger?.warn?.({instanceId:e,traceId:i.traceId,streamId:i.streamId,previousRevision:s.revision,revision:i.revision},"app-session.event.forward.gap"),this.lastAppSessionEventByInstance.set(e,{streamId:i.streamId??s?.streamId,revision:i.revision??s?.revision}),this.logger?.info?.({instanceId:e,traceId:i.traceId,eventType:t.type,streamId:i.streamId,revision:i.revision},"app-session.event.forward.message")}replaySessionAuthority(e){if(!this.sessionAuthorityReplayedOutputs.has(e)&&e.readyState===p.OPEN){this.sessionAuthorityReplayedOutputs.add(e);for(const[t,n]of this.sessionStreamsHelloByInstance){const i=n.streams.map(e=>{const n=e.topic===de?this.aiSessionProjectionByInstance.get(t):this.appSessionProjectionByInstance.get(t);return n?n.streamId!==e.streamId?{...e,streamId:n.streamId,latestRevision:n.revision,earliestRetainedRevision:n.revision}:{...e,latestRevision:Math.max(e.latestRevision,n.revision)}:e});this.sendOutput(e,JSON.stringify({type:"node-agent.streams.hello",instanceId:t,payload:{...n,streams:i}}))}for(const[t,n]of this.aiSessionProjectionByInstance)this.sendForwarded(e,this.createEvent(le,{meta:{streamId:n.streamId,instanceId:t,revision:n.revision,traceId:`ais_replay_${Date.now().toString(36)}`,generatedAt:n.lastEventAt,reason:"startup"},snapshot:n.snapshot},{instanceId:t}));for(const[t,n]of this.appSessionProjectionByInstance)this.sendForwarded(e,this.createEvent(Sr,{meta:{streamId:n.streamId,instanceId:t,revision:n.revision,traceId:`aps_replay_${Date.now().toString(36)}`,generatedAt:n.lastEventAt,reason:"startup"},snapshot:n.snapshot},{instanceId:t}))}}}function ao(e){const t=Os.safeParse(co(e));return t.success?t.data:void 0}function co(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 lo(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 uo(e){const t=e.type===le?vt:e.type===ue?wt:e.type===pe?St:void 0;if(!t)return;const n=$s(t,e.payload);return n.success?{type:e.type,payload:n.data}:void 0}function po(e){return e.topic===de&&(e.type===le||e.type===ue||e.type===pe)}function mo(e){if(!function(e){return!1!==e.ready&&(!e.runtimeVersion||["matched","failed"].includes(e.runtimeVersion.phase))}(e))return;const t=e.target?.api||e.target?.web;if(t)try{const e=new URL("/api/events",t);return e.searchParams.set("aiSessionTransient","1"),e.searchParams.set("aiSessionAuthoritySnapshot","1"),e.protocol="https:"===e.protocol?"wss:":"ws:",e.toString()}catch{return}}const ho=new Set(["provisioning","starting","registering","registered","running","unhealthy"]),go=JSON.stringify({id:"{{.ID}}",name:"{{.Name}}",cpu:"{{.CPUPerc}}",memory:"{{.MemUsage}}",memoryPercent:"{{.MemPerc}}",network:"{{.NetIO}}",blockIo:"{{.BlockIO}}",pids:"{{.PIDs}}"});class fo{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(!ho.has(t.status))return wo(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=yo(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,yo(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=>ho.has(e.status)&&(e.runtime.containerId||e.runtime.containerName));for(const t of e.filter(e=>ho.has(e.status)&&!e.runtime.containerId&&!e.runtime.containerName))this.update(So(t.id));for(const t of e.filter(e=>!ho.has(e.status)))this.update(wo(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",go,...n],{timeoutMs:5e3});this.applyDockerOutput(t,e.stdout,i)}catch(e){if(1===t.length)return void this.update(Eo(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",go,t],{timeoutMs:5e3});this.applyDockerOutput([e],n.stdout,i)}catch(t){this.update(Eo(e.id,i,t instanceof Error?t.message:String(t)))}}))}}applyDockerOutput(e,t,n){const i=function(e,t=(new Date).toISOString()){const n=new Map;for(const i of e.split(/\r?\n/).filter(Boolean)){let e;try{e=JSON.parse(i)}catch{continue}const s=vo(e.id),r=vo(e.name),o=s||r;if(!o)continue;const a=Io(vo(e.memory)),c=Io(vo(e.network)),d=Io(vo(e.blockIo)),l=hs.parse({instanceId:o,runtimeKind:"docker",state:"available",sampledAt:t,cpu:Ao(e.cpu,"usagePercent"),memory:a?{usageBytes:a[0],...void 0!==a[1]?{limitBytes:a[1]}:{},...Ao(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:bo(e.pids)});s&&n.set(s,l),r&&n.set(r,l)}return n}(t,n);for(const t of e){const e=[t.runtime.containerId,t.runtime.containerName].filter(Boolean),s=[...i.entries()].find(([t])=>e.some(e=>e===t||e.startsWith(t)||t.startsWith(e)))?.[1];this.update(s?{...s,instanceId:t.id}:Eo(t.id,n,"Container metrics were not returned by Docker."))}}update(e){const t=hs.parse(e);this.snapshots.set(t.instanceId,t),this.publish?.(t)}}function yo(e){return[e.status,e.runtime.containerId||"",e.runtime.containerName||""].join("\0")}function Io(e){if(!e)return;const[t,n]=e.split("/").map(e=>function(e){const t=e.trim().match(/^([0-9]+(?:\.[0-9]+)?)\s*([kmgtpe]?i?b)$/i);if(!t)return;const n=Number(t[1]),i=t[2].toLowerCase(),s=i.includes("i"),r="b"===i[0]?"":i[0],o=r?"kmgtpe".indexOf(r)+1:0;return Math.round(n*(s?1024:1e3)**o)}(e||""));return void 0===t?void 0:[t,n]}function Ao(e,t){const n=Number(vo(e).replace(/%$/,""));return Number.isFinite(n)&&n>=0?{[t]:n}:void 0}function bo(e){const t=Number(vo(e));return Number.isFinite(t)&&t>=0?t:void 0}function vo(e){return"string"==typeof e||"number"==typeof e?String(e).trim():""}function wo(e){return{instanceId:e,runtimeKind:"docker",state:"stopped",sampledAt:(new Date).toISOString()}}function So(e){return{instanceId:e,runtimeKind:"docker",state:"pending",sampledAt:(new Date).toISOString()}}function Eo(e,t,n){return{instanceId:e,runtimeKind:"docker",state:"unavailable",sampledAt:t,error:n.slice(0,2048)}}function No(e,t,n){return Object.assign(new Error(e),{statusCode:t,code:n})}function zo(e){const i=n.resolve(e);let s;try{s=t.statSync(i)}catch(e){const t=e&&"object"==typeof e?e.code:void 0;if("ENOENT"===t||"ENOTDIR"===t)throw No(`Folder ${i} was not found.`,404,"NODE_FOLDER_PATH_NOT_FOUND");throw No(`Folder ${i} is not accessible.`,403,"NODE_FOLDER_PATH_UNREADABLE")}if(!s.isDirectory())throw No(`Path ${i} is not a folder.`,400,"NODE_FOLDER_PATH_NOT_DIRECTORY");try{t.accessSync(i,t.constants.R_OK|t.constants.X_OK)}catch{throw No(`Folder ${i} is not accessible.`,403,"NODE_FOLDER_PATH_UNREADABLE")}return i}function To(e){try{return t.statSync(e).isDirectory()}catch{return!1}}function _o(){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(To)}function ko(){const e=n.resolve(c.homedir()),t=_o().map(e=>n.resolve(e));return[...To(e)?[{kind:"home",name:n.basename(e)||e,path:e}]:[],...t.map(e=>({kind:"root",name:e,path:e}))]}function Co(e,i){let s;try{s=t.statSync(e)}catch{return}if(!s.isDirectory())return;const r=n.resolve(e),o=n.basename(r)||r;let a=[];try{a=i>0?t.readdirSync(r,{withFileTypes:!0}):[]}catch{a=[]}const c=i>0?a.filter(e=>e.isDirectory()||e.isSymbolicLink()&&To(n.join(r,e.name))).sort((e,t)=>e.name.localeCompare(t.name)).slice(0,80).flatMap(e=>{const t=Co(n.join(r,e.name),i-1);return t?[t]:[]}):[];return{name:o,path:r,children:c}}function Oo(e){return(e.path?[zo(e.path)]:_o()).flatMap(t=>{const n=Co(t,e.depth);return n?[n]:[]})}function Ro(){return process.env.TASK_HANDOFF_NODE_AGENT_DATA_DIR||n.join(c.homedir(),".config","task-handoff","node-agent")}function xo(e=Ro()){const t=n.resolve(e);return{dataDir:t,identityPath:n.join(t,"identity.json"),settingsPath:n.join(t,"runtime-settings.json"),localFoldersDir:n.join(t,"local-folders"),nodeRuntimesDir:n.join(t,"node-runtimes"),controlledInstancesDir:n.join(t,"controlled-instances"),environmentTemplatesDir:n.join(t,"environment-templates"),instancePrivateConfigsDir:n.join(t,"instance-private-configs"),nodeModelsDir:n.join(t,"models"),modelAssignmentsDir:n.join(t,"model-assignments"),modelEnvironmentsDir:n.join(t,"model-environments"),gitCredentialPayloadsDir:n.join(t,"git-credentials","payloads"),gitCredentialAssignmentsDir:n.join(t,"git-credentials","assignments"),gitCredentialAuthorizationSetsDir:n.join(t,"git-credentials","authorization-sets"),gitWorkspaceProvisioningIntentsDir:n.join(t,"git-credentials","workspace-provisioning-intents"),updatesDir:n.join(t,"updates"),logsDir:n.join(t,"logs")}}function Po(e,t){const i=n.extname(e);return`${i?e.slice(0,-i.length):e}.${t}${i}`}function Do(e,n=10485760,i=2){if(!t.existsSync(e))return!1;const s=t.lstatSync(e);if(!s.isFile()||s.isSymbolicLink()||s.size<=n)return!1;if(i>0){!function(e,n){if(!(n<=0)){t.rmSync(Po(e,n),{force:!0});for(let i=n-1;i>=1;i-=1){const n=Po(e,i);t.existsSync(n)&&t.renameSync(n,Po(e,i+1))}}}(e,i);const s=function(e,n){const i=t.statSync(e),s=Math.min(i.size,n),r=Buffer.allocUnsafe(s),o=t.openSync(e,"r");let a=0;try{for(;a<s;){const e=t.readSync(o,r,a,s-a,i.size-s+a);if(0===e)break;a+=e}}finally{t.closeSync(o)}return a===s?r:r.subarray(0,a)}(e,n);t.writeFileSync(Po(e,1),s,{mode:384})}return t.truncateSync(e,0),t.chmodSync(e,384),!0}class Mo{logsDir;localInstancesRoot;localInstancesTrashRoot;options;constructor(e,t={}){this.options=t,this.logsDir=e.logsDir,this.localInstancesRoot=n.join(e.dataDir,"local-instances"),this.localInstancesTrashRoot=n.join(e.dataDir,"local-instances-trash")}run(e){this.capNodeAgentLogs();const n=new Set(e);if(t.existsSync(this.localInstancesRoot)){ie(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??te,s=[];for(const r of t.readdirSync(e.trashRoot,{withFileTypes:!0})){const o=ne(e.trashRoot,r.name);try{const e=Number(r.name.split("-",1)[0]);if(!Number.isFinite(e)||e+i>n)continue;const a=t.lstatSync(o);a.isSymbolicLink()?t.unlinkSync(o):a.isDirectory()?t.rmSync(o,{recursive:!0,force:!0}):t.unlinkSync(o),s.push(o)}catch(t){e.logger?.("retired persistence entry cleanup failed",{path:o,error:t instanceof Error?t.message:String(t)})}}return s}({trashRoot:this.localInstancesTrashRoot,retentionMs:this.options.retentionMs??te,nowMs:this.now(),logger:this.options.logger})}capActiveInstanceLogs(e){for(const t of e)this.capControlledInstanceLogs(t)}capNodeAgentLogs(){const e=[];for(const t of["node-agent.out.log","node-agent.err.log"]){const i=n.join(this.logsDir,t);try{Do(i)&&e.push(i)}catch(e){this.options.logger?.("node-agent log rotation failed",{filePath:i,error:e instanceof Error?e.message:String(e)})}}return e}capControlledInstanceLogs(e){const t=n.resolve(this.localInstancesRoot,e);if(n.dirname(t)!==n.resolve(this.localInstancesRoot))return[];const i=n.join(t,"logs"),s=[];for(const t of["controlled-instance.out.log","controlled-instance.err.log"]){const r=n.join(i,t);try{Do(r)&&s.push(r)}catch(t){this.options.logger?.("controlled instance log rotation failed",{instanceId:e,filePath:r,error:t instanceof Error?t.message:String(t)})}}return s}retire(e){try{return function(e){const n=ne(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}`);ie(e.trashRoot);const s=e.nowMs??Date.now();let r=0,o=`${s}-${e.entryName}`;for(;t.existsSync(ne(e.trashRoot,o));)r+=1,o=`${s}-${r}-${e.entryName}`;const a=ne(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 jo(e,t=process.platform){const i=n.resolve(e),s=d.createHash("sha256").update(i).digest("hex").slice(0,16);return"win32"===t?`\\\\.\\pipe\\task-handoff-node-agent-${s}`:n.join("/tmp",`task-handoff-node-agent-${process.getuid?.()??"user"}`,`${s}.sock`)}async function Lo(e,t,n={}){const s=n.method||"GET",r="string"==typeof n.body||n.body instanceof Buffer?n.body:void 0===n.body||null===n.body?void 0:String(n.body),o=new Headers(n.headers||{});return void 0===r||o.has("content-length")||o.set("content-length",String(Buffer.byteLength(r))),new Promise((a,c)=>{const d=i.request({socketPath:e,method:s,path:`/api/node-agent${t}`,headers:Object.fromEntries(o.entries())},e=>{const t=e.statusCode||500;a(new Response("HEAD"!==s&&204!==t&&205!==t&&304!==t?h.Readable.toWeb(e):null,{status:t,headers:e.headers}))});d.on("error",c);const l=()=>d.destroy(new DOMException("The operation was aborted.","AbortError"));n.signal?.aborted?l():n.signal?.addEventListener("abort",l,{once:!0}),d.once("close",()=>n.signal?.removeEventListener("abort",l)),void 0!==r&&d.write(r),d.end()})}const Fo="runtime-manifest.json";class $o 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 Uo(e,t=""){const i=[],s=await g.readdir(n.join(e,t),{withFileTypes:!0});for(const r of s){const s=t?n.posix.join(t,r.name):r.name;if(!t&&s===Fo)continue;const o=n.join(e,...s.split("/"));if(r.isDirectory()){i.push(...await Uo(e,s));continue}if(r.isSymbolicLink()){const t=await g.readlink(o);if(n.isAbsolute(t))throw new $o("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload symlink is absolute: ${s}`);const r=n.resolve(n.dirname(o),t),a=n.relative(n.resolve(e),r);if(!a||".."===a||a.startsWith(`..${n.sep}`)||n.isAbsolute(a))throw new $o("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload symlink escapes the artifact: ${s}`);if(!await g.lstat(r).catch(()=>{}))throw new $o("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload symlink is broken: ${s}`);i.push({absolutePath:o,relativePath:s,kind:"symlink",target:t,size:Buffer.byteLength(t)});continue}if(!r.isFile())throw new $o("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload contains unsupported entry: ${s}`);const a=await g.lstat(o);i.push({absolutePath:o,relativePath:s,kind:"file",size:a.size})}return i}async function Vo(e){const n=(await Uo(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 Ho(e){for(const[t,n]of[["version",e.version],["platform",e.platform],["arch",e.arch]])if(!/^[0-9A-Za-z._-]+$/.test(n))throw new $o("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Invalid runtime artifact ${t}: ${n}`);return`${e.version}-${e.platform}-${e.arch}`}function Bo(e,t){return`${Ho(e)}-${e.sha256}-${t}`}async function qo(e){const n=d.createHash("sha256");for await(const i of t.createReadStream(e))n.update(i);return n.digest("hex")}class Ko{#e;#t;#n=new Map;constructor(e){this.#e=e.cacheDir,this.#t=e.fetchImpl??fetch}resolve(e,t){const n=mi.parse(e);if(!/^[a-f0-9]{64}$/.test(t.archiveSha256))throw new $o("INSTANCE_RUNTIME_ARTIFACT_INVALID","Runtime archive SHA-256 is invalid.");if((t.archiveUrl?1:0)+(t.archivePath?1:0)!=1)throw new $o("INSTANCE_RUNTIME_ARTIFACT_INVALID","Runtime artifact source must specify exactly one archive location.");const i=Bo(n,t.archiveSha256),s=this.#n.get(i);if(s)return s;const r=this.#i(n,t).finally(()=>this.#n.delete(i));return this.#n.set(i,r),r}async#i(e,i){if(!/^[a-f0-9]{64}$/.test(i.archiveSha256))throw new $o("INSTANCE_RUNTIME_ARTIFACT_INVALID","Runtime archive SHA-256 is invalid.");const s=Bo(e,i.archiveSha256),r=n.join(this.#e,"archives"),o=n.join(r,`${s}.tar.gz`);if(await g.mkdir(r,{recursive:!0}),await this.#s(o,e,i.archiveSha256))return{identity:e,archivePath:o,cacheHit:!0};await g.rm(o,{force:!0});const a=n.join(r,`.${s}.${d.randomUUID()}.part`);try{const n=await g.open(a,"wx");if(i.archivePath)await f.pipeline(t.createReadStream(i.archivePath),n.createWriteStream());else{const e=await this.#t(i.archiveUrl);if(!e.ok||!e.body)throw await n.close(),new $o("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 qo(a)!==i.archiveSha256)throw new $o("INSTANCE_RUNTIME_ARTIFACT_INVALID","Downloaded runtime archive SHA-256 does not match release metadata.");return await this.#r(a,e),await g.rename(a,o),{identity:e,archivePath:o,cacheHit:!1}}catch(e){if(e instanceof $o)throw e;throw new $o("INSTANCE_RUNTIME_ARTIFACT_UNAVAILABLE","Could not download runtime artifact.",{cause:e,retryable:!0})}finally{await g.rm(a,{force:!0})}}async#s(e,t,n){try{return await qo(e)===n&&(await this.#r(e,t),!0)}catch{return!1}}async#r(e,t){const i=n.join(this.#e,"validation",`${Ho(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 $o("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime archive entry escapes the artifact root: ${e}`);const s=t.type;if("File"!==s&&"OldFile"!==s&&"Directory"!==s&&"SymbolicLink"!==s)throw new $o("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime archive contains unsupported entry type ${s??"unknown"}: ${e}`);return!0}})}catch(e){throw new $o("INSTANCE_RUNTIME_ARTIFACT_INVALID","Could not extract runtime artifact safely.",{cause:e})}}(e,i),await async function(e,t,i){const s=await async function(e){let t;try{t=JSON.parse(await g.readFile(n.join(e,Fo),"utf8"))}catch(e){throw new $o("INSTANCE_RUNTIME_ARTIFACT_INVALID","Runtime artifact manifest is missing or invalid JSON.",{cause:e})}const i=$s(mi,t);if(!i.success)throw new $o("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 $o("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime artifact ${"sha256"===n?"SHA-256":n} mismatch: expected ${t[n]}, got ${e[n]}.`)}(s,t),1!==s.formatVersion)throw new $o("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Unsupported runtime artifact format ${s.formatVersion}.`);if(i?.platform&&"universal"!==s.platform&&s.platform!==i.platform)throw new $o("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime artifact platform ${s.platform} does not match ${i.platform}.`);if(i?.arch&&"universal"!==s.arch&&s.arch!==i.arch)throw new $o("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime artifact architecture ${s.arch} does not match ${i.arch}.`);if(void 0!==i?.launcherAbi&&s.launcherAbi>i.launcherAbi)throw new $o("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Runtime requires launcher ABI ${s.launcherAbi}, but the base runtime provides ${i.launcherAbi}.`);const r=function(e,t){if(!e||e.includes("\\")||n.posix.isAbsolute(e))throw new $o("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 $o("INSTANCE_RUNTIME_ARTIFACT_INVALID",`${t} escapes the runtime root.`);return i}(s.entrypoint,"Runtime entrypoint"),o=await g.lstat(n.join(e,...r.split("/"))).catch(()=>{});if(!o?.isFile())throw new $o("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime entrypoint is missing: ${r}`);const a=await Vo(e);if(a!==s.sha256)throw new $o("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload SHA-256 mismatch: expected ${s.sha256}, got ${a}.`);return s}(i,t,{platform:t.platform,arch:t.arch})}finally{await g.rm(i,{recursive:!0,force:!0})}}}async function Go(e,t,i,s=fetch){if("linux"!==t||!["x64","arm64"].includes(i))throw new $o("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Managed controlled-instance updates require a Linux x64 or arm64 target, received ${t}/${i}.`);const r=await async function(e){const t=`controlled-instance-runtime-${e}-linux-universal`,i=function(){const e=process.env.TASK_HANDOFF_BUNDLED_RUNTIME_DIR?.trim();return n.resolve(e||n.join(n.dirname(process.argv[1]||process.cwd()),"..","runtime-artifacts"))}();try{const[s,r]=await Promise.all([g.readFile(n.join(i,`${t}.manifest.json`),"utf8"),g.readFile(n.join(i,`${t}.tar.gz.sha256`),"utf8")]),o=$s(mi,JSON.parse(s));if(!o.success||o.data.version!==e||"linux"!==o.data.platform||"universal"!==o.data.arch)throw new $o("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Bundled controlled-instance ${e} has an invalid Linux manifest.`);const a=r.trim().split(/\s+/)[0]?.toLowerCase();if(!a||!/^[a-f0-9]{64}$/.test(a))throw new $o("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 $o)throw t;throw new $o("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Could not read bundled controlled-instance ${e}.`,{cause:t})}}(e);if(r)return r;const o=`controlled-instance-runtime-${e}-linux-universal`,a=function(e){const t=process.env.TASK_HANDOFF_RUNTIME_RELEASE_BASE_URL?.trim();return t?t.replaceAll("{version}",e).replace(/\/$/,""):`https://github.com/edgestorage/task-handoff/releases/download/v${e}`}(e),c=`${a}/${o}.manifest.json`,d=`${a}/${o}.tar.gz`,l=`${a}/${o}.tar.gz.sha256`,[u,p]=await Promise.all([s(c),s(l)]).catch(t=>{throw new $o("INSTANCE_RUNTIME_ARTIFACT_UNAVAILABLE",`Could not read release metadata for controlled-instance ${e}.`,{cause:t,retryable:!0})});if(!u.ok||!p.ok)throw new $o("INSTANCE_RUNTIME_ARTIFACT_UNAVAILABLE",`Release metadata for controlled-instance ${e} is unavailable (manifest HTTP ${u.status}, checksum HTTP ${p.status}).`,{retryable:u.status>=500||p.status>=500});let m;try{m=await u.json()}catch(t){throw new $o("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Release manifest for controlled-instance ${e} is not valid JSON.`,{cause:t})}const h=$s(mi,m);if(!h.success)throw new $o("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 $o("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Release identity mismatch: requested ${e}-linux-universal, received ${h.data.version}-${h.data.platform}-${h.data.arch}.`);const f=(await p.text()).trim().split(/\s+/)[0]?.toLowerCase();if(!f||!/^[a-f0-9]{64}$/.test(f))throw new $o("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Release checksum for controlled-instance ${e} is invalid.`);return{identity:h.data,source:{archiveUrl:d,archiveSha256:f}}}class Wo{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=ia(i.retryBaseDelayMs??1e3,"retryBaseDelayMs"),this.retryMaxDelayMs=ia(i.retryMaxDelayMs??3e4,"retryMaxDelayMs")}schedule(e,t={}){const n=this.requests.get(e)||{startRequested:!1,resumeCancelled:!1};n.startRequested||=!0===t.startRequested,n.resumeCancelled||=!0===t.resumeCancelled||!0===t.startRequested,n.resumeCancelled&&this.cancelled.delete(e),this.requests.set(e,n);const i=this.inFlight.get(e);if(i)return i;const s=Promise.resolve().then(()=>this.reconcile(e,n)).finally(()=>{this.inFlight.delete(e),this.requests.delete(e)});return this.inFlight.set(e,s),s}isRunning(e){return this.inFlight.has(e)}cancel(e){return this.cancelled.add(e),this.inFlight.get(e)}async reconcile(e,t){let n=this.requireInstance(e);const i=this.desiredVersion();if(this.cancelled.has(e)&&!t.resumeCancelled)return this.storePhase(n,"pending");if(Xo(n))return this.storePhase(n,"pending");const s=n.runtimeVersion?.desiredVersion!==i||t.startRequested||Qo(n)?0:this.remainingRetryDelayMs(n.runtimeVersion);if(s>0&&(await this.delay(s),n=this.requireInstance(e),this.cancelled.has(e)))return this.storePhase(n,"pending");const r=Jo(n),o=r===i&&(await(this.hooks.isInstalled?.(n,i))??!0);if(this.cancelled.has(e))return this.storePhase(this.requireInstance(e),"pending");if(r===i&&o)return this.storeState(n,{desiredVersion:i,actualVersion:r,phase:"matched",attempt:n.runtimeVersion?.attempt||0,matchedAt:this.timestamp()},!Qo(n)&&"failed"!==n.health);if(n=this.storeState(n,function(e,t,n,i=!1){const s=e.runtimeVersion,r=s?.desiredVersion===t&&"matched"!==s.phase;return{desiredVersion:t,...n?{actualVersion:n}:{},phase:"pending",attempt:r?s.attempt:0,error:(r?s.error:void 0)||(n!==t||i?Zo(t,n):ea("INSTANCE_RUNTIME_VERIFICATION_FAILED",`Controlled-instance ${t} is running, but the active runtime artifact does not match the desired release identity.`,t,n,!0))}}(n,i,r,o)),Qo(n)&&!t.startRequested)return n;let a=!1,c=0;try{for(;c<this.maxAttempts;){if(this.cancelled.has(e))return this.storePhase(this.requireInstance(e),"pending");let s;try{if(n=this.storePhase(n,"draining"),await(this.hooks.beginDrain?.(n)),a=!0,n=this.requireInstance(e),Yo(n)){const t=await this.waitUntil(e,this.drainTimeoutMs,e=>!Yo(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)||Qo(this.requireInstance(e))&&!t.startRequested)return this.storePhase(this.requireInstance(e),"pending");if(n=this.storePhase(this.requireInstance(e),"restarting"),await this.hooks.restart(n),this.cancelled.has(e))return this.storePhase(this.requireInstance(e),"pending");n=this.storePhase(this.requireInstance(e),"verifying");const s=await this.waitUntil(e,this.verificationTimeoutMs,e=>Jo(e)===i);if(this.cancelled.has(e))return this.storePhase(this.requireInstance(e),"pending");if(!s)throw ea("INSTANCE_RUNTIME_VERIFICATION_FAILED",`Instance ${e} did not register controlled-instance ${i} after restart.`,i,Jo(this.requireInstance(e)),!0);const r=this.requireInstance(e);if(this.hooks.isInstalled&&!await this.hooks.isInstalled(r,i))throw ea("INSTANCE_RUNTIME_VERIFICATION_FAILED",`Instance ${e} reported controlled-instance ${i}, but its active runtime release is missing.`,i,Jo(r),!0);return this.storeState(r,{desiredVersion:i,actualVersion:i,phase:"matched",attempt:r.runtimeVersion?.attempt||1,matchedAt:this.timestamp()},!Qo(r)&&"failed"!==r.health)}catch(t){if(this.cancelled.has(e))return this.storePhase(this.requireInstance(e),"pending");s=ta(t,i,Jo(this.store.get(e)))}n=this.requireInstance(e);const r=n.runtimeVersion?.attempt||1;if(!s.retryable||c>=this.maxAttempts)return this.storeBatchFailure(n,i,r>=this.maxAttempts&&s.retryable?na(i,Jo(n),this.maxAttempts,s):s);n=this.storeState(n,{desiredVersion:i,...Jo(n)?{actualVersion:Jo(n)}:{},phase:"pending",attempt:r,lastAttemptAt:this.timestamp(),error:s}),await this.delay(this.retryDelayMs(r))}return this.storeBatchFailure(n,i,na(i,Jo(n),this.maxAttempts,n.runtimeVersion?.error))}finally{a&&await(this.hooks.endDrain?.(this.requireInstance(e)))}}storeBatchFailure(e,t,n){const i=Jo(e);return this.storeState(e,{desiredVersion:t,...i?{actualVersion:i}:{},phase:"pending",attempt:e.runtimeVersion?.attempt||0,lastAttemptAt:this.timestamp(),error:n})}retryDelayMs(e){return Math.min(this.retryMaxDelayMs,this.retryBaseDelayMs*2**Math.max(0,e-1))}remainingRetryDelayMs(e){if(!e?.error||!e.lastAttemptAt)return 0;const t=Date.parse(e.lastAttemptAt);return Number.isFinite(t)?Math.max(0,t+this.retryDelayMs(e.attempt||1)-this.now().getTime()):0}storePhase(e,t,n=!1){const i=this.desiredVersion(),s=Jo(e),r=e.runtimeVersion?.desiredVersion===i?e.runtimeVersion.error:void 0;return this.storeState(e,{desiredVersion:i,...s?{actualVersion:s}:{},phase:t,attempt:(e.runtimeVersion?.attempt||0)+(n?1:0),lastAttemptAt:this.timestamp(),...r?{error:r}:"pending"===t?{error:Zo(i,s)}:{}},"restarting"!==t&&void 0)}storeState(e,t,n){const i=this.store.get(e.id)||e;return this.store.put(_s.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 Jo(e){return e?.build?.packageVersion||e?.instanceVersion}function Yo(e){return e.apps.runningCount>0||e.aiSessions.runningCount>0}function Xo(e){return Boolean(e.imageProvisioning&&"ready"!==e.imageProvisioning.phase)}function Qo(e){return["created","stopped","failed"].includes(e.status)}function Zo(e,t){return ea("INSTANCE_RUNTIME_VERSION_MISMATCH",`Expected controlled-instance ${e}, received ${t||"an unknown version"}.`,e,t,!0)}function ea(e,t,n,i,s){return{code:e,message:t,expectedVersion:n,...i?{actualVersion:i}:{},retryable:s}}function ta(e,t,n){if(e&&"object"==typeof e&&"code"in e&&"message"in e){const i=e,s=hi.shape.code.safeParse(i.code);if(s.success&&"string"==typeof i.message)return ea(s.data,i.message,t,n,"boolean"!=typeof i.retryable||i.retryable)}return ea("INSTANCE_RUNTIME_INSTALL_FAILED",e instanceof Error?e.message:String(e),t,n,!0)}function na(e,t,n,i){const s=i?.message?` Last error: ${i.message}`:"";return ea(i?.code||"INSTANCE_RUNTIME_INSTALL_FAILED",`Runtime convergence paused after ${n} attempts and will retry.${s}`,e,t,!0)}function ia(e,t){if(!Number.isFinite(e)||e<0)throw new TypeError(`${t} must be a nonnegative finite number.`);return e}function sa(e,n=448){t.mkdirSync(e,{recursive:!0,mode:n}),t.chmodSync(e,n)}function ra(e,i,s={}){const r=s.directoryMode??448,o=s.fileMode??384;sa(n.dirname(e),r),I.sync(e,`${JSON.stringify(i,null,2)}\n`,{encoding:"utf8",mode:o}),t.chmodSync(e,o)}function oa(e,t){console.warn(JSON.stringify({message:e,...t}))}function aa(e){return e&&"object"==typeof e&&"issues"in e?{issues:e.issues}:{error:e instanceof Error?e.message:String(e)}}function ca(e,n){const i=n.logger||oa;let s;try{s=JSON.parse(t.readFileSync(e,"utf8"))}catch(t){return void i("stored JSON could not be read",{filePath:e,...aa(t)})}if(!n.schema)return s;const r=n.sanitize?n.sanitize(s):s,o=n.schema.safeParse(r);if(o.success)return o.data;const a="strip"in n.schema&&"function"==typeof n.schema.strip?n.schema.strip().safeParse(r):void 0;if(a?.success)return i("unknown stored fields were ignored",{filePath:e,issues:o.error.issues}),a.data;i("stored record failed validation and was isolated",{filePath:e,issues:o.error.issues})}function da(e){return`${e}_${d.randomUUID().replace(/-/g,"").slice(0,20)}`}function la(){return d.randomBytes(24).toString("base64url")}class ua{directory;options;permissionsInitialized=!1;constructor(e,t={}){this.directory=e,this.options=t}init(){if(this.permissionsInitialized&&t.existsSync(this.directory))return;sa(this.directory,this.options.directoryMode??448);const e=this.options.fileMode??384;for(const i of t.readdirSync(this.directory).filter(e=>e.endsWith(".json")))t.chmodSync(n.join(this.directory,i),e);this.permissionsInitialized=!0}filePath(e){return n.join(this.directory,`${e}.json`)}list(){return this.init(),t.readdirSync(this.directory).filter(e=>e.endsWith(".json")).sort().flatMap(e=>{const t=ca(n.join(this.directory,e),this.options);return t?[t]:[]})}get(e){this.init();const n=this.filePath(e);return t.existsSync(n)?ca(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 ra(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 pa{filePathValue;defaults;options;constructor(e,t,n={}){this.filePathValue=e,this.defaults=t,this.options=n}init(){sa(n.dirname(this.filePathValue),this.options.directoryMode??448),t.existsSync(this.filePathValue)?t.chmodSync(this.filePathValue,this.options.fileMode??384):this.put(this.defaults())}get(){return this.init(),t.existsSync(this.filePathValue)?ca(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 ra(this.filePathValue,n,this.options),n}}const ma=a.z.record(a.z.string(),a.z.string()),ha=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 ga{directory;constructor(e){this.directory=e}get(e){try{return ma.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=ma.parse(n);t.mkdirSync(this.directory,{recursive:!0,mode:448});const s=this.filePath(e);return I.sync(s,`${JSON.stringify(i,null,2)}\n`,{encoding:"utf8",mode:384}),t.chmodSync(s,384),i}delete(e){t.rmSync(this.filePath(e),{force:!0})}filePath(e){return n.join(this.directory,`${e}.json`)}}class fa{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=xi.parse(e);this.init();const i=this.filePath(n.id);return I.sync(i,`${JSON.stringify(n,null,2)}\n`,{encoding:"utf8",mode:384}),t.chmodSync(i,384),n}delete(e){const n=this.filePath(e);return!!t.existsSync(n)&&(t.unlinkSync(n),!0)}read(e){try{const i=JSON.parse(t.readFileSync(e,"utf8")),s=n.basename(e,".json"),r=xi.safeParse(i);if(r.success&&r.data.id===s&&Bi(r.data)===r.data.id)return r.data;const o=xi.strip().safeParse(i);return o.success&&o.data.id===s&&Bi(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 ya{directory;constructor(e){this.directory=e}init(){t.mkdirSync(this.directory,{recursive:!0,mode:448}),t.chmodSync(this.directory,448)}get(e){const n=this.filePath(e);if(t.existsSync(n))try{const i=JSON.parse(t.readFileSync(n,"utf8")),s=Mi.safeParse(i);if(s.success)return s.data;const r=Mi.strip().safeParse(i);if(r.success)return console.warn(JSON.stringify({message:"unknown stored model assignment fields were ignored",instanceId:e,filePath:n})),r.data;throw s.error}catch(t){throw Object.assign(new Error(`Stored model assignment for instance ${e} is invalid.`),{statusCode:409,code:"NODE_MODEL_ASSIGNMENT_INVALID",cause:t})}}put(e){const n=Mi.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`)}}class Ia{models;assignments;legacyEnvironments;nodeId;instances;constructor(e,t,n){this.nodeId=t,this.instances=n,this.models=new fa(e.nodeModelsDir,t),this.assignments=new ya(e.modelAssignmentsDir),this.legacyEnvironments=new ga(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,n?.opencodeModelHash])t&&e.set(t,(e.get(t)||0)+1)}return this.models.list().map(t=>this.toPublic(t,e.get(t.id)||0))}create(e){const t=ee(),n=Bi(e),i=this.models.get(n),s=xi.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(s),this.referenceIds(n).length)}deploy(e){const t=Bi(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(xi.parse(e));return this.toPublic(n,this.referenceIds(n.id).length)}update(e,t){const n=this.requireModel(e),i=xi.parse({...n,...t,key:t.key?.trim()?t.key:n.key,createdAt:n.createdAt,updatedAt:ee()}),s=Bi(i),r=this.models.put(xi.parse({...i,id:s}));return this.toPublic(r,this.referenceIds(s).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),this.validateRef("opencode",t.opencodeModelHash),void 0!==t.modelSelection.codexModelHash&&(t.modelSelection.codexModelHash??void 0)!==t.codexModelHash)throw Object.assign(new Error("Codex model selection does not match its node assignment."),{statusCode:400,code:"NODE_MODEL_SELECTION_MISMATCH"});if(void 0!==t.modelSelection.claudeModelHash&&(t.modelSelection.claudeModelHash??void 0)!==t.claudeModelHash)throw Object.assign(new Error("Claude model selection does not match its node assignment."),{statusCode:400,code:"NODE_MODEL_SELECTION_MISMATCH"});if(void 0!==t.modelSelection.opencodeModelHash&&(t.modelSelection.opencodeModelHash??void 0)!==t.opencodeModelHash)throw Object.assign(new Error("OpenCode model selection does not match its node assignment."),{statusCode:400,code:"NODE_MODEL_SELECTION_MISMATCH"});const i=this.assignments.get(e),s=Mi.parse({instanceId:e,codexModelHash:t.codexModelHash,claudeModelHash:t.claudeModelHash,opencodeModelHash:t.opencodeModelHash,updatedAt:ee()});this.assignments.put(s);try{return{assignment:s,instance:this.instances.put(_s.parse({...n,modelSelection:t.modelSelection,updatedAt:ee()}))}}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),...this.environmentForRef("opencode",t.opencodeModelHash)}}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}:"claude"===e?{ANTHROPIC_API_KEY:n.key,ANTHROPIC_BASE_URL:n.endpoint,TASK_HANDOFF_CLAUDE_MODEL:n.model}:{TASK_HANDOFF_OPENCODE_CONFIG_CONTENT:JSON.stringify({$schema:"https://opencode.ai/config.json",model:`task-handoff/${n.model}`,provider:{"task-handoff":{npm:"@ai-sdk/openai-compatible",name:"TaskHandoff",options:{baseURL:n.endpoint,apiKey:n.key},models:{[n.model]:{name:n.name}}}}})}}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(Bi(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||n?.opencodeModelHash===e}).map(e=>e.id)}toPublic(e,t){const{key:n,...i}=e;return Di.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=>!ha.has(e))){this.warnMigration(e,"unknown-fields");continue}const n=[];try{const i=this.migrateApp(t,"codex",n),s=this.migrateApp(t,"claude",n);if(!i&&!s)throw new Error("no complete model configuration");const r={...i?{codexModelHash:i}:{},...s?{claudeModelHash:s}:{}};this.assign(e,{modelSelection:r,codexModelHash:i,claudeModelHash:s}),this.resolvedEnvironment(e),this.legacyEnvironments.delete(e)}catch{this.assignments.delete(e);for(const e of n)this.models.delete(e);this.warnMigration(e,"mapping-failed")}}}migrateApp(e,t,n){const i=e["codex"===t?"OPENAI_API_KEY":"ANTHROPIC_API_KEY"],s="codex"===t?e.TASK_HANDOFF_CODEX_BASE_URL||e.OPENAI_BASE_URL:e.ANTHROPIC_BASE_URL,r="codex"===t?e.TASK_HANDOFF_CODEX_MODEL||e.CODEX_MODEL:e.TASK_HANDOFF_CLAUDE_MODEL||e.CLAUDE_MODEL;if(!i&&!s&&!r)return;if(!i||!s||!r)throw new Error("model configuration incomplete");const o=Bi({app:t,endpoint:s,key:i,model:r}),a=this.models.get(o);if(a){if(a.app!==t||a.key!==i||a.endpoint!==s||a.model!==r||!a.enabled)throw new Error("existing model conflicts with legacy environment");return o}const c=ee();return this.models.put(xi.parse({id:o,name:`Migrated ${"codex"===t?"Codex":"Claude"} model`,endpoint:s,key:i,model:r,app:t,enabled:!0,order:this.nextOrder(),labels:{migratedFrom:"instance-model-environment"},createdAt:c,updatedAt:c})),n.push(o),o}warnMigration(e,t){console.warn(JSON.stringify({message:"legacy model environment was preserved because it could not be migrated",nodeId:this.nodeId,instanceId:e,reason:t}))}}function Aa(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 ba(){return process.env.TASK_HANDOFF_NPM_COMMAND||"npm"}function va(e,i){const s=n.join(e,...i.split("/"),"package.json");try{const e=JSON.parse(t.readFileSync(s,"utf8"));if(e.name!==i||"string"!=typeof e.version||!e.version.trim())throw new Error(`Installed package manifest is invalid: ${s}`);return{name:i,version:e.version.trim()}}catch(e){if("ENOENT"===e.code)return;throw e}}async function wa(e,i){const s=i?function(e){const i=function(e){let t=n.resolve(e);for(;t!==n.dirname(t);){if("node_modules"===n.basename(t)&&"lib"===n.basename(n.dirname(t)))return n.dirname(n.dirname(t));t=n.dirname(t)}}(e);if(!i)return;let s,r=n.resolve(e);for(;r!==n.dirname(r);){try{const e=JSON.parse(t.readFileSync(n.join(r,"package.json"),"utf8"));if("@task-handoff/node-agent"===e.name&&"string"==typeof e.version&&e.version.trim()&&(s=e.version.trim()),"@task-handoff/server"===e.name&&"string"==typeof e.version&&e.version.trim())return{packageName:"@task-handoff/server",currentVersion:e.version.trim(),relatedCurrentVersions:s?[s]:[],installPrefix:i}}catch(e){if("ENOENT"!==e.code)throw e}r=n.dirname(r)}return s?{packageName:"@task-handoff/node-agent",currentVersion:s,relatedCurrentVersions:[],installPrefix:i}:void 0}(i):void 0;if(s)return s;const r=(await e(ba(),["root","--global"])).stdout.trim();if(!r)throw new Error("npm did not return its global module root.");const o=(await e(ba(),["prefix","--global"])).stdout.trim();if(!n.isAbsolute(o))throw new Error(`npm did not return an absolute global prefix: ${o||"empty"}`);const a=va(r,"@task-handoff/server"),c=va(r,"@task-handoff/node-agent");return a?{packageName:"@task-handoff/server",currentVersion:a.version,relatedCurrentVersions:c?[c.version]:[],installPrefix:o}:{packageName:"@task-handoff/node-agent",currentVersion:c?.version,relatedCurrentVersions:[],installPrefix:o}}function Sa(e){if(!e||"object"!=typeof e||Array.isArray(e))return e;const t=e,n="string"==typeof t.updatedAt?t.updatedAt:ee(),i=t.target&&"object"==typeof t.target&&!Array.isArray(t.target)?t.target:void 0,s="controlled-instance"===i?.component,r={updating:"updating-node",downloading:"updating-node",installing:"updating-node",restarting:"restarting-node",completed:"succeeded",success:"succeeded",error:"failed"},o=new Set(["queued","updating-node","restarting-node","converging-instances","succeeded","degraded","failed"]),a="string"==typeof t.status?t.status:"queued",c=s?"failed":o.has(a)?a:r[a]||"failed",d="string"==typeof t.toVersion&&t.toVersion?t.toVersion:"unknown",l=fi.strip().safeParse(t.impact).success?fi.strip().parse(t.impact):{runningInstanceCount:0,stoppedInstanceCount:0,activeInstanceCount:0,restartInstanceCount:0,runningInstanceIds:[],stoppedInstanceIds:[],activeInstanceIds:[]},u=s?{code:"LEGACY_INSTANCE_UPDATE_RETIRED",message:"Independent controlled-instance update jobs were retired in favor of Node reconciliation.",retryable:!1}:"failed"!==c||t.error||o.has(a)||a in r?"string"==typeof t.error?{code:"NODE_UPDATE_FAILED",message:t.error,retryable:!1}:hi.strip().safeParse(t.error).success?hi.strip().parse(t.error):t.error&&"object"==typeof t.error?{code:"NODE_UPDATE_FAILED",message:"string"==typeof t.error.message?t.error.message:"Stored update job contained an unknown error.",retryable:!1}:void 0:{code:"NODE_UPDATE_FAILED",message:`Stored update job used an unknown status: ${a}.`,retryable:!1},{target:p,error:m,...h}=t,g={phase:"succeeded"===c?"succeeded":"failed"===c?"failed":c||"queued",desiredVersion:d,expectedInstanceIds:[],expectedInstanceCount:0,matchedInstanceCount:0,pendingInstanceCount:0,failedInstanceCount:s||"failed"===c?1:0,deferredInstanceCount:0},f=yi.strip().safeParse(t.rollout);return{...h,source:"npm",status:c,impact:l,runtimeArtifacts:Array.isArray(t.runtimeArtifacts)?t.runtimeArtifacts.flatMap(e=>{const t=mi.strip().safeParse(e);return t.success?[t.data]:[]}):[],rollout:f.success?f.data:g,...u?{error:u}:{},...s?{completedAt:t.completedAt||n}:{}}}class Ea{records;constructor(e){this.records=new ua(e.updatesDir,{schema:bi,sanitize:Sa})}init(){this.records.init()}list(){return this.records.list().sort((e,t)=>t.createdAt.localeCompare(e.createdAt))}create(e,t){const n=ee();return this.records.put(bi.parse({id:da("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(bi.parse({...n,...t,id:e,createdAt:n.createdAt,updatedAt:ee()}))}reconcileRollouts(e,t,n={}){const i=new Map(e.map(e=>[e.id,e]));if(n.processStarted)for(const e of this.list().filter(e=>"queued"===e.status))this.patch(e.id,{status:"failed",rollout:{...e.rollout,phase:"failed"},error:{code:"NODE_UPDATE_FAILED",message:"The node agent restarted before the update worker claimed this job.",retryable:!0},completedAt:ee()});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:ee()});continue}const s="converging-instances"!==e.status&&t===e.toVersion?this.patch(e.id,{status:"converging-instances",rollout:{...e.rollout,phase:"converging-instances",nodeVersion:t}}):e;if("converging-instances"!==s.status)continue;const r=s.rollout.expectedInstanceIds,o=r.map(e=>i.get(e)),a=o.filter(e=>e?.ready&&"matched"===e.runtimeVersion?.phase&&e.runtimeVersion.actualVersion===s.toVersion).length,c=o.filter(e=>e&&["created","stopped","failed"].includes(e.status||"")&&"failed"!==e.runtimeVersion?.phase).length,d=o.filter(e=>!e||"failed"===e.runtimeVersion?.phase).length,l=Math.max(0,r.length-a-d-c),u=d>0?"degraded":0===l?"succeeded":"converging-instances";this.patch(s.id,{status:u,rollout:{...s.rollout,phase:u,nodeVersion:t,expectedInstanceCount:r.length,matchedInstanceCount:a,pendingInstanceCount:l,failedInstanceCount:d,deferredInstanceCount:s.impact.stoppedInstanceCount+c},..."succeeded"===u||"degraded"===u?{completedAt:ee()}:{}})}}run(e,t){(async()=>{this.patch(e.id,{status:"updating-node",rollout:{...e.rollout,phase:"updating-node"},startedAt:ee(),error:void 0});try{await t(e),this.patch(e.id,{status:"succeeded",completedAt:ee()})}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:ee()})}})()}}class Na{records;constructor(e){this.records=new ua(e.environmentTemplatesDir,{schema:Yn,sanitize:e=>function(e,t){if(!e||"object"!=typeof e||Array.isArray(e))return e;const n=e,i=new Set(["id","name","sourceInstanceId","nodeId","imageId","internalTag","platform","architecture","sizeBytes","status","error","createdAt","updatedAt"]),s="string"==typeof n.id?n.id:void 0;for(const e of Object.keys(n))i.has(e)||t?.({templateId:s,field:e});const r=Ms(n,[...i]);if(n.error&&"object"==typeof n.error&&!Array.isArray(n.error)){const e=n.error;for(const n of Object.keys(e))["code","message","phase"].includes(n)||t?.({templateId:s,field:`error.${n}`});r.error=Ms(e,["code","message","phase"])}return r}(e,e=>{console.warn(JSON.stringify({message:"unknown stored environment template field was ignored",...e}))})})}init(){this.records.init();for(const e of this.records.list())"creating"===e.status&&this.records.put(Yn.parse({...e,status:"failed",error:{code:"ENVIRONMENT_TEMPLATE_CREATION_INTERRUPTED",message:"Environment template creation was interrupted by a node-agent restart.",phase:"recovery"},updatedAt:ee()}))}list(){return this.records.list()}get(e){return this.records.get(e)}put(e){return this.records.put(Yn.parse(e))}patch(e,t){return this.records.patch(e,t)}delete(e){return this.records.delete(e)}}const za=a.z.record(a.z.string().regex(/^[A-Za-z_][A-Za-z0-9_]*$/),a.z.string()),Ta=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:za,updatedAt:a.z.string().datetime()}).strict();class _a{directory;constructor(e){this.directory=e.instancePrivateConfigsDir}init(){t.mkdirSync(this.directory,{recursive:!0,mode:448}),t.chmodSync(this.directory,448);for(const e of t.readdirSync(this.directory).filter(e=>e.endsWith(".json")))t.chmodSync(n.join(this.directory,e),384)}filePath(e){return n.join(this.directory,`${e}.json`)}get(e){const n=this.filePath(e);if(!t.existsSync(n))return;const i=JSON.parse(t.readFileSync(n,"utf8")),s=i&&"object"==typeof i&&!Array.isArray(i)?i:{},r=Ta.parse({version:s.version,instanceId:s.instanceId,instanceCredential:s.instanceCredential??s.registrationToken,environment:s.environment,updatedAt:s.updatedAt});if(r.instanceId!==e)throw Object.assign(new Error(`Private config identity mismatch for instance ${e}.`),{statusCode:409,code:"INSTANCE_PRIVATE_CONFIG_IDENTITY_MISMATCH"});return(void 0===s.instanceCredential&&void 0!==s.registrationToken||void 0!==s.gitCredentials)&&this.put(r),r}put(e){const n=Ta.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 ka=a.z.string().trim().min(1).max(120).regex(/^[a-zA-Z0-9][a-zA-Z0-9_.:-]*$/),Ca=a.z.string().datetime(),Oa=a.z.number().int().nonnegative(),Ra=a.z.enum(["https-token","ssh-key"]),xa=a.z.enum(["operation-only","instance-retained"]),Pa=a.z.enum(["enabled","disabled"]),Da=a.z.enum(["pending","synced","deferred","revoking","revoked"]),Ma=a.z.object({scheme:a.z.enum(["https","ssh"]),host:a.z.string().trim().min(1).max(253),port:a.z.number().int().min(1).max(65535).optional(),pathPrefix:a.z.string().min(1).max(2048).default("/")}).strict();function ja(e){throw new Error(`Invalid Git credential scope: ${e}`)}function La(e){const t=e.trim().replace(/^\[|\]$/g,"");(!t||t.includes("*")||/[/?#@\s]/.test(t))&&ja("host is invalid");try{const e=new URL(t.includes(":")?`http://[${t}]/`:`http://${t}/`).hostname.replace(/^\[|\]$/g,"").toLowerCase();return(!e||e.length>253||e.includes("*"))&&ja("host is invalid"),e}catch{ja("host is invalid")}}function Fa(e){try{return decodeURIComponent(e)}catch{ja("path contains invalid percent encoding")}}function $a(e){const t=e?.trim()||"/";(t.includes("?")||t.includes("#")||t.includes("\\")||t.includes("\0"))&&ja("path contains an unsupported delimiter");const n=(t.startsWith("/")?t:`/${t}`).split("/").filter(Boolean);for(const e of n){const t=Fa(e);("."===t||".."===t||t.includes("/")||t.includes("\\")||t.includes("\0"))&&ja("path contains an unsafe segment")}return 0===n.length?"/":`/${n.join("/")}/`}function Ua(e){const t=Ma.parse(e),n="https"===t.scheme?443:22;return Ma.parse({scheme:t.scheme,host:La(t.host),...void 0===t.port||t.port===n?{}:{port:t.port},pathPrefix:$a(t.pathPrefix)})}function Va(e){return $a(e.replace(/\.git\/?$/,""))}const Ha=a.z.object({id:ka,name:a.z.string().trim().min(1).max(160),kind:Ra,scope:Ma,secretSet:a.z.literal(!0),status:Pa,revision:Oa,createdAt:Ca,updatedAt:Ca}).strict(),Ba=a.z.object({kind:a.z.literal("https-token"),username:a.z.string().trim().min(1).max(240),token:a.z.string().min(1).max(8192)}).strict(),qa=a.z.object({kind:a.z.literal("ssh-key"),privateKey:a.z.string().min(1).max(131072),passphrase:a.z.string().max(8192).optional(),pinnedKnownHosts:a.z.string().min(1).max(131072)}).strict(),Ka=a.z.discriminatedUnion("kind",[Ba,qa]);a.z.object({name:a.z.string().trim().min(1).max(160),scope:Ma,secret:Ka}).strict().superRefine((e,t)=>{"https"===e.scope.scheme!=("https-token"===e.secret.kind)&&t.addIssue({code:"custom",path:["scope","scheme"],message:"Credential kind must match the remote scheme."});try{Ua(e.scope)}catch(e){t.addIssue({code:"custom",path:["scope"],message:e instanceof Error?e.message:"Invalid Git scope."})}}),a.z.object({name:a.z.string().trim().min(1).max(160).optional(),scope:Ma.optional(),secret:Ka.optional(),status:Pa.optional()}).strict().refine(e=>Object.keys(e).length>0,"At least one credential field must be updated."),a.z.object({items:a.z.array(Ha).max(1e4)}).strict();const Ga=a.z.object({instanceId:ka,credentialId:ka,credentialRevision:Oa,assignmentRevision:Oa,status:Da,authorizedAt:Ca,updatedAt:Ca}).strict(),Wa=a.z.object({credential:Ha,secret:Ka}).strict().superRefine((e,t)=>{e.credential.kind!==e.secret.kind&&t.addIssue({code:"custom",path:["secret","kind"],message:"Credential payload kind mismatch."})}),Ja=a.z.object({instanceId:ka,generation:Oa,credentialIds:a.z.array(ka).max(256).transform(e=>[...new Set(e)].sort()),updatedAt:Ca}).strict(),Ya=a.z.object({remoteUrl:a.z.string().trim().min(1).max(4096)}).strict(),Xa=a.z.discriminatedUnion("status",[a.z.object({status:a.z.literal("ok"),username:a.z.string().min(1).max(240),password:a.z.string().min(1).max(8192)}).strict(),a.z.object({status:a.z.enum(["none","ambiguous","unsupported","missing-host-key","rejected"])}).strict()]),Qa=a.z.object({remoteUrl:a.z.string().trim().min(1).max(4096)}).strict(),Za=a.z.discriminatedUnion("status",[a.z.object({status:a.z.literal("ok"),invocationId:ka,publicIdentity:a.z.string().min(1).max(131072),pinnedKnownHosts:a.z.string().min(1).max(131072)}).strict(),a.z.object({status:a.z.enum(["none","ambiguous","unsupported","missing-host-key","rejected"])}).strict()]),ec=a.z.object({invocationId:ka,frame:a.z.string().min(1).max(1048576)}).strict(),tc=a.z.object({frame:a.z.string().min(1).max(1048576)}).strict(),nc=a.z.object({operationId:ka,retention:xa,payload:Wa}).strict(),ic=a.z.object({operationId:ka,instanceId:ka,remoteUrl:a.z.string().trim().min(1).max(4096),ref:a.z.discriminatedUnion("type",[a.z.object({type:a.z.enum(["branch","tag"]),name:a.z.string().trim().min(1).max(240)}).strict(),a.z.object({type:a.z.literal("commit"),commit:a.z.string().trim().regex(/^[0-9a-fA-F]{4,64}$/,"commit must be a hexadecimal Git object id")}).strict()]),clone:a.z.object({depth:a.z.number().int().positive().max(1e5).optional(),submodules:a.z.boolean().default(!1),lfs:a.z.boolean().default(!1),subdirectory:a.z.string().trim().max(240).refine(e=>!e.startsWith("/")&&!e.split("/").some(e=>".."===e),"subdirectory must be a relative path within the repository").transform(e=>e.split("/").filter(e=>e&&"."!==e).join("/")).default("")}).strict(),credentials:a.z.array(nc).max(256).default([])}).strict();function sc(e){return e&&"object"==typeof e&&!Array.isArray(e)?e:void 0}function rc(e,t){if(e)return Object.fromEntries(t.filter(t=>Object.prototype.hasOwnProperty.call(e,t)).map(t=>[t,e[t]]))}function oc(e){const t=sc(e),n=sc(t?.scope);return Ha.safeParse({...rc(t,["id","name","kind","secretSet","status","revision","createdAt","updatedAt"]),scope:rc(n,["scheme","host","port","pathPrefix"])})}function ac(e,t){let n;try{n=function(e){const t=e.trim();if(t&&!t.includes("\0")||ja("remote is empty or invalid"),/^https?:\/\//i.test(t)||/^ssh:\/\//i.test(t)){let e;$a(t.replace(/^[a-z][a-z0-9+.-]*:\/\/[^/]+/i,"").split(/[?#]/,1)[0]||"/");try{e=new URL(t)}catch{ja("remote URL is invalid")}"https:"!==e.protocol&&"ssh:"!==e.protocol&&ja("remote scheme is unsupported"),(e.password||"https:"===e.protocol&&e.username)&&ja("HTTPS userinfo is forbidden"),(e.search||e.hash)&&ja("query and fragment are forbidden");const n="https:"===e.protocol?"https":"ssh",i=e.port?Number(e.port):void 0;return{...Ua({scheme:n,host:e.hostname,port:i,pathPrefix:Va(e.pathname)}),original:t}}/^[a-z][a-z0-9+.-]*:\/\//i.test(t)&&ja("remote scheme is unsupported");const n=/^(?:([^@/:\s]+)@)?([^/:\s]+):(.+)$/.exec(t);n||ja("remote must use HTTPS, ssh://, or scp-like SSH syntax");const[,,i,s]=n;return(s.includes("?")||s.includes("#"))&&ja("query and fragment are forbidden"),{...Ua({scheme:"ssh",host:i,pathPrefix:Va(s)}),original:t}}(e)}catch(e){return{status:"unsupported",reason:e instanceof Error?e.message:"Unsupported Git remote."}}const i=t.filter(e=>"enabled"===e.status).filter(e=>"https"===n.scheme==("https-token"===e.kind)).filter(e=>function(e,t){const n=Ua(e);return n.scheme===t.scheme&&n.host===t.host&&n.port===t.port&&("/"===n.pathPrefix||t.pathPrefix.startsWith(n.pathPrefix))}(e.scope,n)).map(e=>({candidate:e,specificity:Ua(e.scope).pathPrefix.length}));if(0===i.length)return{status:"none",remote:n};const s=Math.max(...i.map(e=>e.specificity)),r=i.filter(e=>e.specificity===s).map(e=>e.candidate);if(r.length>1)return{status:"ambiguous",remote:n,credentialIds:r.map(e=>e.id).sort()};const o=r[0];return"ssh-key"===o.kind&&!0!==o.pinnedKnownHosts?{status:"missing-host-key",remote:n,credentialId:o.id}:{status:"unique",remote:n,credential:o}}const cc=a.z.object({id:a.z.string().trim().min(1).max(120),payload:Wa,createdAt:a.z.string().datetime(),updatedAt:a.z.string().datetime()}).strict(),dc=Ga.extend({id:a.z.string().trim().min(1).max(300),createdAt:a.z.string().datetime()}).strict(),lc=Ja.extend({id:a.z.string().trim().min(1).max(120),createdAt:a.z.string().datetime()}).strict(),uc=a.z.object({id:a.z.string().trim().min(1).max(120),status:a.z.literal("pending"),input:ic,createdAt:a.z.string().datetime(),updatedAt:a.z.string().datetime(),expiresAt:a.z.string().datetime()}).strict(),pc=a.z.object({id:a.z.string().trim().min(1).max(120),status:a.z.literal("consumed"),operationId:ic.shape.operationId,createdAt:a.z.string().datetime(),updatedAt:a.z.string().datetime(),expiresAt:a.z.string().datetime()}).strict(),mc=a.z.discriminatedUnion("status",[uc,pc]),hc=864e5;function gc(e){return e&&"object"==typeof e&&!Array.isArray(e)?e:void 0}function fc(e){const t=gc(e),n=gc(t?.payload),i=oc(n?.credential),s=gc(n?.secret);return{id:t?.id,payload:{credential:i.success?i.data:n?.credential,secret:"https-token"===s?.kind?{kind:s.kind,username:s.username,token:s.token}:{kind:s?.kind,privateKey:s?.privateKey,passphrase:s?.passphrase,pinnedKnownHosts:s?.pinnedKnownHosts}},createdAt:t?.createdAt,updatedAt:t?.updatedAt}}function yc(e){const t=gc(e);return Object.fromEntries(["id","instanceId","credentialId","credentialRevision","assignmentRevision","status","authorizedAt","createdAt","updatedAt"].flatMap(e=>t&&Object.prototype.hasOwnProperty.call(t,e)?[[e,t[e]]]:[]))}function Ic(e){const t=gc(e);return Object.fromEntries(["id","instanceId","generation","credentialIds","createdAt","updatedAt"].flatMap(e=>t&&Object.prototype.hasOwnProperty.call(t,e)?[[e,t[e]]]:[]))}function Ac(e){const t=gc(e),n="string"==typeof t?.updatedAt?Date.parse(t.updatedAt):Number.NaN;if("consumed"===t?.status)return{id:t.id,status:"consumed",operationId:t.operationId,createdAt:t.createdAt,updatedAt:t.updatedAt,expiresAt:t.expiresAt};const i=function(e){const t=sc(e),n=sc(t?.ref),i=sc(t?.clone),s=Array.isArray(t?.credentials)?t.credentials.map(e=>{const t=sc(e),n=sc(t?.payload),i=oc(n?.credential),s=sc(n?.secret);return{...rc(t,["operationId","retention"]),payload:{credential:i.success?i.data:n?.credential,secret:rc(s,"https-token"===s?.kind?["kind","username","token"]:["kind","privateKey","passphrase","pinnedKnownHosts"])}}}):t?.credentials;return ic.safeParse({...rc(t,["operationId","instanceId","remoteUrl"]),ref:rc(n,["type","name","commit"]),clone:rc(i,["depth","submodules","lfs","subdirectory"]),credentials:s})}(t?.input);return{id:t?.id,status:"pending",input:i.success?i.data:t?.input,createdAt:t?.createdAt,updatedAt:t?.updatedAt,expiresAt:t?.expiresAt||(Number.isFinite(n)?new Date(n+hc).toISOString():t?.updatedAt)}}function bc(e,t){return Object.assign(new Error(`Refusing stale ${e} revision for ${t}.`),{code:"GIT_CREDENTIAL_REVISION_STALE",statusCode:409})}function vc(e,t){return Object.assign(new Error(`Refusing conflicting ${e} revision for ${t}.`),{code:"GIT_CREDENTIAL_REVISION_CONFLICT",statusCode:409})}class wc{payloads;legacyAssignments;authorizationSets;workspaceProvisioning;workspaceProvisioningTtlMs;workspaceProvisioningCleanupTimer;constructor(e,t={}){this.workspaceProvisioningTtlMs=t.workspaceProvisioningTtlMs??hc,this.payloads=new ua(e.gitCredentialPayloadsDir,{schema:cc,sanitize:fc,directoryMode:448,fileMode:384}),this.legacyAssignments=new ua(e.gitCredentialAssignmentsDir,{schema:dc,sanitize:yc,directoryMode:448,fileMode:384}),this.authorizationSets=new ua(e.gitCredentialAuthorizationSetsDir,{schema:lc,sanitize:Ic,directoryMode:448,fileMode:384}),this.workspaceProvisioning=new ua(e.gitWorkspaceProvisioningIntentsDir,{schema:mc,sanitize:Ac,directoryMode:448,fileMode:384})}init(){this.payloads.init(),this.legacyAssignments.init(),this.authorizationSets.init(),this.workspaceProvisioning.init();for(const e of this.workspaceProvisioning.list())("pending"===e.status&&!Sc(e.input)||Date.parse(e.expiresAt)<=Date.now())&&this.workspaceProvisioning.delete(e.id);this.scheduleWorkspaceProvisioningCleanup();const e=new Set(this.legacyAssignments.list().map(e=>e.instanceId));for(const t of e){if(this.authorizationSets.get(t))continue;const e=this.legacyAssignments.list().filter(e=>e.instanceId===t),n=(new Date).toISOString();this.putAuthorizationSet({instanceId:t,generation:Math.max(0,...e.map(e=>e.assignmentRevision)),credentialIds:e.filter(e=>"revoking"!==e.status&&"revoked"!==e.status).map(e=>e.credentialId),updatedAt:n})}}putPayload(e){const t=Wa.parse(e),n=this.payloads.get(t.credential.id);if(n&&n.payload.credential.revision>t.credential.revision)throw bc("payload",t.credential.id);if(n&&n.payload.credential.revision===t.credential.revision&&JSON.stringify(n.payload)!==JSON.stringify(t))throw vc("payload",t.credential.id);const i=(new Date).toISOString();return this.payloads.put({id:t.credential.id,payload:t,createdAt:n?.createdAt||i,updatedAt:i}).payload}getPayload(e){return this.payloads.get(e)?.payload}putAuthorizationSet(e){const t=Ja.parse(e),n=this.authorizationSets.get(t.instanceId);if(n&&n.generation>t.generation)throw bc("authorization set",t.instanceId);if(n&&n.generation===t.generation){if(JSON.stringify(n.credentialIds)!==JSON.stringify(t.credentialIds))throw vc("authorization set",t.instanceId);return this.publicAuthorizationSet(n)}for(const e of t.credentialIds)if(!this.payloads.get(e))throw Object.assign(new Error(`Credential payload ${e} is not deployed.`),{code:"GIT_CREDENTIAL_PAYLOAD_MISSING",statusCode:409});const i=(new Date).toISOString();return this.publicAuthorizationSet(this.authorizationSets.put({id:t.instanceId,...t,createdAt:n?.createdAt||i}))}getAuthorizationSet(e){const t=this.authorizationSets.get(e);return t?this.publicAuthorizationSet(t):{instanceId:e,generation:0,credentialIds:[],updatedAt:new Date(0).toISOString()}}resolve(e,t){const n=this.getAuthorizationSet(e).credentialIds.flatMap(e=>{const t=this.getPayload(e);return t?[t]:[]}),i=ac(t,n.map(e=>({id:e.credential.id,kind:e.credential.kind,scope:e.credential.scope,status:e.credential.status,pinnedKnownHosts:"ssh-key"===e.secret.kind&&Boolean(e.secret.pinnedKnownHosts.trim())}))),s="unique"===i.status?n.find(e=>e.credential.id===i.credential.id):void 0;return{match:i,payload:s}}removePayload(e){if(this.authorizationSets.list().some(t=>t.credentialIds.includes(e)))throw Object.assign(new Error(`Credential payload ${e} is still authorized.`),{code:"GIT_CREDENTIAL_PAYLOAD_IN_USE",statusCode:409});return this.payloads.delete(e)}collectUnreferencedPayloads(){const e=new Set(this.authorizationSets.list().flatMap(e=>e.credentialIds));let t=0;for(const n of this.payloads.list())!e.has(n.id)&&this.payloads.delete(n.id)&&(t+=1);return t}removeInstance(e){const t=this.authorizationSets.delete(e)?1:0;this.workspaceProvisioning.delete(e),this.scheduleWorkspaceProvisioningCleanup();for(const t of this.legacyAssignments.list().filter(t=>t.instanceId===e))this.legacyAssignments.delete(t.id);return t}putWorkspaceProvisioning(e){const t=ic.parse(e);if(!Sc(t))throw Object.assign(new Error("Only operation-only Git provisioning may be persisted."),{code:"GIT_CREDENTIAL_PROVISIONING_RETENTION_INVALID",statusCode:400});const n=this.workspaceProvisioning.get(t.instanceId);if("consumed"===n?.status&&n.operationId===t.operationId)return t;const i=(new Date).toISOString(),s=uc.parse(this.workspaceProvisioning.put({id:t.instanceId,status:"pending",input:t,createdAt:n?.createdAt||i,updatedAt:i,expiresAt:new Date(Date.now()+this.workspaceProvisioningTtlMs).toISOString()})).input;return this.scheduleWorkspaceProvisioningCleanup(),s}getWorkspaceProvisioning(e){const t=this.workspaceProvisioning.get(e);if(t&&"pending"===t.status)return!Sc(t.input)||Date.parse(t.expiresAt)<=Date.now()?(this.workspaceProvisioning.delete(e),void this.scheduleWorkspaceProvisioningCleanup()):t.input}removeWorkspaceProvisioning(e){const t=this.workspaceProvisioning.delete(e);return this.scheduleWorkspaceProvisioningCleanup(),t}discardPendingWorkspaceProvisioning(e){const t=this.workspaceProvisioning.get(e);return!(!t||"pending"!==t.status)&&this.removeWorkspaceProvisioning(e)}completeWorkspaceProvisioning(e,t){const n=this.workspaceProvisioning.get(e);if(!n||"pending"!==n.status||n.input.operationId!==t)return!1;const i=(new Date).toISOString();return this.workspaceProvisioning.put({id:e,status:"consumed",operationId:t,createdAt:n.createdAt,updatedAt:i,expiresAt:new Date(Date.now()+6048e5).toISOString()}),this.scheduleWorkspaceProvisioningCleanup(),!0}workspaceProvisioningStatus(e){const t=this.workspaceProvisioning.get(e);if(t){if(!(Date.parse(t.expiresAt)<=Date.now()))return"pending"===t.status?{status:t.status,operationId:t.input.operationId}:{status:t.status,operationId:t.operationId};this.removeWorkspaceProvisioning(e)}}scheduleWorkspaceProvisioningCleanup(){this.workspaceProvisioningCleanupTimer&&clearTimeout(this.workspaceProvisioningCleanupTimer),this.workspaceProvisioningCleanupTimer=void 0;const e=Math.min(...this.workspaceProvisioning.list().map(e=>Date.parse(e.expiresAt)));Number.isFinite(e)&&(this.workspaceProvisioningCleanupTimer=setTimeout(()=>{this.workspaceProvisioningCleanupTimer=void 0;const e=Date.now();for(const t of this.workspaceProvisioning.list())Date.parse(t.expiresAt)<=e&&this.workspaceProvisioning.delete(t.id);this.scheduleWorkspaceProvisioningCleanup()},Math.max(0,e-Date.now())),this.workspaceProvisioningCleanupTimer.unref?.())}listAssignments(e){return this.legacyAssignments.list().filter(t=>!e||t.instanceId===e).map(({id:e,createdAt:t,...n})=>Ga.parse(n))}publicAuthorizationSet(e){const{id:t,createdAt:n,...i}=e;return Ja.parse(i)}}function Sc(e){return e.credentials.length>0&&e.credentials.every(e=>"operation-only"===e.retention)}const Ec=function(e,t=process.env,n=e){let i;return()=>{const s=t.TASK_HANDOFF_VERSION?.trim();return s||(i||=N(e,t,n),i)}}("@task-handoff/node-agent",process.env,"@task-handoff/control-plane");function Nc(){return Ec()}function zc(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 Tc(e){const t=Nc();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:zc(t,e)}}function _c(e,t,n=!0){if(!n){const n=Nc(),i=e.runtimeVersion;return"matched"===i?.phase&&i.desiredVersion===n&&i.actualVersion===t?i:Tc(t)}const i=Nc(),s=e.runtimeVersion;if(!s||s.desiredVersion!==i)return Tc(t);const r="INSTANCE_RUNTIME_VERSION_MISMATCH"!==s.error?.code?s.error:t===i?void 0:zc(i,t);return gi.parse({...s,desiredVersion:i,...t?{actualVersion:t}:{actualVersion:void 0},..."pending"===s.phase?{error:r||(t!==i?zc(i,t):void 0)}:{}})}const kc="runtime_local_host",Cc="task-handoff.node-agent.builtin";function Oc(e){const t={...e};return delete t[Cc],t}function Rc(e){return"local-folder"===e.type?ki.parse({mode:"local-bind",path:"/workspace",readOnly:!1}):ki.parse({mode:"git-clone",path:"/workspace",readOnly:!1})}function xc(e){const t=_i.parse(e.source),n=e.projectId||("local-folder"===t.type?t.localFolderId:void 0)||("git-repository"===t.type?t.repositoryId:void 0)||("git-template"===t.type?t.templateId:void 0)||`project_${e.id}`;return Oi.parse({id:n,name:"string"==typeof e.sourceSnapshot.name?e.sourceSnapshot.name:e.name,source:t,defaultImageSelection:e.imageSelection,defaultNodeId:e.nodeId,workspacePolicy:Rc(t),labels:{},createdAt:e.createdAt,updatedAt:e.updatedAt})}function Pc(e,t){throw Object.assign(new Error(t),{statusCode:403,code:e})}function Dc(e,t){e!==an&&console.warn(JSON.stringify({message:"protocol version mismatch",peer:t,expectedProtocolVersion:an,actualProtocolVersion:e||"missing",errorCode:"PROTOCOL_VERSION_MISMATCH"}))}function Mc(e){return"none"!==e.capabilities.artifactKind}function jc(e={}){return{...e,requiresImage:!1,supportsControlledInstanceApi:!0,supportsContainerLifecycle:!1,supportsAppSessions:!0,supportsHostSessions:!0,artifactKind:"none",isolation:"none"}}class Lc extends ua{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:s,...r}=e,o=super.put(_s.parse({...r,stateRevision:Math.max(e.stateRevision||0,t)+1})),a=this.hydrate(o);return this.onStored?.(a),a}get(e){const t=super.get(e);return t?this.hydrate(t):void 0}list(){return super.list().map(e=>this.hydrate(e))}hydrate(e){const t=this.privateConfigs.get(e.id)?.instanceCredential||e.registrationToken;return _s.parse({...e,registrationToken:t})}}class Fc{nodeId;paths;localFolders;nodeRuntimes;controlledInstances;environmentTemplates;instancePrivateConfigs;modelRegistry;gitCredentials;updateJobs;node;listenerPort;containerUrlOverride;platform;constructor(e,t,n,i,s,r){this.paths=e,this.nodeId=t,this.localFolders=new ua(e.localFoldersDir,{schema:Ti,sanitize:Kn}),this.nodeRuntimes=new ua(e.nodeRuntimesDir,{schema:ms}),this.instancePrivateConfigs=new _a(e),this.controlledInstances=new Lc(e.controlledInstancesDir,{schema:_s,sanitize:e=>xs(e,e=>{console.warn(JSON.stringify({message:"legacy controlled instance field was ignored",...e}))})},this.instancePrivateConfigs),this.environmentTemplates=new Na(e),this.gitCredentials=new wc(e),this.modelRegistry=new Ia(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 Ea(e),this.listenerPort=s,this.platform=r,this.containerUrlOverride=i;const o=ee();this.node=ps.parse({id:t,name:t,connectionMode:"direct-http",endpoint:n,controlEndpoint:n,containerEndpoint:this.containerUrl,publicWebBase:n?n.replace(/:\d+$/,""):void 0,status:"online",health:"ok",capabilities:{},labels:{},createdAt:o,updatedAt:o})}init(){this.localFolders.init();for(const e of this.localFolders.list())this.localFolders.put(e);if(this.nodeRuntimes.init(),this.instancePrivateConfigs.init(),this.controlledInstances.init(),this.environmentTemplates.init(),this.gitCredentials.init(),this.modelRegistry.init(),this.updateJobs.init(),this.updateJobs.reconcileRollouts(this.controlledInstances.list(),Nc(),{processStarted:!0}),!this.nodeRuntimes.get("runtime_local_docker")){const e=ee();this.nodeRuntimes.put(ms.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(kc),t=ee();this.nodeRuntimes.put(ms.parse({id:kc,nodeId:this.nodeId,name:"Local Runtime",type:"local",status:e?.status||"unknown",accessStrategy:"node-proxy",capabilities:jc(e?.capabilities),labels:{...e?.labels,[Cc]:"true"},createdAt:e?.createdAt||t,updatedAt:e?.updatedAt||t}))}for(const e of this.nodeRuntimes.list())e.nodeId!==this.nodeId&&this.nodeRuntimes.put(ms.parse({...e,nodeId:this.nodeId,updatedAt:ee()}));for(const e of this.localFolders.list())e.nodeId!==this.nodeId&&this.localFolders.put(Ti.parse({...e,nodeId:this.nodeId,updatedAt:ee()}));this.normalizeInstanceRuntimeVersions()}normalizeInstanceRuntimeVersions(){for(const e of this.controlledInstances.list()){const t=Tc(e.build?.packageVersion||e.instanceVersion),n=Mc(this.requireRuntime(e.runtimeId)),i=["created","stopped","failed"].includes(e.status),s=n&&e.runtimeVersion?.desiredVersion===t.desiredVersion?e.runtimeVersion:void 0,r=n?"matched"===t.phase?i?t:{...t,phase:"verifying",matchedAt:void 0}:{...t,phase:"pending",attempt:s?.attempt||0,lastAttemptAt:s?.lastAttemptAt,error:s?.error||t.error}:t;this.controlledInstances.put(_s.parse({...e,ready:!1,runtimeVersion:r,updatedAt:ee()}))}}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=ee()}runningInstanceCount(){const e=new Set(["created","stopped","failed"]);return this.listInstances().filter(t=>!e.has(t.status)).length}createLocalFolder(e){const t=ee(),i=zo(e.path),s=Ti.parse({...e,name:e.name.trim()||n.basename(i),path:i,id:e.id||da("folder"),nodeId:this.nodeId,labels:e.labels||{},createdAt:t,updatedAt:t});return this.localFolders.put(s)}updateLocalFolder(e,t){const i=this.localFolders.get(e);if(!i){const t=new Error(`Local folder ${e} was not found.`);throw Object.assign(t,{statusCode:404,code:"NODE_LOCAL_FOLDER_NOT_FOUND"})}return this.localFolders.put(Ti.parse({...i,name:t.name.trim()||n.basename(i.path),updatedAt:ee()}))}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=ee(),n=ms.parse({...e,id:e.id||da("runtime"),nodeId:this.nodeId,accessStrategy:e.accessStrategy||(i=e.type,"docker"===i?"direct-port":"node-proxy"),capabilities:e.capabilities||{},labels:Oc(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[Cc]){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=ms.parse({...n,...t,id:n.id,nodeId:this.nodeId,accessStrategy:t.accessStrategy||n.accessStrategy,capabilities:t.capabilities||n.capabilities,labels:t.labels?Oc(t.labels):n.labels,createdAt:n.createdAt,updatedAt:ee()});return this.nodeRuntimes.put(i)}deleteRuntime(e){if("true"===this.requireRuntime(e).labels[Cc]){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=ms.parse({...n,...e,id:n.id,nodeId:this.nodeId,createdAt:n.createdAt,updatedAt:ee()});return this.nodeRuntimes.put(t)}):this.nodeRuntimes.put(ms.parse({...n,status:"unknown",updatedAt:ee()}))}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=Rs(t);if(!n.success)throw function(e,t){const n=t.map(e=>`${e.path.join(".")||"body"}: ${e.message}`).join("; ");return Object.assign(new Error(`Stored instance ${e} is not compatible with protocol ${an}: ${n}`),{statusCode:409,code:"NODE_INSTANCE_PAYLOAD_INVALID"})}(e,n.error.issues);return n.data}applyInstanceLifecycle(e,t){return this.controlledInstances.put(function(e,t,n=(new Date).toISOString()){switch(t.type){case"start-requested":return _s.parse({...e,status:"starting",ready:!1,updatedAt:n});case"stop-requested":return _s.parse({...e,status:"stopping",ready:!1,updatedAt:n});case"stop-failed":return"stopping"!==e.status?e:_s.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 _s.parse({...e,build:void 0,instanceVersion:void 0,ready:!1,updatedAt:n});case"runtime-lifecycle-completed":return function(e,t,n,i){if(t.stateRevision>e.stateRevision&&["failed","stopping","stopped","deleting"].includes(t.status))return t;const s=t.stateRevision>e.stateRevision&&t.lastHeartbeatAt!==e.lastHeartbeatAt&&"online"===t.agentStatus;return _s.parse({...t,...n,...s?{status:t.status,health:t.health,connectionStatus:t.connectionStatus,agentStatus:t.agentStatus,targetStatus:t.targetStatus,uiAccessStatus:t.uiAccessStatus}:{},ready:!!s&&t.ready,target:n.target?{...t.target,...n.target}:t.target,workspace:n.workspace?s?{...n.workspace,...t.workspace}:{...t.workspace,...n.workspace}:t.workspace,runtime:n.runtime?{...t.runtime,...n.runtime}:t.runtime,updatedAt:i})}(t.baseline,e,t.observation,n);case"stop-completed":return _s.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 _s.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=Rs(e);return t.success?[t.data]:[]})}resolvedAssignedModelEnvironment(e){return this.modelRegistry.resolvedEnvironment(e)}createInstance(e){const t=this.requireRuntime(e.runtimeId),i=ee(),s=e.id||da("inst"),r=function(e){const t=_i.parse(e);return"local-folder"===t.type?t:_i.parse({...t,auth:{type:"none"}})}(e.source),o=e.environmentSource||(e.imageSelection?{type:"image",imageSelection:e.imageSelection}:void 0);if("template"===o?.type&&"docker"!==t.type){const e=new Error(`Runtime ${t.name} does not support environment templates.`);throw Object.assign(e,{statusCode:409,code:"ENVIRONMENT_TEMPLATE_RUNTIME_UNSUPPORTED"}),e}const a="template"===o?.type?this.environmentTemplates.get(o.environmentTemplateId):void 0;if("template"===o?.type&&(!a||"ready"!==a.status)){const e=new Error(`Environment template ${o.environmentTemplateId} is not ready on node ${this.nodeId}.`);throw Object.assign(e,{statusCode:a?409:404,code:a?"ENVIRONMENT_TEMPLATE_NOT_READY":"ENVIRONMENT_TEMPLATE_NOT_FOUND"}),e}if(a&&a.nodeId!==this.nodeId){const e=new Error(`Environment template ${a.id} belongs to node ${a.nodeId}, not ${this.nodeId}.`);throw Object.assign(e,{statusCode:409,code:"ENVIRONMENT_TEMPLATE_NODE_MISMATCH"}),e}if(function(e){return"boolean"==typeof e.capabilities.requiresImage?e.capabilities.requiresImage:"local"!==e.type}(t)&&(!o||"image"===o.type&&!e.image)){const e=new Error(`Runtime ${t.name} requires an image.`);throw Object.assign(e,{statusCode:400,code:"NODE_RUNTIME_IMAGE_REQUIRED"}),e}if("local"===t.type&&"local-folder"!==r.type){const e=new Error("Localhost runtime currently supports local folder sources only.");throw Object.assign(e,{statusCode:400,code:"LOCAL_RUNTIME_REQUIRES_LOCAL_FOLDER"}),e}if("local"===t.type&&this.listInstances().some(e=>"local"===this.requireRuntime(e.runtimeId).type)){const e=new Error("A localhost instance already exists on this node.");throw Object.assign(e,{statusCode:409,code:"LOCAL_RUNTIME_INSTANCE_EXISTS"}),e}const c=a?ns.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?ns.parse(e.image):void 0,d="local"===t.type&&"local-folder"===r.type?n.resolve(r.path):void 0,l=_s.parse({id:s,name:e.name||`instance-${s.replace(/^inst_?/,"").slice(0,6)}`,source:r,sourceSnapshot:e.sourceSnapshot||{},modelSelection:e.modelSelection,projectId:e.projectId,nodeId:this.nodeId,runtimeId:t.id,imageSelection:"image"===o?.type?o.imageSelection:void 0,environmentSource:o,environmentTemplateOrigin:a?{templateId:a.id,nodeId:a.nodeId,imageId:a.imageId,name:a.name,platform:a.platform,architecture:a.architecture}:void 0,imageSnapshot:c,imageProvisioning:c&&"docker"===t.type&&"template"!==o?.type?{phase:"checking-image",requestedReference:c.requestedReference,generation:0,startedAt:i,updatedAt:i}:void 0,status:c&&"docker"===t.type&&"template"!==o?.type?"provisioning":"created",health:"unknown",connectionStatus:"unknown",agentStatus:"unknown",targetStatus:"unknown",uiAccessStatus:"unknown",controlMode:"controlled",ready:!1,runtimeVersion:Tc(),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,aiSessionMaxFileAttachmentBytes:e.config?.aiSessionMaxFileAttachmentBytes??oe},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:la(),createdAt:i,updatedAt:i}),u=this.controlledInstances.put(l);return this.instancePrivateConfigs.materialize(u.id,u.registrationToken,this.resolvedAssignedModelEnvironment(u.id)),e.gitWorkspaceProvisioning?.credentials.every(e=>"operation-only"===e.retention)&&this.gitCredentials.putWorkspaceProvisioning(e.gitWorkspaceProvisioning),u}takeGitWorkspaceProvisioning(e){const t=this.gitCredentials.getWorkspaceProvisioning(e);return this.gitCredentials.removeWorkspaceProvisioning(e),t}setGitWorkspaceProvisioning(e){const t=this.requireInstance(e.instanceId);if("local-folder"===t.source.type||t.source.url!==e.remoteUrl)throw Object.assign(new Error(`Git provisioning does not match instance ${t.id}.`),{code:"GIT_WORKSPACE_PROVISIONING_INSTANCE_MISMATCH",statusCode:409});this.gitCredentials.putWorkspaceProvisioning(e)}gitWorkspaceProvisioningFor(e){if("local-folder"===e.source.type)return;const t=this.gitCredentials.getWorkspaceProvisioning(e.id);if(t)return t;const n=this.gitCredentials.getAuthorizationSet(e.id).credentialIds.flatMap(e=>{const t=this.gitCredentials.getPayload(e);return t?[t]:[]}),i=n.map(e=>({id:e.credential.id,kind:e.credential.kind,scope:e.credential.scope,status:e.credential.status,pinnedKnownHosts:"ssh-key"===e.secret.kind&&Boolean(e.secret.pinnedKnownHosts.trim())})),s=ac(e.source.url,i);if("ambiguous"===s.status||"missing-host-key"===s.status)throw Object.assign(new Error(`Git credential resolution failed for instance ${e.id}: ${s.status}.`),{code:`GIT_CREDENTIAL_${s.status.replace(/-/g,"_").toUpperCase()}`,statusCode:409});return{operationId:`gitop_${e.id}_${e.stateRevision}`,instanceId:e.id,remoteUrl:e.source.url,ref:e.source.ref,clone:e.source.clone,credentials:n.map((t,n)=>({operationId:`gitcredop_${e.id}_${e.stateRevision}_${n}`,retention:"instance-retained",payload:t}))}}discardGitWorkspaceProvisioning(e){return this.gitCredentials.discardPendingWorkspaceProvisioning(e)}gitWorkspaceProvisioningStatus(e){return this.gitCredentials.workspaceProvisioningStatus(e)}registerInstance(e,t,n){const i=js.parse(t),s=ee(),r=this.controlledInstances.get(e);if(!r){const t=new Error(`Instance ${e} was not found on node ${this.nodeId}.`);throw Object.assign(t,{statusCode:404,code:"NODE_INSTANCE_NOT_FOUND"}),t}if(this.validateInstanceReport(r,i,n),i.processIncarnationId&&i.processIncarnationId===r.processIncarnationId)return r;Dc(i.protocolVersion,`Instance ${e}`);const o=i.build?.packageVersion||i.instanceVersion,a=Mc(this.requireRuntime(r.runtimeId)),c=_c(r,o,a),d=_s.parse({...r,status:"registered",health:o===Nc()?"ok":"degraded",ready:!a&&o===Nc(),connectionStatus:"online",agentStatus:"online",targetStatus:r.targetStatus,uiAccessStatus:r.uiAccessStatus,controlMode:i.controlMode,protocolVersion:i.protocolVersion,instanceVersion:i.instanceVersion,build:i.build,runtimeVersion:c,processIncarnationId:i.processIncarnationId||r.processIncarnationId,capabilities:i.capabilities,appInventory:i.appInventory,workspace:i.workspace,target:r.target,registrationToken:r.registrationToken||i.registrationToken,lastHeartbeatAt:s,updatedAt:s});return this.controlledInstances.put(d)}heartbeatInstance(e,t,n){const i=this.requireInstance(e);this.validateInstanceToken(i,n);const s=Ls.parse(t);i.processIncarnationId&&s.processIncarnationId&&s.processIncarnationId!==i.processIncarnationId&&function(e,t){throw Object.assign(new Error(t),{statusCode:409,code:"INSTANCE_PROCESS_INCARNATION_MISMATCH"})}(0,`Instance ${e} report belongs to an obsolete controlled-instance process.`),Dc(s.protocolVersion,`Instance ${e}`);const r=ee(),o=i.target,a=i.targetStatus,c=_c(i,s.build?.packageVersion||i.build?.packageVersion||i.instanceVersion,Mc(this.requireRuntime(i.runtimeId))),d=s.health||i.health,l="running"===(s.status||i.status)&&"failed"!==d,u=_s.parse({...i,...s,target:o,ready:l,health:d,runtimeVersion:c,processIncarnationId:s.processIncarnationId||i.processIncarnationId,agentStatus:"online",targetStatus:a,uiAccessStatus:a,connectionStatus:"online",build:s.build||i.build,lastHeartbeatAt:r,updatedAt:r});return this.controlledInstances.put(u)}validateInstanceReport(e,t,n){this.validateInstanceToken(e,n||t.registrationToken),t.instanceId&&t.instanceId!==e.id&&Pc("INSTANCE_ID_MISMATCH",`Instance ${t.instanceId} cannot register as ${e.id}.`),t.nodeId&&t.nodeId!==this.nodeId&&Pc("INSTANCE_NODE_MISMATCH",`Instance ${e.id} belongs to node ${this.nodeId}.`),t.runtimeId&&t.runtimeId!==e.runtimeId&&Pc("INSTANCE_RUNTIME_MISMATCH",`Instance ${e.id} belongs to runtime ${e.runtimeId}.`),t.imageSelection&&t.imageSelection.imageId!==e.imageSelection?.imageId&&Pc("INSTANCE_IMAGE_MISMATCH",`Instance ${e.id} belongs to image ${e.imageSelection?.imageId}.`)}validateInstanceToken(e,t){e.registrationToken&&t===e.registrationToken||Pc("INSTANCE_REGISTRATION_TOKEN_INVALID",`Invalid registration token for instance ${e.id}.`)}authenticateInstance(e,t){const n=this.requireInstance(e);return this.validateInstanceToken(n,t),n}context(e,t=this.resolvedAssignedModelEnvironment(e.id)){const n=e.imageSnapshot||ns.parse({id:"img_localhost",origin:"custom",name:"Localhost",repository:"localhost",tag:"local",requestedReference:"localhost:local",pullPolicy:"if-not-present",capabilities:[],optionalApps:[],defaultEnv:{},labels:{},createdAt:e.createdAt,updatedAt:e.updatedAt});this.instancePrivateConfigs.get(e.id);const i=this.instancePrivateConfigs.materialize(e.id,e.registrationToken,t),s=this.gitWorkspaceProvisioningFor(e);return{project:xc(e),image:n,node:this.node,runtime:this.requireRuntime(e.runtimeId),instance:e,nodeAgentUrl:this.containerUrl,modelEnv:t,privateConfigPath:this.instancePrivateConfigs.filePath(i.instanceId),...s?{gitWorkspaceProvisioning:s,completeGitWorkspaceProvisioning:()=>this.gitCredentials.completeWorkspaceProvisioning(e.id,s.operationId)}:{}}}}async function $c(e,t){const n=function(e){const t=Hc(e),n=[],i=t.pathname.split("/").filter(Boolean).at(-1)||"";return Wc(n,Vc(t.toString(),/^v\d+$/.test(i)?"models":"v1/models")),Wc(n,new URL("/v1/models",t.origin).toString()),Wc(n,new URL("/models",t.origin).toString()),n}(t.endpoint),i=Date.now();let s;for(const r of n){const n=await Bc(e,r,{method:"GET",headers:{accept:"application/json",authorization:`Bearer ${t.key}`}});if(404===n.status||405===n.status){s=n.status;continue}if(!n.ok)throw Kc("MODEL_DISCOVERY_FAILED",n.status);const o=await qc(n,"MODEL_DISCOVERY_RESPONSE_INVALID"),a=Array.isArray(o.data)?o.data:void 0;if(!a)throw Gc("MODEL_DISCOVERY_RESPONSE_INVALID","The model endpoint returned an invalid model list.",502);return{models:Jc(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 Gc("MODEL_DISCOVERY_UNSUPPORTED","No compatible model-list endpoint was found for this endpoint.",502,s)}async function Uc(e,t){const n=Date.now(),i="codex"===t.app||"opencode"===t.app?await Bc(e,Vc(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 Bc(e,function(e){const t=Hc(e),n=t.pathname.split("/").filter(Boolean).at(-1)||"";return Vc(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 Kc("MODEL_TEST_FAILED",i.status);if((await qc(i,"MODEL_TEST_RESPONSE_INVALID")).error)throw Gc("MODEL_TEST_RESPONSE_INVALID","The model endpoint returned an error payload.",502);return{success:!0,latencyMs:Date.now()-n}}function Vc(e,t){const n=Hc(e);return n.pathname=`${n.pathname.replace(/\/+$/,"")}/${t.replace(/^\/+/,"")}`,n.search="",n.hash="",n.toString()}function Hc(e){let t;try{t=new URL(e.trim())}catch{throw Gc("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 Gc("MODEL_ENDPOINT_INVALID","The model endpoint must be an HTTP or HTTPS URL without embedded credentials.",400);return t}async function Bc(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 Gc(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 qc(e,t){const n=await e.text();if(n.length>1e6)throw Gc(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 Gc(t,"The model endpoint returned invalid JSON.",502)}}function Kc(e,t){return Gc(e,401===t||403===t?"The model endpoint rejected the API key.":"The model endpoint rejected the request.",502,t)}function Gc(e,t,n,i){return Object.assign(new Error(t),{code:e,statusCode:n,...i?{details:{upstreamStatus:i}}:{}})}function Wc(e,t){e.includes(t)||e.push(t)}function Jc(e){const t=new Set;return e.filter(e=>!t.has(e.id)&&(t.add(e.id),!0))}const Yc=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(),Xc=Yc.extend({model:a.z.string().trim().min(1).max(240),app:a.z.enum(["codex","claude","opencode"])}).strict();class Qc{invocations=new Map;store;idleTtlMs;maxTtlMs;cleanupTimer;constructor(e,t={}){this.store=e,this.idleTtlMs=t.idleTtlMs??6e4,this.maxTtlMs=t.maxTtlMs??3e5}resolveHttps(e,t){const{match:n,payload:i}=this.store.resolve(e,t);return"unique"!==n.status||"https-token"!==i?.secret.kind?{status:n.status}:{status:"ok",username:i.secret.username,password:i.secret.token}}async prepareSsh(e,i){this.cleanupExpired();const{match:s,payload:r}=this.store.resolve(e,i);if("unique"!==s.status||"ssh-key"!==r?.secret.kind)return{status:s.status};const o=`gitssh_${d.randomUUID()}`,a=t.mkdtempSync(n.join(c.tmpdir(),"task-handoff-node-git-ssh-"));t.chmodSync(a,448);const l=n.join(a,"agent.sock"),u=n.join(a,"askpass.sh");let p;t.writeFileSync(u,"#!/bin/sh\nprintf '%s' \"${TASK_HANDOFF_SSH_KEY_PASSPHRASE:-}\"\n",{mode:448});try{const n=await ed("ssh-agent",["-s","-a",l]);if(p=Number(/SSH_AGENT_PID=(\d+)/.exec(n)?.[1]),!Number.isInteger(p)||p<=0)throw new Error("ssh-agent did not report a process id.");const s={...process.env,SSH_AUTH_SOCK:l,SSH_ASKPASS:u,SSH_ASKPASS_REQUIRE:"force",DISPLAY:process.env.DISPLAY||":0",TASK_HANDOFF_SSH_KEY_PASSPHRASE:r.secret.passphrase||""};await td("ssh-add",["-"],r.secret.privateKey,s);const c=await ed("ssh-add",["-L"],s);t.rmSync(u,{force:!0});const d=Date.now();return this.invocations.set(o,{instanceId:e,remoteUrl:i,credentialId:r.credential.id,credentialRevision:r.credential.revision,socketPath:l,agentPid:p,directory:a,idleExpiresAt:d+this.idleTtlMs,absoluteExpiresAt:d+this.maxTtlMs}),this.scheduleCleanup(),{status:"ok",invocationId:o,publicIdentity:c,pinnedKnownHosts:r.secret.pinnedKnownHosts}}catch(e){if(p)try{process.kill(p,"SIGTERM")}catch{}throw t.rmSync(a,{recursive:!0,force:!0}),e}}async exchangeAgentFrame(e,t,n){this.cleanupExpired();const i=this.invocations.get(t);if(!i||i.instanceId!==e)throw Zc("GIT_CREDENTIAL_SSH_INVOCATION_INVALID",404);const{match:s,payload:r}=this.store.resolve(e,i.remoteUrl);if("unique"!==s.status||"ssh-key"!==r?.secret.kind||r.credential.id!==i.credentialId||r.credential.revision!==i.credentialRevision)throw this.release(t,e),Zc("GIT_CREDENTIAL_SSH_INVOCATION_REVOKED",403);const o=Buffer.from(n,"base64");if(o.length<5||o.length>1048576||o.readUInt32BE(0)!==o.length-4)throw Zc("GIT_CREDENTIAL_SSH_AGENT_FRAME_INVALID",400);i.idleExpiresAt=Math.min(i.absoluteExpiresAt,Date.now()+this.idleTtlMs),this.scheduleCleanup();const a=Math.max(1,Math.min(i.idleExpiresAt,i.absoluteExpiresAt)-Date.now());try{const e=await function(e,t,n){return new Promise((i,s)=>{const r=m.createConnection(e),o=[];let a=0,c=!1;const d=(e,t)=>{c||(c=!0,r.destroy(),e?s(e):i(t))};r.setTimeout(n),r.once("timeout",()=>d(new Error("Managed Git SSH agent exchange timed out."))),r.once("error",e=>d(e)),r.once("end",()=>d(new Error("Managed Git SSH agent closed before returning a complete frame."))),r.once("close",()=>d(new Error("Managed Git SSH agent closed before returning a complete frame."))),r.on("data",e=>{o.push(e);const t=Buffer.concat(o);!a&&t.length>=4&&(a=t.readUInt32BE(0)+4,a<5||a>1048576)?d(new Error("Managed Git SSH agent returned an invalid frame length.")):a&&t.length>=a&&d(void 0,t.subarray(0,a))}),r.once("connect",()=>r.write(t,e=>{e&&d(e)}))})}(i.socketPath,o,a);return{frame:e.toString("base64")}}catch{throw this.release(t,e),Zc("GIT_CREDENTIAL_SSH_AGENT_UNAVAILABLE",502)}}release(e,n){const i=this.invocations.get(e);if(!i||void 0!==n&&i.instanceId!==n)return!1;this.invocations.delete(e);try{process.kill(i.agentPid,"SIGTERM")}catch{}return t.rmSync(i.directory,{recursive:!0,force:!0}),this.scheduleCleanup(),!0}close(){this.cleanupTimer&&clearTimeout(this.cleanupTimer),this.cleanupTimer=void 0;for(const e of[...this.invocations.keys()])this.release(e)}cleanupExpired(){const e=Date.now();for(const[t,n]of this.invocations)(n.idleExpiresAt<=e||n.absoluteExpiresAt<=e)&&this.release(t)}scheduleCleanup(){this.cleanupTimer&&clearTimeout(this.cleanupTimer),this.cleanupTimer=void 0;const e=Math.min(...[...this.invocations.values()].map(e=>Math.min(e.idleExpiresAt,e.absoluteExpiresAt)));Number.isFinite(e)&&(this.cleanupTimer=setTimeout(()=>{this.cleanupTimer=void 0,this.cleanupExpired(),this.scheduleCleanup()},Math.max(0,e-Date.now())),this.cleanupTimer.unref?.())}}function Zc(e,t){return Object.assign(new Error("Managed Git broker request was rejected."),{code:e,statusCode:t})}function ed(e,t,n=process.env){return td(e,t,void 0,n)}function td(e,t,n,i){return new Promise((s,r)=>{const o=l.spawn(e,t,{shell:!1,env:i,stdio:[void 0===n?"ignore":"pipe","pipe","pipe"]}),a=[];o.stdout.on("data",e=>a.push(e)),o.once("error",()=>r(new Error(`Managed Git SSH broker could not start ${e}.`))),o.once("close",t=>0===t?s(Buffer.concat(a).toString("utf8")):r(new Error(`Managed Git SSH broker command ${e} failed.`))),void 0!==n&&o.stdin.end(n)})}const nd=a.z.object({credentialId:a.z.string().trim().min(1).max(120)}).strict(),id=a.z.object({id:a.z.string().trim().min(1).max(120)}).strict(),sd=id.extend({invocationId:a.z.string().trim().min(1).max(120)}).strict();function rd(e){const t=e.authorization;return"string"==typeof t&&t.startsWith("Bearer ")?t.slice(7).trim():void 0}const od=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(),ad=a.z.object({id:a.z.string().trim().min(1).max(120).optional(),name:a.z.string().trim().max(160),path:a.z.string().trim().min(1).max(4096),defaultImageSelection:xn.optional(),labels:a.z.record(a.z.string(),a.z.string()).default({})}).strict(),cd=a.z.object({name:a.z.string().trim().max(160)}).strict(),dd=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(),ld=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:xn.optional(),environmentSource:Pn.optional(),projectId:a.z.string().trim().min(1).max(120).optional(),image:ns.optional(),source:_i,sourceSnapshot:a.z.record(a.z.string(),a.z.unknown()).default({}),config:a.z.object({autoImportAgentConfigs:a.z.boolean().optional(),defaultCodexPermissionMode:He.optional(),aiSessionHistoryLimit:a.z.number().int().min(1).max(mt).optional(),aiSessionAttachmentRetentionDays:a.z.number().int().min(0).max(365).optional(),aiSessionMaxFileAttachmentBytes:a.z.number().int().positive().max(ae).optional()}).strict().optional(),modelSelection:_s.shape.modelSelection,gitWorkspaceProvisioning:ic.optional()}).strict().superRefine((e,t)=>{e.environmentSource&&e.imageSelection&&t.addIssue({code:"custom",path:["environmentSource"],message:"environmentSource and imageSelection are mutually exclusive."}),"template"===e.environmentSource?.type&&e.image&&t.addIssue({code:"custom",path:["image"],message:"Template environment source is resolved by the node-agent and cannot include an image snapshot."}),e.gitWorkspaceProvisioning&&"local-folder"===e.source.type&&t.addIssue({code:"custom",path:["gitWorkspaceProvisioning"],message:"Git provisioning requires a Git source."})}),ud=a.z.object({name:a.z.string().trim().min(1).max(160).optional(),config:a.z.object({autoImportAgentConfigs:a.z.boolean().optional(),defaultCodexPermissionMode:He.optional(),aiSessionHistoryLimit:a.z.number().int().min(1).max(mt).optional(),aiSessionAttachmentRetentionDays:a.z.number().int().min(0).max(365).optional(),aiSessionMaxFileAttachmentBytes:a.z.number().int().positive().max(ae).optional()}).strict().optional(),modelSelection:_s.shape.modelSelection.optional()}).strict(),pd=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(),md=pd.omit({id:!0}).partial().strict();function hd(e){const t=e.authorization;return"string"==typeof t&&t.startsWith("Bearer ")?t.slice(7).trim():void 0}class gd{operations=new Map;intents=new Map;intent(e){const t=this.intents.get(e);if(t)return t;const n={controller:new AbortController};return this.intents.set(e,n),n}invalidate(e){this.intents.get(e)?.controller.abort();const t={controller:new AbortController};return this.intents.set(e,t),t}isIntentCurrent(e,t){return this.intents.get(e)===t}signal(e,t){const n=this.intents.get(e);return n===t?n.controller.signal:AbortSignal.abort()}clearIntent(e){this.intents.delete(e)}async run(e,t){const n=this.operations.get(e)||Promise.resolve();let i;const s=new Promise(e=>{i=e});this.operations.set(e,s),await n;try{return await t()}finally{i(),this.operations.get(e)===s&&this.operations.delete(e)}}}const fd=a.z.object({gitWorkspaceProvisioning:ic.optional()}).strict().default({});class yd{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=ee();return this.state.controlledInstances.put(_s.parse({...t,status:"provisioning",health:"unknown",imageProvisioning:{phase:"checking-image",requestedReference:t.imageSnapshot.requestedReference,generation:(t.imageProvisioning?.generation||0)+1,startedAt:n,updatedAt:n},updatedAt:n}))}provision(e,t){if(this.stopped)return Promise.resolve();const n=e.imageProvisioning?.generation;if(void 0===n)return Promise.resolve();const i=`${e.id}:${n}`,s=this.inFlight.get(i);if(s)return s;const r=this.provisionGeneration(e,n,t).finally(()=>{this.inFlight.get(i)===r&&this.inFlight.delete(i)});return this.inFlight.set(i,r),r}async stop(){this.stopped=!0,this.abortController.abort(),await Promise.allSettled([...this.inFlight.values()])}async provisionGeneration(e,t,n){const i=this.currentGeneration(e.id,t,!0,e.createdAt);if(!i)return;let s,r=0,o=!1,a=Promise.resolve();try{const c=await this.images.ensure(i.imageSnapshot.requestedReference,n=>{a=a.then(async()=>{if(!s)try{await this.updatePhase(e.id,t,n,e.createdAt)}catch(e){s={error:e}}})},n=>{this.stopped||(o=!0,r=n.sequence,this.publishTerminalOutput(e,t,n))},this.abortController.signal);if(await a,s)throw s.error;if(this.stopped)return;o&&this.publishFinished(e,t,r+1,"succeeded");const d=async()=>{if(this.stopped)return;const i=this.currentGeneration(e.id,t,!0,e.createdAt);if(!i)return;const s=this.state.controlledInstances.put(_s.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:ee()},updatedAt:ee()}));this.options.sync(),this.options.diagnostic({instanceId:e.id,action:"image.provision",reference:c.requestedReference,digest:c.resolvedDigest,pulled:c.pulled},"node instance image provisioning completed"),"starting"===s.status&&await(n?.())};await(this.options.runInstanceOperation?.(e.id,d)??d())}catch(n){if(await a,s&&(n=s.error),this.stopped)return;o&&this.publishFinished(e,t,r+1,"failed");const i=n instanceof Error?n.message:String(n),c=async()=>{if(this.stopped)return;const n=this.currentGeneration(e.id,t,!1,e.createdAt);n?.imageProvisioning&&["provisioning","starting"].includes(n.status)&&(this.state.controlledInstances.put(_s.parse({...n,status:"failed",health:"failed",imageProvisioning:{...n.imageProvisioning,phase:"failed",error:i,updatedAt:ee()},updatedAt:ee()})),this.options.sync(),this.options.warn({instanceId:e.id,action:"image.provision",reference:n.imageProvisioning.requestedReference,error:i},"node instance image provisioning failed"))};await(this.options.runInstanceOperation?.(e.id,c)??c())}}currentGeneration(e,t,n=!0,i){const s=this.state.controlledInstances.get(e);if(!(!s||i&&s.createdAt!==i||s.imageProvisioning?.generation!==t||n&&!s.imageSnapshot))return s}async updatePhase(e,t,n,i){if(this.stopped)return;const s=async()=>{if(this.stopped)return;const s=this.currentGeneration(e,t,!0,i);s&&["provisioning","starting"].includes(s.status)&&(this.state.controlledInstances.put(_s.parse({...s,status:"starting"===s.status?"starting":"provisioning",imageProvisioning:{...s.imageProvisioning,phase:n,error:void 0,updatedAt:ee()},updatedAt:ee()})),this.options.sync())};await(this.options.runInstanceOperation?.(e,s)??s())}eventBase(e,t){return{instanceId:e.id,generation:t,requestedReference:e.imageProvisioning.requestedReference,observedAt:ee()}}publishTerminalOutput(e,t,n){for(const[i,s]of function(e,t=6e4){const n=[];for(let i=0;i<e.length;i+=t)n.push(e.slice(i,i+t));return n}(n.data).entries())this.options.publish(ss,{...this.eventBase(e,t),sequence:1e3*n.sequence+i,data:s,...n.replay?{replay:!0}:{}},e.id)}publishFinished(e,t,n,i){this.options.publish(rs,{...this.eventBase(e,t),sequence:1e3*n,outcome:i},e.id)}}const Id=a.z.object({name:a.z.string().trim().min(1).max(160)}).strict();function Ad(e,t,n){return{code:"object"==typeof e&&e&&"code"in e&&"string"==typeof e.code?e.code:t,message:e instanceof Error?e.message:String(e),phase:n}}class bd{templateOperations=new gd;store;privateConfigs;docker;requireInstanceValue;requireRuntimeValue;runInstanceOperationValue;isImageReferencedValue;constructor(e,t,n,i,s,r,o=()=>!1){this.store=e,this.privateConfigs=t,this.docker=n,this.requireInstanceValue=i,this.requireRuntimeValue=s,this.runInstanceOperationValue=r,this.isImageReferencedValue=o}list(){return this.store.list()}require(e){const t=this.store.get(e);if(!t)throw Object.assign(new Error(`Environment template ${e} was not found.`),{statusCode:404,code:"ENVIRONMENT_TEMPLATE_NOT_FOUND"});return t}runTemplateOperation(e,t){return this.templateOperations.run(e,async()=>t())}async create(e,t){const n=Id.parse(t),i=this.requireInstanceValue(e),s=this.requireRuntimeValue(i.runtimeId);if("docker"!==s.type)throw Object.assign(new Error(`Runtime ${s.name} does not support environment templates.`),{statusCode:409,code:"ENVIRONMENT_TEMPLATE_RUNTIME_UNSUPPORTED"});if(!i.runtime.containerName)throw Object.assign(new Error(`Instance ${i.id} does not have a Docker container.`),{statusCode:409,code:"ENVIRONMENT_TEMPLATE_CONTAINER_NOT_FOUND"});const r=ee(),o=da("envtpl"),a=`task-handoff/environment-template:${o.toLowerCase().replace(/[^a-z0-9_.-]/g,"-")}`;return this.store.put(Yn.parse({id:o,name:n.name,sourceInstanceId:i.id,nodeId:i.nodeId,internalTag:a,status:"creating",createdAt:r,updatedAt:r})),this.runInstanceOperationValue(i.id,async()=>{let e,t=!1;try{const n=this.requireInstanceValue(i.id);if("docker"!==this.requireRuntimeValue(n.runtimeId).type||!n.runtime.containerName)throw Object.assign(new Error(`Instance ${i.id} is no longer a valid Docker template source.`),{code:"ENVIRONMENT_TEMPLATE_SOURCE_CHANGED"});const s=this.privateConfigs.get(i.id);if(!s)throw Object.assign(new Error(`Instance ${i.id} private configuration is missing.`),{code:"INSTANCE_PRIVATE_CONFIG_MISSING"});const r=[s.instanceCredential,...Object.values(s.environment)];await this.docker.inspectContainerConfigSecurity(n.runtime.containerName,r),e=await this.docker.commitEnvironmentTemplate(n.runtime.containerName,n.runtime.containerId,a),t=!0;const c=await this.docker.inspectEnvironmentTemplateImage(a);return await this.docker.inspectImageConfigSecurity(a,r),this.store.put(Yn.parse({...this.require(o),...c,status:"ready",error:void 0,updatedAt:ee()}))}catch(n){return t&&(await this.docker.untagEnvironmentTemplate(a,e).catch(()=>!1),e&&await this.docker.garbageCollectEnvironmentTemplateImage(e).catch(()=>!1)),this.store.put(Yn.parse({...this.require(o),status:"failed",error:Ad(n,"ENVIRONMENT_TEMPLATE_CREATE_FAILED","commit"),updatedAt:ee()}))}})}async delete(e){return this.runTemplateOperation(e,async()=>{const t=this.require(e);this.store.put(Yn.parse({...t,status:"deleting",error:void 0,updatedAt:ee()}));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(Yn.parse({...t,status:"failed",error:Ad(e,"ENVIRONMENT_TEMPLATE_DELETE_FAILED","delete"),updatedAt:ee()})),e}})}async releaseUnusedImage(e){return!this.store.list().some(t=>t.imageId===e)&&!this.isImageReferencedValue(e)&&this.docker.garbageCollectEnvironmentTemplateImage(e)}}const vd=new Set(["DELETE","GET","HEAD","PATCH","POST","PUT","OPTIONS"]);function wd(e){return"string"==typeof e&&vd.has(e.toUpperCase())?e.toUpperCase():"GET"}const Sd=new Set(["content-encoding","content-length","transfer-encoding"]),Ed=67108864;function Nd(e){return Object.fromEntries([...e.entries()].filter(([e])=>!Sd.has(e.toLowerCase())))}function zd(e){return e.bodyBase64?Buffer.from(e.bodyBase64,"base64"):e.body}function Td(){const e=Number(process.env.TASK_HANDOFF_INSTANCE_PROXY_MAX_RESPONSE_BYTES);return Number.isSafeInteger(e)&&e>0?e:67108864}const _d="x-task-handoff-trace-id";function kd(e){return e.startsWith("/")?e:`/${e}`}function Cd(e,t){return e.code(502).send({error:{code:"INSTANCE_PROXY_RESPONSE_TOO_LARGE",message:`Instance response exceeds ${t} bytes.`}})}async function Od(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 Rd(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 xd(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 Rd(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 Rd(e,"endpoint must be an origin-only http://127.0.0.1:<port> URL");return i.origin}const Pd=a.z.object({version:a.z.literal(1),externalListener:Is}).strict();function Dd(e){return"all-ipv4"===e?"0.0.0.0":"127.0.0.1"}function Md(e){if(!e||"object"!=typeof e||Array.isArray(e))return e;const t=e,n=t.externalListener&&"object"==typeof t.externalListener&&!Array.isArray(t.externalListener)?t.externalListener:{},i=Object.keys(t).filter(e=>"version"!==e&&"externalListener"!==e),s=Object.keys(n).filter(e=>"bindScope"!==e&&"port"!==e);return(i.length||s.length)&&console.warn(JSON.stringify({message:"unknown stored node agent runtime setting fields were ignored",filePath:"runtime-settings.json",fields:[...i,...s.map(e=>`externalListener.${e}`)]})),{version:t.version,externalListener:{bindScope:n.bindScope,port:n.port}}}async function jd(e){const t=Dd(e.bindScope);return!await new Promise(t=>{const n=m.createConnection({host:"127.0.0.1",port:e.port}),i=e=>{n.removeAllListeners(),n.destroy(),t(e)};n.once("connect",()=>i(!0)),n.once("error",()=>i(!1)),n.setTimeout(250,()=>i(!1))})&&new Promise(n=>{const i=m.createServer();i.once("error",()=>n(!1)),i.listen({host:t,port:e.port,exclusive:!0},()=>i.close(()=>n(!0)))})}class Ld{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 As.parse({...this.config,host:Dd(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:Dd(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 ${Dd(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=bs.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 ${Dd(t.bindScope)}:${t.port}: ${e instanceof Error?e.message:String(e)}`),{statusCode:409,code:"NODE_AGENT_LISTENER_BIND_FAILED"})}try{this.settings.put({version:1,externalListener:t})}catch(e){throw await this.stop(),await this.restore(n),Object.assign(new Error(`Failed to persist node agent TCP listener: ${e instanceof Error?e.message:String(e)}`),{statusCode:500,code:"NODE_AGENT_LISTENER_PERSIST_FAILED"})}this.config=t,this.source="persisted",this.status="listening",this.error=void 0,this.state.setListenerPort(t.port);const i=this.current();return this.onActiveListener?.(i),i}async shutdown(){await this.updateQueue,await this.stop()}snapshot(){return{config:this.config,source:this.source,status:this.status,error:this.error}}async restore(e){if(this.config=e.config,this.source=e.source,this.status=e.status,this.error=e.error,"listening"===e.status)try{await this.listen(e.config)}catch(e){this.status="error",this.error=`Failed to restore previous listener: ${e instanceof Error?e.message:String(e)}`,this.app.log.error({error:this.error},"node agent TCP listener rollback failed")}this.state.setListenerPort(e.config.port),"listening"===this.status&&this.onActiveListener?.(this.current())}async listen(e){await new Promise((t,n)=>{const i=e=>{this.app.server.off("listening",s),n(e)},s=()=>{this.app.server.off("error",i),t()};this.app.server.once("error",i),this.app.server.once("listening",s),this.app.server.listen({host:Dd(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 Fd="TASK_HANDOFF_NODE_AGENT_V1",$d="/api/node-tunnel";function Ud(e=""){return d.createHash("sha256").update(e).digest("hex")}function Vd(e,t){return d.createHmac("sha256",e).update(function(e){return[Fd,e.keyId,e.method.toUpperCase(),e.pathWithQuery,e.timestamp,e.nonce,e.bodySha256].join("\n")}(t)).digest("hex")}function Hd(e){const t=e.timestamp||(new Date).toISOString(),n=e.nonce||d.randomBytes(18).toString("base64url"),i=Ud(e.body||""),s=Vd(e.secret,{keyId:e.keyId,method:e.method,pathWithQuery:e.pathWithQuery,timestamp:t,nonce:n,bodySha256:i});return{"x-taskhandoff-node-id":e.nodeId,"x-taskhandoff-key-id":e.keyId,"x-taskhandoff-timestamp":t,"x-taskhandoff-nonce":n,"x-taskhandoff-body-sha256":i,"x-taskhandoff-signature":s}}class Bd{usedNonces=new Map;identity;nodeId;overrideSecret;overrideKeyId;nowMs;constructor(e,t,n,i,s=Date.now){this.identity=e,this.nodeId=t,this.overrideSecret=n,this.overrideKeyId=i,this.nowMs=s}hasRemoteSecrets(){return this.identity.remoteSecrets(this.overrideSecret,this.overrideKeyId).length>0}verify(e){const t=function(e){const t=new Map;for(const[n,i]of Object.entries(e)){const e=Array.isArray(i)?i.join(","):"string"==typeof i?i:void 0===i?"":String(i);t.set(n.toLowerCase(),e)}return{nodeId:t.get("x-taskhandoff-node-id")||"",keyId:t.get("x-taskhandoff-key-id")||"",timestamp:t.get("x-taskhandoff-timestamp")||"",nonce:t.get("x-taskhandoff-nonce")||"",bodySha256:t.get("x-taskhandoff-body-sha256")||"",signature:t.get("x-taskhandoff-signature")||""}}(e.headers);if(!t.nodeId&&!t.signature)return!1;const n="DELETE"===e.method&&"/api/node-agent/pairing/current"===e.url.split("?")[0],i=this.identity.remoteSecrets(this.overrideSecret,this.overrideKeyId,n);if(!i.length)return!1;if(t.nodeId!==this.nodeId)throw Object.assign(new Error("Invalid node agent HMAC node id."),{statusCode:401,code:"NODE_AGENT_HMAC_NODE_MISMATCH"});if(!t.keyId)throw Object.assign(new Error("Node agent HMAC key id is missing."),{statusCode:401,code:"NODE_AGENT_HMAC_KEY_MISSING"});const s=i.filter(e=>t.keyId===e.keyId);if(!s.length)throw Object.assign(new Error("Invalid node agent HMAC key id."),{statusCode:401,code:"NODE_AGENT_HMAC_KEY_INVALID"});const r=Date.parse(t.timestamp);if(!Number.isFinite(r)||Math.abs(this.nowMs()-r)>6e4)throw Object.assign(new Error("Node agent HMAC timestamp is outside the allowed window."),{statusCode:401,code:"NODE_AGENT_HMAC_TIMESTAMP_INVALID"});if(!t.nonce)throw Object.assign(new Error("Node agent HMAC nonce is missing."),{statusCode:401,code:"NODE_AGENT_HMAC_NONCE_MISSING"});this.pruneNonces();const o=`${t.nodeId}:${t.keyId}:${t.nonce}`;if(this.usedNonces.has(o))throw Object.assign(new Error("Node agent HMAC nonce was already used."),{statusCode:401,code:"NODE_AGENT_HMAC_NONCE_REPLAY"});const a=Ud(null==(c=e.body)?"":"string"==typeof c||Buffer.isBuffer(c)?c:JSON.stringify(c));var c;if(t.bodySha256!==a)throw Object.assign(new Error("Node agent HMAC body hash mismatch."),{statusCode:401,code:"NODE_AGENT_HMAC_BODY_HASH_INVALID"});if(!s.some(n=>function(e,t){const n=Buffer.from(e,"hex"),i=Buffer.from(t,"hex");return n.length===i.length&&d.timingSafeEqual(n,i)}(t.signature,Vd(n.secret,{keyId:t.keyId,method:e.method,pathWithQuery:e.url,timestamp:t.timestamp,nonce:t.nonce,bodySha256:a}))))throw Object.assign(new Error("Invalid node agent HMAC signature."),{statusCode:401,code:"NODE_AGENT_HMAC_SIGNATURE_INVALID"});return this.usedNonces.set(o,r+6e4+1),t.keyId}pruneNonces(){const e=this.nowMs();for(const[t,n]of this.usedNonces)n<=e&&this.usedNonces.delete(t)}}const qd=a.z.string().trim().min(1).max(160),Kd=a.z.string().datetime(),Gd=a.z.string().min(1).max(4096),Wd=a.z.string().trim().url().max(2048),Jd=a.z.object({id:qd,keyId:qd,name:a.z.string().trim().min(1).max(160).optional(),secret:Gd,pairedAt:Kd,revokedAt:Kd.optional(),updatedAt:Kd}).strip(),Yd=a.z.object({id:qd,pairingKeyId:qd,name:a.z.string().trim().min(1).max(160).optional(),url:Wd,enabled:a.z.boolean().default(!0),createdAt:Kd,updatedAt:Kd}).strip(),Xd=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(),Qd=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(),Zd=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(),el=new Set(["nodeId","createdAt","updatedAt","pairingInvites","controlPlanePairings","controlPlaneConnections","remoteControlPlanes"]),tl=new Set(["id","keyId","name","secret","pairedAt","revokedAt","updatedAt"]),nl=new Set(["id","pairingKeyId","name","url","enabled","createdAt","updatedAt"]),il=new Set(["id","keyId","name","url","secret","pairedAt","updatedAt","active"]);function sl(e,t){console.warn(JSON.stringify({message:e,...t}))}function rl(e,t){return Object.assign(new Error(e,void 0===t?void 0:{cause:t}),{code:"NODE_AGENT_IDENTITY_INVALID"})}function ol(e,t){return Object.keys(e).filter(e=>!t.has(e))}function al(e,t,n){const i=Kd.safeParse(e);return i.success?i.data:(n("invalid node agent identity timestamp was replaced",{field:t}),ee())}function cl(e,t){if(!e||"object"!=typeof e||Array.isArray(e))throw rl("Node agent identity must be a JSON object.");const n=e,i=qd.safeParse(n.nodeId);if(!i.success)throw rl("Node agent identity has an invalid nodeId.",i.error);const s=i.data,r=ol(n,el);r.length&&t("unknown node agent identity fields were ignored",{fields:r}),Array.isArray(n.pairingInvites)&&n.pairingInvites.length&&t("persisted node agent pairing invites were discarded",{count:n.pairingInvites.length});const o=Array.isArray(n.remoteControlPlanes)?n.remoteControlPlanes.flatMap(e=>{if(!e||"object"!=typeof e||Array.isArray(e))return[];const n=e,i=ol(n,il);i.length&&t("unknown legacy node agent remote control-plane fields were ignored",{fields:i});const s=Jd.safeParse(n);if(!s.success)return t("invalid legacy node agent control-plane pairing was ignored",{issues:s.error.issues}),[];const r=n.url?Yd.safeParse({id:`connection_${s.data.keyId}`,pairingKeyId:s.data.keyId,name:n.name,url:n.url,enabled:!1!==n.active,createdAt:s.data.pairedAt,updatedAt:s.data.updatedAt}):void 0;return[{pairing:s.data,...r?.success?{connection:r.data}:{}}]}):[],a=(e,n,i,s)=>Array.isArray(e)?e.flatMap(e=>{if(!e||"object"!=typeof e||Array.isArray(e))return t(`invalid node agent ${s} was ignored`,{}),[];const r=ol(e,n);r.length&&t(`unknown node agent ${s} fields were ignored`,{fields:r});const o=i.safeParse(e);return o.success?[o.data]:(t(`invalid node agent ${s} was ignored`,{issues:o.error.issues}),[])}):[];return{nodeId:s,createdAt:al(n.createdAt,"createdAt",t),updatedAt:al(n.updatedAt,"updatedAt",t),controlPlanePairings:n.controlPlanePairings?a(n.controlPlanePairings,tl,Jd,"control-plane pairing"):o.map(e=>e.pairing),controlPlaneConnections:n.controlPlaneConnections?a(n.controlPlaneConnections,nl,Yd,"control-plane connection"):o.flatMap(e=>e.connection?[e.connection]:[])}}class dl{paths;logger;constructor(e,t={}){this.paths=e,this.logger=t.logger||sl}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 rl(`Node agent identity contains invalid JSON: ${this.paths.identityPath}`,e)}return cl(n,this.logger)}init(){const e=this.read();if(!e)return;const n=JSON.parse(t.readFileSync(this.paths.identityPath,"utf8"));("pairingInvites"in n||"remoteControlPlanes"in n)&&this.write(e)}write(e){t.mkdirSync(n.dirname(this.paths.identityPath),{recursive:!0});const i=cl({...e,updatedAt:ee()},this.logger);I.sync(this.paths.identityPath,`${JSON.stringify(i,null,2)}\n`,{encoding:"utf8",mode:384})}}class ll{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 ul{store;pairingInvites=new ll;controlPlaneConnectionOperations=new Map;constructor(e){this.store=new dl(e),this.store.init()}async runControlPlaneConnectionOperation(e,t){const n=e.replace(/\/$/,""),i=this.controlPlaneConnectionOperations.get(n)||Promise.resolve();let s;const r=new Promise(e=>{s=e});this.controlPlaneConnectionOperations.set(n,r),await i;try{return await t()}finally{s(),this.controlPlaneConnectionOperations.get(n)===r&&this.controlPlaneConnectionOperations.delete(n)}}resolveNodeId(e){if(e?.trim())return this.writeNodeId(e.trim()),e.trim();const t=this.store.read();if(t?.nodeId)return t.nodeId;const n=da("node");return this.writeNodeId(n),n}createPairingInvite(e){const t=ee(),n=new Date(Date.now()+(e.expiresInMs||6e5)).toISOString(),i=la(),s={tokenHash:Ud(i),createdAt:t,expiresAt:n,...e.controlPlaneName?{controlPlaneName:e.controlPlaneName}:{}};return this.pairingInvites.put(s.tokenHash,s),{...s,token:i}}completePairingInvite(e){const t=this.store.read()||this.newIdentity(),n=Ud(e.joinToken),i=this.pairingInvites.take(n);if(!i){const e=new Error("Node agent pairing invite is invalid or expired.");throw Object.assign(e,{statusCode:401,code:"NODE_AGENT_PAIRING_INVITE_INVALID"}),e}const s=ee(),r={id:e.controlPlaneId||da("cp"),keyId:da("key"),...e.controlPlaneName||i.controlPlaneName?{name:e.controlPlaneName||i.controlPlaneName}:{},secret:la(),pairedAt:s,updatedAt:s};return this.store.write({...t,controlPlanePairings:[...(t.controlPlanePairings||[]).filter(e=>e.id!==r.id),r]}),r}stageControlPlaneConnection(e){const{pairing:t,connection:n}=this.createControlPlaneConnection(e),i=this.store.read()||this.newIdentity(),s=n.url.replace(/\/$/,""),r=(i.controlPlaneConnections||[]).filter(e=>e.id===n.id||e.url.replace(/\/$/,"")===s);return this.store.write({...i,controlPlanePairings:[...(i.controlPlanePairings||[]).filter(e=>e.keyId!==t.keyId),t],controlPlaneConnections:[...(i.controlPlaneConnections||[]).filter(e=>e.id!==n.id&&e.url.replace(/\/$/,"")!==s),n]}),{pairing:t,connection:n,replacedConnections:r}}commitControlPlaneConnection(e,t={}){const n=this.store.read()||this.newIdentity(),i={...e.pairing,...t.name?{name:t.name}:{}},s={...e.connection,...t.name?{name:t.name}:{}},r=new Set((n.controlPlaneConnections||[]).map(e=>e.pairingKeyId)),o=new Set(e.replacedConnections.map(e=>e.pairingKeyId));return this.store.write({...n,controlPlanePairings:[...(n.controlPlanePairings||[]).filter(e=>e.keyId!==i.keyId&&(!o.has(e.keyId)||r.has(e.keyId))),i],controlPlaneConnections:[...(n.controlPlaneConnections||[]).filter(e=>e.id!==s.id),s]}),{pairing:i,connection:s}}rollbackControlPlaneConnection(e){const t=this.store.read();if(!t)return;const n=new Set(e.replacedConnections.map(e=>e.id));this.store.write({...t,controlPlanePairings:(t.controlPlanePairings||[]).filter(t=>t.keyId!==e.pairing.keyId),controlPlaneConnections:[...(t.controlPlaneConnections||[]).filter(t=>t.id!==e.connection.id&&!n.has(t.id)),...e.replacedConnections]})}createControlPlaneConnection(e){const t=ee(),n={id:da("cp"),keyId:da("key"),...e.name?{name:e.name}:{},secret:la(),pairedAt:t,updatedAt:t};return{pairing:n,connection:{id:da("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=ee();return this.store.write({...t,controlPlanePairings:t.controlPlanePairings.map(t=>t.keyId===e?{...t,revokedAt:i,updatedAt:i}:t)}),{keyId:e,revoked:!0,revokedAt:i}}deleteControlPlaneConnection(e){const t=this.store.read();if(!t)return!1;const n=(t.controlPlaneConnections||[]).filter(t=>t.id!==e);return n.length!==(t.controlPlaneConnections||[]).length&&(this.store.write({...t,controlPlaneConnections:n}),!0)}remoteSecrets(e,t,n=!1){return[...(this.store.read()?.controlPlanePairings||[]).filter(e=>n||!e.revokedAt).map(e=>({keyId:e.keyId,secret:e.secret})),...e&&t?[{keyId:t,secret:e}]:[]]}isRevokedPairing(e){return Boolean(this.store.read()?.controlPlanePairings?.some(t=>t.keyId===e&&t.revokedAt))}reverseTunnelSecret(e,t,n){if(t&&n)return{keyId:n,secret:t};const i=this.store.read(),s=(i?.controlPlanePairings||[]).filter(e=>!e.revokedAt);if(!s.length)return;if(e){const t=e.replace(/\/$/,""),n=(i?.controlPlaneConnections||[]).find(e=>e.url.replace(/\/$/,"")===t),r=n&&s.find(e=>e.keyId===n.pairingKeyId);if(r)return{keyId:r.keyId,secret:r.secret}}const r=[...s].sort((e,t)=>t.updatedAt.localeCompare(e.updatedAt))[0];return r?{keyId:r.keyId,secret:r.secret}:void 0}newIdentity(){return{nodeId:this.resolveNodeId(),createdAt:ee(),updatedAt:ee(),controlPlanePairings:[],controlPlaneConnections:[]}}writeNodeId(e){const t=this.store.read();this.store.write({...t||{createdAt:ee()},nodeId:e,updatedAt:ee(),controlPlanePairings:t?.controlPlanePairings||[],controlPlaneConnections:t?.controlPlaneConnections||[]})}}const pl=a.z.string().trim().min(1).max(160);const ml=vi.strict();function hl(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 gl{preflights=new Map;options;applying=!1;constructor(e){this.options=e}async check(e){const t=Ii.parse(e),n=hl(this.options.listInstances()),i=await wa(this.options.runCommand,this.options.moduleDir),s=this.options.currentRuntimeVersion(),r=this.options.managedUpdateSupport?.(i)||{supported:!0};if(!r.supported)return Ai.parse({source:"npm",channel:t.channel,currentVersion:i.currentVersion||s,availableVersion:i.currentVersion||s||"unavailable",impact:n,updateAvailable:!1,supported:!1,reason:r.reason||"Managed updates are unavailable on this node.",checkedAt:(new Date).toISOString()});const o="@task-handoff/server"===i.packageName?[...new Set([...i.relatedCurrentVersions,s])]:i.relatedCurrentVersions,a=await async function(e){const t=e.packageName||"@task-handoff/node-agent",n=await async function(e,t,n){const i=function(e){return"stable"===e?"latest":e}(n),s=await e(ba(),["view",`${t}@${i}`,"version","--json"]).catch(e=>{if(!function(e){if(!e||"object"!=typeof e)return!1;const t=e,n=[t.message,t.details?.stdout,t.details?.stderr].filter(e=>"string"==typeof e).join("\n");return/\bE404\b/i.test(n)}(e))throw e});if(!s)return;const r=JSON.parse(s.stdout);if("string"!=typeof r)throw new Error(`npm did not resolve ${t}@${i} to one version.`);return r}(e.runCommand,t,e.channel);if(!n)return function(e){return Ai.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:ee()})}({channel:e.channel,currentVersion:e.currentVersion,impact:e.impact});const i=Aa(e.currentVersion,n)||(e.relatedCurrentVersions||[]).some(e=>Aa(e,n)),s=i?await async function(e,t,n){const i=await e(ba(),["view",`${t}@${n}`,"dist.integrity","--json"]),s=JSON.parse(i.stdout);if("string"!=typeof s||!/^sha(?:256|384|512)-[A-Za-z0-9+/=]+$/.test(s))throw Object.assign(new Error(`npm did not return immutable integrity metadata for ${t}@${n}.`),{statusCode:502,code:"NODE_UPDATE_PREFLIGHT_FAILED",retryable:!0});return s}(e.runCommand,t,n):void 0;return Ai.parse({source:"npm",channel:e.channel,currentVersion:e.currentVersion,availableVersion:n,...s?{artifactRef:`npm:${t}@${n}#${s}`}:{},runtimeArtifacts:e.runtimeArtifacts||[],impact:e.impact||{runningInstanceCount:0,stoppedInstanceCount:0,activeInstanceCount:0,restartInstanceCount:0,runningInstanceIds:[],stoppedInstanceIds:[],activeInstanceIds:[]},updateAvailable:i,checkedAt:ee()})}({channel:t.channel,currentVersion:i.currentVersion||s,runCommand:this.options.runCommand,packageName:i.packageName,relatedCurrentVersions:o,impact:n});if(!a.updateAvailable)return a;const c={...a,runtimeArtifacts:await this.options.resolveRuntimeArtifacts(a.availableVersion),preflightToken:la()};return this.preflights.set(c.preflightToken,{result:c,expiresAt:Date.now()+6e5}),c}async apply(e){const i=ml.parse(e),s=this.preflights.get(i.preflightToken);(!s||s.expiresAt<=Date.now())&&await this.consumePreflight(i),this.applying&&this.throwAlreadyRunning(),this.applying=!0;try{const{check:e,selection:s}=await this.consumePreflight(i);if(this.options.jobs.list().some(e=>!["succeeded","degraded","failed"].includes(e.status))&&this.throwAlreadyRunning(),!e.supported)throw Object.assign(new Error(e.reason||"The requested update is not supported."),{statusCode:400,code:"UPDATE_UNSUPPORTED"});if(!e.updateAvailable)throw Object.assign(new Error(e.reason||"No update is available for the selected channel."),{statusCode:409,code:"UPDATE_NOT_AVAILABLE"});const r=this.options.jobs.create(this.options.nodeId,e),{worker:o,packaged:a,expectedWorker:c}=function(e,i=t.existsSync){const s=[n.resolve(e,"..","bin","task-handoff-node-update-worker"),n.resolve(e,"..","..","bin","task-handoff-node-update-worker")],r=s.find(i),o=n.resolve(e,"..","..","..","..","scripts","node-update-worker.cts");return r?{worker:r,packaged:!0,expectedWorker:s[0]}:i(o)?{worker:o,packaged:!1,expectedWorker:s[0]}:{worker:void 0,packaged:!1,expectedWorker:s[0]}}(this.options.moduleDir);if(!o)throw this.options.jobs.patch(r.id,{status:"failed",rollout:{...r.rollout,phase:"failed"},error:{code:"NODE_UPDATE_FAILED",message:`Update worker was not found: ${c}`,retryable:!1},completedAt:(new Date).toISOString()}),Object.assign(new Error(`Node agent update worker was not found: ${c}`),{statusCode:500,code:"UPDATE_WORKER_NOT_FOUND"});const d=process.env.TASK_HANDOFF_CONTROL_PLANE_HEALTH_URL?.trim();try{await this.options.runCommand("systemd-run",["--unit",`task-handoff-update-${r.id}`,"--collect","--property=Type=exec",...a?[o]:[process.execPath,o],"--job-file",this.options.jobs.records.filePath(r.id),"--target-version",r.toVersion,"--npm-command",ba(),"--install-prefix",s.installPrefix,...process.env.TASK_HANDOFF_NODE_AGENT_IPC_PATH?.trim()?["--node-agent-ipc-path",process.env.TASK_HANDOFF_NODE_AGENT_IPC_PATH.trim()]:[],...d?["--control-plane-health-url",d]:[]])}catch(e){const t=e instanceof Error?e.message:String(e);throw this.options.jobs.patch(r.id,{status:"failed",rollout:{...r.rollout,phase:"failed"},error:{code:"NODE_UPDATE_FAILED",message:`Failed to launch the node update worker: ${t}`,retryable:!0},completedAt:(new Date).toISOString()}),Object.assign(new Error(`Failed to launch the node update worker: ${t}`),{statusCode:500,code:"NODE_UPDATE_WORKER_LAUNCH_FAILED",cause:e})}return await this.waitForWorkerClaim(r)}finally{this.applying=!1}}async consumePreflight(e){const t=this.preflights.get(e.preflightToken);if(this.preflights.delete(e.preflightToken),!t||t.expiresAt<=Date.now())throw Object.assign(new Error("The update preflight is missing or expired. Check for updates again."),{statusCode:409,code:"UPDATE_PREFLIGHT_EXPIRED"});const n=t.result,i=await wa(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(hl(this.options.listInstances()))||this.throwStale();const s=await this.options.resolveRuntimeArtifacts(n.availableVersion);return JSON.stringify(n.runtimeArtifacts)!==JSON.stringify(s)&&this.throwStale(),{check:n,selection:i}}throwStale(){throw Object.assign(new Error("The update target or affected instances changed after preflight. Check for updates again."),{statusCode:409,code:"UPDATE_PREFLIGHT_STALE"})}throwAlreadyRunning(){throw Object.assign(new Error("Another server update is already running on this node."),{statusCode:409,code:"SERVER_UPDATE_ALREADY_RUNNING"})}async waitForWorkerClaim(e){const t=this.options.workerClaimTimeoutMs??5e3,n=this.options.workerClaimPollMs??50,i=Date.now()+t;for(;Date.now()<=i;){const t=this.options.jobs.records.get(e.id);if(!t)throw Object.assign(new Error(`Update job ${e.id} disappeared before the worker claimed it.`),{statusCode:500,code:"UPDATE_JOB_NOT_FOUND"});if("queued"!==t.status)return t;if(Date.now()>=i)break;await new Promise(e=>setTimeout(e,Math.max(1,Math.min(n,i-Date.now()))))}const s=this.options.jobs.records.get(e.id);if("queued"!==s?.status)return s||e;throw this.options.jobs.patch(e.id,{status:"failed",rollout:{...s.rollout,phase:"failed"},error:{code:"NODE_UPDATE_FAILED",message:"The node update worker did not claim the queued job after systemd accepted it.",retryable:!0},completedAt:(new Date).toISOString()}),Object.assign(new Error("The node update worker did not start after systemd accepted the update job."),{statusCode:500,code:"NODE_UPDATE_WORKER_START_TIMEOUT"})}}const fl=new Set(["provisioning","starting","registering","registered","running"]);function yl(e){return fl.has(e.status)&&!Xo(e)}function Il(e){return _s.parse({...e,health:"unknown",connectionStatus:"offline",agentStatus:"offline",targetStatus:"unknown",uiAccessStatus:"unknown",target:{...e.target,status:"unknown"},updatedAt:ee()})}class Al{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)&&!Xo(t)&&(this.restoredInstances.add(e),this.restoreErrors.delete(e),!0)}allowRecovery(e){this.suppressedInstances.delete(e);const t=this.pendingUnexpectedExits.get(e);void 0!==t&&(this.pendingUnexpectedExits.delete(e),this.applyUnexpectedLocalExit(e,t))}completeSuppressedOperation(e){this.pendingUnexpectedExits.delete(e),this.restoredInstances.delete(e),this.restoreErrors.delete(e),this.unexpectedExitRetries.delete(e)}forgetInstance(e){this.restoredInstances.delete(e),this.restoreErrors.delete(e),this.unexpectedExitRetries.delete(e),this.suppressedInstances.delete(e),this.activeRestores.delete(e),this.pendingUnexpectedExits.delete(e)}async suppressRecovery(e){this.suppressedInstances.add(e),await(this.activeRestores.get(e)?.catch(()=>{}))}handleUnexpectedLocalExit(e,t){this.stopped||(this.suppressedInstances.has(e)?this.pendingUnexpectedExits.set(e,t):this.applyUnexpectedLocalExit(e,t))}applyUnexpectedLocalExit(e,t){const n=this.options.state.requireInstance(e);if("local"!==this.options.state.requireRuntime(n.runtimeId).type)return;this.restoredInstances.delete(e);const i=this.options.nowMs?.()??Date.now(),s=this.unexpectedExitRetries.get(e),r=this.options.crashStableWindowMs??3e4,o=s&&i-s.lastExitAt<r?s.attempt+1:1;this.unexpectedExitRetries.set(e,{attempt:o,lastExitAt:i});const a=this.options.retryBaseDelayMs??1e3,c=1===o?0:Math.min(this.options.retryMaxDelayMs??3e4,a*2**Math.min(o-2,10)),d=t instanceof Error?t.message:String(t);this.restoreErrors.set(e,{message:d,attempt:o,nextAttemptAt:i+c}),this.options.state.applyInstanceLifecycle(e,{type:"runtime-exited",error:t}),this.requestCycle(c)}async restoreManagedInstances(){if(this.stopped)return;const{state:e}=this.options;for(const t of e.listInstances()){if(this.stopped)return;"docker"===e.requireRuntime(t.runtimeId).type&&["provisioning","starting"].includes(t.status)&&"ready"!==t.imageProvisioning?.phase&&this.options.provisionImage(t)}const t=e.listInstances().filter(t=>{if(this.restoredInstances.has(t.id))return!1;if(this.suppressedInstances.has(t.id))return!1;const n=e.requireRuntime(t.runtimeId);if("local"===n.type){const e=this.restoreErrors.get(t.id);return(fl.has(t.status)||"failed"===t.status)&&(!e||e.nextAttemptAt<=(this.options.nowMs?.()??Date.now()))}return"docker"===n.type&&yl(t)});await Promise.all(t.map(async t=>{if(this.stopped)return;const n=async()=>{if(this.stopped)return;const n=e.listInstances().find(e=>e.id===t.id);if(!n)return;if(!this.isRestoreCandidate(n))return;const i=this.restoreErrors.get(n.id);try{const t=this.options.restoreInstance(n.id);this.activeRestores.set(n.id,t);try{await t}finally{this.activeRestores.get(n.id)===t&&this.activeRestores.delete(n.id)}if(this.stopped||this.suppressedInstances.has(n.id))return;if(await this.options.autoImport(e.requireInstance(n.id)),this.stopped||this.suppressedInstances.has(n.id))return;if(this.restoreErrors.get(n.id)!==i)return;if(!this.markRestored(n.id))throw new Error(`Restored instance ${n.id} did not reach a recoverable running state.`)}catch(t){if(this.stopped||this.suppressedInstances.has(n.id))return;"local"===e.requireRuntime(n.runtimeId).type&&e.applyInstanceLifecycle(n.id,{type:"start-failed",error:t});const i=t instanceof Error?t.message:String(t),s=this.restoreErrors.get(n.id),r=(s?.attempt??0)+1,o=this.options.retryBaseDelayMs??1e3,a=Math.min(this.options.retryMaxDelayMs??3e4,o*2**Math.min(r-1,10)),c=(this.options.nowMs?.()??Date.now())+a;this.restoreErrors.set(n.id,{message:i,attempt:r,nextAttemptAt:c}),s?.message===i&&s.attempt===r||this.options.warn({instanceId:n.id,action:"restore",runtimeId:n.runtimeId,error:i,attempt:r,nextAttemptAt:new Date(c).toISOString()},"node instance restore failed; recovery will retry")}};await(this.options.runInstanceOperation?.(t.id,n)??n())}))}isRestoreCandidate(e){if(this.restoredInstances.has(e.id)||this.suppressedInstances.has(e.id))return!1;const t=this.options.state.requireRuntime(e.runtimeId);if("local"===t.type){const t=this.restoreErrors.get(e.id);return(fl.has(e.status)||"failed"===e.status)&&(!t||t.nextAttemptAt<=(this.options.nowMs?.()??Date.now()))}return"docker"===t.type&&yl(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)&&!Xo(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(Il(e))}async runCycle(){await this.restoreManagedInstances(),this.stopped||await this.recoverManagedInstances()}runAndContinue(){if(this.stopped)return;const e=this.runCycle().catch(e=>this.options.error({error:e},"node agent startup recovery cycle failed"));this.activeCycle=e,e.finally(()=>{this.activeCycle===e&&(this.activeCycle=void 0),this.cycleRequested?(this.cycleRequested=!1,this.cycleRequestDelayMs=void 0,this.scheduleNext()):this.scheduleNext()})}scheduleNext(){if(this.stopped)return;const e=this.options.nowMs?.()??Date.now(),t=new Map(this.options.state.listInstances().map(e=>[e.id,e])),n=[...this.restoreErrors.entries()].reduce((e,[n,i])=>{const s=t.get(n);return!s||this.restoredInstances.has(n)||this.suppressedInstances.has(n)||"local"!==this.options.state.requireRuntime(s.runtimeId).type?e:fl.has(s.status)||"failed"===s.status?Math.min(e,i.nextAttemptAt):e},Number.POSITIVE_INFINITY),i=Math.min(this.options.intervalMs??1e4,Math.max(0,n-e));this.timer=setTimeout(()=>{this.timer=void 0,this.runAndContinue()},i),this.timer.unref?.()}requestCycle(e=0){if(this.started&&!this.stopped){if(this.activeCycle)return this.cycleRequested=!0,void(this.cycleRequestDelayMs=void 0===this.cycleRequestDelayMs?e:Math.min(this.cycleRequestDelayMs,e));this.timer&&clearTimeout(this.timer),this.timer=setTimeout(()=>{this.timer=void 0,this.runAndContinue()},e),this.timer.unref?.()}}}function bl(e,t){const n=new URL(t.tunnelUrl);n.searchParams.set("nodeId",t.nodeId);const i=t.secret?Hd({nodeId:t.nodeId,keyId:t.keyId,secret:t.secret,method:"GET",pathWithQuery:`${n.pathname}${n.search}`}):{},s=new p(n,{headers:i}),r=new Map,o=new Map,a=new Map;let c;s.on("error",i=>{e.log.warn({nodeId:t.nodeId,tunnelUrl:`${n.origin}${n.pathname}`,error:i instanceof Error?i.message:String(i)},"node agent reverse tunnel connection failed")});const d=e=>{const n=e.startsWith("/")?e:`/${e}`,i="function"==typeof t.port?t.port():t.port,s=new URL(`/api/node-agent${n}`,`http://127.0.0.1:${i}`);return s.protocol="ws:",s},l=(e,n,i,s={})=>{const r=e.startsWith("/")?e:`/${e}`;return{...s,...t.secret&&t.keyId?Hd({nodeId:t.nodeId,keyId:t.keyId,secret:t.secret,method:n,pathWithQuery:`/api/node-agent${r}`,body:i}):t.token?{authorization:`Bearer ${t.token}`}:{}}},u=e=>t.secret?Hd({nodeId:t.nodeId,keyId:t.keyId,secret:t.secret,method:"GET",pathWithQuery:`${e.pathname}${e.search}`}):{},m=(e,t,n)=>{const i=r.get(e);r.delete(e),i?.upstream&&C(i.upstream,t,n),i?.tunnel&&C(i.tunnel,t,n)},h=(e,t,n=!1)=>new Promise((i,s)=>{e.send(t,{binary:n,compress:!1},e=>e?s(e):i())});s.on("open",()=>{s.send(JSON.stringify({type:"node-agent.identify",nodeId:t.nodeId,serverTime:(new Date).toISOString()})),c=e.nodeAgentEventForwarder?.addOutput(s,{legacyFallbackMs:1e3})}),s.on("close",()=>{for(const e of r.keys())m(e,1001,"Reverse tunnel disconnected.");for(const[e,t]of o)o.delete(e),t.controller.abort(),C(t.tunnel,1001,"Reverse tunnel disconnected.");for(const[e,t]of a)a.delete(e),t.abort();c?.(),c=void 0});return s.on("message",i=>{(async i=>{let c;try{c=JSON.parse(String(i))}catch{return void s.send(JSON.stringify({type:"node-agent.error",code:"INVALID_JSON"}))}const g=c&&"object"==typeof c?c:{};if("control-plane.event-subscribe"!==g.type){if("control-plane.http.open"===g.type){const i="string"==typeof g.streamId?g.streamId:"",r="string"==typeof g.route&&g.route.startsWith("/")?g.route:"/health",a=g.init&&"object"==typeof g.init?g.init:{},c=a.headers&&"object"==typeof a.headers?a.headers:{},d=wd(a.method);let m;try{m=Sn(a.body)}catch(n){return e.log.warn({nodeId:t.nodeId,messageType:g.type,streamId:i,error:n instanceof Error?n.message:String(n)},"node agent reverse tunnel request body rejected"),void s.send(JSON.stringify({type:"node-agent.error",code:"NODE_TUNNEL_REQUEST_BODY_INVALID",streamId:i}))}const f=new AbortController,y=(e=>{const t=new URL(n);return t.pathname=`${t.pathname.replace(/\/$/,"")}/http-streams/${encodeURIComponent(e)}`,t})(i),I=new p(y,{headers:u(y)});return o.set(i,{tunnel:I,controller:f}),I.on("open",async()=>{try{const e=await fetch((e=>{const n=e.startsWith("/")?e:`/${e}`,i="function"==typeof t.port?t.port():t.port;return new URL(`/api/node-agent${n}`,`http://127.0.0.1:${i}`)})(r),{method:d,headers:l(r,d,m,c),body:Buffer.isBuffer(m)?new Uint8Array(m):m,signal:f.signal});if(await h(I,JSON.stringify({type:"node-agent.http.head",streamId:i,status:e.status,headers:Object.fromEntries(e.headers.entries())})),e.body){const t=e.body.getReader();for(;;){const{done:e,value:n}=await t.read();if(e)break;await h(I,Buffer.from(n),!0)}}await h(I,JSON.stringify({type:"node-agent.http.end",streamId:i})),I.close(1e3,"HTTP stream completed.")}catch(e){I.readyState===p.OPEN&&(await h(I,JSON.stringify({type:"node-agent.http.error",streamId:i,message:e instanceof Error?e.message:String(e)})).catch(()=>{}),I.close(1011,"HTTP stream failed."))}finally{o.delete(i)}}),I.on("close",()=>{f.abort(),o.delete(i)}),void I.on("error",()=>f.abort())}if("control-plane.http.cancel"===g.type){const e="string"==typeof g.streamId?g.streamId:"",t=o.get(e);if(!t)return;return o.delete(e),t.controller.abort(),void C(t.tunnel,1e3,"string"==typeof g.reason?g.reason:"HTTP stream canceled.")}if("control-plane.websocket.open"===g.type){const e="string"==typeof g.streamId?g.streamId:"",t="string"==typeof g.route?g.route:"",i=Array.isArray(g.protocols)?g.protocols.filter(e=>"string"==typeof e):void 0;try{const o=l(t,"GET",void 0),a=i?.length?new p(d(t),i,{headers:o}):new p(d(t),{headers:o}),c=(e=>{const t=new URL(n);return t.pathname=`${t.pathname.replace(/\/$/,"")}/streams/${encodeURIComponent(e)}`,t})(e),m=new p(c,{headers:u(c)});r.set(e,{upstream:a,tunnel:m,close:(e=1e3,t="")=>{C(a,e,t),C(m,e,t)}}),a.on("open",()=>{s.send(JSON.stringify({type:"node-agent.websocket.open",streamId:e,protocol:a.protocol}))}),function(e,t,n={}){const i=n.pendingFrameLimit??256,s=n.maxFrameBytes??8388608,r=n.maxTotalBytes??1073741824,o=n.maxBufferedBytes??16777216;let a=!1,c=T(t);const d=[],l=[];let u,p=0,m=0,h=0;const g=e=>Buffer.isBuffer(e)||e instanceof ArrayBuffer||ArrayBuffer.isView(e)?e.byteLength:Buffer.byteLength("string"==typeof e?e:String(e),"utf8"),f=(i,o)=>{const a=g(o);return h+=a,n.onFrame?.(i,a),!(a>s||h>r)||(C(e,1009,"WebSocket bridge traffic limit exceeded."),C(t,1009,"WebSocket bridge traffic limit exceeded."),!1)},y=()=>{u&&(clearTimeout(u),u=void 0)},I=(n,i)=>{const s=i.bytes;if((n.bufferedAmount??0)+s>o)return C(e,1013,"WebSocket bridge consumer is too slow."),C(t,1013,"WebSocket bridge consumer is too slow."),!1;try{return function(e,t){e.send(t.data,{binary:t.isBinary,compress:!1})}(n,i),!0}catch{return C(e,1011,"WebSocket bridge send failed."),C(t,1011,"WebSocket bridge send failed."),!1}},A=(n,s,r)=>{if(s.length>=i)return C(e,1011,"WebSocket bridge pending frame limit exceeded."),void C(t,1011,"WebSocket bridge pending frame limit exceeded.");const a="upstream"===n?p:m;if((("upstream"===n?t:e).bufferedAmount??0)+a+r.bytes>o)return C(e,1013,"WebSocket bridge consumer is too slow."),void C(t,1013,"WebSocket bridge consumer is too slow.");s.push(r),"upstream"===n?p+=r.bytes:m+=r.bytes};n.upstreamOpenTimeoutMs&&!c&&(u=setTimeout(()=>{c||a||(C(e,1011,"Upstream websocket did not open."),C(t))},n.upstreamOpenTimeoutMs)),e.on("open",()=>O(e,l,t=>I(e,t),e=>{m-=e.bytes})),t.on("open",()=>{y(),c=!0,n.onUpstreamOpen?.(),O(t,d,e=>I(t,e),e=>{p-=e.bytes})}),e.on("message",(e,n=!1)=>{if(!f("client-to-upstream",e))return;const i={data:e,isBinary:Boolean(n),bytes:g(e)};T(t)?I(t,i):A("upstream",d,i)}),t.on("message",(t,n=!1)=>{if(!f("upstream-to-client",t))return;const i={data:t,isBinary:Boolean(n),bytes:g(t)};T(e)?I(e,i):A("client",l,i)}),t.on("close",(t,i)=>{y(),n.onUpstreamClose?.(t,i),(c||a||!n.onUpstreamCloseBeforeOpen?.())&&C(e,t,i)}),t.on("error",t=>{n.onUpstreamError?.(t),(c||a||!n.onUpstreamErrorBeforeOpen?.(t))&&C(e)}),e.on("close",(e,i)=>{y(),a=!0,n.onClientClose?.(e,i),C(t,e,i)}),e.on("error",e=>{y(),a=!0,n.onClientError?.(e),C(t,1011,"WebSocket bridge client failed.")})}(m,a,{pendingFrameLimit:256,upstreamOpenTimeoutMs:1e4,onClientClose:()=>{r.delete(e)},onClientError:t=>{r.delete(e),s.send(JSON.stringify({type:"node-agent.websocket.error",streamId:e,message:t instanceof Error?t.message:String(t)}))},onUpstreamClose:(t,n)=>{r.delete(e);const i=k(t),o=_(n);s.send(JSON.stringify({type:"node-agent.websocket.close",streamId:e,...void 0===i?{}:{code:i},...o?{reason:o}:{}}))},onUpstreamError:t=>{r.delete(e),s.send(JSON.stringify({type:"node-agent.websocket.error",streamId:e,message:t instanceof Error?t.message:String(t)}))}})}catch(t){s.send(JSON.stringify({type:"node-agent.websocket.error",streamId:e,message:t instanceof Error?t.message:String(t)}))}return}if("control-plane.websocket.close"===g.type){const e="string"==typeof g.streamId?g.streamId:"";return void m(e,"number"==typeof g.code?g.code:1e3,"string"==typeof g.reason?g.reason:"")}if("control-plane.request.cancel"===g.type){const e="string"==typeof g.requestId?g.requestId:"";return a.get(e)?.abort(),void a.delete(e)}if("control-plane.request"===g.type){const n="string"==typeof g.requestId?g.requestId:"",i=g.init&&"object"==typeof g.init?g.init:{},r="string"==typeof g.route&&g.route.startsWith("/")?g.route:"/health",o=i.headers&&"object"==typeof i.headers?i.headers:{},c=wd(i.method);let d;try{d=Sn(i.body)}catch(i){return e.log.warn({nodeId:t.nodeId,messageType:g.type,requestId:n,error:i instanceof Error?i.message:String(i)},"node agent reverse tunnel request body rejected"),void s.send(JSON.stringify({type:"node-agent.response",requestId:n,status:400,error:{code:"NODE_TUNNEL_REQUEST_BODY_INVALID",message:"Reverse tunnel request body does not match the negotiated protocol."}}))}const u=new AbortController;a.set(n,u);try{const t=await e.inject({method:c,url:`/api/node-agent${r}`,headers:l(r,c,d,o),payload:d,signal:u.signal});if(u.signal.aborted)return;s.send(JSON.stringify({type:"node-agent.response",requestId:n,status:t.statusCode,headers:t.headers,body:t.body}))}catch(e){if(u.signal.aborted)return;s.send(JSON.stringify({type:"node-agent.response",requestId:n,status:502,error:{code:"NODE_AGENT_REVERSE_INJECT_FAILED",message:e instanceof Error?e.message:String(e)}}))}finally{a.delete(n)}}}else e.nodeAgentEventForwarder?.setOutputSubscription?.(s,g.aiSessionTransient,g.eventEnvelopeVersion)})(i).catch(n=>{e.log.warn({nodeId:t.nodeId,error:n instanceof Error?n.message:String(n)},"node agent reverse tunnel message rejected");try{s.send(JSON.stringify({type:"node-agent.error",code:"INVALID_TUNNEL_MESSAGE"}))}catch{}})}),s}function vl(e,t){return Number.isFinite(e)&&Number(e)>0?Number(e):t}function wl(e){if(!e.length)return;const t=[...e].sort((e,t)=>e-t);return t[Math.ceil(.95*t.length)-1]}function Sl(e){return e.unref?.(),e}class El{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=vl(e.connectTimeoutMs,1e4),this.handshakeTimeoutMs=vl(e.handshakeTimeoutMs,1e4),this.heartbeatIntervalMs=vl(e.heartbeatIntervalMs,25e3),this.heartbeatTimeoutMs=vl(e.heartbeatTimeoutMs,15e3),this.heartbeatMissThreshold=Math.max(1,Math.floor(vl(e.heartbeatMissThreshold,2))),this.stableThresholdMs=vl(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=Sl(this.setTimeoutFn(()=>this.timeout("connect"),this.connectTimeoutMs))}opened(){this.stopped||(this.clearTimer("connectTimer"),this.setPhase("handshaking"),this.handshakeTimer=Sl(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=Sl(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:wl(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=Sl(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 Nl(e){const t=new URL($d,e);return t.protocol="https:"===t.protocol?"wss:":"ws:",t.toString()}const zl=new Set(["linux","darwin","win32","freebsd","openbsd","aix","sunos"]);function Tl(e){return zl.has(e)?e:"unknown"}function _l(e){return!0===e.managedArtifacts}class kl{managedArtifacts=!0;executor;runCommand;platform;arch;constructor(e,t,n,i){this.executor=e,this.runCommand=t,this.platform=n,this.arch=i}artifactTarget(e){return this.executor.inspectRuntimeTarget(e?.instance.runtime.containerName)}resolveInstanceWeb(e){return this.executor.resolveInstanceWeb(e)}async installRuntime(e,t){const n=e.instance.runtime.containerName;if(!n)throw Object.assign(new Error(`Instance ${e.instance.id} does not have a Docker container.`),{code:"INSTANCE_RUNTIME_INSTALL_FAILED"});await this.executor.installRuntimeReleaseWithRecovery({containerName:n,expectedContainerId:e.instance.runtime.containerId,artifactPath:t.archivePath,identity:t.identity})}async inspectRuntime(e,t){const n=e.instance.runtime.containerName;if(!n)return!1;const i=function(e,t){return e.packageName===t.packageName&&e.version===t.version&&e.platform===t.platform&&e.arch===t.arch&&e.formatVersion===t.formatVersion&&e.launcherAbi===t.launcherAbi&&e.entrypoint===t.entrypoint&&e.sha256===t.sha256}(await this.executor.inspectRuntimeVersion(n),t),s=e.instance.runtime.labels["task-handoff.bootstrap-backup"];return i&&s&&await this.executor.removeBootstrapBackup(s,e.instance.id),i}start(e){return this.executor.start(e)}stop(e){return this.executor.stop(e)}restart(e){return this.executor.restart(e,e.instance.runtime.containerId)}delete(e,t){return this.executor.delete(e,t)}async check(e){try{const t=(await this.runCommand("docker",["version","--format","{{.Server.Version}}"],{timeoutMs:5e3})).stdout.trim();return{status:"online",capabilities:{...e.capabilities,daemon:{status:"online",hostPlatform:Tl(this.platform),...t?{serverVersion:t}:{}}}}}catch(t){return{status:"offline",capabilities:{...e.capabilities,daemon:{status:"offline",hostPlatform:Tl(this.platform),error:t instanceof Error?t.message:String(t)}}}}}}class Cl{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(_l)}async stopAll(){await(this.local.stopAll?.())}}const Ol="task-handoff.local-process-nonce",Rl=1e3,xl=1e4,Pl=2e3;function Dl(e,t){try{e?.(t)}catch{}}function Ml(e){return e.runtime.port?`http://127.0.0.1:${e.runtime.port}`:void 0}async function jl(e,t){try{const n=await fetch(`${e}/api/internal/node-agent/process-identity`,{headers:{authorization:`Bearer ${t}`},signal:AbortSignal.timeout(Rl)});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 Ll(e,t){if(P.processStartIdentity(e)!==t)return!1;try{process.kill(e,"SIGTERM")}catch{return!0}const n=Date.now()+xl;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()+Pl;for(;Date.now()<i;){try{process.kill(e,0)}catch{return!0}await new Promise(e=>setTimeout(e,50))}return!1}function Fl(e,t){return Object.assign(new Error(t),{statusCode:503,code:"LOCAL_INSTANCE_STOP_UNCONFIRMED",instanceId:e.id})}async function $l(e){return!await function(e){return new Promise(t=>{const n=m.createConnection({host:"127.0.0.1",port:e}),i=e=>{n.removeAllListeners(),n.destroy(),t(e)};n.once("connect",()=>i(!0)),n.once("error",()=>i(!1)),n.setTimeout(250,()=>i(!1))})}(e)&&new Promise(t=>{const n=m.createServer();n.once("error",()=>t(!1)),n.listen({host:"127.0.0.1",port:e,exclusive:!0},()=>n.close(()=>t(!0)))})}const Ul=$l;function Vl(e,t){return null!==e.exitCode||null!==e.signalCode?Promise.resolve(!0):new Promise(n=>{const i=setTimeout(()=>{e.off("exit",s),n(null!==e.exitCode||null!==e.signalCode)},t);i.unref();const s=()=>{clearTimeout(i),n(!0)};e.once("exit",s)})}async function Hl(e,t=1e4,n=2e3,i){if(await Vl(e,t))return;Dl(i,{stage:"graceful-timeout",pid:e.pid,timeoutMs:t});let s=!1;if(null===e.exitCode&&null===e.signalCode&&(e.kill("SIGKILL"),s=!0,Dl(i,{stage:"force-signal-sent",pid:e.pid,signal:"SIGKILL"})),!await Vl(e,n))throw Dl(i,{stage:"force-exit-unconfirmed",pid:e.pid,signal:"SIGKILL",timeoutMs:n}),Object.assign(new Error(`Controlled instance process pid=${e.pid??"unknown"} did not exit after SIGKILL.`),{statusCode:503,code:"LOCAL_INSTANCE_PROCESS_EXIT_UNCONFIRMED",pid:e.pid});s&&Dl(i,{stage:"force-exit-confirmed",pid:e.pid,signal:"SIGKILL"})}class Bl{children=new Map;readyChildren=new WeakSet;expectedExits=new WeakSet;lifecycleReporters=new WeakMap;lockPath;onUnexpectedExit;onUnexpectedExitError;constructor(e,t,n){this.lockPath=e,this.onUnexpectedExit=t,this.onUnexpectedExitError=n}track(e,t,n){this.children.set(e,t),n&&this.lifecycleReporters.set(t,n),t.once("exit",(n,i)=>{if(this.release(e,t),this.readyChildren.has(t)&&!this.expectedExits.has(t)){const s={instanceId:e,pid:t.pid,code:n,signal:i},r=e=>{try{this.onUnexpectedExitError?.(e,s)}catch{}};try{Promise.resolve(this.onUnexpectedExit?.(s)).catch(r)}catch(e){r(e)}}})}markReady(e,t){return this.children.get(e)===t&&null===t.exitCode&&null===t.signalCode&&(this.readyChildren.add(t),!0)}release(e,t){this.children.get(e)===t&&this.children.delete(e)}async stop(e){const t=this.children.get(e.id);if(t){this.expectedExits.add(t);const n=this.lifecycleReporters.get(t);return t.killed||(t.kill("SIGTERM"),Dl(n,{stage:"graceful-signal-sent",pid:t.pid,signal:"SIGTERM"})),this.children.delete(e.id),void await Hl(t,xl,Pl,n)}const i=await async function(e){const t=Ml(e),n=e.runtime.labels?.[Ol];if(!t||!n||!e.registrationToken)return;const i=await jl(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(Rl)})).ok?i:void 0}catch{return}}(e);if(i){const t=Ml(e),n=Date.now()+xl;for(;t&&Date.now()<n;){if(!await jl(t,e.registrationToken))return;await new Promise(e=>setTimeout(e,50))}const s=t?await jl(t,e.registrationToken):void 0;if(s&&s.instanceId===i.instanceId&&s.pid===i.pid&&s.processNonce===i.processNonce&&s.startIdentity===i.startIdentity&&s.startIdentity&&await Ll(s.pid,s.startIdentity))return;throw Fl(e,`Controlled instance ${e.id} accepted shutdown but its exit could not be confirmed.`)}const s=function(e=function(){const e="win32"===process.platform?c.tmpdir():"/tmp";return n.join(e,`task-handoff-local-controlled-instance-${function(){const e=process.getuid?.();return void 0!==e?String(e):c.userInfo().username.replace(/[^a-zA-Z0-9_.-]/g,"_")}()}.lock`)}()){return $(e)}(this.lockPath),r=await async function(e){const t=Ml(e);if(t)try{const[n,i]=await Promise.all([fetch(`${t}/api/instance/status`,{signal:AbortSignal.timeout(Rl)}),fetch(`${t}/api/diagnostics`,{signal:AbortSignal.timeout(Rl)})]);if(!n.ok||!i.ok)return;const s=await n.json(),r=await i.json(),o=r.data?.runtime?.pid;if(s.data?.id!==e.id||"controlled"!==s.data.controlMode||"number"!=typeof o||!Number.isInteger(o)||o<=0)return;const a=P.processStartIdentity(o);return a?{pid:o,startIdentity:a}:void 0}catch{return}}(e);if(r){if(await Ll(r.pid,r.startIdentity))return;throw Fl(e,`Legacy controlled instance ${e.id} did not exit after termination.`)}if(s?.instanceId===e.id&&H(s))throw Fl(e,`Local controlled instance ${e.id} is still owned by pid ${s.pid}, but its process identity could not be verified.`)}async waitUntilHealthy(e,t,n,i,s=function(e=process.env.TASK_HANDOFF_LOCAL_PROCESS_READY_TIMEOUT_MS){const t=Number(e);return Number.isFinite(t)&&t>0?t:3e4}()){const r=Date.now()+s;for(;Date.now()<r;){if(null!==n.exitCode||null!==n.signalCode)return!1;const s=await jl(e,i);if(s&&s.instanceId===t.instanceId&&s.pid===t.pid&&s.processNonce===t.processNonce&&s.startIdentity===t.startIdentity)return!0;await new Promise(e=>setTimeout(e,100))}return!1}async stopAll(){const e=Array.from(this.children.values());for(const t of e){this.expectedExits.add(t);const e=this.lifecycleReporters.get(t);t.killed||(t.kill("SIGTERM"),Dl(e,{stage:"graceful-signal-sent",pid:t.pid,signal:"SIGTERM"}))}this.children.clear(),await Promise.all(e.map(e=>Hl(e,xl,Pl,this.lifecycleReporters.get(e))))}}async function ql(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 Kl{runCommand;paths;nodeAgentUrl;processSupervisor;async resolveInstanceWeb(e){const t=e.instance.runtime.port;if(!t)throw Object.assign(new Error(`Instance ${e.instance.id} does not have a node-owned local runtime port.`),{statusCode:409,code:"INSTANCE_RUNTIME_ENDPOINT_UNAVAILABLE"});return`http://127.0.0.1:${t}`}commandOverride;lockPath;constructor(e,t,n,i,s,r,o){this.runCommand=e,this.paths=t,this.nodeAgentUrl=n,this.commandOverride=i,this.lockPath=s,this.processSupervisor=new Bl(s,r,o)}async start(e){await this.processSupervisor.stop(e.instance);const i=function(e){if("local-folder"!==e.source.type){const e=new Error("Localhost runtime currently supports local folder sources only.");throw Object.assign(e,{statusCode:400,code:"LOCAL_RUNTIME_REQUIRES_LOCAL_FOLDER"}),e}return n.resolve(e.source.path)}(e.instance),s=e.instance.runtime.port,r=!!s&&await $l(s),o="allocate"===process.env.TASK_HANDOFF_LOCAL_INSTANCE_PORT_CONFLICT;if(s&&!r&&!o)throw Object.assign(new Error(`Local controlled instance port 127.0.0.1:${s} is already in use.`),{statusCode:409,code:"LOCAL_INSTANCE_PORT_IN_USE"});const a=s&&r?s:await async function(){const e=Number(process.env.TASK_HANDOFF_LOCAL_INSTANCE_PORT_START||19e3),t=Number.isInteger(e)&&e>0?e:19e3;for(let e=t;e<t+1e3&&e<=65535;e+=1)if(await Ul(e))return e;throw Object.assign(new Error(`No free localhost port found in range ${t}-${Math.min(t+999,65535)}.`),{statusCode:503,code:"LOCAL_INSTANCE_PORT_UNAVAILABLE"})}(),u=n.join(this.paths.dataDir,"local-instances",e.instance.id),p=n.join(u,"logs");t.mkdirSync(p,{recursive:!0,mode:448}),t.chmodSync(u,448),t.chmodSync(p,448);const[m,...h]=function(e){if(e)return e;const i=n.resolve(process.cwd(),"bin","task-handoff.js");if(t.existsSync(i))return[process.execPath,i,"web"];throw Object.assign(new Error("The bundled controlled-instance command is unavailable."),{statusCode:500,code:"LOCAL_CONTROLLED_COMMAND_MISSING"})}(this.commandOverride),g=[...h,"--host","127.0.0.1","--port",String(a)],f=d.randomUUID(),y=n.join(p,"controlled-instance.out.log"),I=n.join(p,"controlled-instance.err.log");Do(y),Do(I);const A=t.mkdtempSync(function(e,t=process.platform,i=c.tmpdir()){const s="darwin"===t?"/private/tmp":i,r=d.createHash("sha256").update(e).digest("hex").slice(0,12);return n.join(s,`th-git-${r}-`)}(e.instance.id));t.chmodSync(A,448);const b=t.openSync(y,"a",384),v=t.openSync(I,"a",384),w=l.spawn(m,g,{cwd:i,detached:!1,stdio:["ignore",b,v],env:{...process.env,TASK_HANDOFF_CONTROL_MODE:"controlled",TASK_HANDOFF_RUNTIME_KIND:"local",TASK_HANDOFF_CONTROLLED_INSTANCE_VERSION:Nc(),...this.lockPath?{TASK_HANDOFF_LOCAL_CONTROLLED_INSTANCE_LOCK_PATH:this.lockPath}:{},TASK_HANDOFF_NODE_AGENT_URL:this.nodeAgentUrl(),TASK_HANDOFF_INSTANCE_ID:e.instance.id,TASK_HANDOFF_INSTANCE_NAME:e.instance.name,TASK_HANDOFF_REGISTRATION_TOKEN:e.instance.registrationToken||"",TASK_HANDOFF_PROJECT_ID:e.project.id,TASK_HANDOFF_NODE_ID:e.node.id,TASK_HANDOFF_RUNTIME_ID:e.runtime.id,TASK_HANDOFF_LOCAL_PROCESS_NONCE:f,TASK_HANDOFF_WORKSPACE:i,TASK_HANDOFF_WORKSPACE_MODE:"local-bind",TASK_HANDOFF_DATA_DIR:u,TASK_HANDOFF_LOG_DIR:p,TASK_HANDOFF_APP_SESSION_PERSIST:"1",TASK_HANDOFF_CODEX_APP_SERVER:process.env.TASK_HANDOFF_CODEX_APP_SERVER||"1",TASK_HANDOFF_WEB_PORT:String(a),TASK_HANDOFF_WEB_HOST:"127.0.0.1",TASK_HANDOFF_GIT_CREDENTIAL_SOCKET:n.join(A,"broker.sock"),...e.modelEnv||{}}});t.closeSync(b),t.closeSync(v);try{await function(e){return new Promise((t,n)=>{const i=()=>{e.off("error",s),t()},s=t=>{e.off("spawn",i),n(t)};e.once("spawn",i),e.once("error",s)})}(w)}catch(e){t.rmSync(A,{recursive:!0,force:!0});const s=e instanceof Error?e.message:String(e);try{t.appendFileSync(n.join(p,"controlled-instance.lifecycle.log"),`[${(new Date).toISOString()}] spawn failed command=${m} cwd=${i} error=${s}\n`)}catch{}throw Object.assign(new Error(`Controlled instance process could not start with command ${m} in ${i}: ${s}`),{statusCode:500,code:"LOCAL_INSTANCE_PROCESS_SPAWN_FAILED"})}const S=n.join(p,"controlled-instance.lifecycle.log");this.processSupervisor.track(e.instance.id,w,e=>{t.appendFileSync(S,`[${(new Date).toISOString()}] shutdown stage=${e.stage} pid=${e.pid??""} signal=${e.signal??""} timeoutMs=${e.timeoutMs??""}\n`)}),w.on("error",e=>{try{t.appendFileSync(S,`[${(new Date).toISOString()}] process error pid=${w.pid??""} error=${e.message}\n`)}catch{}}),w.once("exit",(e,n)=>{t.rmSync(A,{recursive:!0,force:!0});try{t.appendFileSync(S,`[${(new Date).toISOString()}] exited pid=${w.pid??""} code=${e??""} signal=${n??""}\n`)}catch{}});const E=`http://127.0.0.1:${a}`,N=w.pid?P.processStartIdentity(w.pid):void 0;if(!(w.pid&&e.instance.registrationToken&&await this.processSupervisor.waitUntilHealthy(E,{instanceId:e.instance.id,pid:w.pid,processNonce:f,startIdentity:N},w,e.instance.registrationToken)&&this.processSupervisor.markReady(e.instance.id,w)))throw this.processSupervisor.release(e.instance.id,w),null===w.exitCode&&null===w.signalCode&&w.kill("SIGTERM"),await Hl(w),Object.assign(new Error(`Controlled instance process did not become ready for instance ${e.instance.id} on ${E}.`),{statusCode:503,code:"LOCAL_INSTANCE_PROCESS_NOT_READY"});return{status:"registering",health:"unknown",connectionStatus:"online",agentStatus:"unknown",targetStatus:"unknown",uiAccessStatus:"unknown",target:{strategy:"direct-port",status:"unknown",web:E,api:`${E}/api`},workspace:{mode:"local-bind",status:"pending",path:i},runtime:{kind:"local",workspacePath:i,pid:w.pid,port:a,labels:{...e.instance.runtime.labels,"task-handoff.runtime-kind":"local",[Ol]:f}}}}async stop(e){return await this.processSupervisor.stop(e.instance),{status:"stopped",health:"unknown",connectionStatus:"offline",agentStatus:"offline",targetStatus:"unknown",uiAccessStatus:"unknown",target:{...e.instance.target,status:"unknown"},runtime:e.instance.runtime}}async restart(e){return this.start(e)}async delete(e,t){return await this.stop(e),Hn.parse({instanceId:e.instance.id,containerDeleted:!0,completed:!0,deletedVolumes:[],retainedVolumes:[],volumeResults:[]})}async check(e){const[t,n]=await Promise.all([ql(this.runCommand,"codex"),ql(this.runCommand,"claude")]);return{status:"online",capabilities:jc({...e.capabilities,apps:{terminal:!0,codex:t,claude:n}})}}async stopAll(){await this.processSupervisor.stopAll()}}const Gl=["codex","claude"],Wl=5e3,Jl=P.processStartIdentity(process.pid);function Yl(e){const t=process.env[e]?.trim();return t||void 0}function Xl(e){const t=e.authorization;return"string"==typeof t&&t.startsWith("Bearer ")?t.slice(7).trim():void 0}function Ql(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 Zl(e){return!e.ip&&!e.socket.remoteAddress&&!e.socket.remoteFamily}async function eu(e,t,n){const i=new AbortController,s=setTimeout(()=>i.abort(),2e3);try{return(await e(`${await n(t)}/api/health`,{signal:i.signal})).ok?"reachable":"endpoint-unreachable"}catch{return"endpoint-unreachable"}finally{clearTimeout(s)}}async function tu(e,t,n,i){const s=new AbortController,r=setTimeout(()=>s.abort(),i);try{return await e(t,{...n,signal:s.signal})}finally{clearTimeout(r)}}async function nu(e,t,n,i,s){if(!t.config.autoImportAgentConfigs)return void i.diagnostic({instanceId:t.id,action:n},"node instance config auto-import skipped");if("reachable"!==t.targetStatus)return;const r=await s(t),o=Number(process.env.TASK_HANDOFF_CONFIG_AUTO_IMPORT_TIMEOUT_MS||Wl);for(const s of Gl)try{const a=await tu(e,`${r}/api/config-sync/import/${encodeURIComponent(s)}`,{method:"POST"},Number.isFinite(o)&&o>0?o:Wl);if(!a.ok){i.warn({instanceId:t.id,action:n,preset:s,statusCode:a.status},"node instance config auto-import failed");continue}i.diagnostic({instanceId:t.id,action:n,preset:s},"node instance config auto-import completed")}catch(e){i.warn({instanceId:t.id,action:n,preset:s,error:e instanceof Error?e.message:String(e)},"node instance config auto-import failed")}}async function iu(e,t,n,i,s=async e=>xd(e)){const r=t.requireInstance(n);if(t.instancePrivateConfigs.materialize(r.id,r.registrationToken,t.resolvedAssignedModelEnvironment(n)),"reachable"!==r.targetStatus)return!1;let o;try{o=await tu(e,`${await s(r)}/api/internal/model-environment`,{method:"PUT",headers:{"content-type":"application/json",authorization:`Bearer ${r.registrationToken}`},body:JSON.stringify(t.resolvedAssignedModelEnvironment(n))},Wl)}catch(e){return i?.({instanceId:n,targetWeb:r.target.web,error:e instanceof Error?e.message:String(e)},"node instance model environment live sync deferred"),!1}return!!o.ok||(i?.({instanceId:n,targetWeb:r.target.web,statusCode:o.status},"node instance model environment live sync deferred"),!1)}async function su(e,t,n,i,s,r,o="request",a){const c=e.requireInstance(i);if(c.imageProvisioning&&"ready"!==c.imageProvisioning.phase&&"docker"===e.requireRuntime(c.runtimeId).type)return s.diagnostic({instanceId:i,action:"start",reason:o,runtimeId:c.runtimeId,imageId:c.imageSelection?.imageId,imagePhase:c.imageProvisioning.phase},"node instance start queued until image provisioning completes"),e.controlledInstances.put(_s.parse({...c,status:"starting",updatedAt:ee()}));s.diagnostic({instanceId:i,action:"start",reason:o,runtimeId:c.runtimeId,imageId:c.imageSelection?.imageId},"node instance start requested");const d=e.applyInstanceLifecycle(i,{type:"start-requested"}),l=t.forRuntime(e.requireRuntime(d.runtimeId)),u=await l.start({...e.context(d),signal:a}),p=u.target?.web?await eu(n,_s.parse({...d,...u,target:{...d.target,...u.target},workspace:u.workspace?{...d.workspace,error:void 0,...u.workspace}:d.workspace,runtime:u.runtime?{...d.runtime,...u.runtime}:d.runtime,updatedAt:ee()}),r):"unknown",m=e.applyInstanceLifecycle(i,{type:"runtime-lifecycle-completed",baseline:d,observation:{...u,target:u.target?{...u.target,status:p}:void 0,workspace:u.workspace?{error:void 0,...u.workspace}:void 0,targetStatus:p,uiAccessStatus:p}});return s.diagnostic({instanceId:i,action:"start",reason:o,status:m.status,connectionStatus:m.connectionStatus,targetStatus:m.targetStatus,targetWeb:m.target.web,containerName:m.runtime.containerName},"node instance start completed"),m}async function ru(e={}){const i=e.token||process.env.TASK_HANDOFF_NODE_AGENT_TOKEN,c=Number(e.port||process.env.TASK_HANDOFF_NODE_AGENT_PORT||"8091"),d=`http://127.0.0.1:${c}`,l=e.containerUrl||process.env.TASK_HANDOFF_NODE_AGENT_CONTAINER_URL,u=xo(e.dataDir),m=e.remoteSecret||process.env.TASK_HANDOFF_NODE_AGENT_REMOTE_SECRET,g=e.remoteKeyId||process.env.TASK_HANDOFF_NODE_AGENT_REMOTE_KEY_ID,f=new ul(u),y=f.resolveNodeId(e.nodeId||process.env.TASK_HANDOFF_NODE_ID),I=e.connectionMode||("local-ipc"===process.env.TASK_HANDOFF_NODE_AGENT_CONNECTION_MODE?"local-ipc":"local-loopback"),A=e.ipcPath||process.env.TASK_HANDOFF_NODE_AGENT_IPC_PATH||jo(u.dataDir),b="local-ipc"===I?`ipc://${encodeURIComponent(A)}`:d,v=e.platform||process.platform,S=e.arch||process.arch,E=new Fc(u,y,d,l,c,v);E.node.connectionMode=I,E.node.controlEndpoint=b,E.node.endpoint=b,E.init();const N=e.dockerCommandRunner||qs,T=new Gs(N,e.dockerTerminalCommandRunner),_=new sr(N,{publishHost:"127.0.0.1",imageService:T});let k;const C=new Cl(new kl(_,N,v,S),new Kl(e.dockerCommandRunner||qs,u,()=>E.localNodeAgentUrl,function(){const e=process.env.TASK_HANDOFF_LOCAL_CONTROLLED_COMMAND_ARGV?.trim();if(!e){const e=process.env.TASK_HANDOFF_LOCAL_CONTROLLED_COMMAND?.trim();return e?e.split(/\s+/):void 0}let t;try{t=JSON.parse(e)}catch{throw Object.assign(new Error("TASK_HANDOFF_LOCAL_CONTROLLED_COMMAND_ARGV must be valid JSON."),{code:"LOCAL_CONTROLLED_COMMAND_INVALID"})}if(!Array.isArray(t)||!t.length||t.some(e=>"string"!=typeof e||!e))throw Object.assign(new Error("TASK_HANDOFF_LOCAL_CONTROLLED_COMMAND_ARGV must be a non-empty string array."),{code:"LOCAL_CONTROLLED_COMMAND_INVALID"});return t}(),e.localControlledInstanceLockPath||process.env.TASK_HANDOFF_LOCAL_CONTROLLED_INSTANCE_LOCK_PATH,e=>k.handleUnexpectedLocalExit(e.instanceId,new Error(`Local controlled instance exited unexpectedly (pid=${e.pid??"unknown"}, code=${e.code??"none"}, signal=${e.signal??"none"}).`)),(e,t)=>B.log.error({error:e,instanceId:t.instanceId,pid:t.pid},"local controlled instance exit recovery failed"))),O=async e=>xd(e,await C.forRuntime(E.requireRuntime(e.runtimeId)).resolveInstanceWeb(E.context(e))),R=e.updateCommandRunner||e.dockerCommandRunner||qs,x=e.fetchImpl||fetch,P=new Map,D=async e=>{const t=E.requireInstance(e);if(!fn(t.capabilities).features.aiSessionPersistenceSettings||"reachable"!==t.targetStatus||!t.registrationToken)return!1;const n=function(e){return yn(e).retentionSettings}(t.capabilities),i=function(e){return!0===yn(e).fileSizeLimitSettings}(t.capabilities),s=`${t.processIncarnationId||"unknown"}:${t.config.aiSessionHistoryLimit}:${n?t.config.aiSessionAttachmentRetentionDays:"unsupported"}:${i?t.config.aiSessionMaxFileAttachmentBytes:"unsupported"}`;if(P.get(e)===s)return!0;let r;try{r=await tu(x,`${await O(t)}/api/internal/ai-session-persistence-settings`,{method:"PUT",headers:{"content-type":"application/json",authorization:`Bearer ${t.registrationToken}`},body:JSON.stringify({historyLimit:t.config.aiSessionHistoryLimit,...n?{attachmentRetentionDays:t.config.aiSessionAttachmentRetentionDays}:{},...i?{maxFileAttachmentBytes:t.config.aiSessionMaxFileAttachmentBytes}:{}})},Wl)}catch(t){return se.warn({instanceId:e,error:t instanceof Error?t.message:String(t)},"node instance AI session persistence settings live sync deferred"),!1}return r.ok?(P.set(e,s),!0):(se.warn({instanceId:e,statusCode:r.status},"node instance AI session persistence settings live sync deferred"),!1)},M=new Ko({cacheDir:n.join(u.dataDir,"runtime-artifacts"),fetchImpl:x}),j=e.resolveRuntimeArtifactRelease||((e,t,n)=>Go(e,t,n,x)),L=async(t,n,i)=>{const s=await n.artifactTarget(i);if(e.resolveRuntimeArtifact)return e.resolveRuntimeArtifact(t,s.platform,s.arch);const r=await j(t,s.platform,s.arch);if(r.identity.launcherAbi>s.launcherAbi)throw Object.assign(new Error(`Runtime requires launcher ABI ${r.identity.launcherAbi}, but ${s.platform}-${s.arch} provides ABI ${s.launcherAbi}.`),{code:"INSTANCE_BASE_RUNTIME_INCOMPATIBLE",retryable:!1});return M.resolve(r.identity,r.source)},F=e=>C.forRuntime(E.requireRuntime(e.runtimeId)),$=e=>{const t=F(e);return _l(t)?t:void 0},U=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})},V=e=>Boolean($(e)),H=(e,t)=>{const n=E.context(e);return L(t,U(e),n)},B=r({logger:e.logger??!0}),q=new Mo(u,{logger:(e,t)=>B.log.warn(t,e)}),K=()=>E.listInstances().map(e=>e.id),G=()=>{try{q.run(K())}catch(e){B.log.warn({error:e},"node-agent persistence maintenance failed")}};G();const W=setInterval(()=>{G()},216e5);W.unref();const J=setInterval(()=>{(()=>{try{q.capNodeAgentLogs(),q.capActiveInstanceLogs(K())}catch(e){B.log.warn({error:e},"node-agent open log maintenance failed")}})()},6e4);J.unref();const Y={requests:0,active:0,completed:0,aborted:0,limitRejected:0,responseBytes:0,totalDurationMs:0,maxResponseBytes:Td()};B.decorate("nodeAgentState",E),await B.register(o,{options:z});const X=new oo(E,i,{logger:B.log,safetyIntervalMs:Number(process.env.TASK_HANDOFF_EVENT_CONNECTION_SAFETY_INTERVAL_MS)||void 0}),Q=new Wo(E.controlledInstances,Nc,{isInstalled:async(e,t)=>{const n=await H(e,t),i=await U(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(_s.parse({...t,runtime:{...t.runtime,labels:n},updatedAt:ee()}))}return i},beginDrain:async e=>{try{const t=await async function(e,t,n=async e=>xd(e)){const i=await n(t);if(t.registrationToken&&(await tu(e,`${i}/api/internal/node-agent/drain`,{method:"POST",headers:{authorization:`Bearer ${t.registrationToken}`}},1e4)).ok)return{requested:t.apps.runningCount,failures:[]};const s=await tu(e,`${i}/api/apps/sessions`,{method:"GET",headers:{"cache-control":"no-cache"}},5e3);if(!s.ok)throw new Error(`Could not list app sessions for runtime drain (HTTP ${s.status}).`);const r=function(e){if(!e||"object"!=typeof e||Array.isArray(e))return[];const t=e.data;if(Array.isArray(t))return t;if(!t||"object"!=typeof t||Array.isArray(t))return[];const n=t.snapshot,i=(n&&"object"==typeof n&&!Array.isArray(n)?n:t).sessions;return Array.isArray(i)?i:[]}(await s.json()).flatMap(e=>{if(!e||"object"!=typeof e||Array.isArray(e))return[];const t=e;return"running"===t.status&&"string"==typeof t.id&&t.id?[t.id]:[]}),o=await Promise.all(r.map(async t=>{try{const n=await tu(e,`${i}/api/apps/sessions/${encodeURIComponent(t)}/stop`,{method:"POST"},5e3);return n.ok?void 0:{sessionId:t,error:`HTTP ${n.status}`}}catch(e){return{sessionId:t,error:e instanceof Error?e.message:String(e)}}}));return{requested:r.length,failures:o.filter(e=>Boolean(e))}}(x,e,O);t.failures.length?B.log.warn({instanceId:e.id,requested:t.requested,failures:t.failures},"runtime convergence could not stop every app session"):B.log.info({instanceId:e.id,requested:t.requested},"runtime convergence requested app session drain")}catch(t){B.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=>xd(e)){return!!t.registrationToken&&(await tu(e,`${await n(t)}/api/internal/node-agent/resume`,{method:"POST",headers:{authorization:`Bearer ${t.registrationToken}`}},5e3)).ok}(x,e,O)&&B.log.info({instanceId:e.id},"runtime convergence released app session drain")}catch(t){B.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=U(e);await n.installRuntime(E.context(e),await H(e,t))},restart:async e=>{const t=F(e),n=E.applyInstanceLifecycle(e.id,{type:"convergence-restart-requested"}),i=await t.restart(E.context(n)),s=_s.parse({...n,...i,target:i.target?{...n.target,...i.target}:n.target,runtime:i.runtime?{...n.runtime,...i.runtime}:n.runtime,updatedAt:ee()}),r=await eu(x,s,O);E.applyInstanceLifecycle(e.id,{type:"runtime-lifecycle-completed",baseline:n,observation:{...i,target:i.target?{...i.target,status:r}:void 0,targetStatus:r,uiAccessStatus:r}})},onForcedDrain:e=>B.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=>{X.publishInstanceLifecycle(e),E.updateJobs.reconcileRollouts(E.listInstances(),Nc())}),X.start(),B.decorate("nodeAgentEventForwarder",X);const Z=new fo(N,()=>E.listInstances().filter(e=>"docker"===E.requireRuntime(e.runtimeId).type),e=>X.publish("instance.metrics.snapshot",e,{instanceId:e.instanceId}));Z.start(),B.decorate("nodeAgentRuntimeMetrics",Z);const te=(le=process.env.TASK_HANDOFF_DIAGNOSTIC_LOGS,["1","true","yes","on"].includes(String(le||"").trim().toLowerCase())),ne=new Bd(f,y,m,g),ie=(e,t)=>{te&&B.log.info(e,t)},se={diagnostic:ie,warn:(e,t)=>B.log.warn(e,t)},re=new gd,oe=new bd(E.environmentTemplates,E.instancePrivateConfigs,_,e=>E.requireInstance(e),e=>E.requireRuntime(e),(e,t)=>re.run(e,t),e=>E.listInstances().some(t=>t.environmentTemplateOrigin?.imageId===e)),ae=async(e,t,n=()=>!0,i)=>{try{if(!n())return E.requireInstance(e);let s=E.requireInstance(e);"failed"===s.runtimeVersion?.phase&&V(s)&&(s=E.controlledInstances.put(_s.parse({...s,ready:!1,runtimeVersion:Tc(Jo(s)),updatedAt:ee()})));const r=E.requireRuntime(s.runtimeId);await su(E,C,x,e,se,O,t,i);const o=E.requireInstance(e);if("docker"===r.type&&o.imageProvisioning&&"ready"!==o.imageProvisioning.phase)return X.syncNow(),o;if(!n())return E.requireInstance(e);k.markRestored(e);let a=E.requireInstance(e);if(V(a)){try{a=await Q.schedule(e,{startRequested:!0})}catch(n){a=E.requireInstance(e),se.warn({instanceId:e,action:"runtime.converge",reason:t,error:n instanceof Error?n.message:String(n)},"node instance runtime convergence failed after start")}"matched"!==a.runtimeVersion?.phase&&a.runtimeVersion?.error&&se.warn({instanceId:e,action:"runtime.converge",reason:t,error:a.runtimeVersion.error},"node instance started with pending runtime convergence")}return n()?(await nu(x,a,"start",se,O),X.syncNow(),a):E.requireInstance(e)}catch(n){throw E.applyInstanceLifecycle(e,{type:"start-failed",error:n}),X.syncNow(),se.warn({instanceId:e,action:"start",reason:t,error:n instanceof Error?n.message:String(n)},"node instance start failed"),n}},ce=new yd(E,T,{sync:()=>X.syncNow(),diagnostic:se.diagnostic,warn:se.warn,publish:(e,t,n)=>X.publish(e,t,{instanceId:n}),runInstanceOperation:(e,t)=>re.run(e,t)}),de=e=>{const t=re.intent(e.id);ce.provision(e,async()=>{await ae(e.id,"image-ready",()=>re.isIntentCurrent(e.id,t),re.signal(e.id,t)).catch(()=>{})})};var le;k=new Al({state:E,runtimeAdapters:C,convergence:Q,restoreInstance:e=>su(E,C,x,e,se,O,"restore"),autoImport:e=>nu(x,e,"start",se,O),provisionImage:de,stopImageProvisioning:()=>ce.stop(),usesManagedArtifact:V,warn:se.warn,error:(e,t)=>B.log.error(e,t),runInstanceOperation:(e,t)=>re.run(e,t)});const ue=new gl({nodeId:y,jobs:E.updateJobs,runCommand:R,currentRuntimeVersion:Nc,listInstances:()=>E.listInstances(),resolveRuntimeArtifacts:async e=>(await(async e=>{const t=new Map;for(const e of C.managedAdapters()){const n=await e.artifactTarget();t.set(`${n.platform}-${n.arch}`,{adapter:e})}for(const e of E.listInstances()){const n=$(e);if(!n)continue;const i=E.context(e),s=await n.artifactTarget(i);t.set(`${s.platform}-${s.arch}`,{adapter:n,context:i})}return(await Promise.all([...t.values()].map(({adapter:t,context:n})=>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:w&&"SCRIPT"===w.tagName.toUpperCase()&&w.src||new URL("cli.js",document.baseURI).href)?n.dirname(s.fileURLToPath("undefined"==typeof document?require("url").pathToFileURL(__filename).href:w&&"SCRIPT"===w.tagName.toUpperCase()&&w.src||new URL("cli.js",document.baseURI).href)):__dirname,managedUpdateSupport:e.managedUpdateSupport||(n=>"linux"!==(e.platform||process.platform)?{supported:!1,reason:"Managed server updates require Linux and systemd."}:"function"==typeof process.getuid&&0!==process.getuid()?{supported:!1,reason:"Managed server updates require the node agent to run as root."}:t.existsSync("/run/systemd/system")?"@task-handoff/server"!==n.packageName||process.env.TASK_HANDOFF_CONTROL_PLANE_HEALTH_URL?.trim()?process.env.TASK_HANDOFF_NODE_AGENT_IPC_PATH?.trim()?{supported:!0}:{supported:!1,reason:"Managed server updates require the node-agent IPC readiness endpoint."}:{supported:!1,reason:"Managed server updates require a local control-plane health URL."}:{supported:!1,reason:"Managed server updates require an active systemd host."})});return B.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);(te||i.statusCode>=500)&&(i.statusCode>=500?B.log.error.bind(B.log):B.log.warn.bind(B.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}:{}}})}),B.addHook("preHandler",async e=>{const t=ne.verify(e);if(t){if(f.isRevokedPairing(t)&&"/api/node-agent/pairing/current"!==e.url.split("?")[0]){const e=new Error("The node agent pairing used for this request has been revoked.");throw Object.assign(e,{statusCode:401,code:"NODE_AGENT_HMAC_KEY_REVOKED"}),e}e.nodeAgentAuthKeyId=t}else if(Zl(e)){if(i&&Xl(e.headers)!==i){const e=new Error("Invalid node agent token.");throw Object.assign(e,{statusCode:401,code:"NODE_AGENT_UNAUTHORIZED"}),e}}else if("/api/node-agent/pairing/complete"!==e.url.split("?")[0]&&!function(e){const t=e.split("?")[0];return/^\/api\/node-agent\/instances\/[^/]+\/(register|heartbeat)$/.test(t)||/^\/api\/node-agent\/instances\/[^/]+\/git-credentials\//.test(t)}(e.url)){if(ne.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 Ql(e.ip)||Ql(e.socket.remoteAddress)||!e.ip&&!e.socket.remoteAddress&&!e.socket.remoteFamily}(e)){const e=new Error("Local node agent access is only accepted from loopback or local IPC connections.");throw Object.assign(e,{statusCode:401,code:"NODE_AGENT_LOCAL_TOKEN_REQUIRES_LOOPBACK"}),e}if(i&&Xl(e.headers)!==i){const e=new Error("Invalid node agent token.");throw Object.assign(e,{statusCode:401,code:"NODE_AGENT_UNAUTHORIZED"}),e}}}),B.addHook("onClose",async()=>{clearInterval(W),clearInterval(J),Z.stop(),X.stop(),await k.stop()}),B.decorate("nodeAgentRestoreManagedInstances",()=>k.restoreManagedInstances()),B.decorate("nodeAgentRecoverManagedInstances",()=>k.recoverManagedInstances()),B.decorate("nodeAgentStartRecoverySupervisor",()=>k.start()),B.get("/api/node-agent/health",async()=>{return{data:{ok:!0,role:"node-agent",process:{pid:process.pid,...Jl?{startIdentity:Jl}:{}},listener:{host:"127.0.0.1",port:E.currentListenerPort},nodeId:y,platform:Tl(v),arch:process.arch,protocolVersion:an,capabilities:{modelEndpointProbe:!0,aiSessionHistoryLimit:!0,aiSessionAttachmentRetention:!0,aiSessionFileAttachmentLimit:!0,folderPlaces:!0,localFolderNameUpdate:!0,managedGitCredentials:{registry:!0,runtimeBroker:!0,workspaceProvisioning:{docker:!0,kubernetes:!1,local:!1}}},build:(e="node-agent",{component:e,packageName:"@task-handoff/node-agent",packageVersion:Nc(),protocolVersion:an,buildId:Yl("TASK_HANDOFF_BUILD_ID"),builtAt:Yl("TASK_HANDOFF_BUILT_AT"),gitCommit:Yl("TASK_HANDOFF_GIT_COMMIT"),imageRef:Yl("TASK_HANDOFF_IMAGE_REF"),imageDigest:Yl("TASK_HANDOFF_IMAGE_DIGEST")}),instanceProxy:{...Y},eventTransport:X.eventTransportHealth(),serverTime:(new Date).toISOString()}};var e}),function(e,t){e.get("/api/node-agent/settings/external-listener",async e=>({data:t(e).current()})),e.patch("/api/node-agent/settings/external-listener",async e=>({data:await t(e).update(e.body)}))}(B,e=>{if(!Zl(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(!B.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 B.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)}))}(B,ue,E.updateJobs),function(e,t){const{identity:n,nodeId:i,fetchImpl:s}=t;e.post("/api/node-agent/pairing/invites",async(e,t)=>{const s=n.createPairingInvite(Xd.parse(e.body||{}));return t.code(201).send({data:{nodeId:i,joinToken:s.token,expiresAt:s.expiresAt}})}),e.post("/api/node-agent/pairing/complete",async(e,t)=>{const s=n.completePairingInvite(Qd.parse(e.body));return t.code(201).send({data:{nodeId:i,keyId:s.keyId,secret:s.secret,pairedAt:s.pairedAt}})}),e.get("/api/node-agent/control-plane-pairings",async e=>({data:n.listControlPlanePairings(e.nodeAgentAuthKeyId)})),e.delete("/api/node-agent/control-plane-pairings/:keyId",async e=>{const t=pl.parse(e.params.keyId);return{data:{deleted:n.deleteControlPlanePairing(t,e.nodeAgentAuthKeyId)}}}),e.delete("/api/node-agent/pairing/current",async e=>({data:n.revokeCurrentControlPlanePairing(e.nodeAgentAuthKeyId||"")})),e.get("/api/node-agent/control-plane-connections",async()=>({data:n.listControlPlaneConnections().map(e=>({...e,...t.reverseTunnels()?.state(e.id)||{status:e.enabled?"connecting":"disabled"}}))})),e.delete("/api/node-agent/control-plane-connections/:connectionId",async e=>{const i=pl.parse(e.params.connectionId),s=n.deleteControlPlaneConnection(i);return s&&t.reverseTunnels()?.connectConfigured(),{data:{deleted:s}}}),e.post("/api/node-agent/control-plane-connections",async(e,r)=>{const o=Zd.parse(e.body),a=function(e){const t=new URL(e);if("http:"!==t.protocol&&"https:"!==t.protocol){const e=new Error("Control-plane URL must use http or https.");throw Object.assign(e,{statusCode:400,code:"NODE_AGENT_REMOTE_CONTROL_PLANE_URL_INVALID"}),e}return t.toString().replace(/\/$/,"")}(o.controlPlaneUrl);return n.runControlPlaneConnectionOperation(a,async()=>{const e=n.stageControlPlaneConnection({url:a,...o.controlPlaneName?{name:o.controlPlaneName}:{},enabled:!1!==o.activate});let c;try{c=await async function(e,t,n){const i=await e(new URL("/api/node-join/complete",t).toString(),{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(n)}),s=await i.json().catch(()=>({}));if(!i.ok){const e=new Error(s.error?.message||`Control-plane node join failed with HTTP ${i.status}.`);throw Object.assign(e,{statusCode:i.status,code:s.error?.code||"NODE_AGENT_REMOTE_JOIN_FAILED"}),e}return s.data||{}}(s,a,{joinToken:o.joinToken,nodeId:i,nodeName:t.nodeName(),keyId:e.pairing.keyId,secret:e.pairing.secret,pairedAt:e.pairing.pairedAt})}catch(t){throw n.rollbackControlPlaneConnection(e),t}const d=n.commitControlPlaneConnection(e,{name:o.controlPlaneName||("string"==typeof c.name&&c.name?c.name:void 0)});let l,u=d.connection.enabled?"saved":"disabled";const p=t.reverseTunnels();if(p)try{p.connectConfigured(),d.connection.enabled&&(u="connecting")}catch(e){u="failed",l=e instanceof Error?e.message:String(e)}return r.code(201).send({data:{pairing:n.listControlPlanePairings().find(e=>e.keyId===d.pairing.keyId),connection:d.connection,tunnel:{status:u,...l?{error:l}:{}}}})})})}(B,{identity:f,nodeId:y,nodeName:()=>E.node.name,fetchImpl:x,reverseTunnels:()=>B.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(pd.parse(e.body))})),e.patch("/api/node-agent/runtimes/:id",async e=>({data:t.updateRuntime(e.params.id,md.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(dd.parse(e.query))})),e.post("/api/node-agent/local-folders",async(e,n)=>n.code(201).send({data:t.createLocalFolder(ad.parse(e.body))})),e.patch("/api/node-agent/local-folders/:id",async e=>({data:t.updateLocalFolder(e.params.id,cd.parse(e.body))})),e.delete("/api/node-agent/local-folders/:id",async e=>({data:{deleted:t.deleteLocalFolder(e.params.id)}}))}(B,{listRuntimes:()=>E.nodeRuntimes.list(),createRuntime:e=>E.createRuntime(e),updateRuntime:(e,t)=>E.updateRuntime(e,t),deleteRuntime:e=>E.deleteRuntime(e),checkRuntime:async e=>{const t=E.requireRuntime(e);return E.checkRuntime(e,C.forRuntime(t))},listLocalFolders:()=>E.localFolders.list(),listFolderPlaces:ko,listFolderTree:Oo,createLocalFolder:e=>E.createLocalFolder(e),updateLocalFolder:(e,t)=>E.updateLocalFolder(e,t),deleteLocalFolder:e=>E.localFolders.delete(e)}),function(e,t,n,i){e.get("/api/node-agent/models",async()=>({data:t.list()})),e.post("/api/node-agent/models",async(e,n)=>n.code(201).send({data:t.create($i.parse(e.body))})),e.post("/api/node-agent/models/discover",async e=>{const n=Yc.parse(e.body);return{data:await $c(i,{...n,key:t.resolveProbeKey(n.existingModelId,n.key)})}}),e.post("/api/node-agent/models/test",async e=>{const n=Xc.parse(e.body);return{data:await Uc(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=Vi.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,Ui.parse(e.body))})),e.delete("/api/node-agent/models/:id",async e=>({data:{deleted:t.delete(e.params.id)}})),e.put("/api/node-agent/instances/:id/model-assignment",async e=>{const i=e.params.id,s=t.assign(i,Hi.parse(e.body));return await n(i),{data:s}})}(B,E.modelRegistry,e=>iu(x,E,e,se.warn,O),x),function(e,t){const n=new Qc(t.gitCredentials);e.addHook("onClose",async()=>n.close()),e.put("/api/node-agent/git-credentials/:credentialId",async e=>{const n=nd.parse(e.params),i=Wa.parse(e.body);if(i.credential.id!==n.credentialId)throw Object.assign(new Error("Credential payload identity mismatch."),{code:"GIT_CREDENTIAL_IDENTITY_MISMATCH",statusCode:409});return{data:t.gitCredentials.putPayload(i).credential}}),e.delete("/api/node-agent/git-credentials/:credentialId",async e=>({data:{deleted:t.gitCredentials.removePayload(nd.parse(e.params).credentialId)}})),e.get("/api/node-agent/instances/:id/git-credential-authorizations",async e=>{const{id:n}=id.parse(e.params);return t.requireInstance(n),{data:t.gitCredentials.getAuthorizationSet(n)}}),e.put("/api/node-agent/instances/:id/git-credential-authorizations",async e=>{const{id:n}=id.parse(e.params);t.requireInstance(n);const i=Ja.parse(e.body);if(i.instanceId!==n)throw Object.assign(new Error("Git credential authorization identity mismatch."),{code:"GIT_CREDENTIAL_AUTHORIZATION_IDENTITY_MISMATCH",statusCode:409});return{data:t.gitCredentials.putAuthorizationSet(i)}}),e.post("/api/node-agent/instances/:id/git-credentials/https",async e=>{const{id:i}=id.parse(e.params);t.authenticateInstance(i,rd(e.headers));const s=Ya.parse(e.body);return{data:Xa.parse(n.resolveHttps(i,s.remoteUrl))}}),e.post("/api/node-agent/instances/:id/git-credentials/ssh/prepare",async e=>{const{id:i}=id.parse(e.params);t.authenticateInstance(i,rd(e.headers));const s=Qa.parse(e.body);return{data:Za.parse(await n.prepareSsh(i,s.remoteUrl))}}),e.post("/api/node-agent/instances/:id/git-credentials/ssh/agent",async e=>{const{id:i}=id.parse(e.params);t.authenticateInstance(i,rd(e.headers));const s=ec.parse(e.body);return{data:tc.parse(await n.exchangeAgentFrame(i,s.invocationId,s.frame))}}),e.delete("/api/node-agent/instances/:id/git-credentials/ssh/:invocationId",async e=>{const{id:i,invocationId:s}=sd.parse(e.params);return t.authenticateInstance(i,rd(e.headers)),{data:{deleted:n.release(s,i)}}})}(B,E),function(e,t){e.get("/api/node-agent/environment-templates",async()=>({data:t.list()})),e.get("/api/node-agent/environment-templates/:id",async e=>({data:Yn.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)}))}(B,oe),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(ld.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,ud.parse(e.body));return await t.afterUpdate(n),{data:n}}),e.post("/api/node-agent/instances/:id/register",async(e,n)=>{const i=e.params.id,s=t.sanitizeReport(i,"register",e.body),r=t.register(i,js.parse(s),hd(e.headers));return t.afterReport(r,"register"),n.code(201).send({data:r})}),e.post("/api/node-agent/instances/:id/heartbeat",async e=>{const n=e.params.id,i=t.sanitizeReport(n,"heartbeat",e.body),s=t.heartbeat(n,Ls.parse(i),hd(e.headers));return t.afterReport(s,"heartbeat"),{data:s}})}(B,{list:()=>E.listInstances(),create:e=>"template"===e.environmentSource?.type?oe.runTemplateOperation(e.environmentSource.environmentTemplateId,()=>E.createInstance(e)):E.createInstance(e),retryImageProvisioning:e=>ce.retry(e),update:(e,t)=>{const n=E.requireInstance(e);return E.controlledInstances.put(_s.parse({...n,...t,...t.config?{config:{...n.config,...t.config}}:{},updatedAt:ee()}))},register:(e,t,n)=>E.registerInstance(e,t,n),heartbeat:(e,t,n)=>E.heartbeatInstance(e,t,n),sanitizeReport:(e,t,n)=>{const i=n&&"object"==typeof n&&!Array.isArray(n)?n.protocolVersion:void 0;if("string"!=typeof i||i===an)return n;const s=({field:n,action:s})=>B.log.warn({instanceId:e,report:t,protocolVersion:i,expectedProtocolVersion:an,field:n,action:s},"cross-version controlled instance report sanitized");return"register"===t?function(e,t){if(!e||"object"!=typeof e||Array.isArray(e))return e;const n=e,i=["instanceId","projectId","source","nodeId","runtimeId","imageSelection","instanceVersion","protocolVersion","build","controlMode","capabilities","appInventory","target","workspace","registrationToken","processIncarnationId"],s=new Set([...i,"imageId"]);for(const e of Object.keys(n))s.has(e)||t?.({field:e,action:"ignored"});return Object.prototype.hasOwnProperty.call(n,"imageId")&&t?.({field:"imageId",action:"migrated"}),{...Ms(n,i),imageSelection:qn(n.imageSelection,n.imageId)}}(n,s):function(e,t){if(!e||"object"!=typeof e||Array.isArray(e))return e;const n=["status","health","protocolVersion","build","capabilities","appInventory","apps","aiSessions","triggers","workspace","target","processIncarnationId"],i=new Set(n);for(const n of Object.keys(e))i.has(n)||t?.({field:n,action:"ignored"});return Ms(e,n)}(n,s)},afterCreate:e=>{X.syncNow(),e.imageProvisioning&&de(e)},afterImageRetry:e=>{X.syncNow(),de(e)},afterUpdate:async e=>{X.syncNow(),await D(e.id)},afterReport:(e,t)=>{X.syncNow(),D(e.id),"register"===t?ie({instanceId:e.id,action:t,protocolVersion:e.protocolVersion,build:e.build,targetStatus:e.targetStatus,targetStrategy:e.target.strategy},"node instance registered"):ie({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"),!V(e)||e.ready&&"matched"===e.runtimeVersion?.phase||Q.schedule(e.id).catch(n=>B.log.error({instanceId:e.id,error:n},`runtime convergence after ${t} failed`))}}),B.get("/api/node-agent/events",{websocket:!0},(e,t)=>{const n=e;n.send(JSON.stringify({type:"node-agent.events.connected",nodeId:y,serverTime:(new Date).toISOString()}));const i=t.query,s=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,t.eventEnvelopeVersion)}catch{}}),n.on("close",s),n.on("error",s)}),B.get("/api/node-agent/docker/images",async()=>({data:await yr(e.dockerCommandRunner)})),B.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 Z.snapshot(t)}}),function(e,t,n,i,s,r=new gd){const o=e=>r.intent(e),a=e=>Promise.resolve(i.cancel(e)).then(()=>({ok:!0}),e=>({ok:!1,error:e})),c=(e,t)=>{if(!r.isIntentCurrent(e,t))throw Object.assign(new Error(`Instance operation for ${e} was superseded by stop or delete.`),{statusCode:409,code:"INSTANCE_OPERATION_SUPERSEDED"})},d=(e,t)=>{const n=r.signal;return"function"==typeof n?n.call(r,e,t):void 0},l=(e,n)=>{if(n){if(n.instanceId!==e)throw Object.assign(new Error(`Git provisioning belongs to ${n.instanceId}, not ${e}.`),{code:"GIT_WORKSPACE_PROVISIONING_INSTANCE_MISMATCH",statusCode:409});t.setGitWorkspaceProvisioning(n)}},u=(e,n)=>{if(!n)return e;const i=t.gitWorkspaceProvisioningStatus(e.id);return"consumed"===i?.status&&i.operationId===n.operationId?{instance:e,gitWorkspaceProvisioningOperationId:n.operationId}:e};e.post("/api/node-agent/instances/:id/start",async e=>{const t=fd.parse(e.body),n=e.params.id,i=o(n);return r.run(n,async()=>(c(n,i),l(n,t.gitWorkspaceProvisioning),s.allowRecovery(n),{data:u(await s.start(n,()=>r.isIntentCurrent(n,i),d(n,i)),t.gitWorkspaceProvisioning)}))}),e.post("/api/node-agent/instances/:id/runtime/reconcile",async e=>{const n=e.params.id;fd.parse(e.body);const a=o(n);return r.run(n,async()=>{c(n,a);const e=t.requireInstance(n);t.putInstance(_s.parse({...e,ready:!1,runtimeVersion:Tc(Jo(e)),updatedAt:ee()})),c(n,a);const r=await i.schedule(n,{startRequested:!["created","stopped"].includes(e.status),resumeCancelled:!0});return c(n,a),s.sync(),{data:r}})}),e.post("/api/node-agent/instances/:id/stop",async e=>{const i=e.params.id;t.requireInstance(i),t.discardGitWorkspaceProvisioning(i),r.invalidate(i);const o=a(i);return r.run(i,async()=>{const e=t.requireInstance(i);t.applyLifecycle(i,{type:"stop-requested"});try{await s.suppressRecovery(i);const e=await o;if("error"in e)throw e.error;const r=t.requireInstance(i);s.diagnostic({instanceId:i,action:"stop",runtimeId:r.runtimeId,containerName:r.runtime.containerName},"node instance stop requested"),await n.forRuntime(t.requireRuntime(r.runtimeId)).stop(t.context(r))}catch(n){try{t.applyLifecycle(i,{type:"stop-failed",baseline:e}),s.sync()}finally{s.allowRecovery(i)}throw n}const r=t.applyLifecycle(i,{type:"stop-completed"});return s.completeSuppressedRecovery(i),s.sync(),s.diagnostic({instanceId:i,action:"stop",status:r.status,connectionStatus:r.connectionStatus,containerName:r.runtime.containerName},"node instance stop completed"),{data:r}})}),e.post("/api/node-agent/instances/:id/restart",async e=>{const a=e.params.id,d=fd.parse(e.body),p=o(a);return r.run(a,async()=>{c(a,p),l(a,d.gitWorkspaceProvisioning),s.allowRecovery(a);let e=t.requireInstance(a);if(s.isManaged(e)&&(!e.ready||"matched"!==e.runtimeVersion?.phase)){"failed"===e.runtimeVersion?.phase&&(e=t.putInstance(_s.parse({...e,runtimeVersion:Tc(Jo(e)),updatedAt:ee()}))),c(a,p);const n=await i.schedule(a,{startRequested:!0});return c(a,p),s.sync(),{data:u(n,d.gitWorkspaceProvisioning)}}s.diagnostic({instanceId:a,action:"restart",runtimeId:e.runtimeId,imageId:e.imageSelection?.imageId,containerName:e.runtime.containerName},"node instance restart requested");const r=await n.forRuntime(t.requireRuntime(e.runtimeId)).restart(t.context(e));let o=t.applyLifecycle(a,{type:"runtime-lifecycle-completed",baseline:e,observation:{...r,target:r.target?{...e.target,...r.target}:void 0}});s.markRestarted(a),c(a,p);const m=_s.parse({...o,updatedAt:ee()}),h=await s.probe(m);return c(a,p),o=t.applyLifecycle(a,{type:"runtime-lifecycle-completed",baseline:o,observation:{target:{...o.target,status:h},targetStatus:h,uiAccessStatus:h}}),await s.autoImport(o),s.sync(),s.diagnostic({instanceId:a,action:"restart",status:o.status,connectionStatus:o.connectionStatus,targetStatus:o.targetStatus,targetWeb:o.target.web,containerName:o.runtime.containerName},"node instance restart completed"),{data:u(o,d.gitWorkspaceProvisioning)}})}),e.post("/api/node-agent/instances/:id/delete",async e=>{const i=e.params.id,o=Un.parse(e.body);t.requireInstance(i),r.invalidate(i);const c=a(i);return r.run(i,async()=>{const e=t.requireInstance(i);"deleting"!==e.status&&t.applyLifecycle(i,{type:"stop-requested"});try{await s.suppressRecovery(i);const e=await c;if("error"in e)throw e.error;const a=t.requireInstance(i);t.putInstance(_s.parse({...a,status:"deleting",ready:!1,updatedAt:ee()})),s.diagnostic({instanceId:i,action:"delete",runtimeId:a.runtimeId,containerName:a.runtime.containerName},"node instance delete requested");const d=await n.forRuntime(t.requireRuntime(a.runtimeId)).delete(t.context(a,{}),o);if(!d.completed)return s.diagnostic({instanceId:i,action:"delete",volumeResults:d.volumeResults},"node instance delete requires retry"),s.sync(),{data:d};s.diagnostic({instanceId:i,action:"delete"},"node instance delete completed");const l=t.deleteInstance(i);return l&&(s.forgetRecovery(i),r.clearIntent(i)),s.deleteMetadata(i),l&&s.retireInstanceData(i),l&&a.environmentTemplateOrigin?.imageId&&s.releaseEnvironmentImage&&await s.releaseEnvironmentImage(a.environmentTemplateOrigin.imageId).catch(e=>{s.diagnostic({instanceId:i,action:"release-environment-image",error:e instanceof Error?e.message:String(e)},"environment image cleanup deferred after instance deletion")}),s.sync(),{data:d}}catch(n){try{t.putInstance(_s.parse({...e,updatedAt:ee()})),s.sync()}finally{s.allowRecovery(i)}throw n}})})}(B,{requireInstance:e=>E.requireInstance(e),requireRuntime:e=>E.requireRuntime(e),putInstance:e=>E.controlledInstances.put(e),deleteInstance:e=>E.controlledInstances.delete(e),applyLifecycle:(e,t)=>E.applyInstanceLifecycle(e,t),context:(e,t)=>E.context(e,t),setGitWorkspaceProvisioning:e=>E.setGitWorkspaceProvisioning(e),discardGitWorkspaceProvisioning:e=>E.discardGitWorkspaceProvisioning(e),gitWorkspaceProvisioningStatus:e=>E.gitWorkspaceProvisioningStatus(e)},C,Q,{start:(e,t,n)=>ae(e,"request",t,n),sync:()=>X.syncNow(),isManaged:V,probe:e=>eu(x,e,O),autoImport:e=>nu(x,e,"restart",se,O),markRestarted:e=>k.markRestored(e),allowRecovery:e=>k.allowRecovery(e),suppressRecovery:e=>k.suppressRecovery(e),forgetRecovery:e=>k.forgetInstance(e),completeSuppressedRecovery:e=>k.completeSuppressedOperation(e),deleteMetadata:e=>{P.delete(e),E.modelRegistry.deleteInstanceMetadata(e),E.gitCredentials.removeInstance(e),E.gitCredentials.collectUnreferencedPayloads(),E.discardGitWorkspaceProvisioning(e),E.instancePrivateConfigs.delete(e)},retireInstanceData:e=>{q.retire(e)},releaseEnvironmentImage:e=>oe.releaseUnusedImage(e),diagnostic:ie},re),function(e,t){const{fetchImpl:n,metrics:i,diagnostic:s}=t;e.post("/api/node-agent/instances/:id/proxy",async(e,i)=>{const r=performance.now(),o=e.params.id,a=od.parse(e.body),c=await t.instanceBase(o),d=kd(a.path);"POST"===a.method&&"/api/apps/sessions"===d&&await t.syncModelEnvironment(o),s({instanceId:o,action:"proxy",method:a.method,path:d,instanceBase:c},"node instance proxy requested");const l=await Od(n,`${c}${d}`,{method:a.method,headers:{...a.headers},body:zd(a)},{instanceId:o,method:a.method,path:d,diagnostic:s}),u=l.headers.get("content-type")||"application/octet-stream",p=await l.text(),m=performance.now()-r,h=l.headers.get(_d)||a.headers[_d],g=function(...e){return e.map(e=>String(e||"").trim()).filter(Boolean).join(", ")}(l.headers.get("server-timing"),function(e,t){return`node_proxy;dur=${(Number.isFinite(t)?Math.max(0,t):0).toFixed(1)}`}(0,m));i.header("server-timing",g),h&&i.header(_d,h),s({instanceId:o,action:"proxy",method:a.method,path:d,statusCode:l.status,contentType:u,durationMs:m,traceId:h},"node instance proxy completed"),i.code(l.status).type(u).send(p)}),e.post("/api/node-agent/instances/:id/proxy/stream",{bodyLimit:Ed},async(e,r)=>{const o=Date.now();i.requests+=1,i.active+=1;const a=new AbortController;let c=0,d=!1,l=!1;const u=e=>{l||(l=!0,i.active-=1,i.totalDurationMs+=Date.now()-o,i.responseBytes+=c,i[e]+=1)},p=()=>{a.abort(),d&&u("aborted")};e.raw.once("aborted",p),r.raw.once("close",p);try{const o=e.params.id,l=od.parse(e.body),p=await t.instanceBase(o),m=kd(l.path);s({instanceId:o,action:"proxy.stream",method:l.method,path:m,instanceBase:p},"node instance streaming proxy requested");const g=await Od(n,`${p}${m}`,{method:l.method,headers:{...l.headers},body:zd(l),signal:a.signal},{instanceId:o,method:l.method,path:m,diagnostic:s}),f=Number(g.headers.get("content-length"));if(Number.isFinite(f)&&f>i.maxResponseBytes)return i.limitRejected+=1,a.abort(),Cd(r,i.maxResponseBytes);r.code(g.status);for(const[e,t]of Object.entries(Nd(g.headers)))r.header(e,t);if(!g.body||"HEAD"===l.method)return u("completed"),r.send();const y=new h.Transform({transform(e,t,n){if(c+=e.length,c>i.maxResponseBytes)return i.limitRejected+=1,a.abort(),void n(Object.assign(new Error("Instance proxy response limit exceeded."),{code:"INSTANCE_PROXY_RESPONSE_TOO_LARGE"}));n(null,e)}});return d=!0,y.once("end",()=>u("completed")),y.once("error",()=>u("aborted")),r.send(h.Readable.fromWeb(g.body).pipe(y))}catch(e){throw u("aborted"),e}finally{e.raw.off("aborted",p),d||u("completed")}}),e.post("/api/node-agent/instances/:id/proxy/raw",{bodyLimit:Ed},async(e,r)=>{const o=e.params.id,a=od.parse(e.body),c=await t.instanceBase(o),d=kd(a.path);s({instanceId:o,action:"proxy.raw",method:a.method,path:d,instanceBase:c},"node instance raw proxy requested");const l=await Od(n,`${c}${d}`,{method:a.method,headers:{...a.headers},body:zd(a)},{instanceId:o,method:a.method,path:d,diagnostic:s}),u=Number(l.headers.get("content-length"));if(Number.isFinite(u)&&u>i.maxResponseBytes)return i.limitRejected+=1,await(l.body?.cancel("Instance proxy response limit exceeded.").catch(()=>{})),Cd(r,i.maxResponseBytes);let p;try{p=await async function(e,t){if(!e.body)return Buffer.alloc(0);const n=[];let i=0;const s=e.body.getReader();for(;;){const{done:e,value:r}=await s.read();if(e)break;if(i+=r.byteLength,i>t)throw await s.cancel("Instance proxy response limit exceeded.").catch(()=>{}),Object.assign(new Error("Instance proxy response limit exceeded."),{code:"INSTANCE_PROXY_RESPONSE_TOO_LARGE"});n.push(Buffer.from(r))}return Buffer.concat(n,i)}(l,i.maxResponseBytes)}catch(e){if(!(e instanceof Error)||"INSTANCE_PROXY_RESPONSE_TOO_LARGE"!==e.code)throw e;return i.limitRejected+=1,Cd(r,i.maxResponseBytes)}return s({instanceId:o,action:"proxy.raw",method:a.method,path:d,statusCode:l.status,byteLength:p.length},"node instance raw proxy completed"),{data:{status:l.status,headers:Nd(l.headers),bodyBase64:p.toString("base64")}}}),e.get("/api/node-agent/instances/:id/proxy/ws/*",{websocket:!0},async(e,n)=>{const i=n.params.id,r=n.params["*"]||"",o=n.url.indexOf("?"),a=o>=0?n.url.slice(o):"";let c;try{const o=await t.instanceBase(i),d=new URL(`/${r}${a}`,`${o}/`);d.protocol="https:"===d.protocol?"wss:":"ws:";const l=function(e){const t=Object.entries(e).find(([e])=>"sec-websocket-protocol"===e.toLowerCase()),n=t?.[1],i=(Array.isArray(n)?n.join(","):"string"==typeof n?n:"").split(",").map(e=>e.trim()).filter(Boolean);return i.length?i:void 0}(n.headers);s({instanceId:i,action:"proxy.ws",path:`/${r}${a}`,upstreamUrl:d.toString(),protocols:l||[]},"node instance websocket proxy opening"),c=l?new p(d,l,{perMessageDeflate:!1}):new p(d,{perMessageDeflate:!1}),c.on("open",()=>{s({instanceId:i,action:"proxy.ws",path:`/${r}${a}`},"node instance websocket proxy opened"),e.on("message",(e,t)=>c?.readyState===p.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===p.OPEN&&e.send(n?t:t.toString(),{binary:n,compress:!1})),c.on("close",()=>{s({instanceId:i,action:"proxy.ws",path:`/${r}${a}`},"node instance websocket proxy closed"),e.close()}),c.on("error",t=>{s({instanceId:i,action:"proxy.ws",path:`/${r}${a}`,error:t instanceof Error?t.message:String(t)},"node instance websocket proxy failed"),e.close(1011,"Instance websocket proxy failed.")})}catch(t){s({instanceId:i,action:"proxy.ws",path:`/${r}${a}`,error:t instanceof Error?t.message:String(t)},"node instance websocket endpoint unavailable"),c?.close(),e.close(1011,"Instance websocket endpoint is not reachable.")}})}(B,{fetchImpl:x,metrics:Y,instanceBase:e=>O(E.requireInstance(e)),syncModelEnvironment:e=>iu(x,E,e,se.warn,O),diagnostic:ie}),B}async function ou(e){const s=xo(e.dataDir),r=function(e,i={}){return function(e,i={}){t.mkdirSync(n.dirname(e),{recursive:!0});const s=P.processStartIdentity(process.pid),r={pid:process.pid,hostname:c.hostname(),command:process.argv.join(" "),acquiredAt:(new Date).toISOString(),token:d.randomUUID(),...void 0!==i.component?{component:i.component}:{},...s?{startIdentity:s}:{},...void 0!==i.dataDir?{dataDir:i.dataDir}:{},...void 0!==i.host?{host:i.host}:{},...void 0!==i.port?{port:i.port}:{},...void 0!==i.instanceId?{instanceId:i.instanceId}:{}};for(let n=0;n<5;n+=1)try{return t.mkdirSync(e),t.writeFileSync(j(e),`${JSON.stringify({token:r.token,pid:r.pid,startIdentity:r.startIdentity,startedAt:(new Date).toISOString()})}\n`,{encoding:"utf8",mode:384,flag:"wx"}),B(e,r),{lockPath:e,owner:r,updateDetails:t=>q(e,r,t),release(){const n=U(e);n?.token===r.token&&t.rmSync(e,{recursive:!0,force:!0})}}}catch(s){if("EEXIST"!==s.code)throw s;const r=U(e);if(H(r))throw new D(e,r,i.error);if(!r&&(G(e)||Y(e)<(i.incompleteLockStaleMs??2e3))){if(n+1<5){J();continue}throw new D(e,void 0,i.error)}const o=d.randomUUID();if(!X(e,o)){if(n+1<5){J();continue}throw new D(e,U(e),i.error)}const a=U(e);if(H(a))throw W(L(e)),new D(e,a,i.error);if(r?.token&&a?.token!==r.token){W(L(e));continue}if(!Z(e,o))continue;t.rmSync(e,{recursive:!0,force:!0})}const o=U(e);throw new D(e,o,i.error)}(e,{...i,component:"node-agent",error:{label:"Node agent",code:"NODE_AGENT_ALREADY_RUNNING"}})}(function(){const e=process.env.TASK_HANDOFF_NODE_AGENT_LOCK_PATH?.trim();return e?n.resolve(e):n.join(c.tmpdir(),`task-handoff-node-agent-${process.getuid?.()??"user"}.lock`)}(),{dataDir:s.dataDir});try{const c=(o=e.host,a=e.port,Is.parse({bindScope:"0.0.0.0"===o.trim()?"all-ipv4":"loopback",port:a})),d=t.existsSync(s.settingsPath),l=function(e,t){return new pa(e.settingsPath,()=>({version:1,externalListener:t}),{schema:Pd,sanitize:Md})}(s,c);let u=l.get().externalListener;if("allocate"===process.env.TASK_HANDOFF_NODE_AGENT_PORT_CONFLICT){const e=await async function(e,t=20){for(let n=0;n<t&&e.port+n<=65535;n+=1){const t={...e,port:e.port+n};if(await jd(t))return t}throw Object.assign(new Error(`No available node-agent port found starting at ${e.port}.`),{statusCode:503,code:"NODE_AGENT_LISTENER_PORT_UNAVAILABLE"})}(u);e.port!==u.port&&(l.put({version:1,externalListener:e}),u=e)}const p=e=>{if(!r.updateDetails({dataDir:s.dataDir,host:e.host,port:e.port,instanceId:void 0}))throw new Error("Node agent singleton ownership changed while publishing listener state.")},m={...e,port:u.port},h=await ru(m),g=h.nodeAgentState;if(!g)throw new Error("Node agent state was not initialized.");const f=new ul(s).resolveNodeId(e.nodeId||process.env.TASK_HANDOFF_NODE_ID),y=function(e,t,n,i){const s=t.token||process.env.TASK_HANDOFF_NODE_AGENT_TOKEN,r=new ul(n),o=new Map;let a=!1;const c=(t,n)=>{if(a||n.retry.pending||o.get(t)!==n)return;const s=n.retry.schedule(()=>{a||o.get(t)!==n||n.socket||d(t,n)});s&&(n.status="reconnecting",n.nextRetryAt=new Date(Date.now()+s.delay).toISOString(),e.log.info({nodeId:i,tunnelUrl:new URL(n.config.tunnelUrl).origin,attempt:s.attempt,delay:s.delay},"node agent reverse tunnel reconnect scheduled"))},d=(n,r)=>{let d;r.status=r.lastDisconnectedAt?"reconnecting":"connecting",r.error=void 0,r.failureReason=void 0,r.nextRetryAt=void 0;try{d=bl(e,{...r.config,nodeId:i,port:()=>e.nodeAgentState.currentListenerPort,token:s})}catch(e){return r.status="failed",r.lastDisconnectedAt=(new Date).toISOString(),r.error=e instanceof Error?e.message:String(e),void c(n,r)}r.socket=d;const l=new El({connectTimeoutMs:t.connectTimeoutMs,handshakeTimeoutMs:t.handshakeTimeoutMs,heartbeatIntervalMs:t.heartbeatIntervalMs,heartbeatTimeoutMs:t.heartbeatTimeoutMs,heartbeatMissThreshold:t.heartbeatMissThreshold,stableThresholdMs:t.stableThresholdMs,ping:()=>d.ping(),onTimeout:e=>{o.get(n)===r&&r.socket===d&&(r.status="failed",r.failureReason=`Reverse tunnel ${e} timeout.`,r.error=r.failureReason,d.terminate())},onStable:()=>r.retry.reset()});return r.supervisor=l,l.start(),d.on("open",()=>{o.get(n)===r&&r.socket===d&&(r.status="connecting",l.opened())}),d.on("message",t=>{if(o.get(n)!==r||r.socket!==d)return;if(l.activity(),"connected"===r.status)return;let s;try{s=JSON.parse(String(t))}catch{return}const a=s&&"object"==typeof s?s.type:void 0;"control-plane.hello"!==a&&"control-plane.identified"!==a||(l.activity(),l.healthy(),r.status="connected",r.lastConnectedAt=(new Date).toISOString(),r.nextRetryAt=void 0,r.error=void 0,e.log.info({nodeId:i,tunnelUrl:new URL(r.config.tunnelUrl).origin},"node agent reverse tunnel connected"))}),d.on("pong",()=>l.pong()),d.on("close",(t,s)=>{if(o.get(n)!==r||r.socket!==d)return;l.close(),r.socket=void 0,r.lastDisconnectedAt=(new Date).toISOString();const u=`WebSocket closed${t?` (${t})`:""}${s?`: ${Buffer.isBuffer(s)?s.toString("utf8"):String(s)}`:""}`;r.error=r.failureReason||u,a||(e.log.warn({nodeId:i,tunnelUrl:new URL(r.config.tunnelUrl).origin,code:t,reason:Buffer.isBuffer(s)?s.toString("utf8"):String(s||""),error:r.error,closeOrigin:r.failureReason?"supervisor":"transport"},"node agent reverse tunnel disconnected"),c(n,r))}),d.on("error",e=>{o.get(n)===r&&r.socket===d&&(r.status="failed",r.failureReason=e instanceof Error?e.message:String(e),r.error=r.failureReason,d.terminate())}),d},l=(e,t)=>{const n=o.get(e);n?.retry.cancel(),n?.supervisor?.close();const i={config:t,retry:new no,status:"connecting"};return o.set(e,i),n?.socket?.close(1e3,"Reverse tunnel reconnecting."),d(e,i)},u=(e,t)=>e.tunnelUrl===t.tunnelUrl&&e.keyId===t.keyId&&e.secret===t.secret;return{connectConfigured:()=>{a=!1;const n=new Map,s=r.resolvedControlPlaneAccess(),c=new Set;for(const{connection:t,pairing:r}of s.connections){if(!t.enabled)continue;if(!r){e.log.warn({nodeId:i,connectionId:t.id,pairingKeyId:t.pairingKeyId},"node agent control-plane connection has no pairing");continue}const s=Nl(t.url);n.set(t.id,{tunnelUrl:s,keyId:r.keyId,secret:r.secret}),c.add(s)}const d=function(e){const t=e.controlPlaneTunnelUrl||process.env.TASK_HANDOFF_CONTROL_PLANE_TUNNEL_URL;return t?new URL(t).toString():void 0}(t);if(d&&!c.has(d)){const e=r.reverseTunnelSecret(process.env.TASK_HANDOFF_CONTROL_PLANE_URL,t.remoteSecret||process.env.TASK_HANDOFF_NODE_AGENT_REMOTE_SECRET,t.remoteKeyId||process.env.TASK_HANDOFF_NODE_AGENT_REMOTE_KEY_ID);n.set(`explicit:${d}`,{tunnelUrl:d,keyId:e?.keyId,secret:e?.secret}),c.add(d)}const p=s.hasPersistedAccess?void 0:function(){const e=process.env.TASK_HANDOFF_CONTROL_PLANE_URL;if(!e)return;const t=new URL($d,e);return t.protocol="https:"===t.protocol?"wss:":"ws:",t.toString()}();if(p&&!c.has(p)){const e=r.reverseTunnelSecret(process.env.TASK_HANDOFF_CONTROL_PLANE_URL,t.remoteSecret||process.env.TASK_HANDOFF_NODE_AGENT_REMOTE_SECRET,t.remoteKeyId||process.env.TASK_HANDOFF_NODE_AGENT_REMOTE_KEY_ID);n.set(`bootstrap:${p}`,{tunnelUrl:p,keyId:e?.keyId,secret:e?.secret})}(e=>{for(const[t,n]of o)e.has(t)||(n.retry.cancel(),n.supervisor?.close(),o.delete(t),n.socket?.close(1e3,"Reverse tunnel configuration removed."));for(const[t,n]of e){const e=o.get(t);e&&u(e.config,n)||l(t,n)}})(n)},state:e=>{const t=o.get(e);if(!t)return;const n=t.supervisor?.diagnostics();return{status:t.status,...void 0===n?.pingRttMs?{}:{pingRttMs:n.pingRttMs},...void 0===n?.pingRttP95Ms?{}:{pingRttP95Ms:n.pingRttP95Ms},consecutiveReconnects:t.retry.attempts,...t.lastConnectedAt?{lastConnectedAt:t.lastConnectedAt}:{},...t.lastDisconnectedAt?{lastDisconnectedAt:t.lastDisconnectedAt}:{},...t.nextRetryAt?{nextRetryAt:t.nextRetryAt}:{},...t.error?{error:t.error}:{}}},closeAll:()=>{a=!0;for(const e of o.values())e.retry.cancel(),e.supervisor?.close(),e.socket?.close(1001,"Node agent shutting down.");o.clear()}}}({log:h.log,inject:e=>h.inject(e),nodeAgentEventForwarder:h.nodeAgentEventForwarder,nodeAgentState:g},m,s,f);h.decorate("nodeAgentReverseTunnels",y);const I=new Ld({app:h,state:g,settings:l,config:u,source:d?"persisted":"bootstrap",onActiveListener:p});let A;h.decorate("nodeAgentListenerManager",I),function(e){let t=!1;const n=async n=>{if(!t){t=!0,y.closeAll(),A?.close();try{await e.close()}finally{process.exitCode=n?0:process.exitCode}}},i=()=>{n("SIGINT")},s=()=>{n("SIGTERM")};process.once("SIGINT",i),process.once("SIGTERM",s),e.addHook("onClose",async()=>{process.off("SIGINT",i),process.off("SIGTERM",s)})}(h),h.addHook("onClose",async()=>{A?.close(),r.release()});try{await h.ready();const r=e.ipcPath||process.env.TASK_HANDOFF_NODE_AGENT_IPC_PATH||jo(s.dataDir);A=await async function(e,s){!function(e,i=process.platform){if("win32"!==i){t.mkdirSync(n.dirname(e),{recursive:!0,mode:448});try{t.chmodSync(n.dirname(e),448)}catch{}try{t.unlinkSync(e)}catch(e){if("ENOENT"!==e.code)throw e}}}(s);const r=i.createServer((t,n)=>{e.server.emit("request",t,n)});return r.on("upgrade",(t,n,i)=>{e.server.emit("upgrade",t,n,i)}),await new Promise((e,t)=>{r.once("error",t),r.listen(s,()=>{r.off("error",t),e()})}),r}(h,r),await I.start(),y.connectConfigured(),h.nodeAgentStartRecoverySupervisor?.()}catch(e){throw await h.close(),e}}catch(e){throw r.release(),e}var o,a}const au="task-handoff-node-agent.service",cu=`/etc/systemd/system/${au}`,du="/etc/task-handoff/node-agent.env",lu=["@task-handoff/node-agent","@task-handoff/controlled-instance"];function uu(e,t,n){const i=e.run(t,n);if(0!==i.status){const e=function(e){return[e.stdout,e.stderr].filter(Boolean).map(e=>String(e).trim()).filter(Boolean).join("\n")}(i);throw new Error(`${t} ${n.join(" ")} failed${e?`:\n${e}`:""}`)}}function pu(e,t){for(const n of e.split(/\r?\n/)){const e=n.indexOf("=");if(!(e<0||n.slice(0,e).trim()!==t))return n.slice(e+1).trim()}}const mu={getuid:()=>process.getuid?.(),exists:t.existsSync,readText:e=>t.readFileSync(e,"utf8"),remove:(e,n)=>t.rmSync(e,n),run:(e,t)=>l.spawnSync(e,t,{encoding:"utf8"}),confirmDeleteData:async function(e){if(!v.stdin.isTTY||!v.stdout.isTTY)return!1;const t=b.createInterface({input:v.stdin,output:v.stdout});try{const n=await t.question(`Delete Node Agent data at ${e}? This removes identity, configuration, logs, and managed-instance metadata. Docker volumes are preserved. [y/N] `);return/^(?:y|yes)$/i.test(n.trim())}finally{t.close()}},log:e=>console.log(e)};function hu(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 gu(e){if("local-ipc"!==e&&"local-loopback"!==e)throw new Error("Connection mode must be local-ipc or local-loopback.");return e}function fu(e){const t=Number(e);if(!Number.isInteger(t)||t<=0)throw new Error("Expiry must be a positive integer.");return t}(async function(){const t=new e.Command;t.name("task-handoff-node-agent").description("Run a TaskHandoff node agent.").version(N("@task-handoff/cli")).option("--host <host>","Node agent host",process.env.TASK_HANDOFF_NODE_AGENT_HOST||"127.0.0.1").option("-p, --port <port>","Node agent port",hu,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",gu).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 ou({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",fu).option("--json","Print raw JSON output").action(async e=>{const n=t.opts(),i=e.ipcPath||n.ipcPath||process.env.TASK_HANDOFF_NODE_AGENT_IPC_PATH,s=e.dataDir||n.dataDir||process.env.TASK_HANDOFF_NODE_AGENT_DATA_DIR,r=e.endpoint?void 0:i||jo(s||Ro()),o=await async function(e){const t={"content-type":"application/json",...e.token?{authorization:`Bearer ${e.token}`}:{}},n=JSON.stringify({...e.expiresInMs?{expiresInMs:e.expiresInMs}:{}}),i=e.endpoint?await fetch(`${e.endpoint.replace(/\/$/,"")}/api/node-agent/pairing/invites`,{method:"POST",headers:t,body:n}):await Lo(e.ipcPath,"/pairing/invites",{method:"POST",headers:t,body:n}),s=await i.json().catch(()=>({}));if(!i.ok)throw new Error(s.error?.message||`Node agent pairing invite failed with HTTP ${i.status}`);const r="string"==typeof s.data?.joinToken?s.data.joinToken:"";if(!r)throw new Error("Node agent pairing invite response did not include a join token.");return{nodeId:"string"==typeof s.data?.nodeId?s.data.nodeId:"",joinToken:r,expiresAt:"string"==typeof s.data?.expiresAt?s.data.expiresAt:""}}({endpoint:e.endpoint,ipcPath:r,token:e.token,expiresInMs:e.expiresInMs});e.json?console.log(JSON.stringify(o,null,2)):(o.nodeId&&console.log(`Node: ${o.nodeId}`),console.log(`Join token: ${o.joinToken}`),o.expiresAt&&console.log(`Expires: ${o.expiresAt}`))}),t.command("connect").description("Connect this Node Agent to a reachable Control Plane.").requiredOption("--control-plane <url>","Public Control Plane base URL").requiredOption("--join-token <token>","One-time join token issued by the Control Plane").option("--control-plane-name <name>","Control Plane display name").option("--endpoint <url>","Use the Node Agent HTTP endpoint instead of its local IPC socket").option("--ipc-path <path>","Local Node Agent IPC socket path").option("--data-dir <path>","Node Agent data directory used to locate its IPC socket").option("--token <token>","Bearer token for local Node Agent access",process.env.TASK_HANDOFF_NODE_AGENT_TOKEN).option("--json","Print raw JSON output").action(async e=>{const n=t.opts(),i=e.ipcPath||n.ipcPath||process.env.TASK_HANDOFF_NODE_AGENT_IPC_PATH,s=e.dataDir||n.dataDir||process.env.TASK_HANDOFF_NODE_AGENT_DATA_DIR,r=e.endpoint?void 0:i||jo(s||Ro()),o=await async function(e){const t={"content-type":"application/json",...e.token?{authorization:`Bearer ${e.token}`}:{}},n=JSON.stringify({controlPlaneUrl:e.controlPlane,joinToken:e.joinToken,...e.controlPlaneName?{controlPlaneName:e.controlPlaneName}:{},activate:!0}),i=e.endpoint?await fetch(`${e.endpoint.replace(/\/$/,"")}/api/node-agent/control-plane-connections`,{method:"POST",headers:t,body:n}):await Lo(e.ipcPath,"/control-plane-connections",{method:"POST",headers:t,body:n}),s=await i.json().catch(()=>({}));if(!i.ok)throw new Error(s.error?.message||`Node Agent connection failed with HTTP ${i.status}`);return s.data}({controlPlane:e.controlPlane,joinToken:e.joinToken,controlPlaneName:e.controlPlaneName,endpoint:e.endpoint,ipcPath:r,token:e.token});e.json?console.log(JSON.stringify(o,null,2)):(console.log(`Control Plane: ${String(o?.connection?.url||e.controlPlane)}`),console.log(`Connection: ${String(o?.tunnel?.status||"saved")}`))}),t.command("uninstall").description("Uninstall the Node Agent service and packages; data is preserved by default.").option("--data-dir <path>","Override the installed Node Agent data directory").option("--delete-data","Delete Node Agent data without prompting").option("--keep-data","Preserve Node Agent data without prompting").action(async e=>{await async function(e,t=mu){if(e.deleteData&&e.keepData)throw new Error("--delete-data and --keep-data cannot be used together.");if(0!==t.getuid())throw new Error("Run this command as root so the Node Agent service and packages can be removed.");const i=t.exists(du)?t.readText(du):"",s=function(e,t){if(e.dataDir?.trim())return n.resolve(e.dataDir.trim());if(t.exists(du)){const e=pu(t.readText(du),"TASK_HANDOFF_NODE_AGENT_DATA_DIR");if(e)return n.resolve(e)}return n.resolve(Ro())}(e,{exists:e=>e===du&&Boolean(i),readText:()=>i});if(s===n.parse(s).root)throw new Error(`Refusing to use a filesystem root as the Node Agent data directory: ${s}`);const r=pu(i,"TASK_HANDOFF_NPM_COMMAND")||process.env.TASK_HANDOFF_NPM_COMMAND||"npm";if(t.exists(cu)){const e=t.readText(cu);if(!/^ExecStart=\S*task-handoff-node-agent(?:\s|$)/m.test(e))throw new Error(`Refusing to remove ${au} because it is not owned by a standalone Node Agent installation.`);uu(t,"systemctl",["disable","--now",au]),t.remove(cu,{force:!0}),uu(t,"systemctl",["daemon-reload"])}uu(t,r,["uninstall","--global",...lu]),t.remove(du,{force:!0}),t.log("TaskHandoff Node Agent service and packages were removed.");const o=!!e.deleteData||!e.keepData&&await t.confirmDeleteData(s);return o?(t.remove(s,{recursive:!0,force:!0}),t.log(`Node Agent data was deleted from ${s}.`)):t.log(`Node Agent data was preserved at ${s}.`),{dataDir:s,dataDeleted:o}}(e)}),await t.parseAsync(process.argv)})().catch(e=>{console.error(e instanceof Error?e.message:String(e)),process.exitCode=1});