@task-handoff/node-agent 0.0.31 → 0.0.33

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -1 +1 @@
1
- "use strict";var e=require("commander"),t=require("node:fs"),n=require("node:path"),i=require("node:http"),s=require("node:url"),o=require("fastify"),r=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("node:async_hooks"),_=require("drizzle-orm"),E=require("drizzle-orm/sqlite-core"),w=require("node:sqlite"),T=require("drizzle-orm/node-sqlite"),b=require("semver"),S=require("cron-parser"),v=require("node:readline/promises"),N=require("node:process"),O="undefined"!=typeof document?document.currentScript:null;function z(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 C(e){if(e)try{return n.dirname(t.realpathSync(e))}catch{return}}function R(e,t=process.env,i=e){const s=t.TASK_HANDOFF_VERSION?.trim();if(s)return s;const o=i.split("/").at(-1),r=process.argv[1]?n.resolve(process.argv[1]):void 0,a=r?n.dirname(r):void 0,c=[C(r),a,process.cwd()].filter(e=>Boolean(e));for(const t of new Set(c)){let i=t;for(;;){const t=z(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(o){const e=z(n.join(t,"packages",o,"package.json"),i);if(e)return e}d||=z(n.join(t,"package.json"));const e=n.dirname(t);if(e===t)break;t=e}}return d||"unknown"}const x={perMessageDeflate:{threshold:256,serverNoContextTakeover:!0,clientNoContextTakeover:!0,concurrencyLimit:4,zlibDeflateOptions:{level:1}}};function k(e){return e.readyState===(e.OPEN??1)}function D(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 P(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 L(e,t,n){e.close(P(t),D(n)||void 0)}function M(e,t,n,i){if(k(e))for(const e of t.splice(0))if(i(e),!n(e))return}function j(e,t,n={}){const i=n.pendingFrameLimit??256,s=n.maxFrameBytes??8388608,o=n.maxTotalBytes??1073741824,r=n.maxBufferedBytes??16777216;let a=!1,c=k(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,r)=>{const a=g(r);return h+=a,n.onFrame?.(i,a),!(a>s||h>o)||(L(e,1009,"WebSocket bridge traffic limit exceeded."),L(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>r)return L(e,1013,"WebSocket bridge consumer is too slow."),L(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 L(e,1011,"WebSocket bridge send failed."),L(t,1011,"WebSocket bridge send failed."),!1}},A=(n,s,o)=>{if(s.length>=i)return L(e,1011,"WebSocket bridge pending frame limit exceeded."),void L(t,1011,"WebSocket bridge pending frame limit exceeded.");const a="upstream"===n?p:m;if((("upstream"===n?t:e).bufferedAmount??0)+a+o.bytes>r)return L(e,1013,"WebSocket bridge consumer is too slow."),void L(t,1013,"WebSocket bridge consumer is too slow.");s.push(o),"upstream"===n?p+=o.bytes:m+=o.bytes};return n.upstreamOpenTimeoutMs&&!c&&(u=setTimeout(()=>{c||a||(L(e,1011,"Upstream websocket did not open."),L(t))},n.upstreamOpenTimeoutMs)),e.on("open",()=>M(e,l,t=>I(e,t),e=>{m-=e.bytes})),t.on("open",()=>{y(),c=!0,n.onUpstreamOpen?.(),M(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)};k(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)};k(e)?I(e,i):A("client",l,i)}),t.on("close",(t,i)=>{y(),n.onUpstreamClose?.(t,i),(c||a||!n.onUpstreamCloseBeforeOpen?.())&&L(e,t,i)}),t.on("error",t=>{n.onUpstreamError?.(t),(c||a||!n.onUpstreamErrorBeforeOpen?.(t))&&L(e)}),e.on("close",(e,i)=>{y(),a=!0,n.onClientClose?.(e,i),L(t,e,i)}),e.on("error",e=>{y(),a=!0,n.onClientError?.(e),L(t,1011,"WebSocket bridge client failed.")}),{close:(n,i)=>{y(),L(t,n,i),L(e,n,i)}}}var U,F,$=function(){if(F)return U;F=1;const e=t,{spawnSync:n}=l;return U={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 H 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 q(e){return n.join(e,"owner.json")}function V(e){return n.join(e,"initializing.json")}function B(e){return n.join(e,"recovering.json")}function K(e){return Number.isInteger(e)&&Number(e)>0}function G(e){try{const n=JSON.parse(t.readFileSync(q(e),"utf8"));if(K(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(!(K(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 W=G;function X(e){if(!K(e))return!1;try{return process.kill(Number(e),0),!0}catch(e){return"EPERM"===e.code}}function Y(e){if(!e||!X(e.pid))return!1;if(!e.startIdentity)return!0;const t=$.processStartIdentity(e.pid);return void 0===t||t===e.startIdentity}function J(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 o=Z(e);if(o?.token!==i.token)throw te(s),new Error(`Process lock initialization was superseded: ${e}`);t.renameSync(s,q(e)),te(V(e))}function Q(e,i,s){const o=W(e);if(o?.token!==i.token)return!1;const r={...i};for(const[e,t]of Object.entries(s))void 0===t?delete r[e]:Object.assign(r,{[e]:t});const a=n.join(e,`.owner-update-${i.token}-${d.randomUUID()}.tmp`);try{if(t.writeFileSync(a,`${JSON.stringify(r,null,2)}\n`,{encoding:"utf8",mode:384,flag:"wx"}),W(e)?.token!==i.token)return!1;t.renameSync(a,q(e));for(const e of Object.keys(i))delete i[e];return Object.assign(i,r),!0}catch(e){if("ENOENT"===e.code)return!1;throw e}finally{te(a)}}function Z(e){try{return JSON.parse(t.readFileSync(V(e),"utf8"))}catch{return}}function ee(e){const t=Z(e);return K(t?.pid)&&Y({pid:t.pid,startIdentity:t.startIdentity})}function te(e){try{t.unlinkSync(e)}catch(e){if("ENOENT"!==e.code)throw e}}function ne(){Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,20)}function ie(e){try{const n=Z(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 se(e,i){try{return t.writeFileSync(B(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=B(e),s=oe(i),o=Date.parse(s?.startedAt||"");if(X(s?.pid)||Number.isFinite(o)&&Date.now()-o<2e3)return!1;const r=n.join(e,`.recovering-${d.randomUUID()}.stale`);try{t.renameSync(i,r)}catch(e){if(["ENOENT","EEXIST"].includes(e.code||""))return!1;throw e}const a=oe(r);if(a?.token===s?.token)return te(r),!0;try{t.linkSync(r,i)}catch(e){if("EEXIST"!==e.code)throw e}finally{te(r)}return!1}(e)&&se(e,i);if("ENOENT"===s.code)return!1;throw s}}function oe(e){try{return JSON.parse(t.readFileSync(e,"utf8"))}catch{return}}function re(e,t){return oe(B(e))?.token===t}function ae(){return(new Date).toISOString()}const ce=6048e5;function de(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 le(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 ue=a.z.string().trim().min(1).max(120),pe=20971520,me=512e3,he=me,ge=pe,fe=41943040,ye="ai.sessions",Ie="ai-session.snapshot",Ae="ai-session.patch",_e="ai-session.removed",Ee="ai-session.message-delta",we="ai-session.timeline-item",Te="ai-session.timeline-item-delta",be=a.z.string().trim().min(1).max(80),Se=a.z.enum(["app-session","ai-session"]),ve=a.z.enum(["image","file"]),Ne={scopeType:a.z.enum(["session","create-request"]),scopeId:a.z.string().trim().min(1).max(160),kind:ve,name:a.z.string().trim().min(1).max(240),mime:a.z.string().trim().min(1).max(120)};a.z.object({...Ne,size:a.z.coerce.number().int().positive().max(pe)}).strict();const Oe=a.z.string().regex(/^cia_[a-f0-9]{24}$/);a.z.object({attachmentId:Oe,...Ne,size:a.z.number().int().positive().max(pe)}).strict(),a.z.object({offset:a.z.coerce.number().int().nonnegative()}).strict(),a.z.object({attachmentId:Oe,offset:a.z.number().int().nonnegative()}),a.z.object({id:Oe,kind:ve,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(pe),expiresAt:a.z.string().datetime()});const ze=a.z.object({id:a.z.string().trim().min(1).max(120),kind:ve,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)}),Ce=a.z.enum(["available","expired","missing"]),Re=ze.extend({contentState:Ce.default("available")}).strict(),xe=a.z.object({id:a.z.string().trim().min(1).max(240),text:a.z.string(),attachments:a.z.array(Re).max(6).default([])}).strict(),ke=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 De=a.z.enum(["thinking","tool","editing","approval","responding","unknown"]),Pe=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(),Le=a.z.enum(["running","completed","failed","waiting"]),Me=a.z.object({id:a.z.string().trim().min(1).max(240),turnId:a.z.string().trim().min(1).max(240)}).strict(),je=Me.extend({type:a.z.literal("user-message"),text:a.z.string(),attachments:a.z.array(Re).max(6).optional()}).strict(),Ue=Me.extend({type:a.z.literal("ai-message"),text:a.z.string()}).strict(),Fe=Me.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:Le.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(),$e=a.z.discriminatedUnion("type",[je,Ue,Fe]);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($e),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($e),generatedAt:a.z.string().datetime()}).strict();const He=a.z.enum(["pending-init","running","interrupted","completed","errored","shutdown","not-found"]),qe=a.z.enum(["started","interacted","interrupted"]),Ve=a.z.object({threadId:a.z.string().trim().min(1).max(240),path:a.z.string().trim().max(4096).optional(),status:He,activity:qe.optional(),message:a.z.string().trim().max(1e3).optional(),updatedAt:a.z.string().datetime()}).strict();function Be(e){return"completed"!==e.status}const Ke=a.z.array(Ve).max(50).transform(e=>e.filter(Be)),Ge=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}),We=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(),Xe=a.z.string().trim().min(1).max(240),Ye=a.z.discriminatedUnion("kind",[a.z.object({kind:a.z.literal("fork"),parentProviderSessionId:Xe,throughTurnId:a.z.string().trim().min(1).max(240).optional()}).strict(),a.z.object({kind:a.z.literal("subagent"),parentProviderSessionId:Xe}).strict()]),Je=a.z.preprocess(function(e){if(!e||"object"!=typeof e||Array.isArray(e))return;const t=e;if("fork"===t.kind){const e=Ye.safeParse({kind:"fork",parentProviderSessionId:t.parentProviderSessionId,..."string"==typeof t.throughTurnId?{throughTurnId:t.throughTurnId}:{}});return e.success?e.data:void 0}if("subagent"===t.kind){const e=Ye.safeParse({kind:"subagent",parentProviderSessionId:t.parentProviderSessionId});return e.success?e.data:void 0}},Ye.optional()),Qe=a.z.union([ze.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?pe:me;(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.`})}),ze.extend({source:a.z.object({type:a.z.literal("runtime-path"),path:a.z.string().trim().min(1).max(4096)}).strict()}).strict()]),Ze=ze.extend({sourceType:a.z.enum(["inline","runtime-path"])}).strict(),et=a.z.union([a.z.object({id:a.z.string().trim().min(1).max(120),kind:ve.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:ve,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()]),tt=a.z.enum(["auto","queue","steer","immediate"]),nt=a.z.enum(["ask","auto-review","full-access"]),it=a.z.enum(["review","rename","goal","compact"]);a.z.object({command:it,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:it,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 st=a.z.object({name:a.z.string().trim().min(1).max(240),path:a.z.string().trim().min(1).max(4096)}),ot=a.z.discriminatedUnion("kind",[st.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(),st.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(),st.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()]),rt=a.z.array(ot).max(20).default([]),at=a.z.enum(["plugin","skill","file","directory","app"]),ct=a.z.object({kind:at,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."})}),dt=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(ct).max(1e3).default([]),diagnostics:a.z.array(dt).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(ct.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 lt=a.z.object({message:a.z.string().trim().min(1).max(2e4),mode:tt.optional(),permissionMode:nt.optional()}),ut=lt.extend({attachments:a.z.array(Qe).max(6).default([]),references:rt}).strict().superRefine((e,t)=>{e.attachments.reduce((e,t)=>e+("inline"===t.source.type?t.size:0),0)>fe&&t.addIssue({code:a.z.ZodIssueCode.custom,path:["attachments"],message:"Inline attachments must be 41943040 bytes or less in total."})}),pt=lt.extend({attachments:a.z.array(et).max(6).default([]),references:rt}).strict(),mt=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(),ht=a.z.object({modelEntityId:a.z.string().trim().min(1).max(120),modelName:a.z.string().trim().min(1).max(240)}).strict(),gt=a.z.enum(["none","minimal","low","medium","high","xhigh","max","ultra"]);ut.extend({agent:be,cwd:mt,cwdFolderId:a.z.string().trim().min(1).max(120).optional(),clientRequestId:a.z.string().trim().min(1).max(160),modelSelection:ht.optional(),reasoningEffort:gt.optional(),storyId:ue.optional()}).strict();const ft=a.z.object({mode:a.z.enum(["current-folder","worktree"]),branch:a.z.string().trim().min(1).max(1024)}).strict();pt.extend({agent:be,cwdFolderId:a.z.string().trim().min(1).max(120).optional(),gitSelection:ft.optional(),clientRequestId:a.z.string().trim().min(1).max(160),modelSelection:ht.optional(),reasoningEffort:gt.optional(),storyId:ue.optional()}).strict(),a.z.object({clientRequestId:a.z.string().trim().min(1).max(160),modelSelection:ht}).strict(),a.z.object({sessionId:a.z.string().trim().min(1).max(120),accepted:a.z.literal(!0)}).strict(),a.z.object({clientRequestId:a.z.string().trim().min(1).max(160),reasoningEffort:gt}).strict(),a.z.object({sessionId:a.z.string().trim().min(1).max(120),accepted:a.z.literal(!0)}).strict(),a.z.object({storyId:ue.nullable()}).strict(),a.z.object({sessionId:a.z.string().trim().min(1).max(120),storyId:ue.optional()}).strict(),a.z.object({disposition:a.z.enum(["created","already-created"]),aiSessionId:a.z.string().trim().min(1).max(120),providerSessionId:a.z.string().trim().min(1).max(240),creationSource:a.z.literal("ai-session")}).strict();const yt=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:yt.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:Se}).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:Se}).strict(),a.z.object({disposition:a.z.enum(["cleared","already-cleared"]),aiSessionId:a.z.string().trim().min(1).max(120),clearedSessionIds:a.z.array(a.z.string().trim().min(1).max(120))}).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(Ze).max(6).default([]),references:rt,permissionMode:nt.optional(),status:a.z.enum(["queued","sending","failed"]).default("queued"),createdAt:a.z.string().datetime(),updatedAt:a.z.string().datetime(),error:a.z.string().trim().max(4e3).optional()}).strict(),At=a.z.object({revision:a.z.number().int().min(0).default(0),pendingCount:a.z.number().int().min(0).default(0),items:a.z.array(It).max(100).default([])}).strict().default({revision:0,pendingCount:0,items:[]}),_t=a.z.enum(["control","realtime","adapter-snapshot","transcript-tail","transcript-scan","process-scan","app-session"]),Et=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(),wt=a.z.object({id:a.z.string().trim().min(1).max(240),providerTurnId:a.z.string().trim().max(240).optional(),source:_t.optional(),userPrompt:a.z.string().trim().optional(),userMessages:a.z.array(xe).max(100).optional(),status:a.z.enum(["queued","running","waiting","completed","failed"]).default("running"),phase:De.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(Et).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(),Tt=wt.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(),bt=a.z.object({id:a.z.string().trim().min(1).max(120),agent:be,creationSource:Se.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:Je,providerMeta:a.z.record(a.z.string(),a.z.unknown()).optional(),modelSelection:ht.optional(),reasoningEffort:gt.optional(),storyId:ue.optional(),appBindingKeys:a.z.array(a.z.string().trim().min(1).max(240)).max(20).optional(),actions:We.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(wt).max(50).optional(),status:ke.default("running"),phase:De.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:Pe.optional(),toolCallsSinceLastMessage:a.z.number().int().min(0).default(0),subAgents:Ke.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:Ge,queue:At}).strict(),St=bt.pick({id:!0,appBindingKeys:!0,cwd:!0,error:!0,providerMeta:!0,modelSelection:!0,reasoningEffort:!0,queue:!0,subAgents:!0}).strict(),vt=wt.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(),Nt=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(vt).max(50)}).strict(),Ot=a.z.object({sessionId:a.z.string().trim().min(1).max(120),revision:a.z.string().trim().min(1).max(64),turn:wt}).strict(),zt=a.z.string().trim().min(1).max(64),Ct=a.z.object({kind:a.z.literal("not-modified"),revision:zt}).strict();a.z.discriminatedUnion("kind",[Ct,a.z.object({kind:a.z.literal("updated"),revision:zt,detail:St}).strict()]),a.z.discriminatedUnion("kind",[Ct,a.z.object({kind:a.z.literal("updated"),revision:zt,index:Nt}).strict()]),a.z.discriminatedUnion("kind",[Ct,a.z.object({kind:a.z.literal("updated"),revision:zt,body:Ot}).strict()]);const Rt=a.z.object({session:bt,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(),xt=Rt.omit({session:!0}).extend({sessionId:a.z.string().trim().min(1).max(120),messageId:a.z.string().trim().min(1).max(240).optional()}).strict();a.z.object({sessionId:a.z.string().trim().min(1).max(120),queueRevision:a.z.number().int().min(0),action:a.z.enum(["retry","remove","edit","reorder"]),queueId:a.z.string().trim().min(1).max(120).optional()}).strict(),a.z.union([xt,Rt.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 xt.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 kt=a.z.object({id:a.z.string().trim().min(1).max(120),agent:be,creationSource:Se,providerSessionId:a.z.string().trim().min(1).max(240),lineage:Je,modelSelection:ht.optional(),reasoningEffort:gt.optional(),storyId: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(kt).max(1e4).default([])}).strict(),a.z.object({items:a.z.array(kt).max(1e4).default([])}).strict(),a.z.object({item:kt,turns:a.z.array(Tt).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:Se}).strict();const Dt=wt.omit({userMessages:!0}),Pt=bt.pick({id:!0,agent:!0,creationSource:!0,appSessionId:!0,appId:!0,providerSessionId:!0,lineage:!0,providerMeta:!0,modelSelection:!0,reasoningEffort:!0,storyId:!0,appBindingKeys:!0,actions:!0,activeTurnId:!0,title:!0,cwd:!0,cwdFolderId:!0,userPrompt:!0,turns:!0,status:!0,phase:!0,summary:!0,lastMessage:!0,lastMessageItemId:!0,currentTool:!0,toolCallsSinceLastMessage:!0,subAgents:!0,queue:!0,startedAt:!0,updatedAt:!0,error:!0}).extend({turns:a.z.array(Dt).max(50).optional(),detailRevision:a.z.string().trim().min(1).max(64).optional(),turnsRevision:a.z.string().trim().min(1).max(64).optional(),latestTurnRef:a.z.object({id:wt.shape.id,bodyRevision:a.z.string().trim().min(1).max(64)}).strict().optional(),turnCount:a.z.number().int().min(0).optional(),subAgentCount:a.z.number().int().min(0).optional(),lastUserMessageAt:a.z.string().datetime().optional()}).strict(),Lt=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(Pt).default([]),updatedAt:a.z.string().datetime()}).strict(),Mt=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:Lt}).strict();Lt.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 jt=a.z.enum(["provider-event","app-session-created","app-session-updated","app-session-deleted","discovery-scan","control-action","heartbeat-sync","startup"]),Ut=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:jt}).strict(),Ft=a.z.object({meta:Ut,snapshot:Lt}).strict(),$t=a.z.object({meta:Ut,upserted:a.z.array(Pt).default([]),removed:a.z.array(a.z.string().trim().min(1).max(120)).default([])}).strict(),Ht=a.z.object({meta:Ut,sessionIds:a.z.array(a.z.string().trim().min(1).max(120)).default([]),expiresAt:a.z.string().datetime()}).strict(),qt=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(),Vt=qt.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:$e,generatedAt:a.z.string().datetime()}).strict();const Bt=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),field:a.z.literal("output"),delta:a.z.string().min(1),generatedAt:a.z.string().datetime()}).strict(),Kt=Bt.omit({instanceId:!0,nodeId:!0,providerSessionId:!0}).strict();function Gt(e){return Kt.parse({sessionId:e.sessionId,turnId:e.turnId,itemId:e.itemId,field:e.field,delta:e.delta,generatedAt:e.generatedAt})}function Wt(e,t){if(t?.subagents||"subagent"!==e.lineage?.kind)return e;const{lineage:n,...i}=e;return i}function Xt(e,t){return t?.subagents?e:{...e,sessions:e.sessions.map(e=>Wt(e,t))}}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(Ie),payload:Ft}).strict(),a.z.object({type:a.z.literal(Ae),payload:$t}).strict(),a.z.object({type:a.z.literal(_e),payload:Ht}).strict()])).default([])}).strict();const Yt=a.z.object({source:_t,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(),Jt=Yt.extend({type:a.z.literal("snapshot"),agent:a.z.string().trim().min(1).max(80),creationSource:Se.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:Ye.optional(),providerMeta:a.z.record(a.z.string(),a.z.unknown()).optional(),modelSelection:ht.optional(),reasoningEffort:gt.optional(),storyId:ue.optional(),appBindingKeys:a.z.array(a.z.string().trim().min(1).max(240)).max(20).optional(),actions:We.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(wt).max(50).optional(),status:ke.optional(),phase:De.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:Pe.optional(),toolCallsSinceLastMessage:a.z.number().int().min(0).optional(),subAgents:Ke.optional(),transcriptPath:a.z.string().trim().max(4096).optional(),transcriptSize:a.z.number().int().min(0).optional(),replaceActivity:a.z.boolean().optional()}).strict(),Qt=Yt.extend({type:a.z.literal("event"),sessionId:a.z.string().trim().min(1).max(120),kind:a.z.enum(["lifecycle","send-ack","turn-started","user-message","assistant-message","approval-requested","turn-completed","session-error","tool-activity","sub-agent-activity","context-compaction","model-selection","reasoning-effort"]),modelSelection:ht.optional(),reasoningEffort:gt.optional(),activeTurnId:a.z.string().trim().max(240).optional(),providerTurnId:a.z.string().trim().max(240).optional(),userPrompt:a.z.string().trim().optional(),userMessage:xe.optional(),text:a.z.string().optional(),itemId:a.z.string().trim().max(240).optional(),status:ke.optional(),phase:De.optional(),summary:a.z.string().trim().max(1e3).optional(),error:a.z.string().trim().max(4e3).optional(),currentTool:Pe.nullable().optional(),toolCallsSinceLastMessage:a.z.number().int().min(0).optional(),subAgents:Ke.optional(),contextCompaction:Et.optional(),counters:a.z.object({toolCalls:a.z.number().int().min(0).optional(),edits:a.z.number().int().min(0).optional(),approvals:a.z.number().int().min(0).optional()}).strict().optional()}).strict().superRefine((e,t)=>{if("model-selection"===e.kind?e.modelSelection||t.addIssue({code:"custom",path:["modelSelection"],message:"model-selection events require modelSelection"}):void 0!==e.modelSelection&&t.addIssue({code:"custom",path:["modelSelection"],message:"modelSelection is only valid for model-selection events"}),"reasoning-effort"===e.kind?e.reasoningEffort||t.addIssue({code:"custom",path:["reasoningEffort"],message:"reasoning-effort events require reasoningEffort"}):void 0!==e.reasoningEffort&&t.addIssue({code:"custom",path:["reasoningEffort"],message:"reasoningEffort is only valid for reasoning-effort events"}),"session-error"!==e.kind||e.error||t.addIssue({code:"custom",path:["error"],message:"session-error events require error"}),"context-compaction"===e.kind?e.contextCompaction||t.addIssue({code:"custom",path:["contextCompaction"],message:"context-compaction events require contextCompaction"}):void 0!==e.contextCompaction&&t.addIssue({code:"custom",path:["contextCompaction"],message:"contextCompaction is only valid for context-compaction events"}),"send-ack"!==e.kind&&"user-message"!==e.kind&&void 0!==e.userMessage&&t.addIssue({code:"custom",path:["userMessage"],message:"userMessage is only valid for send-ack and user-message events"}),"sub-agent-activity"===e.kind?e.subAgents||t.addIssue({code:"custom",path:["subAgents"],message:"sub-agent-activity events require subAgents"}):void 0!==e.subAgents&&t.addIssue({code:"custom",path:["subAgents"],message:"subAgents is only valid for sub-agent-activity events"}),"tool-activity"!==e.kind)return void 0!==e.currentTool&&t.addIssue({code:"custom",path:["currentTool"],message:"currentTool is only valid for tool-activity events"}),void(void 0!==e.toolCallsSinceLastMessage&&t.addIssue({code:"custom",path:["toolCallsSinceLastMessage"],message:"toolCallsSinceLastMessage is only valid for tool-activity events"}));"currentTool"in e||t.addIssue({code:"custom",path:["currentTool"],message:"tool-activity events require currentTool"}),void 0===e.toolCallsSinceLastMessage&&t.addIssue({code:"custom",path:["toolCallsSinceLastMessage"],message:"tool-activity events require toolCallsSinceLastMessage"})});a.z.discriminatedUnion("type",[Jt,Qt]);const Zt=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()]),en=a.z.union([Zt,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()]),tn=a.z.object({promptTemplate:a.z.string().trim().min(1).max(2e4)}).strict(),nn=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(),sn=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:en,action:tn,policy:nn.default({maxConcurrentRuns:1,whenBusy:"skip"}),createdAt:a.z.string().datetime(),updatedAt:a.z.string().datetime()}).strict(),on=a.z.object({type:a.z.literal("ai-session"),aiSessionId:a.z.string().trim().min(1).max(160)}).strict(),rn=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:on,localName:a.z.string().trim().min(1).max(160).optional(),createdAt:a.z.string().datetime(),updatedAt:a.z.string().datetime()}).strict(),an=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(),cn=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:on,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(sn).default([]),deployments:a.z.array(rn).default([]),runtime:a.z.array(an).default([]),recentRuns:a.z.array(cn).default([])}).strict();const dn=a.z.object({config:sn,deployment:rn,runtime:an.optional()}).strict();a.z.object({instanceId:a.z.string().trim().min(1).max(160),sessionId:a.z.string().trim().min(1).max(160),mutation:dn.optional()}).strip(),a.z.object({instanceId:a.z.string().trim().min(1).max(160),sessionId:a.z.string().trim().min(1).max(160),configHash:sn.shape.configHash}).strip();const ln=a.z.object({instanceId:a.z.string().trim().min(1).max(160),instanceName:a.z.string().trim().min(1).max(160),deployment:rn,runtime:an.optional()}).strip(),un=cn.extend({instanceName:a.z.string().trim().min(1).max(160).optional()}).strip(),pn=a.z.object({configHash:a.z.string().trim().min(8).max(80),config:sn,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(ln),recentRuns:a.z.array(un)}).strip();a.z.object({updatedAt:a.z.string().datetime(),triggers:a.z.array(pn)}).strip(),a.z.object({name:sn.shape.name,description:sn.shape.description,source:en,action:tn,policy:nn.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 mn=a.z.string().regex(/^\d{4}-\d{2}-\d{2}$/,"Proxy protocol version must use YYYY-MM-DD format."),hn=a.z.string().trim().min(1).max(160).regex(/^[a-zA-Z0-9][a-zA-Z0-9_.:-]*$/),gn=a.z.string().datetime(),fn=a.z.string().trim().min(32).max(4096),yn=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 In=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"})),An=a.z.object({code:In,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(),_n=a.z.enum(["active","revoked"]),En=a.z.object({id:hn,targetNodeId:hn,status:_n,createdBy:hn,expiresAt:gn,revokedAt:gn.optional(),createdAt:gn,updatedAt:gn}).strict();a.z.object({targetNodeId:hn,expiresInSeconds:a.z.number().int().min(60).max(3600).default(600)}).strict(),a.z.object({invite:En,token:a.z.string().trim().min(24).max(512),proxyOrigin:yn,protocolVersion:mn}).strict();const wn=a.z.enum(["active","revoked"]),Tn=a.z.object({id:hn,claimId:hn,sourceControlPlaneId:hn,targetNodeId:hn,bindingKeyId:hn,status:wn,revision:a.z.number().int().positive(),lastError:An.optional(),revokedAt:gn.optional(),createdAt:gn,updatedAt:gn}).strict();a.z.object({protocolVersion:mn,inviteToken:a.z.string().trim().min(24).max(512).optional(),claimId:hn,sourceControlPlaneId:hn,targetNodeId:hn.optional(),bindingKeyId:hn,credential:fn}).strict(),a.z.object({sourceControlPlaneId:hn,bindingKeyId:hn,credential:fn}).strict();const bn=a.z.object({id:hn,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:gn.optional(),capabilities:a.z.record(a.z.string(),a.z.unknown()).default({})}).strict(),Sn=a.z.object({protocolVersion:mn,binding:Tn,streamId:hn,revision:a.z.number().int().nonnegative(),observedAt:gn,target:bn}).strict(),vn=a.z.object({type:a.z.literal("control-plane-proxy.event"),protocolVersion:mn,streamId:hn,bindingId:hn,sourceControlPlaneId:hn,targetNodeId:hn,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:bn,event:a.z.object({type:a.z.string().trim().min(1).max(240),topic:a.z.string().trim().min(1).max(240),createdAt:gn}).strict()}).strict(),Nn=a.z.object({type:a.z.literal("control-plane-proxy.events.ready"),protocolVersion:mn,streamId:hn,bindingId:hn,sourceControlPlaneId:hn,targetNodeId:hn,latestRevision:a.z.number().int().nonnegative(),earliestRetainedRevision:a.z.number().int().nonnegative()}).strict(),On=a.z.object({type:a.z.literal("control-plane-proxy.snapshot-required"),protocolVersion:mn,streamId:hn,bindingId:hn,sourceControlPlaneId:hn,targetNodeId:hn,sinceRevision:a.z.number().int().nonnegative(),latestRevision:a.z.number().int().nonnegative(),earliestRetainedRevision:a.z.number().int().nonnegative(),error:An}).strict();a.z.discriminatedUnion("type",[vn,Nn,On]),a.z.object({protocolVersion:mn,binding:Tn,target:Sn.shape.target}).strict(),a.z.object({id:hn,claimId:hn,proxyOrigin:yn,requestedName:a.z.string().trim().min(1).max(160).optional(),sourceControlPlaneId:hn,targetNodeId:hn.optional(),bindingKeyId:hn,credential:fn,status:a.z.enum(["pending","compensation-required"]),createdAt:gn,updatedAt:gn,expiresAt:gn}).strict().omit({credential:!0}),a.z.object({id:hn,nodeId:hn,proxyOrigin:yn,proxyBindingId:hn,targetNodeId:hn,sourceControlPlaneId:hn,bindingKeyId:hn,credential:fn,createdAt:gn,updatedAt:gn}).strict();const zn=a.z.string().trim().min(1).max(120),Cn=a.z.object({selectModelAtCreate:a.z.boolean().default(!1),selectProviderAtCreate:a.z.boolean().default(!1),switchModelWithinProvider:a.z.boolean().default(!1),switchProviderDuringSession:a.z.boolean().default(!1)}).strip().default({selectModelAtCreate:!1,selectProviderAtCreate:!1,switchModelWithinProvider:!1,switchProviderDuringSession:!1}),Rn=a.z.object({selectAtCreate:a.z.boolean().default(!1),updateDuringSession:a.z.boolean().default(!1)}).strip().default({selectAtCreate:!1,updateDuringSession:!1}),xn=a.z.object({subagents:a.z.boolean().default(!1)}).strip().default({subagents:!1}),kn=a.z.object({agent:zn,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(),permissionModes:a.z.array(a.z.enum(["ask","auto-review","full-access"])).max(3).default([]),timeline:a.z.object({sessionRead:a.z.boolean().default(!1),turnRead:a.z.boolean().default(!1),liveItems:a.z.boolean().default(!1)}).passthrough(),modelSelection:Cn.optional(),reasoningEffort:Rn.optional(),hierarchy:xn.optional()}).passthrough(),Dn=a.z.array(kn).max(100).default([]),Pn="2026-08-27",Ln=new Set(["2026-08-01","2026-08-16","2026-08-17","2026-08-20",Pn]),Mn=a.z.string().regex(/^\d{4}-\d{2}-\d{2}$/,"Protocol version must use YYYY-MM-DD format."),jn=a.z.string().trim().min(1).max(120),Un=a.z.enum(["low","medium","high"]),Fn=a.z.enum(["none","friendly","pragmatic"]),$n=a.z.object({modelEntityId:a.z.string().trim().min(1).max(120),modelName:a.z.string().trim().min(1).max(240)}).strict(),Hn=a.z.object({modelVerbosity:Un.optional(),personality:Fn.optional(),multiAgent:a.z.object({enabled:a.z.boolean().default(!0),maxConcurrentThreads:a.z.number().int().min(1).max(64).optional(),defaultModel:$n.optional(),defaultReasoningEffort:gt.optional()}).strict().default({enabled:!0})}).strict();function qn(){return{features:{appRuntime:!1,tty:!1,gui:!1,browser:!1,browserTunnel:!1,screenshots:!1,logs:!1,aiSessionWorkspaceSelection:!1,aiSessionPersistenceSettings:!1,privateModelCatalog:!1,codexManagedSettings:!1,nodeAgentConnectionUpdate:!1,gitCliCredentialBroker:!1,gitCredentialProxy:!1,aiSessionTimeline:{sessionReadAgents:[],turnReadAgents:[],liveItemAgents:[]},aiSessionConversationAttachments:{metadataAgents:[],contentAgents:[],uploadAgents:[],retentionSettings:!1,fileSizeLimitSettings:!1},aiSessionProviders:[]}}}const Vn=a.z.object({sessionReadAgents:a.z.array(jn).max(100).default([]),turnReadAgents:a.z.array(jn).max(100).default([]),liveItemAgents:a.z.array(jn).max(100).default([])}).passthrough(),Bn=a.z.object({metadataAgents:a.z.array(jn).max(100).default([]),contentAgents:a.z.array(jn).max(100).default([]),uploadAgents:a.z.array(jn).max(100).default([]),retentionSettings:a.z.boolean().default(!1),fileSizeLimitSettings:a.z.boolean().default(!1)}).passthrough(),Kn=a.z.object({appRuntime:a.z.boolean().default(!1),tty:a.z.boolean().default(!1),gui:a.z.boolean().default(!1),browser:a.z.boolean().default(!1),browserTunnel:a.z.boolean().optional(),screenshots:a.z.boolean().default(!1),logs:a.z.boolean().default(!1),aiSessionWorkspaceSelection:a.z.boolean().default(!1),aiSessionPersistenceSettings:a.z.boolean().default(!1),privateModelCatalog:a.z.boolean().optional(),codexManagedSettings:a.z.boolean().optional(),nodeAgentConnectionUpdate:a.z.boolean().optional(),gitCliCredentialBroker:a.z.boolean().optional(),gitCredentialProxy:a.z.boolean().optional(),aiSessionTimeline:Vn.default(function(){return{sessionReadAgents:[],turnReadAgents:[],liveItemAgents:[]}}),aiSessionConversationAttachments:Bn.optional(),aiSessionProviders:Dn.optional()}).passthrough(),Gn=a.z.object({features:Kn.default(function(){return{appRuntime:!1,tty:!1,gui:!1,browser:!1,browserTunnel:!1,screenshots:!1,logs:!1,aiSessionWorkspaceSelection:!1,aiSessionPersistenceSettings:!1,privateModelCatalog:!1,codexManagedSettings:!1,nodeAgentConnectionUpdate:!1,gitCliCredentialBroker:!1,gitCredentialProxy:!1,aiSessionTimeline:{sessionReadAgents:[],turnReadAgents:[],liveItemAgents:[]},aiSessionConversationAttachments:{metadataAgents:[],contentAgents:[],uploadAgents:[],retentionSettings:!1,fileSizeLimitSettings:!1},aiSessionProviders:[]}})}).passthrough(),Wn=a.z.object({nodeAgentUrl:a.z.string().trim().url().max(2048).refine(e=>{const t=new URL(e);return/^https?:$/.test(t.protocol)&&!t.username&&!t.password&&"/"===t.pathname&&!t.search&&!t.hash},"Node agent URL must be an HTTP(S) origin.")}).strict();function Xn(e){const t={features:{appRuntime:!1,tty:!1,gui:!1,browser:!1,browserTunnel:!1,screenshots:!1,logs:!1,aiSessionWorkspaceSelection:!1,aiSessionPersistenceSettings:!1,privateModelCatalog:!1,codexManagedSettings:!1,nodeAgentConnectionUpdate:!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,o={appRuntime:!1,tty:!1,gui:!1,browser:!1,browserTunnel:!1,screenshots:!1,logs:!1,aiSessionWorkspaceSelection:!1,aiSessionPersistenceSettings:!1,privateModelCatalog:!1,codexManagedSettings:!1,nodeAgentConnectionUpdate:!1,gitCliCredentialBroker:!1,gitCredentialProxy:!1,aiSessionTimeline:{sessionReadAgents:[],turnReadAgents:[],liveItemAgents:[]},aiSessionConversationAttachments:{metadataAgents:[],contentAgents:[],uploadAgents:[],retentionSettings:!1,fileSizeLimitSettings:!1},aiSessionProviders:[]};for(const e of["appRuntime","tty","gui","browser","browserTunnel","screenshots","logs","aiSessionWorkspaceSelection","aiSessionPersistenceSettings","privateModelCatalog","codexManagedSettings","nodeAgentConnectionUpdate","gitCliCredentialBroker","gitCredentialProxy"]){const t=a.z.boolean().safeParse(s[e]);t.success&&(o[e]=t.data)}const r=Vn.safeParse(s.aiSessionTimeline);r.success&&(o.aiSessionTimeline=r.data);const c=Bn.safeParse(s.aiSessionConversationAttachments);c.success&&(o.aiSessionConversationAttachments=c.data);const d=Dn.safeParse(s.aiSessionProviders);return d.success&&(o.aiSessionProviders=d.data),Gn.parse({...n,features:{...s,...o}})}function Yn(e){return Xn(e).features.aiSessionConversationAttachments}const Jn=a.z.string().trim().min(1).max(120).regex(/^[a-zA-Z0-9][a-zA-Z0-9_.:-]*$/),Qn=a.z.string().datetime(),Zn=a.z.record(a.z.string(),a.z.string()).default({}),ei=a.z.record(a.z.string(),a.z.string()).default({}),ti=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 ni(e){if(null==e)return;const t=ti.parse(e);return"utf8"===t.encoding?t.data:Buffer.from(t.data,"base64")}const ii=/^[A-Za-z0-9_][A-Za-z0-9_.-]{0,127}$/,si=/^sha256:([a-fA-F0-9]{64})$/,oi=/^(?:localhost|[a-z0-9](?:[a-z0-9.-]*[a-z0-9])?)(?::[1-9][0-9]{0,4})?$/,ri=/^[a-z0-9]+(?:(?:[._]|__|-+)[a-z0-9]+)*$/;function ai(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),o=i?si.exec(i):void 0;if(i&&!o)throw new Error("Docker image digest must use sha256 followed by 64 hexadecimal characters.");const r=s.lastIndexOf("/"),a=s.lastIndexOf(":"),c=a>r,d=c?s.slice(a+1):void 0,l=c?s.slice(0,a):s;if(d&&!ii.test(d))throw new Error("Docker image tag is invalid.");if(!d&&!o)throw new Error("Docker image reference must include an explicit tag or sha256 digest.");const u=l.split("/");if(!u.length||u.some(e=>!e))throw new Error("Docker image repository path is invalid.");const p=u.length>1&&(u[0].includes(".")||u[0].includes(":")||"localhost"===u[0]),m=p?u.slice(1):u;if(p&&!oi.test(u[0].toLowerCase()))throw new Error("Docker image registry host or port is invalid.");if(!m.length||m.some(e=>!ri.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=o?`sha256:${o[1].toLowerCase()}`:void 0;return`${h}${d?`:${d}`:""}${g?`@${g}`:""}`}function ci(e){const t=ai(e),n=t.indexOf("@"),i=-1===n?void 0:t.slice(n+1),s=-1===n?t:t.slice(0,n),o=s.lastIndexOf("/"),r=s.lastIndexOf(":"),a=r>o;return{reference:t,repository:a?s.slice(0,r):s,tag:a?s.slice(r+1):void 0,digest:i}}const di=a.z.string().trim().min(1).max(512).transform((e,t)=>{try{return ai(e)}catch(e){return t.addIssue({code:"custom",message:e instanceof Error?e.message:String(e)}),a.z.NEVER}}),li=a.z.string().trim().transform((e,t)=>{const n=si.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)}),ui=a.z.object({modelEntityIds:a.z.array(Jn).max(64).transform(e=>[...new Set(e)]).optional(),codexModelHash:Jn.nullable().optional(),claudeModelHash:Jn.nullable().optional(),opencodeModelHash:Jn.nullable().optional()}).strict().default({}),pi=a.z.object({imageId:Jn,tag:a.z.string().trim().min(1).max(128).regex(ii).optional()}).strict(),mi=a.z.discriminatedUnion("type",[a.z.object({type:a.z.literal("image"),imageSelection:pi}).strict(),a.z.object({type:a.z.literal("template"),environmentTemplateId:Jn}).strict()]),hi=a.z.enum(["creating","ready","failed","deleting"]),gi=a.z.enum(["linux","darwin","win32","freebsd","openbsd","aix","sunos","unknown"]),fi=a.z.enum(["x64","arm64","arm","ia32","ppc64","s390x","riscv64","unknown"]),yi=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(),Ii=a.z.object({templateId:Jn,nodeId:Jn,imageId:li,name:a.z.string().trim().min(1).max(160),platform:gi,architecture:fi}).strict(),Ai=a.z.enum(["data","agent-home","workspace"]),_i=a.z.object({deleteVolumes:a.z.boolean()}).strict(),Ei=a.z.object({role:Ai,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(),wi=a.z.object({instanceId:Jn,containerDeleted:a.z.boolean(),completed:a.z.boolean(),deletedVolumes:a.z.array(Ei),retainedVolumes:a.z.array(Ei),volumeResults:a.z.array(Ei)}).strict(),Ti={img_default:"market_taskhandoff_browser",img_codex:"market_taskhandoff_codex",img_ai:"market_taskhandoff_ai"};function bi(e,t){if(e&&"object"==typeof e&&!Array.isArray(e)){const t=e;return{imageId:"string"==typeof t.imageId&&Ti[t.imageId]||t.imageId,..."string"==typeof t.tag?{tag:t.tag}:{}}}if("string"==typeof t)return{imageId:Ti[t]||t}}function Si(e){if(!e||"object"!=typeof e||Array.isArray(e))return e;const t=e,{defaultImageId:n,...i}=t;return{...i,defaultImageSelection:bi(t.defaultImageSelection,n)}}const vi=a.z.object({id:Jn,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(),Ni=a.z.object({code:a.z.enum(["APP_CATALOG_INVALID"]),message:a.z.string().trim().min(1).max(500)}).strict(),Oi=a.z.object({items:a.z.array(vi).max(256),observedAt:Qn,issues:a.z.array(Ni).max(32).default([])}).strict(),zi=a.z.object({id:Jn,name:a.z.string().trim().min(1).max(160),sourceInstanceId:Jn,nodeId:Jn,imageId:li.optional(),internalTag:a.z.string().trim().min(1).max(512).optional(),platform:gi.optional(),architecture:fi.optional(),sizeBytes:a.z.number().int().nonnegative().optional(),status:hi,error:yi.optional(),createdAt:Qn,updatedAt:Qn}).strict().superRefine((e,t)=>{if("ready"===e.status)for(const n of["imageId","internalTag","platform","architecture","sizeBytes"])void 0===e[n]&&t.addIssue({code:"custom",path:[n],message:`Ready environment template requires ${n}.`});"failed"!==e.status||e.error||t.addIssue({code:"custom",path:["error"],message:"Failed environment template requires an error diagnostic."})}),Ci=a.z.enum(["apt","dnf","brew","npm"]),Ri=a.z.enum(["user","passwordless-sudo","root"]),xi=a.z.object({platform:gi,arch:fi,installers:a.z.array(Ci).max(8),privilege:Ri,installerAccess:a.z.object({npmGlobalWritable:a.z.boolean().optional()}).strict().optional()}).strict(),ki=a.z.enum(["installed","not-installed","broken","unsupported"]),Di=a.z.enum(["recipe","bundled","external","none"]),Pi=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(),Li=a.z.object({id:Jn,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:ki,managementSource:Di,version:a.z.string().trim().max(120).optional(),canInstall:a.z.boolean(),canUninstall:a.z.boolean(),installReason:Pi.optional(),uninstallReason:Pi.optional(),activeJobId:Jn.optional()}).strict(),Mi=a.z.enum(["install","uninstall"]),ji=a.z.enum(["queued","running","succeeded","failed","cancelled","interrupted"]),Ui=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"]}),Fi=a.z.object({executable:a.z.string().trim().min(1).max(4096),args:a.z.array(a.z.string().max(4096)).max(128)}).strict(),$i=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(Jn).max(64).optional()}).strict(),Hi=a.z.object({id:Jn,requestId:Jn.optional(),appId:Jn,operation:Mi,state:ji,phase:a.z.string().trim().min(1).max(120).optional(),progress:Ui.optional(),command:Fi.optional(),logTail:a.z.string().max(32768).optional(),logTruncated:a.z.boolean().optional(),error:$i.optional(),requestedAt:Qn,startedAt:Qn.optional(),finishedAt:Qn.optional(),updatedAt:Qn}).strict(),qi=a.z.object({streamId:Jn,sequence:a.z.number().int().nonnegative(),capabilities:xi,apps:a.z.array(Li).max(256),activeJobs:a.z.array(Hi).max(256),recentJobs:a.z.array(Hi).max(256),observedAt:Qn}).strict();a.z.object({requestId:Jn.optional()}).strict(),a.z.object({job:Hi}).strict(),a.z.object({type:a.z.literal("app-management"),streamId:Jn,sequence:a.z.number().int().nonnegative(),observedAt:Qn,job:Hi.optional(),snapshot:qi.optional()}).strict().refine(e=>void 0!==e.job||void 0!==e.snapshot,{message:"An app management event requires a job or snapshot."});const Vi=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:Mn.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:Mn,build:Vi.extend({component:a.z.literal("control-plane"),packageVersion:a.z.string().trim().min(1).max(80)}).loose(),serverTime:Qn}).loose()}).loose();const Bi=a.z.enum(["stable","beta","alpha"]),Ki=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(),Gi=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(),Wi=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:Qn.optional(),matchedAt:Qn.optional(),error:Gi.optional()}).strict(),Xi=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(Jn).max(1024).default([]),stoppedInstanceIds:a.z.array(Jn).max(1024).default([]),activeInstanceIds:a.z.array(Jn).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(Jn).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(),Ji=a.z.object({channel:Bi.default("stable")}).strict(),Qi=a.z.object({source:a.z.literal("npm"),channel:Bi,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(Ki).default([]),impact:Xi,updateAvailable:a.z.boolean(),supported:a.z.boolean().default(!0),reason:a.z.string().trim().max(2048).optional(),checkedAt:Qn,preflightToken:a.z.string().trim().min(16).max(240).optional()}).strict(),Zi=a.z.object({id:Jn,nodeId:Jn,source:a.z.literal("npm"),channel:Bi,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(Ki).default([]),impact:Xi,rollout:Yi,status:a.z.enum(["queued","updating-node","restarting-node","converging-instances","succeeded","degraded","failed"]),error:Gi.optional(),startedAt:Qn.optional(),completedAt:Qn.optional(),createdAt:Qn,updatedAt:Qn}).strict(),es=a.z.object({channel:Bi,targetVersion:a.z.string().trim().min(1).max(240),preflightToken:a.z.string().trim().min(16).max(240)}).strict(),ts=a.z.object({type:a.z.enum(["branch","tag"]),name:a.z.string().trim().min(1).max(240)}).strict(),ns=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(),is=a.z.discriminatedUnion("type",[ts,ns]),ss=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(),os=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:Jn,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:is.default({type:"branch",name:"main"}),auth:ss.default({type:"none"}),clone:os.default({submodules:!1,lfs:!1,subdirectory:""}),defaultImageSelection:pi.optional(),labels:Zn,createdAt:Qn,updatedAt:Qn}).strict();const rs=a.z.object({id:Jn,nodeId:Jn,name:a.z.string().trim().min(1).max(160),path:a.z.string().trim().min(1).max(4096),defaultImageSelection:pi.optional(),labels:Zn,createdAt:Qn,updatedAt:Qn}).strict(),as=a.z.discriminatedUnion("type",[a.z.object({type:a.z.literal("git-repository"),repositoryId:Jn.optional(),url:a.z.string().trim().min(1).max(2048),provider:a.z.string().trim().max(80).optional(),ref:is.default({type:"branch",name:"main"}),auth:ss.default({type:"none"}),clone:os.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:is.default({type:"branch",name:"main"}),auth:ss.default({type:"none"}),clone:os.default({submodules:!1,lfs:!1,subdirectory:""})}).strict(),a.z.object({type:a.z.literal("local-folder"),localFolderId:Jn.optional(),path:a.z.string().trim().min(1).max(4096),ownerNodeId:Jn.optional()}).strict()]),cs=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(),ds=a.z.enum(["codex","claude","opencode"]),ls=a.z.enum(["openai-responses","openai-chat-completions","anthropic-messages"]),us=a.z.object({name:a.z.string().trim().min(1).max(240),order:a.z.number().int().min(0).max(1e6).default(0)}).strict(),ps=a.z.object({id:Jn,name:a.z.string().trim().min(1).max(160),source:as,defaultImageSelection:pi.optional(),defaultNodeId:Jn.optional(),workspacePolicy:cs,labels:Zn,createdAt:Qn,updatedAt:Qn}).strict(),ms=a.z.object({id:Jn,name:a.z.string().trim().min(1).max(160),endpoint:a.z.string().trim().min(1).max(2048),key:a.z.string().trim().min(1).max(4096),model:a.z.string().trim().min(1).max(240),modelNames:a.z.array(us).max(256).default([]),protocols:a.z.array(ls).max(3).default([]),app:ds,enabled:a.z.boolean().default(!0),order:a.z.number().int().min(0).max(1e6).default(0),labels:Zn,createdAt:Qn,updatedAt:Qn}).strict(),hs=ms,gs=ms.omit({key:!0}).extend({keyPreview:a.z.string().trim().min(1).max(160),keySet:a.z.boolean()}).strict(),fs=gs.extend({referenceCount:a.z.number().int().min(0)}).strict(),ys=a.z.object({instanceId:Jn,modelEntityIds:a.z.array(Jn).max(64).transform(e=>[...new Set(e)]).optional(),codexModelHash:Jn.optional(),claudeModelHash:Jn.optional(),opencodeModelHash:Jn.optional(),updatedAt:Qn}).strict().transform(e=>({...e,modelEntityIds:e.modelEntityIds?.length?e.modelEntityIds:[...new Set([e.codexModelHash,e.claudeModelHash,e.opencodeModelHash].filter(e=>Boolean(e)))]})),Is=a.z.discriminatedUnion("type",[a.z.object({type:a.z.literal("control-plane"),name:ms.shape.name,enabled:ms.shape.enabled,order:ms.shape.order}).strict(),a.z.object({type:a.z.literal("node"),nodeId:Jn,name:ms.shape.name,enabled:ms.shape.enabled,order:ms.shape.order,referenceCount:a.z.number().int().min(0)}).strict()]),As=a.z.object({id:Jn,model:gs,locations:a.z.array(Is).min(1),referenceCount:a.z.number().int().min(0).default(0)}).strict(),_s=a.z.object({nodeId:Jn,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(As),nodeDiagnostics:a.z.array(_s).default([]),updatedAt:Qn}).strict();const Es=ms.omit({id:!0,createdAt:!0,updatedAt:!0}).strict(),ws=Es.partial().strict(),Ts=ms,bs=a.z.object({modelSelection:ui,modelEntityIds:a.z.array(Jn).max(64).transform(e=>[...new Set(e)]).optional(),codexModelHash:Jn.optional(),claudeModelHash:Jn.optional(),opencodeModelHash:Jn.optional()}).strict().transform(e=>({...e,modelEntityIds:e.modelEntityIds||e.modelSelection.modelEntityIds||[...new Set([e.codexModelHash,e.claudeModelHash,e.opencodeModelHash].filter(e=>Boolean(e)))]}));function Ss(e){const t={app:ds.parse(e.app),endpoint:ms.shape.endpoint.parse(e.endpoint),key:ms.shape.key.parse(e.key),model:ms.shape.model.parse(e.model)};return`mdl_${d.createHash("sha256").update(JSON.stringify(t)).digest("hex")}`}const vs=a.z.enum(["market","custom"]),Ns=a.z.enum(["active","deprecated","yanked"]),Os=a.z.discriminatedUnion("kind",[a.z.object({kind:a.z.literal("builtin"),key:a.z.string().trim().min(1).max(120)}).strict(),a.z.object({kind:a.z.literal("remote"),url:a.z.string().trim().url().max(2048),mediaType:a.z.enum(["image/png","image/jpeg","image/webp"]).optional(),digest:li.optional()}).strict()]),zs=a.z.array(a.z.string().trim().min(1).max(80)).default([]),Cs=a.z.array(a.z.string().trim().min(1).max(120)).default([]),Rs=a.z.record(a.z.string().trim().min(2).max(35),a.z.string().trim().min(1).max(4096)),xs=a.z.object({os:a.z.string().trim().min(1).max(40),architecture:a.z.string().trim().min(1).max(40),digest:li.optional(),downloadSizeBytes:a.z.number().int().positive().optional(),unpackedSizeBytes:a.z.number().int().positive().optional()}).strict(),ks=a.z.object({name:a.z.string().trim().min(1).max(128).regex(ii),version:a.z.string().trim().min(1).max(160).optional(),reference:di,manifestDigest:li.optional(),publishedAt:Qn.optional(),platforms:a.z.array(xs).default([]),status:Ns.default("active")}).strict(),Ds=a.z.object({id:Jn,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:Rs.optional(),cover:Os.optional(),repository:a.z.string().trim().min(1).max(512),defaultTag:a.z.string().trim().min(1).max(128).regex(ii),tags:a.z.array(ks).min(1),capabilities:zs,optionalApps:Cs,defaultEnv:ei,labels:Zn,status:Ns.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:Mn,catalogId:Jn,revision:a.z.string().trim().min(1).max(240),source:a.z.enum(["embedded","remote","cache"]),generatedAt:Qn,expiresAt:Qn.optional(),items:a.z.array(Ds)}).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:Qn,error:a.z.string().trim().max(4096).optional()}).strict(),a.z.object({id:Jn,origin:a.z.literal("custom"),name:a.z.string().trim().min(1).max(160),description:a.z.string().trim().max(4096).optional(),localizedDescriptions:Rs.optional(),cover:Os.optional(),reference:di,repository:a.z.string().trim().min(1).max(512),tag:a.z.string().trim().min(1).max(128).regex(ii).optional(),pullPolicy:a.z.literal("if-not-present").default("if-not-present"),capabilities:zs,optionalApps:Cs,defaultEnv:ei,labels:Zn,createdAt:Qn,updatedAt:Qn}).strict();const Ps=a.z.object({name:a.z.string().trim().min(1).max(128).regex(ii),version:a.z.string().trim().min(1).max(160).optional(),reference:di,manifestDigest:li.optional(),status:Ns}).strict(),Ls=a.z.object({id:Jn,origin:vs,name:a.z.string().trim().min(1).max(160),description:a.z.string().trim().max(4096).optional(),localizedDescriptions:Rs.optional(),cover:Os,repository:a.z.string().trim().min(1).max(512),tag:a.z.string().trim().min(1).max(128).regex(ii).optional(),availableTags:a.z.array(Ps),reference:di,digest:li.optional(),downloadSizeBytes:a.z.number().int().positive().optional(),unpackedSizeBytes:a.z.number().int().positive().optional(),capabilities:zs,optionalApps:Cs,defaultEnv:ei,labels:Zn,readOnly:a.z.boolean(),lifecycleStatus:Ns.optional(),market:a.z.object({catalogId:Jn,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(),Ms=a.z.object({id:Jn,origin:vs,name:a.z.string().trim().min(1).max(160),description:a.z.string().trim().max(4096).optional(),localizedDescriptions:Rs.optional(),cover:Os.optional(),repository:a.z.string().trim().min(1).max(512),tag:a.z.string().trim().min(1).max(128).regex(ii).optional(),requestedReference:di,resolvedDigest:li.optional(),resolvedReference:di.optional(),downloadSizeBytes:a.z.number().int().positive().optional(),pullPolicy:a.z.literal("if-not-present").default("if-not-present"),capabilities:zs,optionalApps:Cs,defaultEnv:ei,labels:Zn,market:a.z.object({catalogId:Jn,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:Qn,updatedAt:Qn}).strict(),js=a.z.object({phase:a.z.enum(["checking-image","pulling-image","resolving-image","ready","failed"]),requestedReference:di,generation:a.z.number().int().nonnegative().default(0),error:a.z.string().trim().max(4096).optional(),startedAt:Qn,updatedAt:Qn}).strict(),Us="image.pull.terminal.output",Fs="image.pull.terminal.finished",$s=a.z.object({instanceId:Jn,generation:a.z.number().int().nonnegative(),requestedReference:di,sequence:a.z.number().int().nonnegative(),observedAt:Qn}).strict(),Hs=$s.extend({data:a.z.string().min(1).max(65536),replay:a.z.boolean().optional()}).strict(),qs=$s.extend({outcome:a.z.enum(["succeeded","failed"])}).strict();$s.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 Vs=a.z.discriminatedUnion("kind",[a.z.object({kind:a.z.literal("direct")}).strict(),a.z.object({kind:a.z.literal("control-plane-proxy"),proxyId:Jn,proxyBindingId:Jn,targetNodeId:Jn}).strict()]),Bs=a.z.object({pingRttMs:a.z.number().nonnegative().optional(),pingRttP95Ms:a.z.number().nonnegative().optional(),consecutiveReconnects:a.z.number().int().nonnegative(),nextRetryAt:Qn.optional()}).strict();a.z.object({nodeId:Jn,inviteId:Jn.optional()}).strict(),a.z.discriminatedUnion("status",[a.z.object({id:Jn,status:a.z.literal("pending")}).strict(),a.z.object({id:Jn,status:a.z.literal("completed"),nodeId:Jn}).strict()]);const Ks=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:Qn.optional(),target:bn.optional(),lastError:An.optional(),updatedAt:Qn}).strict(),Gs=a.z.object({id:Jn,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:Vs.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:Jn.optional(),secret:a.z.string().trim().max(4096).optional(),pairedAt:Qn.optional(),pairing:a.z.object({status:a.z.enum(["pending","paired","expired"]).default("pending"),joinToken:a.z.string().trim().max(4096).optional(),expiresAt:Qn.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:Ks.optional(),appInventory:Oi.optional(),labels:Zn,lastSeenAt:Qn.optional(),createdAt:Qn,updatedAt:Qn}).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:Jn,status:a.z.enum(["unknown","online","offline","degraded"]),health:a.z.enum(["unknown","ok","degraded","failed"]),lastSeenAt:Qn.nullable(),connectionPhase:a.z.enum(["connecting","handshaking","healthy","reconnecting","suspect","offline"]).nullable(),connectionDiagnostics:Bs.nullable(),proxyState:Ks.nullable()}).strict();const Ws=a.z.object({id:Jn,nodeId:Jn,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:Zn,createdAt:Qn,updatedAt:Qn}).strict(),Xs=a.z.object({instanceId:Jn,runtimeKind:a.z.literal("docker"),state:a.z.enum(["pending","available","stopped","unavailable"]),sampledAt:Qn,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(),Ys=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(),Js=a.z.object({multiEntityAssignment:a.z.boolean().default(!1),privateModelCatalog:a.z.boolean().default(!1)}).strip(),Qs=a.z.object({enabled:a.z.boolean().default(!1),agentTools:a.z.boolean().default(!1),sessionRetention:a.z.boolean().default(!1),maxFileBytes:a.z.number().int().positive().default(33554432),maxBatchPaths:a.z.number().int().min(1).max(100).default(20)}).strip(),Zs=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:Ys.optional(),managedModels:Js.optional(),stories:Qs.optional(),codexManagedSettings:a.z.boolean().optional()}).strip(),eo=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:Qn.optional(),lastCongestedAt:Qn.optional()}).strip();a.z.object({ok:a.z.boolean().optional(),role:a.z.string().optional(),nodeId:Jn.optional(),platform:gi.optional(),arch:fi.optional(),protocolVersion:Mn.optional(),capabilities:Zs.optional(),build:Vi.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:eo.optional(),serverTime:Qn.optional()}).strip();const to=a.z.object({bindScope:a.z.enum(["loopback","all-ipv4"]),port:a.z.number().int().min(1).max(65535)}).strict(),no=to.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(),io=to;a.z.object({nodeId:Jn,joinToken:a.z.string().trim().min(1),expiresAt:Qn}).passthrough(),a.z.object({nodeId:Jn,keyId:Jn,secret:a.z.string().regex(/^[A-Za-z0-9_-]{32,128}$/),pairedAt:Qn}).strict();const so=a.z.object({id:Jn,keyId:Jn,name:a.z.string().trim().min(1).max(160).optional(),pairedAt:Qn,updatedAt:Qn,current:a.z.boolean()}).passthrough();a.z.object({keyId:Jn,revoked:a.z.literal(!0),revokedAt:Qn}).strict(),a.z.object({id:Jn,pairingKeyId:Jn,url:a.z.string().trim().min(1).max(2048),name:a.z.string().trim().min(1).max(160).optional(),enabled:a.z.boolean(),createdAt:Qn,updatedAt:Qn,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:Qn.optional(),lastConnectedAt:Qn.optional(),lastDisconnectedAt:Qn.optional(),error:a.z.string().optional()}).passthrough(),a.z.object({pairing:so,connection:a.z.object({id:Jn,pairingKeyId:Jn,url:a.z.string().trim().min(1).max(2048),name:a.z.string().trim().min(1).max(160).optional(),enabled:a.z.boolean(),createdAt:Qn,updatedAt:Qn}).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 oo=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:Ls,status:a.z.enum(["available","pull-required","unknown"]),localImage:oo.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 ro=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(ro)}).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 ao=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(),co=a.z.object({...ao.shape}).strict(),lo=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"}),uo=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(),po=a.z.object({id:Jn,name:a.z.string().trim().min(1).max(160),projectId:Jn.optional(),source:as,sourceSnapshot:a.z.record(a.z.string(),a.z.unknown()).default({}),modelSelection:ui,nodeId:Jn,runtimeId:Jn,imageSelection:pi.optional(),environmentSource:mi.optional(),environmentTemplateOrigin:Ii.optional(),imageSnapshot:Ms.optional(),imageProvisioning:js.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:Mn.optional(),instanceVersion:a.z.string().trim().max(80).optional(),build:Vi.optional(),runtimeVersion:Wi.optional(),ready:a.z.boolean().default(!1),capabilities:Gn.default(qn),appInventory:Oi.optional(),config:a.z.object({autoImportAgentConfigs:a.z.boolean().default(!0),codexConfigEnabled:a.z.boolean().default(!0),codexHomeMode:a.z.enum(["default","taskhandoff"]).default("taskhandoff"),defaultCodexPermissionMode:nt.default("ask"),codexSettings:Hn.optional(),aiSessionHistoryLimit:a.z.number().int().min(1).max(500).default(50),aiSessionAttachmentRetentionDays:a.z.number().int().min(0).max(365).default(30),aiSessionMaxFileAttachmentBytes:a.z.number().int().positive().max(ge).default(he)}).strict().default({autoImportAgentConfigs:!0,codexConfigEnabled:!0,codexHomeMode:"taskhandoff",defaultCodexPermissionMode:"ask",aiSessionHistoryLimit:50,aiSessionAttachmentRetentionDays:30,aiSessionMaxFileAttachmentBytes:he}),workspace:uo.default({status:"unknown"}),target:ao.default({strategy:"direct-port",status:"unknown"}),access:lo,apps:a.z.object({runningCount:a.z.number().int().min(0).default(0),problemCount:a.z.number().int().min(0).default(0),updatedAt:Qn.optional(),revision:a.z.number().int().min(0).optional()}).strict().default({runningCount:0,problemCount:0}),aiSessions:Lt.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:sn,deployments:a.z.array(rn).default([]),runtime:a.z.array(an).default([])}).strict()).default([]),recentRuns:a.z.array(cn).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:Qn.optional(),createdAt:Qn,updatedAt:Qn}).strict(),mo=a.z.union([po.transform(e=>({instance:e,gitWorkspaceProvisioningOperationId:void 0})),a.z.object({instance:po,gitWorkspaceProvisioningOperationId:Jn.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:yo(t.instance),..."string"==typeof t.gitWorkspaceProvisioningOperationId?{gitWorkspaceProvisioningOperationId:t.gitWorkspaceProvisioningOperationId}:{}}:yo(t)},mo);const ho="instance.lifecycle.snapshot",go=a.z.object({instanceId:po.shape.id,revision:a.z.number().int().min(0),updatedAt:Qn,status:po.shape.status.unwrap(),health:po.shape.health.unwrap(),connectionStatus:po.shape.connectionStatus.unwrap(),accessStatus:a.z.enum(["reachable","endpoint-unreachable"]),imageProvisioning:js.optional(),workspace:uo,runtime:po.shape.runtime.unwrap(),runtimeVersion:Wi.optional(),ready:a.z.boolean(),lastHeartbeatAt:Qn.optional()}).strict();function fo(e,t){return po.safeParse(yo(e,t))}function yo(e,t){if(!e||"object"!=typeof e||Array.isArray(e))return e;const n=e,i=new Set(Object.keys(po.shape)),s={};for(const[e,o]of Object.entries(n))i.has(e)?s[e]=o:t?.({instanceId:"string"==typeof n.id?n.id:void 0,field:e});if(n.capabilities&&"object"==typeof n.capabilities&&!Array.isArray(n.capabilities)){const e={...n.capabilities};Object.prototype.hasOwnProperty.call(e,"apps")&&(t?.({instanceId:"string"==typeof n.id?n.id:void 0,field:"capabilities.apps"}),delete e.apps),s.capabilities=Xn(e)}else s.capabilities=Xn(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=_o(e,["id","name","kind","source","availability","diagnosticCode"]);return!i||"object"!=typeof i||Array.isArray(i)?i:{...i,capabilities:_o(e.capabilities,["automation","supportsCwdSelection"])}}):i.items,issues:Array.isArray(i.issues)?i.issues.map(e=>_o(e,["code","message"])):i.issues},o=Oi.safeParse(s);return o.success?o.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,o=as.options.find(e=>e.shape.type.value===s);if(!o)return e;const r="local-folder"===s?["type","localFolderId","path","ownerNodeId"]:"git-template"===s?["type","url","templateId","ref","auth","clone"]:["type","repositoryId","url","provider","ref","auth","clone"],a=_o(i,r);if("local-folder"!==s){const e=function(e,t,n){const i=e&&"object"==typeof e&&!Array.isArray(e)?e:void 0,s=is.safeParse(_o(i,["type","name","commit"]));if(s.success)return s.data;const o="string"==typeof i?.commit?i.commit.trim():"",r="string"==typeof i?.name?i.name.trim():"",a=o?is.safeParse({type:"commit",commit:o}):r?is.safeParse({type:"tag"===i?.type?"tag":"branch",name:r}):is.safeParse({type:"branch",name:"main"});return a.success?(t?.({instanceId:n,field:"source.ref"}),a.data):void 0}(i.ref,t,n),s=Io(ss,_o(i.auth,["type","secretId"]),"source.auth",t,n),o=Io(os,_o(i.clone,["depth","submodules","lfs","subdirectory"]),"source.clone",t,n);e?a.ref=e:delete a.ref,s?a.auth=s:delete a.auth,o?a.clone=o:delete a.clone}const c=Io(o,a,"source",t,n);return c?(Object.keys(i).some(e=>!r.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=Io(Vi,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=Io(Pt,e,`aiSessions.sessions.${i}`,t,n);return s?[s]:[]}):[],o={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:Qn.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"}),Lt.parse(o)}(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,o)=>{const r=Io(i,e,`${s}.${o}`,t,n);return r?[r]:[]}):[],o=Array.isArray(i.configs)?i.configs.flatMap((e,i)=>{if(!e||"object"!=typeof e||Array.isArray(e))return[];const o=e;Object.keys(o).some(e=>!["configHash","config","deployments","runtime"].includes(e))&&t?.({instanceId:n,field:`triggers.configs.${i}`});const r=function(e,t,n,i){if(!e||"object"!=typeof e||Array.isArray(e))return;const s=e,o=_o(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"];o.source=_o(e,t)}return o.action=_o(s.action,["promptTemplate"]),o.policy=_o(s.policy,["cooldownMs","maxConcurrentRuns","whenBusy"]),Io(sn,o,t,n,i)}(o.config,`triggers.configs.${i}.config`,t,n);return"string"==typeof o.configHash&&r?[{configHash:o.configHash,config:r,deployments:s(o.deployments,rn,`triggers.configs.${i}.deployments`),runtime:s(o.runtime,an,`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:o,recentRuns:s(i.recentRuns,cn,"triggers.recentRuns")}}(n.triggers,t,"string"==typeof n.id?n.id:void 0),s.apps=Io(po.shape.apps.unwrap(),_o(n.apps,["runningCount","problemCount","updatedAt","revision"]),"apps",t,"string"==typeof n.id?n.id:void 0)||{runningCount:0,problemCount:0},s.config=Io(po.shape.config.unwrap(),_o(n.config,["autoImportAgentConfigs","codexConfigEnabled","codexHomeMode","defaultCodexPermissionMode","codexSettings","aiSessionHistoryLimit","aiSessionAttachmentRetentionDays","aiSessionMaxFileAttachmentBytes"]),"config",t,"string"==typeof n.id?n.id:void 0)||{autoImportAgentConfigs:!0,codexConfigEnabled:!0,codexHomeMode:"taskhandoff",defaultCodexPermissionMode:"ask",aiSessionHistoryLimit:50,aiSessionAttachmentRetentionDays:30,aiSessionMaxFileAttachmentBytes:he},s.modelSelection=Io(ui.unwrap(),_o(n.modelSelection,["modelEntityIds","codexModelHash","claudeModelHash","opencodeModelHash"]),"modelSelection",t,"string"==typeof n.id?n.id:void 0)||{},s.imageSnapshot=function(e,t,n,i){if(!e||"object"!=typeof e||Array.isArray(e))return e;const s=e,o=function(e){if(!e||"object"!=typeof e||Array.isArray(e))return e;const t=e,n=new Set(["id","origin","name","description","localizedDescriptions","cover","reference","repository","tag","image","registry","pullPolicy","capabilities","optionalApps","defaultEnv","labels","createdAt","updatedAt"]);for(const e of Object.keys(t))n.has(e);"string"==typeof t.id&&t.id;const i="string"==typeof t.image?t.image:void 0;Object.prototype.hasOwnProperty.call(t,"registry");let s,o="string"==typeof t.reference?t.reference:i;if(o)try{o=ai(o)}catch{if(!o.includes("@")&&o.lastIndexOf(":")<=o.lastIndexOf("/"))try{o=ai(`${o}:latest`)}catch{}}try{s=o?ci(o):void 0}catch{}return{id:t.id,origin:"custom",name:t.name,description:t.description,localizedDescriptions:t.localizedDescriptions,cover:_o(t.cover,["kind","key","url","mediaType","digest"]),reference:s?.reference??o,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:r,...a}=o,c=s.requestedReference??r;let d;try{d="string"==typeof c?ci(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?_o(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 o="string"==typeof n.imageId?{img_default:"market_taskhandoff_browser",img_codex:"market_taskhandoff_codex",img_ai:"market_taskhandoff_ai"}[n.imageId]||n.imageId:void 0,r=_o(n.imageSelection,["imageId","tag"]);s.imageSelection=r||(o?{imageId:o,tag:s.imageSnapshot?.tag}:void 0),s.imageProvisioning=Io(js,_o(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},o=s(i.desiredVersion);if(!o)return void t?.({instanceId:n,field:"runtimeVersion.desiredVersion"});const r=new Set(Wi.shape.phase.options),a="string"==typeof i.phase?i.phase:"pending",c=r.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,o="string"==typeof e.message?e.message.trim().slice(0,4096):"";if(o){const i=new Set(Gi.shape.code.options),r="string"==typeof e.code&&i.has(e.code)?e.code:"INSTANCE_RUNTIME_INSTALL_FAILED";r!==e.code&&t?.({instanceId:n,field:"runtimeVersion.error.code"});const a=s(e.expectedVersion),c=s(e.actualVersion);d={code:r,message:o,...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:o,...s(i.actualVersion)?{actualVersion:s(i.actualVersion)}:{},retryable:!1});const l=s(i.actualVersion),u=Qn.safeParse(i.lastAttemptAt),p=Qn.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:o,...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=Io(uo,n.workspace,"workspace",t,"string"==typeof n.id?n.id:void 0)||{status:"unknown"},s.environmentSource=Io(mi,n.environmentSource,"environmentSource",t,"string"==typeof n.id?n.id:void 0),s.environmentTemplateOrigin=Io(Ii,n.environmentTemplateOrigin,"environmentTemplateOrigin",t,"string"==typeof n.id?n.id:void 0),s.runtime=Io(po.shape.runtime.unwrap(),n.runtime,"runtime",t,"string"==typeof n.id?n.id:void 0)||{labels:{}},s.target=Io(ao,_o(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=Io(lo,_o(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(po.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 Io(e,t,n,i,s){if(!t||"object"!=typeof t||Array.isArray(t))return;let o=structuredClone(t),r=!1;for(let t=0;t<20;t+=1){const t=e.safeParse(o);if(t.success)return r&&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=Ao(o,e.path);if(t&&"object"==typeof t&&!Array.isArray(t))for(const n of e.keys)Object.prototype.hasOwnProperty.call(t,n)&&(delete t[n],a=!0,r=!0)}if(!a){const r=structuredClone(o);let a=!1;for(const e of t.error.issues){if(!e.path.length||"string"!=typeof e.path.at(-1))continue;const t=Ao(r,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(r);if(t.success)return i?.({instanceId:s,field:n}),t.data}break}}i?.({instanceId:s,field:n})}function Ao(e,t){let n=e;for(const e of t){if(!n||"object"!=typeof n)return;n=n[e]}return n}function _o(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 Eo=a.z.object({instanceId:Jn.optional(),projectId:Jn.optional(),source:as.optional(),nodeId:Jn.optional(),runtimeId:Jn.optional(),imageSelection:pi.optional(),instanceVersion:a.z.string().trim().max(80).optional(),protocolVersion:Mn,build:Vi.optional(),controlMode:a.z.enum(["standalone","controlled"]).default("controlled"),capabilities:Gn.default(qn),appInventory:Oi.optional(),target:co.optional(),workspace:uo.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)=>{Ln.has(e.protocolVersion)&&!e.appInventory&&t.addIssue({code:"custom",path:["appInventory"],message:"Current protocol register payload requires appInventory."})}),wo=a.z.object({status:po.shape.status.optional(),health:po.shape.health.optional(),protocolVersion:Mn,build:Vi.optional(),capabilities:po.shape.capabilities.optional(),appInventory:Oi.optional(),apps:po.shape.apps.optional(),aiSessions:po.shape.aiSessions.optional(),triggers:po.shape.triggers.optional(),workspace:uo.optional(),target:co.optional(),processIncarnationId:a.z.string().trim().min(1).max(120).optional()}).strict().superRefine((e,t)=>{Ln.has(e.protocolVersion)&&!e.appInventory&&t.addIssue({code:"custom",path:["appInventory"],message:"Current protocol heartbeat payload requires appInventory."})}),To=a.z.enum(["web","telegram","wechat","dingding","lark"]);function bo(e,t){let n=Oo(t);for(let t=0;t<100;t+=1){const t=e.safeParse(n);if(t.success)return t;const i=So(t.error.issues);let s=!1;for(const e of i){const t=No(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 So(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)=>vo(t)<vo(e)?t:e);n.push(...So(s,[...t,...i.path]))}return n}function vo(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(vo)):1)},0)}function No(e,t){let n=e;for(const e of t){if(!n||"object"!=typeof n)return;n=n[e]}return n}function Oo(e){return Array.isArray(e)?e.map(Oo):e&&"object"==typeof e?Object.getPrototypeOf(e)!==Object.prototype&&null!==Object.getPrototypeOf(e)?e:Object.fromEntries(Object.entries(e).map(([e,t])=>[e,Oo(t)])):e}function zo(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 o=l.spawn(e,t,{stdio:["ignore","pipe","pipe"]}),r=[],a=[];let c=!1;const d=n.timeoutMs?setTimeout(()=>{c=!0,o.kill("SIGKILL")},n.timeoutMs):void 0;let u=!1;const p=()=>{u=!0,o.kill("SIGKILL")},m=()=>{d&&clearTimeout(d),n.signal?.removeEventListener("abort",p)};n.signal?.addEventListener("abort",p,{once:!0}),d?.unref?.(),o.stdout.on("data",e=>r.push(Buffer.from(e))),o.stderr.on("data",e=>a.push(Buffer.from(e))),o.on("error",e=>{m(),s(e)}),o.on("close",t=>{m();const o={stdout:Buffer.concat(r).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:o}),void s(t)}if(u)return void s(Object.assign(new Error(`${e} was aborted.`),{code:"RUNTIME_COMMAND_ABORTED",details:o}));if(0===t)return void i(o);const d=new Error(o.stderr||`${e} exited with code ${t}`);Object.assign(d,{statusCode:502,code:"RUNTIME_EXECUTOR_FAILED",details:o}),s(d)})})}a.z.object({id:Jn,channel:To,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:Qn,updatedAt:Qn}).strict(),a.z.object({id:Jn,channel:To,bridgeId:Jn.optional(),chatSessionId:a.z.string().trim().min(1).max(240),userId:a.z.string().trim().max(240).optional(),activeProjectId:Jn.optional(),activeInstanceId:Jn.optional(),activeAiSessionId:a.z.string().trim().min(1).max(120).optional(),lastUsedAt:Qn,createdAt:Qn,updatedAt:Qn}).strict(),a.z.object({source:a.z.object({type:a.z.literal("chat-gateway").default("chat-gateway"),channel:To,bridgeId:Jn.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(Qe).max(6).default([])}).strict().superRefine((e,t)=>{e.attachments.reduce((e,t)=>e+("inline"===t.source.type?t.size:0),0)>fe&&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:Jn,aiSessionId:a.z.string().trim().min(1).max(120)}).strict().optional()}).strict(),a.z.object({id:Jn,instanceId:Jn,projectId:Jn.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:Qn}).strict();const Co=(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 o=[];let r,a=!1,c=!1;try{r=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,r.kill("SIGKILL")},n.timeoutMs):void 0,l=()=>{c=!0;try{r.kill("SIGKILL")}catch{}};n.signal?.addEventListener("abort",l,{once:!0}),d?.unref?.(),r.onData(e=>{o.push(e),n.onData?.(e)}),r.onExit(({exitCode:t})=>{d&&clearTimeout(d),n.signal?.removeEventListener("abort",l);const r={stdout:o.join(""),stderr:""};a?s(Object.assign(new Error(`${e} timed out after ${n.timeoutMs}ms`),{statusCode:504,code:"RUNTIME_COMMAND_TIMEOUT",details:r})):c?s(Object.assign(new Error(`${e} was aborted.`),{code:"RUNTIME_COMMAND_ABORTED",details:r})):0!==t?s(Object.assign(new Error(r.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:r})):i(r)})});class Ro{inFlight=new Map;runCommand;runTerminalCommand;constructor(e=zo,t){this.runCommand=e,this.runTerminalCommand=t||function(e){return e===zo?Co: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=ai(e),o=this.inFlight.get(s);if(o)return t&&(o.phaseListeners.add(t),o.phase&&t(o.phase)),n&&(o.terminalListeners.add(n),o.terminalTail&&n({sequence:o.terminalSequence,data:o.terminalTail,replay:!0})),this.bindAbort(o,i),o.promise;const r=new Set,a=new Set;t&&r.add(t),n&&a.add(n);const c={promise:Promise.resolve(void 0),controller:new AbortController,abortDisposers:new Set,phaseListeners:r,terminalListeners:a,terminalSequence:0,terminalTail:""};return this.bindAbort(c,i),c.promise=this.ensureOnce(s,e=>{c.phase=e,r.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}),o=!1;s||(t("pulling-image"),await this.runTerminalCommand("docker",["pull",e],{cols:120,rows:40,signal:i,onData:n}),o=!0,s=await this.inspect(e,i)),t("resolving-image");const r=(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=r?.split("@").at(-1)?.toLowerCase();return{requestedReference:e,...c?{resolvedDigest:c}:{},resolvedReference:r||e,pulled:o}}async inspect(e,t){const n=await this.runCommand("docker",["image","inspect",e,"--format","{{json .}}"],{signal:t});return JSON.parse(n.stdout.trim()||"{}")}}function xo(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 ko="/run/task-handoff/bootstrap",Do=`${ko}/entrypoint.sh`,Po="/bin/bash",Lo=`${ko}/runtime-installer.mjs`,Mo="/opt/task-handoff/instance-runtime";function jo(e,t){return{role:"runtime",name:`${nr(e)}-runtime`,mountPath:Mo,labels:{"task-handoff.owner":"task-handoff","task-handoff.instance-id":e,"task-handoff.node-id":t,"task-handoff.volume-role":"runtime"}}}function Uo(e){return function(e,t,n){const i=nr(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:o})=>({role:n,name:`${i}-${s}`,mountPath:o,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 Fo=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 $o(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),o=-1===n?"":e.slice(n+1);Fo.has(i)&&s.add(`Config.Env.${i}`),t.some(e=>e&&o.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))(Fo.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 Ho{runCommand;publishHost;images;launcherAssetsDir;portResolutionRetryDelaysMs;constructor(e=zo,t={}){this.runCommand=e,this.images=t.imageService||new Ro(e),this.publishHost=t.publishHost||"127.0.0.1",this.launcherAssetsDir=t.launcherAssetsDir||Wo(),this.portResolutionRetryDelaysMs=t.portResolutionRetryDelaysMs?.length?t.portResolutionRetryDelaysMs:[0,100,250,500,1e3]}async start(e){or(e);const t=e.instance.runtime.containerName||nr(e.instance.id),i=await this.inspectContainerForStart(t);if(i){er(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 Yo("RUNTIME_EXECUTOR_FAILED",`Docker container ${t} belongs to ${s||"an unknown instance"}, not ${e.instance.id}.`);const o=i.mounts.find(e=>"bind"===e.type&&e.destination===ko);if("1"!==i.labels["task-handoff.bootstrap-abi"]||i.entrypoint[0]!==Po||i.command[0]!==Do||!o?.source||n.resolve(o.source)!==n.resolve(this.launcherAssetsDir)){const n=new Set(Uo(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 Yo("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",sr(e,t,{publishHost:this.publishHost,launcherAssetsDir:this.launcherAssetsDir}))}catch(e){throw Yo("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 Yo("GIT_WORKSPACE_PROVISIONING_MISSING",`Git workspace provisioning input is missing for ${e.instance.id}.`);const s=`${nr(e.instance.id)}-git-provision`,o=t.mkdtempSync(n.join(c.tmpdir(),"task-handoff-git-auth-"));t.chmodSync(o,448);try{await this.runCommand("docker",["rm","-f",s],{timeoutMs:3e4}).catch(()=>({stdout:"",stderr:""})),this.materializeGitProvisioningAuth(o,i);const t=function(e,t,i,s={}){const o=e.gitWorkspaceProvisioning;if(!o||"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 r=n.resolve(s.launcherAssetsDir||Wo()),a=Uo(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=${r},dst=${ko},readonly`,"--tmpfs","/run/task-handoff/git-runtime:rw,nosuid,nodev,exec,mode=0700"];o.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",o.remoteUrl),d("TASK_HANDOFF_INSTANCE_ID",e.instance.id),"commit"===o.ref.type?d("TASK_HANDOFF_GIT_COMMIT",o.ref.commit):d("TASK_HANDOFF_GIT_REF",o.ref.name),o.clone.depth&&d("TASK_HANDOFF_GIT_DEPTH",String(o.clone.depth)),d("TASK_HANDOFF_GIT_SUBMODULES",o.clone.submodules?"true":"false"),d("TASK_HANDOFF_GIT_LFS",o.clone.lfs?"true":"false"),o.clone.subdirectory&&d("TASK_HANDOFF_WORKSPACE_SUBDIRECTORY",o.clone.subdirectory),c.push("--entrypoint","/bin/bash",e.instance.environmentTemplateOrigin?.imageId||e.image.resolvedReference||e.image.requestedReference,`${ko}/git-provision.sh`),c}(e,s,o,{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 Yo("GIT_WORKSPACE_PROVISIONING_TIMEOUT",`Git workspace provisioning timed out for ${e}.`);if("RUNTIME_COMMAND_ABORTED"===i)return Yo("GIT_WORKSPACE_PROVISIONING_CANCELLED",`Git workspace provisioning was cancelled for ${e}.`);const s=Qo(t)||"",o=s.match(/TASK_HANDOFF_GIT_PROVISIONING_ERROR=([A-Z_]+)/)?.[1];return Yo(`GIT_WORKSPACE_PROVISIONING_${o&&Jo.has(o)?o:"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(o,{recursive:!0,force:!0})}}materializeGitProvisioningAuth(e,i){const s=(e,i,s)=>{const o=n.join(e,i);t.writeFileSync(o,s,{encoding:"utf8",mode:384}),t.chmodSync(o,384)};i.credentials.forEach((i,o)=>{const r=n.join(e,`credential-${o}`);if(t.mkdirSync(r,{recursive:!0,mode:448}),t.chmodSync(r,448),s(r,"scope.json",JSON.stringify(i.payload.credential.scope)),"https-token"===i.payload.secret.kind)return s(r,"username",i.payload.secret.username),void s(r,"token",i.payload.secret.token);s(r,"private-key",i.payload.secret.privateKey),s(r,"known_hosts",i.payload.secret.pinnedKnownHosts),i.payload.secret.passphrase&&s(r,"passphrase",i.payload.secret.passphrase),s(r,"ssh-askpass.sh",`#!/usr/bin/env bash\ncat /run/task-handoff/git-runtime/credential-${o}/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:""})),Yo("RUNTIME_EXECUTOR_FAILED",`Could not preserve Docker container ${t} before bootstrap migration.`,e)}try{const s=await this.runCommand("docker",sr(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:""})),Yo("RUNTIME_EXECUTOR_FAILED",`Could not recreate Docker container ${t} with the node-agent bootstrap.`,e)}}async inspectContainerConfigSecurity(e,t){$o(await this.runCommand("docker",["inspect","--format","{{json .}}",e]).then(e=>JSON.parse(e.stdout||"{}")).catch(t=>{throw Yo("ENVIRONMENT_TEMPLATE_CONTAINER_INSPECT_FAILED",`Could not inspect Docker container ${e}.`,t)}),t)}async inspectImageConfigSecurity(e,t){$o(await this.runCommand("docker",["image","inspect","--format","{{json .}}",e]).then(e=>JSON.parse(e.stdout||"{}")).catch(e=>{throw Yo("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 Yo("ENVIRONMENT_TEMPLATE_CONTAINER_NOT_FOUND",`Docker container ${e} does not exist.`);er(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 Yo("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=Ko(n.Os),o=Go(n.Architecture),r="number"==typeof n.Size?n.Size:Number.NaN;if(!/^sha256:[a-f0-9]{64}$/.test(i)||!s||!o||!Number.isSafeInteger(r)||r<0)throw new Error("Docker image inspection did not return a valid immutable identity.");return{imageId:i,platform:s,architecture:o,sizeBytes:r}}catch(e){throw Yo("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,Xo(n)]),await this.runCommand("docker",["image","rm",e]),n}catch(e){const t=Qo(e)?.toLowerCase()||"";if(t.includes("no such image")||t.includes("no such object"))return;throw Yo("ENVIRONMENT_TEMPLATE_UNTAG_FAILED","Could not remove the environment template tag.",e)}}async garbageCollectEnvironmentTemplateImage(e){try{try{await this.runCommand("docker",["image","rm",Xo(e)])}catch(e){const t=Qo(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=Qo(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 Yo("ENVIRONMENT_TEMPLATE_GC_FAILED","Could not garbage collect the environment template image.",e)}}async createPersistentVolumes(e,t=new Set){const n=jo(e.instance.id,e.node?.id||"node_unset");for(const i of[...Uo(e),n])await this.createVolume(i),await this.validateOwnedVolume(e.instance.id,i,t.has(i.name))}async createRuntimeVolume(e){await this.createVolume(jo(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 Yo("INSTANCE_VOLUME_CREATE_FAILED",`Could not create managed volume ${e.name}.`,t)}}async validatePersistentVolumes(e,t){for(const n of Uo(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=jo(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 Yo("INSTANCE_VOLUME_INSPECT_FAILED",`Could not inspect managed volume ${t.name}.`,e)}try{const s=JSON.parse(i.stdout||"{}"),o=s.Labels&&"object"==typeof s.Labels&&!Array.isArray(s.Labels)?s.Labels:{},r=s.Name===t.name&&"task-handoff"===o["task-handoff.owner"]&&o["task-handoff.instance-id"]===e&&o["task-handoff.volume-role"]===t.role,a=n&&s.Name===t.name&&0===Object.keys(o).length;if(!r&&!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",o=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":o,"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||nr(e.instance.id),n=await this.inspectContainerId(t);if(!n)throw Yo("INSTANCE_RUNTIME_ENDPOINT_UNAVAILABLE",`Docker container ${t} does not exist.`);return er(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||nr(e.instance.id);try{await this.runCommand("docker",["stop",t])}catch(e){if(!Zo(e))throw Yo("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){or(e);const n=e.instance.runtime.containerName||nr(e.instance.id),i=await this.inspectContainerId(n);if(!i)throw Yo("INSTANCE_RUNTIME_RESTART_FAILED",`Docker container ${n} does not exist.`);er(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 Yo("INSTANCE_RUNTIME_RESTART_FAILED",`Docker container identity changed while restarting ${n}.`);return er(n,s,t,"after restart","INSTANCE_RUNTIME_RESTART_FAILED"),this.runningResult(e,n,s)}async delete(e,t){const n=e.instance.runtime.containerName||nr(e.instance.id),i=await this.inspectContainerForStart(n),s=new Set;if(i){er(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 Yo("RUNTIME_EXECUTOR_FAILED",`Docker container ${n} belongs to ${t||"an unknown instance"}, not ${e.instance.id}.`);for(const t of Uo(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(!Zo(e))throw Yo("RUNTIME_EXECUTOR_FAILED",`Could not delete Docker container ${n}.`,e)}}const o=[];for(const n of Uo(e))if(t.deleteVolumes)try{const t=await this.inspectVolumeForDelete(n.name);if(!t){o.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,r=s.has(n.name)&&t.name===n.name&&0===Object.keys(t.labels).length;if(!i&&!r)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]),o.push({role:n.role,name:n.name,mountPath:n.mountPath,status:"deleted"})}catch(e){o.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 o.push({role:n.role,name:n.name,mountPath:n.mountPath,status:"retained"});return await this.deleteRuntimeVolume(e),wi.parse({instanceId:e.instance.id,containerDeleted:!0,completed:o.every(e=>"failed"!==e.status),deletedVolumes:o.filter(e=>"deleted"===e.status||"missing"===e.status),retainedVolumes:o.filter(e=>"retained"===e.status),volumeResults:o})}async deleteRuntimeVolume(e){const t=jo(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 Yo("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 Yo("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=Qo(e)?.toLowerCase()||"";return t.includes("no such volume")||t.includes("no such object")}(t))return;throw Yo("INSTANCE_VOLUME_INSPECT_FAILED",`Could not inspect managed volume ${e}.`,t)}}async installRuntime(e){const t=await this.installRuntimeRelease(e);er(e.containerName,t,e.expectedContainerId,"before runtime restart","INSTANCE_RUNTIME_RESTART_FAILED");try{await this.runCommand("docker",["restart",t])}catch(t){throw Yo("INSTANCE_RUNTIME_RESTART_FAILED",`Could not restart Docker container ${e.containerName}.`,t)}const n=await this.inspectContainerId(e.containerName);if(!n||n!==t)throw Yo("INSTANCE_RUNTIME_RESTART_FAILED",`Docker container identity changed while updating ${e.containerName}.`);return er(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 Yo("INSTANCE_RUNTIME_INSTALL_FAILED",`Docker container ${e.containerName} does not exist.`);er(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",Lo,"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 Yo("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 Yo("INSTANCE_RUNTIME_INSTALL_FAILED",`Docker container identity changed while installing ${e.containerName}.`);return er(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",Lo,"verify-active"]).catch(()=>{});if(!n?.stdout)return{containerId:t};try{const e=bo(Ki,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 Yo("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 Yo("INSTANCE_BASE_RUNTIME_INCOMPATIBLE","Could not inspect the Docker runtime target.",e)});t||=e.OSType,n||=e.Architecture}const i=Ko(t),s=Go(n);if(!i||!s)throw Yo("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 Yo("INSTANCE_RUNTIME_INSTALL_FAILED",`Docker container ${t} does not exist.`);if(er(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 Yo("INSTANCE_RUNTIME_INSTALL_FAILED",`Docker container ${t} does not expose its immutable image identity.`);const s="/run/task-handoff/runtime-rescue-artifact.tar.gz",o=[`test -r ${Do}`,`test -r ${ko}/instance-launcher.sh`,`test -r ${Lo}`,`install -d -o root -g root -m 0755 ${Mo} ${Mo}/releases ${Mo}/staging ${Mo}/incoming`,`chown -R root:root ${Mo}`,`chmod -R go-w ${Mo}`,`node ${Lo} 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",Po,i.image,"-ceu",o,"task-handoff-runtime-rescue",s,e.identity.version,e.identity.sha256,e.identity.platform,e.identity.arch,String(e.identity.launcherAbi)])}catch(n){throw Yo("INSTANCE_RUNTIME_INSTALL_FAILED",`Could not rescue controlled-instance ${e.identity.version} in stopped container ${t}.`,n)}const r=await this.inspectContainerForStart(t);if(!r)throw Yo("INSTANCE_RUNTIME_INSTALL_FAILED",`Docker container ${t} disappeared during runtime install recovery.`);if(er(t,r.id,i.id,"after runtime install recovery","INSTANCE_RUNTIME_INSTALL_FAILED"),r.running)throw Yo("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 Yo("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Docker container ${e} does not exist.`);er(e,n,t,"before runtime launcher install","INSTANCE_BASE_RUNTIME_INCOMPATIBLE");try{await this.runCommand("docker",["exec","--user","0",n,"bash","-ceu",`test -r ${Do}; test -r ${ko}/instance-launcher.sh; test -r ${Lo}; 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 Yo("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Could not install the runtime launcher in ${e}.`,t)}const i=await this.inspectContainerId(e);if(i!==n)throw Yo("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Docker container identity changed while installing the runtime launcher in ${e}.`);er(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(Zo(t))return;throw Yo("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(Zo(t))return;throw Yo("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]:[],o=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:o,labels:n,mounts:i}}catch(t){throw Yo("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 Bo(s);try{const n=qo((await this.runCommand("docker",["port",e,t])).stdout);if(n)return n}catch(e){n=e}try{const n=Vo((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 Yo("RUNTIME_EXECUTOR_FAILED",`Docker container ${e} does not publish ${t}.`);throw Yo("RUNTIME_EXECUTOR_FAILED",`Could not resolve the published port for Docker container ${e}.`,n)}}function qo(e){const t=e.split(/\r?\n/).find(Boolean);return t?.match(/:(\d+)$/)?.[1]}function Vo(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 Bo(e){return new Promise(t=>setTimeout(t,e))}function Ko(e){return"linux"===e||"darwin"===e?e:"windows"===e||"win32"===e?"win32":void 0}function Go(e){return"amd64"===e||"x86_64"===e||"x64"===e?"x64":"arm64"===e||"aarch64"===e?"arm64":void 0}function Wo(){const e=("undefined"==typeof document?require("url").pathToFileURL(__filename).href:O&&"SCRIPT"===O.tagName.toUpperCase()&&O.src||new URL("cli.js",document.baseURI).href)?n.dirname(s.fileURLToPath("undefined"==typeof document?require("url").pathToFileURL(__filename).href:O&&"SCRIPT"===O.tagName.toUpperCase()&&O.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 Xo(e){return`task-handoff/environment-image:${e.replace(/^sha256:/,"")}`}function Yo(e,t,n){const i=Qo(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 Jo=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 Qo(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 Zo(e){const t=Qo(e)?.toLowerCase()||"";return t.includes("no such container")||t.includes("no such object")}function er(e,t,n,i,s){if(n&&t!==n)throw Yo(s,`Docker container ${e} identity mismatch ${i}: expected ${n}, got ${t}.`)}async function tr(e=zo){return async function(e=zo){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||"",o="<none>"!==n&&"<none>"!==i?`${n}:${i}`:s,r="<none>"!==n&&t.Digest&&"<none>"!==t.Digest?[`${n}@${t.Digest}`]:[];return{repository:n,tag:i,id:s,createdSince:t.CreatedSince,size:t.Size,sizeBytes:xo(t.Size),reference:o,repoDigests:r}}).filter(e=>Boolean(e.reference))}(e)}function nr(e){return`task-handoff-${e.replace(/[^a-zA-Z0-9_.-]/g,"-")}`}function ir(e,t,n){e.push("-e",`${t}=${n}`)}function sr(e,t,i={}){const s=i.publishHost||"127.0.0.1",o=n.resolve(i.launcherAssetsDir||Wo()),r=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=${r}`,"--label",`task-handoff.runtime-id=${a}`,"--label",`task-handoff.image-id=${e.image.id}`,"--label","task-handoff.bootstrap-abi=1","--shm-size","1gb","--security-opt","seccomp=unconfined","--network","bridge","--no-healthcheck","--add-host","host.docker.internal:host-gateway","--tmpfs","/tmp:rw,nosuid,nodev,exec,mode=1777","-p",`${s}::8080`];if(!e.privateConfigPath)throw Object.assign(new Error(`Instance ${e.instance.id} private config was not materialized.`),{statusCode:409,code:"INSTANCE_PRIVATE_CONFIG_MISSING"});c.push("--mount",`type=bind,src=${e.privateConfigPath},dst=/run/task-handoff/instance-private-config.json,readonly`,"--mount",`type=bind,src=${o},dst=${ko},readonly`,"--entrypoint",Po);for(const t of Uo(e))c.push("--mount",`type=volume,src=${t.name},dst=${t.mountPath}`);const d=jo(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:r,TASK_HANDOFF_RUNTIME_ID:a,TASK_HANDOFF_IMAGE_ID:e.image.id,TASK_HANDOFF_INSTANCE_LAUNCHER:`${ko}/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))ir(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"}`):(ir(c,"TASK_HANDOFF_PROJECT_SOURCE",JSON.stringify(e.project.source)),ir(c,"TASK_HANDOFF_WORKSPACE_POLICY",JSON.stringify(e.project.workspacePolicy)),ir(c,"TASK_HANDOFF_GIT_URL",e.project.source.url),"commit"===e.project.source.ref.type?ir(c,"TASK_HANDOFF_GIT_COMMIT",e.project.source.ref.commit):ir(c,"TASK_HANDOFF_GIT_REF",e.project.source.ref.name),e.project.source.clone?.depth&&ir(c,"TASK_HANDOFF_GIT_DEPTH",String(e.project.source.clone.depth)),ir(c,"TASK_HANDOFF_GIT_SUBMODULES",e.project.source.clone?.submodules?"true":"false"),ir(c,"TASK_HANDOFF_GIT_LFS",e.project.source.clone?.lfs?"true":"false"),e.project.source.clone?.subdirectory&&ir(c,"TASK_HANDOFF_WORKSPACE_SUBDIRECTORY",e.project.source.clone.subdirectory));const u={...e.image.labels["task-handoff.image.profile"]?{TASK_HANDOFF_IMAGE_PROFILE:e.image.labels["task-handoff.image.profile"]}:{},TASK_HANDOFF_IMAGE_CAPABILITIES:e.image.capabilities.join(",")};for(const[t,n]of Object.entries(e.image.defaultEnv))t in u||ir(c,t,n);for(const[e,t]of Object.entries(u))ir(c,e,t);return c.push(i.imageReference||e.instance.environmentTemplateOrigin?.imageId||e.image.resolvedReference||e.image.requestedReference,Do,"task-handoff","web"),c}function or(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 rr="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 ar="app-session.snapshot",cr="app-session.patch",dr="app-session.removed",lr=a.z.enum(["created","starting","running","stopping","stopped","exited","failed","closed","terminated","unknown"]),ur=a.z.enum(["tty","vnc","web"]);a.z.object({mode:ur,url:a.z.string().trim().min(1).max(4096),token:a.z.string().trim().min(1).max(512),expiresAt:a.z.string().datetime()}).strict(),a.z.object({revoked:a.z.boolean()}).strict();const pr=new Set(["stopped","failed","exited","closed","terminated"]),mr=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(),hr=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:lr.default("unknown"),bindings:a.z.array(mr).max(40).default([]),workspace:a.z.object({cwd:a.z.string().trim().max(4096).optional()}).strict().optional(),createdAt:a.z.string().datetime().optional(),updatedAt:a.z.string().datetime().optional()})),gr=a.z.object({runningCount:a.z.number().int().min(0).default(0),problemCount:a.z.number().int().min(0).default(0),sessions:a.z.array(hr).default([]),updatedAt:a.z.string().datetime()}).strict(),fr=a.z.object({streamId:a.z.string().trim().min(1).max(240),revision:a.z.number().int().min(0),lastEventAt:a.z.string().datetime(),snapshot:gr}).strict();gr.pick({runningCount:!0,problemCount:!0,updatedAt:!0}).extend({revision:a.z.number().int().min(0).optional()});const yr=a.z.enum(["app-session-created","app-session-updated","app-session-deleted","app-session-recovered","control-action","heartbeat-sync","startup"]),Ir=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:yr}).strict(),Ar=a.z.object({meta:Ir,snapshot:gr}).strict(),_r=a.z.object({meta:Ir,session:hr}).strict(),Er=a.z.object({meta:Ir,sessionId:a.z.string().trim().min(1).max(160),tombstone:hr.optional(),expiresAt:a.z.string().datetime().optional()}).strict();function wr(e,t=(new Date).toISOString()){const n=e.map(e=>function(e){const t=br("string"==typeof e.status?e.status:void 0),n="string"==typeof e.id?e.id:"",i=function(e){const t=zr(e.workspace),n=zr(e.tty),i=zr(e.launch),s=zr(e.ai),o=zr(s.claude),r=Cr(t.cwd)||Cr(n.cwd)||Cr(o.cwd)||Cr(i.cwd);return r?{cwd:r}:void 0}(e),{workspace:s,...o}=e;return hr.parse({...o,status:t,bindings:Or([...(r=e.bindings,Array.isArray(r)?r.flatMap(e=>{const t=mr.safeParse(e);return t.success?[t.data]:[]}):[]),...n?[{type:"app-session",id:n}]:[],...Nr(e)]),...i?{workspace:i}:{}});var r}(e));return gr.parse({runningCount:n.filter(e=>"running"===e.status).length,problemCount:n.filter(e=>"failed"===e.status).length,sessions:n,updatedAt:t})}function Tr(e,t=(new Date).toISOString()){return wr(e.filter(e=>Sr("string"==typeof e.status?e.status:void 0)),t)}function br(e){const t=(e||"unknown").trim().toLowerCase();return"ended"===t?"closed":"terminating"===t?"stopping":lr.options.includes(t)?t:"unknown"}function Sr(e){return!pr.has(br(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 Nr(e){const t=zr(e.ai),n=zr(t.claude),i=zr(t.appServer),s=zr(e.launch),o=[],r=Cr(zr(s.aiSessionResume).providerSessionId),a="codex"===e.appId||"claude"===e.appId||"opencode"===e.appId?e.appId:void 0;a&&r&&o.push({type:"provider-session",agent:a,id:r});const c=Cr(n.short);c&&o.push({type:"adapter-key",adapter:"claude",agent:"claude",id:`short:${c}`,key:`short:${c}`});const d=Cr(n.providerSessionId);d&&o.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=Cr(t.activeThreadId);for(const e of[...new Set([u,...l].filter(Boolean))])o.push({type:"provider-session",agent:"codex",id:e});const p=Cr(i.socketPath);return p&&o.push({type:"adapter-key",adapter:"codex-app-server",agent:"codex",id:`socket:${p}`,key:`socket:${p}`}),o}function Or(e){const t=new Map;for(const n of e)t.set(vr(n),n);return[...t.values()]}function zr(e){return e&&"object"==typeof e&&!Array.isArray(e)?e:{}}function Cr(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(ar),payload:Ar}).strict(),a.z.object({type:a.z.literal(cr),payload:_r}).strict(),a.z.object({type:a.z.literal(dr),payload:Er}).strict()])).default([])}).strict();const Rr="2026-08-25",xr=a.z.object({nodeId:a.z.string().optional(),instanceId:a.z.string().optional()}).passthrough(),kr=a.z.object({v:a.z.literal(1),id:a.z.string().min(1),seq:a.z.number().finite(),type:a.z.string().min(1),topic:a.z.string().min(1),createdAt:a.z.string().datetime(),payload:a.z.unknown(),replay:a.z.literal(!0).optional(),scope:xr.optional()}).passthrough(),Dr=a.z.object({v:a.z.literal(Rr),id:a.z.string().min(1),type:a.z.string().min(1),createdAt:a.z.string().datetime(),payload:a.z.unknown(),topic:a.z.string().min(1).optional(),replay:a.z.literal(!0).optional(),scope:xr.optional()}).passthrough();function Pr(e){return e.startsWith("ai-session.")||e.startsWith("ai.session.")?"ai.sessions":e.startsWith("app-session.")?"app.sessions":e.startsWith("app.management")?"apps":e.startsWith("trigger.")?"triggers":e.startsWith("instance.")?"instances":e.startsWith("node.")?"nodes":e.startsWith("project.")?"projects":e.startsWith("model.")?"models":e.startsWith("image.")?"images":e.startsWith("market.")?"market":e.startsWith("story.")?"stories":"system"}a.z.discriminatedUnion("v",[kr,Dr]),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 Lr=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([])}),Mr=a.z.enum(["ai.sessions","app.sessions"]),jr=a.z.object({topic:Mr,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(),Ur=a.z.object({protocolVersion:a.z.literal(1),streams:a.z.array(jr)}).strict();function Fr(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 $r{retryNumber=0;random;constructor(e=Math.random){this.random=e}get attempts(){return this.retryNumber}next(){return this.retryNumber+=1,{attempt:this.retryNumber,delay:Fr(this.retryNumber,this.random)}}reset(){this.retryNumber=0}}class Hr{backoff;timer;constructor(e=Math.random){this.backoff=new $r(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 qr extends Hr{}function Vr(e,t=6e4){const n=[];for(let i=0;i<e.length;i+=t)n.push(e.slice(i,i+t));return n}const Br=262144,Kr=4194304;class Gr{sockets=new Map;socketUrls=new Map;retries=new Map;outputs=new Set;outputSubscriptions=new Map;outputEnvelopeVersions=new Map;outputHierarchy=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;stopped=!1;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.stopped=!1,this.sync(),this.timer=this.setIntervalFn(()=>{this.safetyReconciliations+=1,this.sync()},this.safetyIntervalMs)}stop(){this.stopped=!0,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.outputHierarchy.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?Lr.parse({}):void 0),this.outputEnvelopeVersions.set(e,1),this.outputHierarchy.set(e,xn.parse(void 0)),t.expectsTransientSubscription||void 0===t.legacyFallbackMs||(n=this.setTimeoutFn(()=>{n=void 0,this.outputs.has(e)&&void 0===this.outputSubscriptions.get(e)&&(this.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.outputHierarchy.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.stopped||this.syncNow()};e.on("close",s),e.on("error",s);for(const t of this.state.listInstances()){const n=Wr(t);n?this.sendForwarded(e,this.createEvent(ho,n,{instanceId:t.id})):this.logger?.warn?.({instanceId:t.id},"instance.lifecycle.snapshot.invalid")}for(const[t,n]of this.imagePullTerminalByInstance)Vr(n.tail).forEach((i,s)=>this.sendForwarded(e,this.createEvent(Us,{...n.output,sequence:n.output.sequence+s,data:i,...0===s?{replay:!0}:{}},{instanceId:t}))),n.finished&&this.sendForwarded(e,this.createEvent(Fs,n.finished,{instanceId:t}));return(t.expectsTransientSubscription||void 0===t.legacyFallbackMs)&&(this.replaySessionAuthority(e),this.syncNow()),s}setOutputSubscription(e,t,n,i){if(!this.outputs.has(e))return!1;const s=Lr.safeParse(t),o=xn.safeParse(i);if(!s.success||!o.success)return!1;this.outputSubscriptions.set(e,s.data),this.outputEnvelopeVersions.set(e,n===Rr?Rr:1),this.outputHierarchy.set(e,o.data),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===Us){const e=bo(Hs,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,o=n.replay||!s?n.data:`${i.tail}${n.data}`.slice(-262144);return void this.imagePullTerminalByInstance.set(n.instanceId,{output:n,tail:o})}if(e===Fs){const e=bo(qs,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(ho,function(e){return go.parse(Xr(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:Pr(e),createdAt:(new Date).toISOString(),payload:t,scope:n}}sendForwarded(e,t){const n=Jr(t),i=n?function(e,t){return t?.subagents||e.type===_e?e:e.type===Ie?{...e,payload:{...e.payload,snapshot:Xt(e.payload.snapshot,t)}}:{...e,payload:{...e.payload,upserted:e.payload.upserted.map(e=>Wt(e,t))}}}(n,this.outputHierarchy.get(e)):void 0,s=i&&i.payload!==t.payload?{...t,payload:i.payload}:t,o=t.type===Ee?qt.safeParse(t.payload):void 0,r=t.type===Te?Bt.safeParse(t.payload):void 0,a=this.outputEnvelopeVersions.get(e)===Rr?function(e,t,n={}){const i=e.scope?n.publicScope&&e.scope.instanceId?{instanceId:e.scope.instanceId}:e.scope:void 0;return{v:Rr,id:e.id,type:e.type,createdAt:e.createdAt,payload:void 0===n.payload?e.payload:n.payload,...e.topic!==Pr(e.type)?{topic:e.topic}:{},...e.replay?{replay:!0}:{},...i&&Object.keys(i).length?{scope:i}:{}}}(s,0,{...o?.success?{payload:(c=o.data,Vt.parse({sessionId:c.sessionId,turnId:c.turnId,itemId:c.itemId,delta:c.delta,generatedAt:c.generatedAt}))}:{},...r?.success?{payload:Gt(r.data)}:{}}):s;var c;const d=JSON.stringify({type:"node-agent.event.forwarded",event:a});this.sendOutput(e,d,s)}sendOutput(e,t,n){const i=Buffer.byteLength(t,"utf8"),s=n?.topic===rr?"app-session":n?.topic===ye?"ai-session":void 0,o=s?{...this.outputDiagnostics.get(e),instanceId:n.scope?.instanceId,eventType:n.type,...Yr(n.payload)}:void 0;if(e.readyState!==p.OPEN)return o&&this.logger?.warn?.({...o,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&&Qr(n)&&i>Kr){if(n.type!==Ie&&this.deferAiSessionAuthority(e,n))return!0;this.observeEventTransportCongestion(e,!1,i),o&&this.logger?.warn?.({...o,bufferedAmount:e.bufferedAmount,bytes:i,maxBytes:Kr,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),o&&this.logger?.warn?.({...o,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),o&&this.logger?.info?.({...o,bufferedAmount:e.bufferedAmount,bytes:i,outcome:"queued"},`${s}.event.output.queued`),!0}catch(t){o&&this.logger?.warn?.({...o,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(!Qr(t))return!1;const n=t.scope?.instanceId;return!!n&&(!!this.pendingAiSessionAuthorityByOutput.get(e)?.has(n)||e.bufferedAmount>=Br)}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=Jr(e);return n?n.payload.meta.streamId!==t.streamId||n.payload.meta.revision!==t.revision?void 0:Ft.parse({meta:n.payload.meta,snapshot:t.snapshot}):void 0}(t,i);if(!s)return!1;const o=this.pendingAiSessionAuthorityByOutput.get(e)||new Map;return o.set(n,{...t,type:Ie,topic:ye,payload:s}),this.pendingAiSessionAuthorityByOutput.set(e,o),this.observeEventTransportCongestion(e,!0),this.logger?.info?.({...this.outputDiagnostics.get(e),instanceId:n,eventType:t.type,...Yr(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>=Br?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)),o=this.eventTransportCongestion;this.eventTransportCongestion={congestedSince:o?.recoveredAt?i:o?.congestedSince||i,lastCongestedAt:i,peakBufferedBytes:Math.max(o?.recoveredAt?0:o?.peakBufferedBytes||0,s),coalescedEvents:(o?.recoveredAt?0:o?.coalescedEvents||0)+(t?1:0),oversizedEvents:(o?.recoveredAt?0:o?.oversizedEvents||0)+(n>0?1:0),peakEventBytes:Math.max(o?.recoveredAt?0:o?.peakEventBytes||0,n)}}eventTransportIsCongested(){return!![...this.pendingAiSessionAuthorityByOutput.values()].some(e=>e.size>0)||[...this.outputs].some(e=>e.readyState===p.OPEN&&e.bufferedAmount>=Br)}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=Zr(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 qr,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:Pr(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===Ee){const e=function(e,t){const n=Vt.safeParse(e);return n.success?qt.parse({instanceId:t,...n.data}):qt.parse(e)}(n.payload,t);return{...n,payload:e,scope:{...n.scope,instanceId:t}}}if(n.type===Te){const e=function(e,t){const n=Kt.safeParse(e);return n.success?Bt.parse({instanceId:t,...n.data}):Bt.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=bo(Ur,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:Rr,aiSessionHierarchy:{subagents:!0},topics:[ye,"app.sessions","apps","instances"]}));const i=n.some(t=>t.messageDeltas.allInstances||t.messageDeltas.instanceIds.includes(e)),s=n.some(e=>e.timelineAllSessions),o=[...new Set(n.flatMap(t=>t.timelineSessions.filter(t=>t.instanceId===e).map(e=>e.sessionId)))],r=n.map(e=>e.replaySince).filter(e=>Boolean(e)).sort()[0];t.send(JSON.stringify({v:1,type:"subscribe",eventEnvelopeVersion:Rr,aiSessionHierarchy:{subagents:!0},topics:[Ie,Ae,_e,...i?[Ee]:[],...s||o.length?[we,Te]:[],"app.sessions","apps","instances"],aiSessionTransient:{...r?{replaySince:r}:{},messageDeltas:{allInstances:i,instanceIds:[]},timelineAllSessions:s,timelineSessions:o.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&&"ai-session.timeline-item-delta"!==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&&Zr(t);if(!n||!this.outputs.size)return;const i=this.retries.get(e)??{timer:new qr};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!==ye)return;if(t.type===Ee||t.type===we||t.type===Te)return;const n=Jr(t);if(n){const t=function(e,t){const{meta:n}=t.payload;if(t.type===Ie)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:Mt.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===Ae){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()],o=Lt.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:Mt.parse({streamId:n.streamId,revision:n.revision,lastEventAt:n.generatedAt,snapshot:o})}}(this.aiSessionProjectionByInstance.get(e),n);"applied"!==t.kind&&"duplicate"!==t.kind&&"stale"!==t.kind||this.aiSessionProjectionByInstance.set(e,t.projection)}const i=Yr(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!==rr)return;const n=function(e){const t=e.type===ar?Ar:e.type===cr?_r:e.type===dr?Er:void 0;if(!t)return;const n=bo(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===ar)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:fr.parse({streamId:n.streamId,revision:n.revision,lastEventAt:n.generatedAt,snapshot:Tr(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===cr){const e=i.findIndex(e=>e.id===t.payload.session.id);Sr(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=wr(i,n.generatedAt);return{kind:"applied",projection:fr.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=Yr(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===ye?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(Ie,{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(ar,{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 Wr(e){const t=go.safeParse(Xr(e));return t.success?t.data:void 0}function Xr(e){return{instanceId:e.id,revision:e.stateRevision,updatedAt:e.updatedAt,status:e.status,health:e.health,connectionStatus:e.connectionStatus,accessStatus:"online"===e.connectionStatus||"online"===e.agentStatus?"reachable":"endpoint-unreachable",imageProvisioning:e.imageProvisioning,workspace:e.workspace,runtime:e.runtime,runtimeVersion:e.runtimeVersion,ready:e.ready,lastHeartbeatAt:e.lastHeartbeatAt}}function Yr(e){const t=e&&"object"==typeof e&&!Array.isArray(e)?e:{},n=t.meta&&"object"==typeof t.meta&&!Array.isArray(t.meta)?t.meta:{};return{streamId:"string"==typeof n.streamId?n.streamId:void 0,revision:"number"==typeof n.revision?n.revision:void 0,traceId:"string"==typeof n.traceId?n.traceId:void 0}}function Jr(e){const t=e.type===Ie?Ft:e.type===Ae?$t:e.type===_e?Ht:void 0;if(!t)return;const n=bo(t,e.payload);return n.success?{type:e.type,payload:n.data}:void 0}function Qr(e){return e.topic===ye&&(e.type===Ie||e.type===Ae||e.type===_e)}function Zr(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.searchParams.set("aiSessionHierarchy","subagents"),e.protocol="https:"===e.protocol?"wss:":"ws:",e.toString()}catch{return}}const ea=new Set(["provisioning","starting","registering","registered","running","unhealthy"]),ta=JSON.stringify({id:"{{.ID}}",name:"{{.Name}}",cpu:"{{.CPUPerc}}",memory:"{{.MemUsage}}",memoryPercent:"{{.MemPerc}}",network:"{{.NetIO}}",blockIo:"{{.BlockIO}}",pids:"{{.PIDs}}"});class na{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(!ea.has(t.status))return ca(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=ia(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,ia(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=>ea.has(e.status)&&(e.runtime.containerId||e.runtime.containerName));for(const t of e.filter(e=>ea.has(e.status)&&!e.runtime.containerId&&!e.runtime.containerName))this.update(da(t.id));for(const t of e.filter(e=>!ea.has(e.status)))this.update(ca(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",ta,...n],{timeoutMs:5e3});this.applyDockerOutput(t,e.stdout,i)}catch(e){if(1===t.length)return void this.update(la(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",ta,t],{timeoutMs:5e3});this.applyDockerOutput([e],n.stdout,i)}catch(t){this.update(la(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=aa(e.id),o=aa(e.name),r=s||o;if(!r)continue;const a=sa(aa(e.memory)),c=sa(aa(e.network)),d=sa(aa(e.blockIo)),l=Xs.parse({instanceId:r,runtimeKind:"docker",state:"available",sampledAt:t,cpu:oa(e.cpu,"usagePercent"),memory:a?{usageBytes:a[0],...void 0!==a[1]?{limitBytes:a[1]}:{},...oa(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:ra(e.pids)});s&&n.set(s,l),o&&n.set(o,l)}return n}(t,n);for(const t of e){const e=[t.runtime.containerId,t.runtime.containerName].filter(Boolean),s=[...i.entries()].find(([t])=>e.some(e=>e===t||e.startsWith(t)||t.startsWith(e)))?.[1];this.update(s?{...s,instanceId:t.id}:la(t.id,n,"Container metrics were not returned by Docker."))}}update(e){const t=Xs.parse(e);this.snapshots.set(t.instanceId,t),this.publish?.(t)}}function ia(e){return[e.status,e.runtime.containerId||"",e.runtime.containerName||""].join("\0")}function sa(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"),o="b"===i[0]?"":i[0],r=o?"kmgtpe".indexOf(o)+1:0;return Math.round(n*(s?1024:1e3)**r)}(e||""));return void 0===t?void 0:[t,n]}function oa(e,t){const n=Number(aa(e).replace(/%$/,""));return Number.isFinite(n)&&n>=0?{[t]:n}:void 0}function ra(e){const t=Number(aa(e));return Number.isFinite(t)&&t>=0?t:void 0}function aa(e){return"string"==typeof e||"number"==typeof e?String(e).trim():""}function ca(e){return{instanceId:e,runtimeKind:"docker",state:"stopped",sampledAt:(new Date).toISOString()}}function da(e){return{instanceId:e,runtimeKind:"docker",state:"pending",sampledAt:(new Date).toISOString()}}function la(e,t,n){return{instanceId:e,runtimeKind:"docker",state:"unavailable",sampledAt:t,error:n.slice(0,2048)}}function ua(e,t,n){return Object.assign(new Error(e),{statusCode:t,code:n})}function pa(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 ua(`Folder ${i} was not found.`,404,"NODE_FOLDER_PATH_NOT_FOUND");throw ua(`Folder ${i} is not accessible.`,403,"NODE_FOLDER_PATH_UNREADABLE")}if(!s.isDirectory())throw ua(`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 ua(`Folder ${i} is not accessible.`,403,"NODE_FOLDER_PATH_UNREADABLE")}return i}function ma(e){try{return t.statSync(e).isDirectory()}catch{return!1}}function ha(){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(ma)}function ga(){const e=n.resolve(c.homedir()),t=ha().map(e=>n.resolve(e));return[...ma(e)?[{kind:"home",name:n.basename(e)||e,path:e}]:[],...t.map(e=>({kind:"root",name:e,path:e}))]}function fa(e,i){let s;try{s=t.statSync(e)}catch{return}if(!s.isDirectory())return;const o=n.resolve(e),r=n.basename(o)||o;let a=[];try{a=i>0?t.readdirSync(o,{withFileTypes:!0}):[]}catch{a=[]}const c=i>0?a.filter(e=>e.isDirectory()||e.isSymbolicLink()&&ma(n.join(o,e.name))).sort((e,t)=>e.name.localeCompare(t.name)).slice(0,80).flatMap(e=>{const t=fa(n.join(o,e.name),i-1);return t?[t]:[]}):[];return{name:r,path:o,children:c}}function ya(e){return(e.path?[pa(e.path)]:ha()).flatMap(t=>{const n=fa(t,e.depth);return n?[n]:[]})}function Ia(){return process.env.TASK_HANDOFF_NODE_AGENT_DATA_DIR||n.join(c.homedir(),".config","task-handoff","node-agent")}function Aa(e=Ia()){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"),databasePath:n.join(t,"node-agent.sqlite"),storyRegistryDir:n.join(t,"story-registry"),storyAutomationsDir:n.join(t,"story-automations"),storyContentDir:n.join(t,"stories"),storyMutationsDir:n.join(t,".story-mutations"),storyTrashDir:n.join(t,".story-trash")}}function _a(e,t){const i=n.extname(e);return`${i?e.slice(0,-i.length):e}.${t}${i}`}function Ea(e,n=10485760,i=2){if(!t.existsSync(e))return!1;const s=t.lstatSync(e);if(!s.isFile()||s.isSymbolicLink()||s.size<=n)return!1;if(i>0){!function(e,n){if(!(n<=0)){t.rmSync(_a(e,n),{force:!0});for(let i=n-1;i>=1;i-=1){const n=_a(e,i);t.existsSync(n)&&t.renameSync(n,_a(e,i+1))}}}(e,i);const s=function(e,n){const i=t.statSync(e),s=Math.min(i.size,n),o=Buffer.allocUnsafe(s),r=t.openSync(e,"r");let a=0;try{for(;a<s;){const e=t.readSync(r,o,a,s-a,i.size-s+a);if(0===e)break;a+=e}}finally{t.closeSync(r)}return a===s?o:o.subarray(0,a)}(e,n);t.writeFileSync(_a(e,1),s,{mode:384})}return t.truncateSync(e,0),t.chmodSync(e,384),!0}class wa{logsDir;localInstancesRoot;localInstancesTrashRoot;privateConfigsDir;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"),this.privateConfigsDir=e.instancePrivateConfigsDir}run(e){this.capNodeAgentLogs();const n=new Set(e);if(this.removeOrphanPrivateConfigs(n),t.existsSync(this.localInstancesRoot)){le(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??ce,s=[];for(const o of t.readdirSync(e.trashRoot,{withFileTypes:!0})){const r=de(e.trashRoot,o.name);try{const e=Number(o.name.split("-",1)[0]);if(!Number.isFinite(e)||e+i>n)continue;const a=t.lstatSync(r);a.isSymbolicLink()?t.unlinkSync(r):a.isDirectory()?t.rmSync(r,{recursive:!0,force:!0}):t.unlinkSync(r),s.push(r)}catch(t){e.logger?.("retired persistence entry cleanup failed",{path:r,error:t instanceof Error?t.message:String(t)})}}return s}({trashRoot:this.localInstancesTrashRoot,retentionMs:this.options.retentionMs??ce,nowMs:this.now(),logger:this.options.logger})}capActiveInstanceLogs(e){for(const t of e)this.capControlledInstanceLogs(t)}capNodeAgentLogs(){const e=[];for(const t of["node-agent.out.log","node-agent.err.log"]){const i=n.join(this.logsDir,t);try{Ea(i)&&e.push(i)}catch(e){this.options.logger?.("node-agent log rotation failed",{filePath:i,error:e instanceof Error?e.message:String(e)})}}return e}capControlledInstanceLogs(e){const t=n.resolve(this.localInstancesRoot,e);if(n.dirname(t)!==n.resolve(this.localInstancesRoot))return[];const i=n.join(t,"logs"),s=[];for(const t of["controlled-instance.out.log","controlled-instance.err.log"]){const o=n.join(i,t);try{Ea(o)&&s.push(o)}catch(t){this.options.logger?.("controlled instance log rotation failed",{instanceId:e,filePath:o,error:t instanceof Error?t.message:String(t)})}}return s}retire(e){try{return function(e){const n=de(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}`);le(e.trashRoot);const s=e.nowMs??Date.now();let o=0,r=`${s}-${e.entryName}`;for(;t.existsSync(de(e.trashRoot,r));)o+=1,r=`${s}-${o}-${e.entryName}`;const a=de(e.trashRoot,r);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)})}}removeOrphanPrivateConfigs(e){if(t.existsSync(this.privateConfigsDir))for(const i of t.readdirSync(this.privateConfigsDir,{withFileTypes:!0})){if(!i.isFile()||!i.name.endsWith(".json"))continue;const s=i.name.slice(0,-5);if(e.has(s))continue;const o=n.join(this.privateConfigsDir,i.name);try{(this.options.removeFile||(e=>t.rmSync(e,{force:!0})))(o)}catch(e){this.options.logger?.("orphan instance private config cleanup failed",{instanceId:s,filePath:o,error:e instanceof Error?e.message:String(e)})}}}now(){return this.options.now?.()??Date.now()}}function Ta(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 ba(e,t,n={}){const s=n.method||"GET",o="string"==typeof n.body||n.body instanceof Buffer?n.body:void 0===n.body||null===n.body?void 0:String(n.body),r=new Headers(n.headers||{});return void 0===o||r.has("content-length")||r.set("content-length",String(Buffer.byteLength(o))),new Promise((a,c)=>{const d=i.request({socketPath:e,method:s,path:`/api/node-agent${t}`,headers:Object.fromEntries(r.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!==o&&d.write(o),d.end()})}const Sa="runtime-manifest.json";class va 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 Na(e,t=""){const i=[],s=await g.readdir(n.join(e,t),{withFileTypes:!0});for(const o of s){const s=t?n.posix.join(t,o.name):o.name;if(!t&&s===Sa)continue;const r=n.join(e,...s.split("/"));if(o.isDirectory()){i.push(...await Na(e,s));continue}if(o.isSymbolicLink()){const t=await g.readlink(r);if(n.isAbsolute(t))throw new va("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload symlink is absolute: ${s}`);const o=n.resolve(n.dirname(r),t),a=n.relative(n.resolve(e),o);if(!a||".."===a||a.startsWith(`..${n.sep}`)||n.isAbsolute(a))throw new va("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload symlink escapes the artifact: ${s}`);if(!await g.lstat(o).catch(()=>{}))throw new va("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload symlink is broken: ${s}`);i.push({absolutePath:r,relativePath:s,kind:"symlink",target:t,size:Buffer.byteLength(t)});continue}if(!o.isFile())throw new va("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload contains unsupported entry: ${s}`);const a=await g.lstat(r);i.push({absolutePath:r,relativePath:s,kind:"file",size:a.size})}return i}async function Oa(e){const n=(await Na(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 za(e){for(const[t,n]of[["version",e.version],["platform",e.platform],["arch",e.arch]])if(!/^[0-9A-Za-z._-]+$/.test(n))throw new va("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Invalid runtime artifact ${t}: ${n}`);return`${e.version}-${e.platform}-${e.arch}`}function Ca(e,t){return`${za(e)}-${e.sha256}-${t}`}async function Ra(e){const n=d.createHash("sha256");for await(const i of t.createReadStream(e))n.update(i);return n.digest("hex")}class xa{#e;#t;#n=new Map;constructor(e){this.#e=e.cacheDir,this.#t=e.fetchImpl??fetch}resolve(e,t){const n=Ki.parse(e);if(!/^[a-f0-9]{64}$/.test(t.archiveSha256))throw new va("INSTANCE_RUNTIME_ARTIFACT_INVALID","Runtime archive SHA-256 is invalid.");if((t.archiveUrl?1:0)+(t.archivePath?1:0)!=1)throw new va("INSTANCE_RUNTIME_ARTIFACT_INVALID","Runtime artifact source must specify exactly one archive location.");const i=Ca(n,t.archiveSha256),s=this.#n.get(i);if(s)return s;const o=this.#i(n,t).finally(()=>this.#n.delete(i));return this.#n.set(i,o),o}async#i(e,i){if(!/^[a-f0-9]{64}$/.test(i.archiveSha256))throw new va("INSTANCE_RUNTIME_ARTIFACT_INVALID","Runtime archive SHA-256 is invalid.");const s=Ca(e,i.archiveSha256),o=n.join(this.#e,"archives"),r=n.join(o,`${s}.tar.gz`);if(await g.mkdir(o,{recursive:!0}),await this.#s(r,e,i.archiveSha256))return{identity:e,archivePath:r,cacheHit:!0};await g.rm(r,{force:!0});const a=n.join(o,`.${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 va("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 Ra(a)!==i.archiveSha256)throw new va("INSTANCE_RUNTIME_ARTIFACT_INVALID","Downloaded runtime archive SHA-256 does not match release metadata.");return await this.#o(a,e),await g.rename(a,r),{identity:e,archivePath:r,cacheHit:!1}}catch(e){if(e instanceof va)throw e;throw new va("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 Ra(e)===n&&(await this.#o(e,t),!0)}catch{return!1}}async#o(e,t){const i=n.join(this.#e,"validation",`${za(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 va("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 va("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime archive contains unsupported entry type ${s??"unknown"}: ${e}`);return!0}})}catch(e){throw new va("INSTANCE_RUNTIME_ARTIFACT_INVALID","Could not extract runtime artifact safely.",{cause:e})}}(e,i),await async function(e,t,i){const s=await async function(e){let t;try{t=JSON.parse(await g.readFile(n.join(e,Sa),"utf8"))}catch(e){throw new va("INSTANCE_RUNTIME_ARTIFACT_INVALID","Runtime artifact manifest is missing or invalid JSON.",{cause:e})}const i=bo(Ki,t);if(!i.success)throw new va("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 va("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 va("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Unsupported runtime artifact format ${s.formatVersion}.`);if(i?.platform&&"universal"!==s.platform&&s.platform!==i.platform)throw new va("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 va("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 va("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Runtime requires launcher ABI ${s.launcherAbi}, but the base runtime provides ${i.launcherAbi}.`);const o=function(e,t){if(!e||e.includes("\\")||n.posix.isAbsolute(e))throw new va("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 va("INSTANCE_RUNTIME_ARTIFACT_INVALID",`${t} escapes the runtime root.`);return i}(s.entrypoint,"Runtime entrypoint"),r=await g.lstat(n.join(e,...o.split("/"))).catch(()=>{});if(!r?.isFile())throw new va("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime entrypoint is missing: ${o}`);const a=await Oa(e);if(a!==s.sha256)throw new va("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 ka(e,t,i,s=fetch){if("linux"!==t||!["x64","arm64"].includes(i))throw new va("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Managed controlled-instance updates require a Linux x64 or arm64 target, received ${t}/${i}.`);const o=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,o]=await Promise.all([g.readFile(n.join(i,`${t}.manifest.json`),"utf8"),g.readFile(n.join(i,`${t}.tar.gz.sha256`),"utf8")]),r=bo(Ki,JSON.parse(s));if(!r.success||r.data.version!==e||"linux"!==r.data.platform||"universal"!==r.data.arch)throw new va("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Bundled controlled-instance ${e} has an invalid Linux manifest.`);const a=o.trim().split(/\s+/)[0]?.toLowerCase();if(!a||!/^[a-f0-9]{64}$/.test(a))throw new va("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Bundled controlled-instance ${e} has an invalid archive checksum.`);return{identity:r.data,source:{archivePath:n.join(i,`${t}.tar.gz`),archiveSha256:a}}}catch(t){if("ENOENT"===t.code)return;if(t instanceof va)throw t;throw new va("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Could not read bundled controlled-instance ${e}.`,{cause:t})}}(e);if(o)return o;const r=`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}/${r}.manifest.json`,d=`${a}/${r}.tar.gz`,l=`${a}/${r}.tar.gz.sha256`,[u,p]=await Promise.all([s(c),s(l)]).catch(t=>{throw new va("INSTANCE_RUNTIME_ARTIFACT_UNAVAILABLE",`Could not read release metadata for controlled-instance ${e}.`,{cause:t,retryable:!0})});if(!u.ok||!p.ok)throw new va("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 va("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Release manifest for controlled-instance ${e} is not valid JSON.`,{cause:t})}const h=bo(Ki,m);if(!h.success)throw new va("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 va("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 va("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Release checksum for controlled-instance ${e} is invalid.`);return{identity:h.data,source:{archiveUrl:d,archiveSha256:f}}}class Da{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=qa(i.retryBaseDelayMs??1e3,"retryBaseDelayMs"),this.retryMaxDelayMs=qa(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(Ma(n))return this.storePhase(n,"pending");const s=n.runtimeVersion?.desiredVersion!==i||t.startRequested||ja(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 o=Pa(n),r=o===i&&(await(this.hooks.isInstalled?.(n,i))??!0);if(this.cancelled.has(e))return this.storePhase(this.requireInstance(e),"pending");if(o===i&&r)return this.storeState(n,{desiredVersion:i,actualVersion:o,phase:"matched",attempt:n.runtimeVersion?.attempt||0,matchedAt:this.timestamp()},!ja(n)&&"failed"!==n.health);if(n=this.storeState(n,function(e,t,n,i=!1){const s=e.runtimeVersion,o=s?.desiredVersion===t&&"matched"!==s.phase;return{desiredVersion:t,...n?{actualVersion:n}:{},phase:"pending",attempt:o?s.attempt:0,error:(o?s.error:void 0)||(n!==t||i?Ua(t,n):Fa("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,o,r)),ja(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),La(n)){const t=await this.waitUntil(e,this.drainTimeoutMs,e=>!La(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)||ja(this.requireInstance(e))&&!t.startRequested)return this.storePhase(this.requireInstance(e),"pending");if(n=this.storePhase(this.requireInstance(e),"restarting"),await this.hooks.restart(n),this.cancelled.has(e))return this.storePhase(this.requireInstance(e),"pending");n=this.storePhase(this.requireInstance(e),"verifying");const s=await this.waitUntil(e,this.verificationTimeoutMs,e=>Pa(e)===i);if(this.cancelled.has(e))return this.storePhase(this.requireInstance(e),"pending");if(!s)throw Fa("INSTANCE_RUNTIME_VERIFICATION_FAILED",`Instance ${e} did not register controlled-instance ${i} after restart.`,i,Pa(this.requireInstance(e)),!0);const o=this.requireInstance(e);if(this.hooks.isInstalled&&!await this.hooks.isInstalled(o,i))throw Fa("INSTANCE_RUNTIME_VERIFICATION_FAILED",`Instance ${e} reported controlled-instance ${i}, but its active runtime release is missing.`,i,Pa(o),!0);return this.storeState(o,{desiredVersion:i,actualVersion:i,phase:"matched",attempt:o.runtimeVersion?.attempt||1,matchedAt:this.timestamp()},!ja(o)&&"failed"!==o.health)}catch(t){if(this.cancelled.has(e))return this.storePhase(this.requireInstance(e),"pending");s=$a(t,i,Pa(this.store.get(e)))}n=this.requireInstance(e);const o=n.runtimeVersion?.attempt||1;if(!s.retryable||c>=this.maxAttempts)return this.storeBatchFailure(n,i,o>=this.maxAttempts&&s.retryable?Ha(i,Pa(n),this.maxAttempts,s):s);n=this.storeState(n,{desiredVersion:i,...Pa(n)?{actualVersion:Pa(n)}:{},phase:"pending",attempt:o,lastAttemptAt:this.timestamp(),error:s}),await this.delay(this.retryDelayMs(o))}return this.storeBatchFailure(n,i,Ha(i,Pa(n),this.maxAttempts,n.runtimeVersion?.error))}finally{a&&await(this.hooks.endDrain?.(this.requireInstance(e)))}}storeBatchFailure(e,t,n){const i=Pa(e);return this.storeState(e,{desiredVersion:t,...i?{actualVersion:i}:{},phase:"pending",attempt:e.runtimeVersion?.attempt||0,lastAttemptAt:this.timestamp(),error:n})}retryDelayMs(e){return Math.min(this.retryMaxDelayMs,this.retryBaseDelayMs*2**Math.max(0,e-1))}remainingRetryDelayMs(e){if(!e?.error||!e.lastAttemptAt)return 0;const t=Date.parse(e.lastAttemptAt);return Number.isFinite(t)?Math.max(0,t+this.retryDelayMs(e.attempt||1)-this.now().getTime()):0}storePhase(e,t,n=!1){const i=this.desiredVersion(),s=Pa(e),o=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(),...o?{error:o}:"pending"===t?{error:Ua(i,s)}:{}},"restarting"!==t&&void 0)}storeState(e,t,n){const i=this.store.get(e.id)||e;return this.store.put(po.parse({...i,runtimeVersion:t,...void 0===n?{}:{ready:n},updatedAt:this.timestamp()}))}async waitUntil(e,t,n){const i=this.now().getTime()+t;for(;;){const t=this.store.get(e);if(t&&n(t))return!0;if(this.cancelled.has(e))return!1;if(this.now().getTime()>=i)return!1;await this.delay(Math.min(this.pollIntervalMs,Math.max(0,i-this.now().getTime())))}}requireInstance(e){const t=this.store.get(e);if(!t)throw new Error(`Instance ${e} was removed during runtime reconciliation.`);return t}timestamp(){return this.now().toISOString()}}function Pa(e){return e?.build?.packageVersion||e?.instanceVersion}function La(e){return e.apps.runningCount>0||e.aiSessions.runningCount>0}function Ma(e){return Boolean(e.imageProvisioning&&"ready"!==e.imageProvisioning.phase)}function ja(e){return["created","stopped","failed"].includes(e.status)}function Ua(e,t){return Fa("INSTANCE_RUNTIME_VERSION_MISMATCH",`Expected controlled-instance ${e}, received ${t||"an unknown version"}.`,e,t,!0)}function Fa(e,t,n,i,s){return{code:e,message:t,expectedVersion:n,...i?{actualVersion:i}:{},retryable:s}}function $a(e,t,n){if(e&&"object"==typeof e&&"code"in e&&"message"in e){const i=e,s=Gi.shape.code.safeParse(i.code);if(s.success&&"string"==typeof i.message)return Fa(s.data,i.message,t,n,"boolean"!=typeof i.retryable||i.retryable)}return Fa("INSTANCE_RUNTIME_INSTALL_FAILED",e instanceof Error?e.message:String(e),t,n,!0)}function Ha(e,t,n,i){const s=i?.message?` Last error: ${i.message}`:"";return Fa(i?.code||"INSTANCE_RUNTIME_INSTALL_FAILED",`Runtime convergence paused after ${n} attempts and will retry.${s}`,e,t,!0)}function qa(e,t){if(!Number.isFinite(e)||e<0)throw new TypeError(`${t} must be a nonnegative finite number.`);return e}function Va(e,n=448){t.mkdirSync(e,{recursive:!0,mode:n}),t.chmodSync(e,n)}function Ba(e,i,s={}){const o=s.directoryMode??448,r=s.fileMode??384;Va(n.dirname(e),o),I.sync(e,`${JSON.stringify(i,null,2)}\n`,{encoding:"utf8",mode:r}),t.chmodSync(e,r)}function Ka(e,t){console.warn(JSON.stringify({message:e,...t}))}function Ga(e){return e&&"object"==typeof e&&"issues"in e?{issues:e.issues}:{error:e instanceof Error?e.message:String(e)}}function Wa(e,n){const i=n.logger||Ka;let s;try{s=JSON.parse(t.readFileSync(e,"utf8"))}catch(t){if(n.rejectInvalid)throw t;return void i("stored JSON could not be read",{filePath:e,...Ga(t)})}if(!n.schema)return s;const o=n.sanitize?n.sanitize(s):s,r=n.schema.safeParse(o);if(r.success)return r.data;if(n.rejectInvalid)throw r.error;const a="strip"in n.schema&&"function"==typeof n.schema.strip?n.schema.strip().safeParse(o):void 0;if(a?.success)return i("unknown stored fields were ignored",{filePath:e,issues:r.error.issues}),a.data;i("stored record failed validation and was isolated",{filePath:e,issues:r.error.issues})}function Xa(e){return`${e}_${d.randomUUID().replace(/-/g,"").slice(0,20)}`}function Ya(){return d.randomBytes(24).toString("base64url")}class Ja{directory;options;permissionsInitialized=!1;constructor(e,t={}){this.directory=e,this.options=t}init(){if(this.permissionsInitialized&&t.existsSync(this.directory))return;Va(this.directory,this.options.directoryMode??448);const e=this.options.fileMode??384;for(const i of t.readdirSync(this.directory).filter(e=>e.endsWith(".json")))t.chmodSync(n.join(this.directory,i),e);this.permissionsInitialized=!0}filePath(e){return n.join(this.directory,`${e}.json`)}list(){return this.init(),t.readdirSync(this.directory).filter(e=>e.endsWith(".json")).sort().flatMap(e=>{const t=Wa(n.join(this.directory,e),this.options);return t?[t]:[]})}get(e){this.init();const n=this.filePath(e);return t.existsSync(n)?Wa(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 Ba(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 Qa{filePathValue;defaults;options;constructor(e,t,n={}){this.filePathValue=e,this.defaults=t,this.options=n}init(){Va(n.dirname(this.filePathValue),this.options.directoryMode??448),t.existsSync(this.filePathValue)?t.chmodSync(this.filePathValue,this.options.fileMode??384):this.put(this.defaults())}get(){return this.init(),t.existsSync(this.filePathValue)?Wa(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 Ba(this.filePathValue,n,this.options),n}}E.sqliteTable("na_migration_ledger",{id:E.text("id").primaryKey(),checksum:E.text("checksum").notNull(),appliedAt:E.text("applied_at").notNull(),details:E.text("details",{mode:"json"}).$type().notNull()});const Za=E.sqliteTable("na_stories",{id:E.text("id").primaryKey(),title:E.text("title").notNull(),description:E.text("description"),createdAt:E.text("created_at").notNull(),updatedAt:E.text("updated_at").notNull(),archivedAt:E.text("archived_at"),maxIdleAiSessions:E.integer("max_idle_ai_sessions").notNull().default(5),nextDocumentSequence:E.integer("next_document_sequence").notNull().default(1)},e=>[E.check("na_stories_max_idle_check",_.sql`${e.maxIdleAiSessions} BETWEEN 1 AND 50`),E.check("na_stories_next_document_sequence_check",_.sql`${e.nextDocumentSequence} > 0`),E.index("na_stories_created_idx").on(e.createdAt)]),ec=E.sqliteTable("na_story_actions",{storyId:E.text("story_id").notNull().references(()=>Za.id,{onDelete:"cascade"}),id:E.text("id").notNull(),title:E.text("title").notNull(),promptTemplate:E.text("prompt_template").notNull(),targetInstanceId:E.text("target_instance_id"),sessionPreset:E.text("session_preset_json",{mode:"json"}).$type(),displayOrder:E.integer("display_order").notNull()},e=>[E.primaryKey({columns:[e.storyId,e.id]}),E.index("na_story_actions_order_idx").on(e.storyId,e.displayOrder,e.id)]),tc=E.sqliteTable("na_story_documents",{storyId:E.text("story_id").notNull().references(()=>Za.id,{onDelete:"cascade"}),storyPath:E.text("story_path").notNull(),title:E.text("title").notNull(),indexedSequence:E.integer("indexed_sequence").notNull(),displayOrder:E.integer("display_order").notNull()},e=>[E.primaryKey({columns:[e.storyId,e.storyPath]}),E.uniqueIndex("na_story_documents_sequence_uq").on(e.storyId,e.indexedSequence),E.index("na_story_documents_page_idx").on(e.storyId,e.indexedSequence,e.storyPath),E.index("na_story_documents_display_idx").on(e.storyId,e.displayOrder,e.storyPath),E.check("na_story_documents_sequence_check",_.sql`${e.indexedSequence} > 0`)]),nc=E.sqliteTable("na_story_automations",{id:E.text("id").primaryKey(),storyId:E.text("story_id").notNull(),actionId:E.text("action_id").notNull(),schedule:E.text("schedule_json",{mode:"json"}).$type().notNull(),enabled:E.integer("enabled",{mode:"boolean"}).notNull(),policy:E.text("policy_json",{mode:"json"}).$type().notNull(),scheduleAnchorAt:E.text("schedule_anchor_at").notNull(),createdAt:E.text("created_at").notNull(),updatedAt:E.text("updated_at").notNull()},e=>[E.foreignKey({columns:[e.storyId,e.actionId],foreignColumns:[ec.storyId,ec.id],name:"na_story_automations_action_fk"}).onDelete("restrict"),E.index("na_story_automations_story_idx").on(e.storyId),E.index("na_story_automations_enabled_idx").on(e.enabled)]),ic=E.sqliteTable("na_story_automation_runs",{id:E.text("id").primaryKey(),automationId:E.text("automation_id").notNull().references(()=>nc.id,{onDelete:"cascade"}),eventType:E.text("event_type",{enum:["manual","schedule"]}).notNull(),status:E.text("status",{enum:["queued","dispatching","running","completed","failed","skipped"]}).notNull(),scheduledFor:E.text("scheduled_for").notNull(),targetInstanceId:E.text("target_instance_id").notNull(),aiSessionId:E.text("ai_session_id"),error:E.text("error_json",{mode:"json"}).$type(),queuedAt:E.text("queued_at").notNull(),startedAt:E.text("started_at"),completedAt:E.text("completed_at"),executionKey:E.text("execution_key").notNull(),requestFingerprint:E.text("request_fingerprint").notNull(),executionInput:E.text("execution_input_json",{mode:"json"}).$type().notNull()},e=>[E.uniqueIndex("na_story_automation_runs_execution_key_uq").on(e.executionKey),E.index("na_story_automation_runs_automation_time_idx").on(e.automationId,e.queuedAt),E.index("na_story_automation_runs_status_idx").on(e.status,e.scheduledFor)]),sc=E.sqliteTable("na_story_file_mutations",{id:E.text("id").primaryKey(),storyId:E.text("story_id").notNull().references(()=>Za.id,{onDelete:"restrict"}),operation:E.text("operation",{enum:["write","rename","delete"]}).notNull(),storyPath:E.text("story_path").notNull(),nextStoryPath:E.text("next_story_path"),title:E.text("title"),temporaryName:E.text("temporary_name"),backupName:E.text("backup_name"),phase:E.text("phase",{enum:["receiving","prepared","files-staged","database-committed","cleanup"]}).notNull(),createdAt:E.text("created_at").notNull(),updatedAt:E.text("updated_at").notNull()},e=>[E.index("na_story_file_mutations_story_idx").on(e.storyId,e.createdAt)]),oc=E.sqliteTable("na_story_deletion_intents",{storyId:E.text("story_id").primaryKey(),phase:E.text("phase",{enum:["prepared","files-staged","database-committed","cleanup"]}).notNull(),trashName:E.text("trash_name"),createdAt:E.text("created_at").notNull(),updatedAt:E.text("updated_at").notNull()}),rc=["health","connectionStatus","agentStatus","targetStatus","uiAccessStatus","ready","protocolVersion","instanceVersion","build","runtimeVersion","capabilities","appInventory","target","access","apps","aiSessions","triggers","runtime","lastHeartbeatAt"];function ac(e){return JSON.stringify(e??null)}function cc(e){return JSON.parse(String(e))}function dc(e,t){if(e.isTransaction)return t();e.exec("BEGIN IMMEDIATE");try{const n=t();return e.exec("COMMIT"),n}catch(t){throw e.exec("ROLLBACK"),t}}class lc{client;constructor(e){this.client=e}get(){return this.client.prepare("SELECT node_id, created_at, updated_at FROM na_node_identity WHERE singleton_key = 1").get()}ensure(e,t){const n=this.get();if(n&&n.node_id!==e)throw Ac("NODE_AGENT_IDENTITY_MISMATCH",`Stored node identity ${n.node_id} does not match ${e}.`);return n||this.client.prepare("INSERT INTO na_node_identity (singleton_key, node_id, created_at, updated_at) VALUES (1, ?, ?, ?)").run(e,t,t),this.get()}}class uc{client;constructor(e){this.client=e}list(){return this.client.prepare("SELECT * FROM na_local_folders ORDER BY id").all().map(fc)}get(e){const t=this.client.prepare("SELECT * FROM na_local_folders WHERE id = ?").get(e);return t?fc(t):void 0}put(e){const t=rs.parse(Si(e));return this.client.prepare("INSERT INTO na_local_folders (id, node_id, name, path, labels_json, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT(id) DO UPDATE SET node_id=excluded.node_id, name=excluded.name, path=excluded.path,\n labels_json=excluded.labels_json, updated_at=excluded.updated_at").run(t.id,t.nodeId,t.name,t.path,ac(t.labels),t.createdAt,t.updatedAt),t}delete(e){return Number(this.client.prepare("DELETE FROM na_local_folders WHERE id = ?").run(e).changes)>0}}class pc{client;constructor(e){this.client=e}list(){return this.client.prepare("SELECT * FROM na_runtimes ORDER BY id").all().map(yc)}get(e){const t=this.client.prepare("SELECT * FROM na_runtimes WHERE id = ?").get(e);return t?yc(t):void 0}put(e){const t=Ws.parse(e);return this.client.prepare("INSERT INTO na_runtimes (id, node_id, name, type, status, access_strategy, capabilities_json, labels_json, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT(id) DO UPDATE SET node_id=excluded.node_id, name=excluded.name, type=excluded.type,\n status=excluded.status, access_strategy=excluded.access_strategy, capabilities_json=excluded.capabilities_json,\n labels_json=excluded.labels_json, updated_at=excluded.updated_at").run(t.id,t.nodeId,t.name,t.type,t.status,t.accessStrategy,ac(t.capabilities),ac(t.labels),t.createdAt,t.updatedAt),t}delete(e){try{return Number(this.client.prepare("DELETE FROM na_runtimes WHERE id = ?").run(e).changes)>0}catch(t){if(String(t).includes("FOREIGN KEY constraint failed"))throw Ac("NODE_RUNTIME_IN_USE",`Runtime ${e} is used by a controlled instance.`,409);throw t}}}class mc{client;constructor(e){this.client=e}list(){return this.client.prepare("SELECT i.*, o.health, o.connection_status, o.ready, o.observed_json,\n o.last_heartbeat_at, o.updated_at AS observation_updated_at\n FROM na_instances i LEFT JOIN na_instance_observations o ON o.instance_id = i.id ORDER BY i.id").all().map(e=>Ic(this.client,e))}get(e){const t=this.client.prepare("SELECT i.*, o.health, o.connection_status, o.ready, o.observed_json,\n o.last_heartbeat_at, o.updated_at AS observation_updated_at\n FROM na_instances i LEFT JOIN na_instance_observations o ON o.instance_id = i.id WHERE i.id = ?").get(e);return t?Ic(this.client,t):void 0}put(e){const t=po.parse(yo(e));return dc(this.client,()=>{const e=this.client.prepare("SELECT state_revision, registration_credential FROM na_instances WHERE id = ?").get(t.id),n=Math.max(t.stateRevision||0,Number(e?.state_revision)||0)+1,i=t.registrationToken||e?.registration_credential,s=function(e){const t={...e};for(const e of rc)delete t[e];for(const e of["id","nodeId","runtimeId","name","status","stateRevision","processIncarnationId","registrationToken","createdAt","updatedAt"])delete t[e];return t}({...t,stateRevision:n}),o=gc(t),r="local-folder"===t.source.type?t.source.localFolderId:void 0;return this.client.prepare("INSERT INTO na_instances\n (id, node_id, runtime_id, source_local_folder_id, name, status, state_revision, process_incarnation_id,\n registration_credential, desired_json, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT(id) DO UPDATE SET node_id=excluded.node_id, runtime_id=excluded.runtime_id,\n source_local_folder_id=excluded.source_local_folder_id, name=excluded.name, status=excluded.status,\n state_revision=excluded.state_revision, process_incarnation_id=excluded.process_incarnation_id,\n registration_credential=excluded.registration_credential, desired_json=excluded.desired_json,\n updated_at=excluded.updated_at").run(t.id,t.nodeId,t.runtimeId,r??null,t.name,t.status,n,t.processIncarnationId??null,i??null,ac(s),t.createdAt,t.updatedAt),this.client.prepare("INSERT INTO na_instance_observations\n (instance_id, health, connection_status, ready, observed_json, last_heartbeat_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT(instance_id) DO UPDATE SET health=excluded.health, connection_status=excluded.connection_status,\n ready=excluded.ready, observed_json=excluded.observed_json, last_heartbeat_at=excluded.last_heartbeat_at,\n updated_at=excluded.updated_at").run(t.id,t.health,t.connectionStatus,t.ready?1:0,ac(o),t.lastHeartbeatAt??null,t.updatedAt),this.get(t.id)})}putObservation(e){const t=po.parse(yo(e));return dc(this.client,()=>{const e=this.client.prepare("SELECT state_revision, registration_credential FROM na_instances WHERE id = ?").get(t.id);if(!e)throw Ac("NODE_INSTANCE_NOT_FOUND",`Instance ${t.id} was not found.`,404);const n=Math.max(t.stateRevision||0,Number(e.state_revision)||0)+1,i=t.registrationToken||e.registration_credential;return this.client.prepare("UPDATE na_instances SET status = ?, state_revision = ?, process_incarnation_id = ?,\n registration_credential = ?, updated_at = ? WHERE id = ?").run(t.status,n,t.processIncarnationId??null,i??null,t.updatedAt,t.id),this.client.prepare("INSERT INTO na_instance_observations\n (instance_id, health, connection_status, ready, observed_json, last_heartbeat_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT(instance_id) DO UPDATE SET health=excluded.health, connection_status=excluded.connection_status,\n ready=excluded.ready, observed_json=excluded.observed_json, last_heartbeat_at=excluded.last_heartbeat_at,\n updated_at=excluded.updated_at").run(t.id,t.health,t.connectionStatus,t.ready?1:0,ac(gc(t)),t.lastHeartbeatAt??null,t.updatedAt),this.get(t.id)})}delete(e){return Number(this.client.prepare("DELETE FROM na_instances WHERE id = ?").run(e).changes)>0}}function hc(e){return{nodeIdentity:new lc(e),localFolders:new uc(e),runtimes:new pc(e),instances:new mc(e)}}function gc(e){return Object.fromEntries(rc.flatMap(t=>void 0===e[t]?[]:[[t,e[t]]]))}function fc(e){return rs.parse({id:e.id,nodeId:e.node_id,name:e.name,path:e.path,labels:cc(e.labels_json),createdAt:e.created_at,updatedAt:e.updated_at})}function yc(e){return Ws.parse({id:e.id,nodeId:e.node_id,name:e.name,type:e.type,status:e.status,accessStrategy:e.access_strategy,capabilities:cc(e.capabilities_json),labels:cc(e.labels_json),createdAt:e.created_at,updatedAt:e.updated_at})}function Ic(e,t){const n=cc(t.desired_json),i=t.observed_json?cc(t.observed_json):{},s=e.prepare("SELECT * FROM na_instance_model_assignments WHERE instance_id = ?").get(String(t.id)),o=s?e.prepare("SELECT model_id FROM na_instance_model_entities WHERE instance_id = ? ORDER BY display_order").all(String(t.id)).map(e=>String(e.model_id)):void 0,r=s?{modelEntityIds:o,...s.legacy_codex_model_id?{codexModelHash:String(s.legacy_codex_model_id)}:{},...s.legacy_claude_model_id?{claudeModelHash:String(s.legacy_claude_model_id)}:{},...s.legacy_opencode_model_id?{opencodeModelHash:String(s.legacy_opencode_model_id)}:{}}:n.modelSelection;return po.parse({...n,...i,modelSelection:r,id:t.id,nodeId:t.node_id,runtimeId:t.runtime_id,name:t.name,status:t.status,stateRevision:t.state_revision,processIncarnationId:t.process_incarnation_id||void 0,registrationToken:t.registration_credential||void 0,health:t.health||"unknown",connectionStatus:t.connection_status||"unknown",ready:Boolean(t.ready),lastHeartbeatAt:t.last_heartbeat_at||void 0,createdAt:t.created_at,updatedAt:t.updated_at})}function Ac(e,t,n=409){return Object.assign(new Error(t),{code:e,statusCode:n})}function _c(e){return JSON.stringify(e??null)}function Ec(e){return JSON.parse(String(e))}class wc{client;constructor(e){this.client=e}list(){return this.client.prepare("SELECT * FROM na_models ORDER BY display_order, id").all().map(Sc)}get(e){const t=this.client.prepare("SELECT * FROM na_models WHERE id = ?").get(e);return t?Sc(t):void 0}put(e){const t=hs.parse(e);return this.client.prepare("INSERT INTO na_models\n (id, name, endpoint, key, model, app, enabled, display_order, model_names_json, protocols_json, labels_json, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT(id) DO UPDATE SET name=excluded.name, endpoint=excluded.endpoint, key=excluded.key,\n model=excluded.model, app=excluded.app, enabled=excluded.enabled, display_order=excluded.display_order,\n model_names_json=excluded.model_names_json, protocols_json=excluded.protocols_json,\n labels_json=excluded.labels_json, updated_at=excluded.updated_at").run(t.id,t.name,t.endpoint,t.key,t.model,t.app,t.enabled?1:0,t.order,_c(t.modelNames),_c(t.protocols),_c(t.labels),t.createdAt,t.updatedAt),t}delete(e){try{return Number(this.client.prepare("DELETE FROM na_models WHERE id = ?").run(e).changes)>0}catch(t){if(String(t).includes("FOREIGN KEY constraint failed")){const t=this.referenceIds(e);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})}throw t}}referenceIds(e){return this.client.prepare("SELECT DISTINCT instance_id FROM (\n SELECT instance_id FROM na_instance_model_entities WHERE model_id = ?\n UNION ALL SELECT instance_id FROM na_instance_model_assignments WHERE legacy_codex_model_id = ?\n UNION ALL SELECT instance_id FROM na_instance_model_assignments WHERE legacy_claude_model_id = ?\n UNION ALL SELECT instance_id FROM na_instance_model_assignments WHERE legacy_opencode_model_id = ?\n ) ORDER BY instance_id").all(e,e,e,e).map(e=>String(e.instance_id))}}class Tc{client;constructor(e){this.client=e}get(e){const t=this.client.prepare("SELECT * FROM na_instance_model_assignments WHERE instance_id = ?").get(e);if(!t)return;const n=this.client.prepare("SELECT model_id FROM na_instance_model_entities WHERE instance_id = ? ORDER BY display_order").all(e).map(e=>String(e.model_id));return ys.parse({instanceId:e,modelEntityIds:n,codexModelHash:t.legacy_codex_model_id||void 0,claudeModelHash:t.legacy_claude_model_id||void 0,opencodeModelHash:t.legacy_opencode_model_id||void 0,updatedAt:t.updated_at})}put(e){const t=ys.parse(e);return this.transaction(()=>{this.client.prepare("INSERT INTO na_instance_model_assignments\n (instance_id, legacy_codex_model_id, legacy_claude_model_id, legacy_opencode_model_id, updated_at)\n VALUES (?, ?, ?, ?, ?)\n ON CONFLICT(instance_id) DO UPDATE SET legacy_codex_model_id=excluded.legacy_codex_model_id,\n legacy_claude_model_id=excluded.legacy_claude_model_id,\n legacy_opencode_model_id=excluded.legacy_opencode_model_id, updated_at=excluded.updated_at").run(t.instanceId,t.codexModelHash??null,t.claudeModelHash??null,t.opencodeModelHash??null,t.updatedAt),this.client.prepare("DELETE FROM na_instance_model_entities WHERE instance_id = ?").run(t.instanceId);const e=this.client.prepare("INSERT INTO na_instance_model_entities (instance_id, model_id, display_order) VALUES (?, ?, ?)");for(const[n,i]of t.modelEntityIds.entries())e.run(t.instanceId,i,n)}),this.get(t.instanceId)}delete(e){return Number(this.client.prepare("DELETE FROM na_instance_model_assignments WHERE instance_id = ?").run(e).changes)>0}transaction(e){if(this.client.isTransaction)return e();this.client.exec("BEGIN IMMEDIATE");try{const t=e();return this.client.exec("COMMIT"),t}catch(e){throw this.client.exec("ROLLBACK"),e}}}function bc(e){return{models:new wc(e),assignments:new Tc(e),transaction(t){if(e.isTransaction)return t();e.exec("BEGIN IMMEDIATE");try{const n=t();return e.exec("COMMIT"),n}catch(t){throw e.exec("ROLLBACK"),t}}}}function Sc(e){const t=Ec(e.model_names_json);return hs.parse({id:e.id,name:e.name,endpoint:e.endpoint,key:e.key,model:e.model,modelNames:t,protocols:Ec(e.protocols_json),app:e.app,enabled:Boolean(e.enabled),order:e.display_order,labels:Ec(e.labels_json),createdAt:e.created_at,updatedAt:e.updated_at})}class vc{client;constructor(e){this.client=e}readIdentity(){const e=this.client.prepare("SELECT node_id, created_at, updated_at FROM na_node_identity WHERE singleton_key = 1").get();if(!e)return;const t=this.client.prepare("SELECT * FROM na_control_plane_pairings ORDER BY updated_at, key_id").all().map(e=>({id:String(e.control_plane_id),keyId:String(e.key_id),...e.name?{name:String(e.name)}:{},secret:String(e.secret),pairedAt:String(e.paired_at),...e.revoked_at?{revokedAt:String(e.revoked_at)}:{},updatedAt:String(e.updated_at)})),n=this.client.prepare("SELECT * FROM na_control_plane_connections ORDER BY updated_at, id").all().map(e=>({id:String(e.id),pairingKeyId:String(e.pairing_key_id),...e.name?{name:String(e.name)}:{},url:String(e.normalized_url),enabled:Boolean(e.enabled),createdAt:String(e.created_at),updatedAt:String(e.updated_at)}));return{nodeId:String(e.node_id),createdAt:String(e.created_at),updatedAt:String(e.updated_at),controlPlanePairings:t,controlPlaneConnections:n}}writeIdentity(e){return this.transaction(()=>{const t=this.readIdentity();if(t&&t.nodeId!==e.nodeId)throw n=`Stored node identity ${t.nodeId} does not match ${e.nodeId}.`,Object.assign(new Error(n),{code:"NODE_AGENT_IDENTITY_MISMATCH",statusCode:409});var n;this.client.prepare("INSERT INTO na_node_identity (singleton_key, node_id, created_at, updated_at) VALUES (1, ?, ?, ?)\n ON CONFLICT(singleton_key) DO UPDATE SET updated_at=excluded.updated_at").run(e.nodeId,e.createdAt,e.updatedAt);const i=(e.controlPlanePairings||[]).map(e=>e.keyId),s=(e.controlPlaneConnections||[]).map(e=>e.id);Oc(this.client,"na_control_plane_connections","id",s),Oc(this.client,"na_control_plane_pairings","key_id",i);const o=this.client.prepare("INSERT INTO na_control_plane_pairings\n (key_id, control_plane_id, name, secret, paired_at, revoked_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT(key_id) DO UPDATE SET control_plane_id=excluded.control_plane_id, name=excluded.name,\n secret=excluded.secret, paired_at=excluded.paired_at, revoked_at=excluded.revoked_at, updated_at=excluded.updated_at");for(const t of e.controlPlanePairings||[])o.run(t.keyId,t.id,t.name??null,t.secret,t.pairedAt,t.revokedAt??null,t.updatedAt);const r=this.client.prepare("INSERT INTO na_control_plane_connections\n (id, pairing_key_id, name, normalized_url, enabled, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT(id) DO UPDATE SET pairing_key_id=excluded.pairing_key_id, name=excluded.name,\n normalized_url=excluded.normalized_url, enabled=excluded.enabled, updated_at=excluded.updated_at");for(const t of e.controlPlaneConnections||[])r.run(t.id,t.pairingKeyId,t.name??null,Nc(t.url),t.enabled?1:0,t.createdAt,t.updatedAt);return this.readIdentity()})}listOperations(e){return(e?.length?this.client.prepare(`SELECT * FROM na_control_plane_connection_operations WHERE phase IN (${e.map(()=>"?").join(",")}) ORDER BY created_at`).all(...e):this.client.prepare("SELECT * FROM na_control_plane_connection_operations ORDER BY created_at").all()).map(zc)}putOperation(e){return this.client.prepare("INSERT INTO na_control_plane_connection_operations\n (id, kind, phase, requested_json, pairing_key_id, connection_id, replaced_connections_json, error_json, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT(id) DO UPDATE SET phase=excluded.phase, pairing_key_id=excluded.pairing_key_id,\n connection_id=excluded.connection_id, replaced_connections_json=excluded.replaced_connections_json,\n error_json=excluded.error_json, updated_at=excluded.updated_at").run(e.id,e.kind,e.phase,JSON.stringify(e.requested),e.pairingKeyId??null,e.connectionId??null,JSON.stringify(e.replacedConnections),e.error?JSON.stringify(e.error):null,e.createdAt,e.updatedAt),e}deleteOperation(e){return Number(this.client.prepare("DELETE FROM na_control_plane_connection_operations WHERE id = ?").run(e).changes)>0}transaction(e){if(this.client.isTransaction)return e();this.client.exec("BEGIN IMMEDIATE");try{const t=e();return this.client.exec("COMMIT"),t}catch(e){throw this.client.exec("ROLLBACK"),e}}}function Nc(e){return new URL(e).toString().replace(/\/$/,"")}function Oc(e,t,n,i){i.length?e.prepare(`DELETE FROM ${t} WHERE ${n} NOT IN (${i.map(()=>"?").join(",")})`).run(...i):e.exec(`DELETE FROM ${t}`)}function zc(e){return{id:String(e.id),kind:String(e.kind),phase:e.phase,requested:JSON.parse(String(e.requested_json)),...e.pairing_key_id?{pairingKeyId:String(e.pairing_key_id)}:{},...e.connection_id?{connectionId:String(e.connection_id)}:{},replacedConnections:JSON.parse(String(e.replaced_connections_json)),...e.error_json?{error:JSON.parse(String(e.error_json))}:{},createdAt:String(e.created_at),updatedAt:String(e.updated_at)}}const Cc=a.z.string().trim().min(1).max(120).regex(/^[a-zA-Z0-9][a-zA-Z0-9_.:-]*$/),Rc=a.z.string().datetime(),xc=a.z.number().int().nonnegative(),kc=a.z.enum(["https-token","ssh-key"]),Dc=a.z.enum(["operation-only","instance-retained"]),Pc=a.z.enum(["enabled","disabled"]),Lc=a.z.enum(["pending","synced","deferred","revoking","revoked"]),Mc=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 jc(e){throw new Error(`Invalid Git credential scope: ${e}`)}function Uc(e){const t=e.trim().replace(/^\[|\]$/g,"");(!t||t.includes("*")||/[/?#@\s]/.test(t))&&jc("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("*"))&&jc("host is invalid"),e}catch{jc("host is invalid")}}function Fc(e){try{return decodeURIComponent(e)}catch{jc("path contains invalid percent encoding")}}function $c(e){const t=e?.trim()||"/";(t.includes("?")||t.includes("#")||t.includes("\\")||t.includes("\0"))&&jc("path contains an unsupported delimiter");const n=(t.startsWith("/")?t:`/${t}`).split("/").filter(Boolean);for(const e of n){const t=Fc(e);("."===t||".."===t||t.includes("/")||t.includes("\\")||t.includes("\0"))&&jc("path contains an unsafe segment")}return 0===n.length?"/":`/${n.join("/")}/`}function Hc(e){const t=Mc.parse(e),n="https"===t.scheme?443:22;return Mc.parse({scheme:t.scheme,host:Uc(t.host),...void 0===t.port||t.port===n?{}:{port:t.port},pathPrefix:$c(t.pathPrefix)})}function qc(e){return $c(e.replace(/\.git\/?$/,""))}const Vc=a.z.object({id:Cc,name:a.z.string().trim().min(1).max(160),kind:kc,scope:Mc,secretSet:a.z.literal(!0),status:Pc,revision:xc,createdAt:Rc,updatedAt:Rc}).strict(),Bc=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(),Kc=a.z.object({kind:a.z.literal("ssh-key"),privateKey:a.z.string().min(1).max(131072),passphrase:a.z.string().max(8192).optional(),pinnedKnownHosts:a.z.string().min(1).max(131072)}).strict(),Gc=a.z.discriminatedUnion("kind",[Bc,Kc]);a.z.object({name:a.z.string().trim().min(1).max(160),scope:Mc,secret:Gc}).strict().superRefine((e,t)=>{"https"===e.scope.scheme!=("https-token"===e.secret.kind)&&t.addIssue({code:"custom",path:["scope","scheme"],message:"Credential kind must match the remote scheme."});try{Hc(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:Mc.optional(),secret:Gc.optional(),status:Pc.optional()}).strict().refine(e=>Object.keys(e).length>0,"At least one credential field must be updated."),a.z.object({items:a.z.array(Vc).max(1e4)}).strict();const Wc=a.z.object({instanceId:Cc,credentialId:Cc,credentialRevision:xc,assignmentRevision:xc,status:Lc,authorizedAt:Rc,updatedAt:Rc}).strict(),Xc=a.z.object({credential:Vc,secret:Gc}).strict().superRefine((e,t)=>{e.credential.kind!==e.secret.kind&&t.addIssue({code:"custom",path:["secret","kind"],message:"Credential payload kind mismatch."})}),Yc=a.z.object({instanceId:Cc,generation:xc,credentialIds:a.z.array(Cc).max(256).transform(e=>[...new Set(e)].sort()),updatedAt:Rc}).strict(),Jc=a.z.object({remoteUrl:a.z.string().trim().min(1).max(4096)}).strict(),Qc=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()]),Zc=a.z.object({remoteUrl:a.z.string().trim().min(1).max(4096)}).strict(),ed=a.z.discriminatedUnion("status",[a.z.object({status:a.z.literal("ok"),invocationId:Cc,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()]),td=a.z.object({invocationId:Cc,frame:a.z.string().min(1).max(1048576)}).strict(),nd=a.z.object({frame:a.z.string().min(1).max(1048576)}).strict(),id=a.z.object({operationId:Cc,retention:Dc,payload:Xc}).strict(),sd=a.z.object({operationId:Cc,instanceId:Cc,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(id).max(256).default([])}).strict();function od(e){return e&&"object"==typeof e&&!Array.isArray(e)?e:void 0}function rd(e,t){if(e)return Object.fromEntries(t.filter(t=>Object.prototype.hasOwnProperty.call(e,t)).map(t=>[t,e[t]]))}function ad(e,t){let n;try{n=function(e){const t=e.trim();if(t&&!t.includes("\0")||jc("remote is empty or invalid"),/^https?:\/\//i.test(t)||/^ssh:\/\//i.test(t)){let e;$c(t.replace(/^[a-z][a-z0-9+.-]*:\/\/[^/]+/i,"").split(/[?#]/,1)[0]||"/");try{e=new URL(t)}catch{jc("remote URL is invalid")}"https:"!==e.protocol&&"ssh:"!==e.protocol&&jc("remote scheme is unsupported"),(e.password||"https:"===e.protocol&&e.username)&&jc("HTTPS userinfo is forbidden"),(e.search||e.hash)&&jc("query and fragment are forbidden");const n="https:"===e.protocol?"https":"ssh",i=e.port?Number(e.port):void 0;return{...Hc({scheme:n,host:e.hostname,port:i,pathPrefix:qc(e.pathname)}),original:t}}/^[a-z][a-z0-9+.-]*:\/\//i.test(t)&&jc("remote scheme is unsupported");const n=/^(?:([^@/:\s]+)@)?([^/:\s]+):(.+)$/.exec(t);n||jc("remote must use HTTPS, ssh://, or scp-like SSH syntax");const[,,i,s]=n;return(s.includes("?")||s.includes("#"))&&jc("query and fragment are forbidden"),{...Hc({scheme:"ssh",host:i,pathPrefix:qc(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=Hc(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:Hc(e.scope).pathPrefix.length}));if(0===i.length)return{status:"none",remote:n};const s=Math.max(...i.map(e=>e.specificity)),o=i.filter(e=>e.specificity===s).map(e=>e.candidate);if(o.length>1)return{status:"ambiguous",remote:n,credentialIds:o.map(e=>e.id).sort()};const r=o[0];return"ssh-key"===r.kind&&!0!==r.pinnedKnownHosts?{status:"missing-host-key",remote:n,credentialId:r.id}:{status:"unique",remote:n,credential:r}}class cd{client;constructor(e){this.client=e}listPayloads(){return this.client.prepare("SELECT * FROM na_git_credential_payloads ORDER BY credential_id").all().map(ld)}getPayload(e){const t=this.client.prepare("SELECT * FROM na_git_credential_payloads WHERE credential_id = ?").get(e);return t?ld(t):void 0}putPayload(e){const t=Xc.parse(e.payload);return this.client.prepare("INSERT INTO na_git_credential_payloads\n (credential_id, revision, public_json, secret_json, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?)\n ON CONFLICT(credential_id) DO UPDATE SET revision=excluded.revision, public_json=excluded.public_json,\n secret_json=excluded.secret_json, updated_at=excluded.updated_at").run(e.id,t.credential.revision,JSON.stringify(t.credential),JSON.stringify(t.secret),e.createdAt,e.updatedAt),{...e,payload:t}}deletePayload(e){return Number(this.client.prepare("DELETE FROM na_git_credential_payloads WHERE credential_id = ?").run(e).changes)>0}collectUnreferencedPayloads(){return Number(this.client.prepare("DELETE FROM na_git_credential_payloads\n WHERE NOT EXISTS (SELECT 1 FROM na_git_authorization_members m WHERE m.credential_id = na_git_credential_payloads.credential_id)").run().changes)}listAuthorizations(){return this.client.prepare("SELECT * FROM na_git_authorization_sets ORDER BY instance_id").all().map(e=>this.authorizationFromRow(e))}getAuthorization(e){const t=this.client.prepare("SELECT * FROM na_git_authorization_sets WHERE instance_id = ?").get(e);return t?this.authorizationFromRow(t):void 0}putAuthorization(e){const t=Yc.parse({instanceId:e.instanceId,generation:e.generation,credentialIds:e.credentialIds,updatedAt:e.updatedAt});return this.transaction(()=>{this.client.prepare("INSERT INTO na_git_authorization_sets (instance_id, generation, created_at, updated_at)\n VALUES (?, ?, ?, ?) ON CONFLICT(instance_id) DO UPDATE SET generation=excluded.generation, updated_at=excluded.updated_at").run(t.instanceId,t.generation,e.createdAt,t.updatedAt),this.client.prepare("DELETE FROM na_git_authorization_members WHERE instance_id = ?").run(t.instanceId);const n=this.client.prepare("INSERT INTO na_git_authorization_members (instance_id, credential_id, display_order) VALUES (?, ?, ?)");for(const[e,i]of t.credentialIds.entries())n.run(t.instanceId,i,e);return this.getAuthorization(t.instanceId)})}putAuthorizationCas(e){const t=Yc.parse({instanceId:e.instanceId,generation:e.generation,credentialIds:e.credentialIds,updatedAt:e.updatedAt});return this.transaction(()=>{const n=this.getAuthorization(t.instanceId);if(n&&n.generation>t.generation)throw dd("GIT_CREDENTIAL_REVISION_STALE",`Refusing stale authorization set revision for ${t.instanceId}.`);if(n&&n.generation===t.generation){if(JSON.stringify(n.credentialIds)!==JSON.stringify(t.credentialIds))throw dd("GIT_CREDENTIAL_REVISION_CONFLICT",`Refusing conflicting authorization set revision for ${t.instanceId}.`);return n}for(const e of t.credentialIds)if(!this.getPayload(e))throw dd("GIT_CREDENTIAL_PAYLOAD_MISSING",`Credential payload ${e} is not deployed.`);if(n){const e=this.client.prepare("UPDATE na_git_authorization_sets\n SET generation = ?, updated_at = ? WHERE instance_id = ? AND generation < ?").run(t.generation,t.updatedAt,t.instanceId,t.generation).changes;if(1!==Number(e))throw dd("GIT_CREDENTIAL_REVISION_STALE",`Authorization set ${t.instanceId} changed concurrently.`)}else this.client.prepare("INSERT INTO na_git_authorization_sets (instance_id, generation, created_at, updated_at)\n VALUES (?, ?, ?, ?)").run(t.instanceId,t.generation,e.createdAt,t.updatedAt);this.client.prepare("DELETE FROM na_git_authorization_members WHERE instance_id = ?").run(t.instanceId);const i=this.client.prepare("INSERT INTO na_git_authorization_members (instance_id, credential_id, display_order) VALUES (?, ?, ?)");for(const[e,n]of t.credentialIds.entries())i.run(t.instanceId,n,e);return this.getAuthorization(t.instanceId)})}deleteAuthorization(e){return Number(this.client.prepare("DELETE FROM na_git_authorization_sets WHERE instance_id = ?").run(e).changes)>0}listProvisioning(){return this.client.prepare("SELECT * FROM na_git_workspace_provisioning ORDER BY instance_id").all().map(ud)}getProvisioning(e){const t=this.client.prepare("SELECT * FROM na_git_workspace_provisioning WHERE instance_id = ?").get(e);return t?ud(t):void 0}putProvisioning(e){const t="pending"===e.status?e.input.operationId:e.operationId;return this.client.prepare("INSERT INTO na_git_workspace_provisioning\n (instance_id, status, operation_id, input_json, created_at, updated_at, expires_at) VALUES (?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT(instance_id) DO UPDATE SET status=excluded.status, operation_id=excluded.operation_id,\n input_json=excluded.input_json, updated_at=excluded.updated_at, expires_at=excluded.expires_at").run(e.id,e.status,t,"pending"===e.status?JSON.stringify(e.input):null,e.createdAt,e.updatedAt,e.expiresAt),this.getProvisioning(e.id)}deleteProvisioning(e){return Number(this.client.prepare("DELETE FROM na_git_workspace_provisioning WHERE instance_id = ?").run(e).changes)>0}deleteExpiredProvisioning(e){return Number(this.client.prepare("DELETE FROM na_git_workspace_provisioning WHERE expires_at <= ?").run(e).changes)}consumeProvisioning(e,t,n,i){return this.transaction(()=>{const s=this.client.prepare("UPDATE na_git_workspace_provisioning\n SET status = 'consumed', input_json = NULL, updated_at = ?, expires_at = ?\n WHERE instance_id = ? AND operation_id = ? AND status = 'pending'").run(n,i,e,t).changes;if(1===Number(s))return!0;const o=this.getProvisioning(e);return"consumed"===o?.status&&o.operationId===t})}authorizationFromRow(e){const t=this.client.prepare("SELECT credential_id FROM na_git_authorization_members WHERE instance_id = ? ORDER BY display_order").all(String(e.instance_id)).map(e=>String(e.credential_id));return{id:String(e.instance_id),instanceId:String(e.instance_id),generation:Number(e.generation),credentialIds:t,createdAt:String(e.created_at),updatedAt:String(e.updated_at)}}transaction(e){if(this.client.isTransaction)return e();this.client.exec("BEGIN IMMEDIATE");try{const t=e();return this.client.exec("COMMIT"),t}catch(e){throw this.client.exec("ROLLBACK"),e}}}function dd(e,t){return Object.assign(new Error(t),{code:e,statusCode:409})}function ld(e){return{id:String(e.credential_id),payload:Xc.parse({credential:JSON.parse(String(e.public_json)),secret:JSON.parse(String(e.secret_json))}),createdAt:String(e.created_at),updatedAt:String(e.updated_at)}}function ud(e){const t={id:String(e.instance_id),createdAt:String(e.created_at),updatedAt:String(e.updated_at),expiresAt:String(e.expires_at)};return"pending"===e.status?{...t,status:"pending",input:sd.parse(JSON.parse(String(e.input_json)))}:{...t,status:"consumed",operationId:String(e.operation_id)}}class pd{tail=Promise.resolve();accepting=!0;run(e){if(!this.accepting)return Promise.reject(Ed("NODE_AGENT_REPOSITORY_QUIESCING","Node Agent storage is shutting down.",503));const t=this.tail.then(e,e);return this.tail=t.then(()=>{},()=>{}),t}async barrier(){await this.tail}stopAccepting(){this.accepting=!1}}function md(e){const t=e.db,n=new pd,i=new A.AsyncLocalStorage;let s=!1;const o=()=>{if(s)throw Ed("NODE_AGENT_REPOSITORY_CLOSED","Node Agent storage is closed.",503)},r=async e=>(o(),i.getStore()||await n.barrier(),e()),a=async e=>(o(),i.getStore()?e():n.run(e));let c;return c={stories:hd(t,r,a),actions:gd(t,r,a),documents:fd(t,r,a),automations:yd(t,r,a),runs:Id(t,r,a),fileMutations:Ad(t,r,a),deletionIntents:_d(t,r,a),topology:hc(e.client),model:bc(e.client),access:new vc(e.client),git:new cd(e.client),transaction:async t=>i.getStore()?t(c):a(async()=>{e.client.exec("BEGIN IMMEDIATE");try{const n=await i.run(!0,()=>t(c));return e.client.exec("COMMIT"),n}catch(t){throw e.client.exec("ROLLBACK"),t}}),transactionSync:t=>{if(o(),e.client.isTransaction)return t(c);e.client.exec("BEGIN IMMEDIATE");try{const n=t(c);return e.client.exec("COMMIT"),n}catch(t){throw e.client.exec("ROLLBACK"),t}},stopAccepting(){n.stopAccepting()},async drain(){await n.barrier()},async checkpoint(){await n.barrier(),await e.checkpoint()},async close(){s||(n.stopAccepting(),await n.barrier(),await e.checkpoint(),s=!0,await e.close())}},c}function hd(e,t,n){return{list:()=>t(()=>e.select().from(Za).orderBy(_.desc(Za.createdAt),_.asc(Za.id))),get:async n=>t(async()=>(await e.select().from(Za).where(_.eq(Za.id,n)).limit(1))[0]),insert:async t=>n(async()=>(await e.insert(Za).values(t),t)),update:async(t,i)=>n(async()=>(await e.update(Za).set(i).where(_.eq(Za.id,t)),(await e.select().from(Za).where(_.eq(Za.id,t)).limit(1))[0])),delete:async t=>n(async()=>Number((await e.delete(Za).where(_.eq(Za.id,t))).changes)>0)}}function gd(e,t,n){return{list:n=>t(()=>e.select().from(ec).where(_.eq(ec.storyId,n)).orderBy(_.asc(ec.displayOrder),_.asc(ec.id))),replace:async(t,i)=>n(async()=>{const n=i.map(e=>e.id);n.length?await e.delete(ec).where(_.and(_.eq(ec.storyId,t),_.notInArray(ec.id,n))):await e.delete(ec).where(_.eq(ec.storyId,t));for(const t of i)await e.insert(ec).values(t).onConflictDoUpdate({target:[ec.storyId,ec.id],set:{title:t.title,promptTemplate:t.promptTemplate,targetInstanceId:t.targetInstanceId,sessionPreset:t.sessionPreset,displayOrder:t.displayOrder}});return i})}}function fd(e,t,n){return{list:n=>t(()=>e.select().from(tc).where(_.eq(tc.storyId,n)).orderBy(_.asc(tc.displayOrder),_.asc(tc.storyPath))),get:async(n,i)=>t(async()=>(await e.select().from(tc).where(_.and(_.eq(tc.storyId,n),_.eq(tc.storyPath,i))).limit(1))[0]),page:async(n,i,s)=>t(async()=>{const t=Number((await e.select({value:_.count()}).from(tc).where(_.eq(tc.storyId,n)))[0]?.value??0);return{items:await e.select({title:tc.title,storyPath:tc.storyPath}).from(tc).where(_.eq(tc.storyId,n)).orderBy(_.desc(tc.indexedSequence),_.asc(tc.storyPath)).limit(s).offset((i-1)*s),totalItems:t}}),insert:async t=>n(async()=>(await e.insert(tc).values(t),t)),update:async(t,i,s)=>n(async()=>{await e.update(tc).set(s).where(_.and(_.eq(tc.storyId,t),_.eq(tc.storyPath,i)))}),replacePath:async(t,i,s)=>n(async()=>{await e.delete(tc).where(_.and(_.eq(tc.storyId,t),_.eq(tc.storyPath,i))),await e.insert(tc).values(s)}),reorder:async(t,i)=>n(async()=>{for(const[n,s]of i.entries())await e.update(tc).set({displayOrder:n}).where(_.and(_.eq(tc.storyId,t),_.eq(tc.storyPath,s)))}),delete:async(t,i)=>n(async()=>Number((await e.delete(tc).where(_.and(_.eq(tc.storyId,t),_.eq(tc.storyPath,i)))).changes)>0)}}function yd(e,t,n){return{list:n=>t(()=>n?e.select().from(nc).where(_.eq(nc.storyId,n)).orderBy(_.asc(nc.createdAt),_.asc(nc.id)):e.select().from(nc).orderBy(_.asc(nc.createdAt),_.asc(nc.id))),get:async n=>t(async()=>(await e.select().from(nc).where(_.eq(nc.id,n)).limit(1))[0]),insert:async t=>n(async()=>(await e.insert(nc).values(t),t)),update:async(t,i)=>n(async()=>(await e.update(nc).set(i).where(_.eq(nc.id,t)),(await e.select().from(nc).where(_.eq(nc.id,t)).limit(1))[0])),referencingActions:async(n,i)=>i.length?t(()=>e.select().from(nc).where(_.and(_.eq(nc.storyId,n),_.inArray(nc.actionId,i)))):[],delete:async t=>n(async()=>Number((await e.delete(nc).where(_.eq(nc.id,t))).changes)>0),deleteForStory:async t=>n(async()=>{await e.delete(nc).where(_.eq(nc.storyId,t))})}}function Id(e,t,n){const i=["queued","dispatching","running"];return{list:n=>t(()=>e.select().from(ic).where(_.eq(ic.automationId,n)).orderBy(_.desc(ic.queuedAt))),get:async n=>t(async()=>(await e.select().from(ic).where(_.eq(ic.id,n)).limit(1))[0]),byExecutionKey:async n=>t(async()=>(await e.select().from(ic).where(_.eq(ic.executionKey,n)).limit(1))[0]),pending:()=>t(()=>e.select().from(ic).where(_.inArray(ic.status,[...i])).orderBy(_.asc(ic.queuedAt))),activeForStory:async n=>t(()=>e.select({run:ic}).from(ic).innerJoin(nc,_.eq(ic.automationId,nc.id)).where(_.and(_.eq(nc.storyId,n),_.inArray(ic.status,[...i]))).then(e=>e.map(e=>e.run))),insert:async t=>n(async()=>(await e.insert(ic).values(t),t)),update:async(t,i)=>n(async()=>(await e.update(ic).set(i).where(_.eq(ic.id,t)),(await e.select().from(ic).where(_.eq(ic.id,t)).limit(1))[0])),trimTerminal:async(t,i)=>n(async()=>{const n=await e.select({id:ic.id}).from(ic).where(_.and(_.eq(ic.automationId,t),_.inArray(ic.status,["completed","failed","skipped"]))).orderBy(_.desc(ic.queuedAt)).limit(2147483647).offset(i);n.length&&await e.delete(ic).where(_.inArray(ic.id,n.map(e=>e.id)))})}}function Ad(e,t,n){return{list:()=>t(()=>e.select().from(sc).orderBy(_.asc(sc.createdAt))),get:async n=>t(async()=>(await e.select().from(sc).where(_.eq(sc.id,n)).limit(1))[0]),insert:async t=>n(async()=>(await e.insert(sc).values(t),t)),update:async(t,i)=>n(async()=>{await e.update(sc).set(i).where(_.eq(sc.id,t))}),delete:async t=>n(async()=>{await e.delete(sc).where(_.eq(sc.id,t))})}}function _d(e,t,n){return{list:()=>t(()=>e.select().from(oc).orderBy(_.asc(oc.createdAt))),get:async n=>t(async()=>(await e.select().from(oc).where(_.eq(oc.storyId,n)).limit(1))[0]),put:async t=>n(async()=>(await e.insert(oc).values(t).onConflictDoUpdate({target:oc.storyId,set:{phase:t.phase,trashName:t.trashName,updatedAt:t.updatedAt}}),t)),delete:async t=>n(async()=>{await e.delete(oc).where(_.eq(oc.storyId,t))})}}function Ed(e,t,n){return Object.assign(new Error(t),{code:e,statusCode:n})}function wd(e,t){return{id:e,sql:t,checksum:d.createHash("sha256").update(t).digest("hex")}}const Td=[wd("0001_story_domain","\nCREATE TABLE na_stories (\n id TEXT PRIMARY KEY NOT NULL, title TEXT NOT NULL, description TEXT,\n created_at TEXT NOT NULL, updated_at TEXT NOT NULL, archived_at TEXT,\n max_idle_ai_sessions INTEGER NOT NULL DEFAULT 5 CHECK(max_idle_ai_sessions BETWEEN 1 AND 50),\n next_document_sequence INTEGER NOT NULL DEFAULT 1 CHECK(next_document_sequence > 0)\n);\nCREATE INDEX na_stories_created_idx ON na_stories(created_at);\nCREATE TABLE na_story_actions (\n story_id TEXT NOT NULL REFERENCES na_stories(id) ON DELETE CASCADE, id TEXT NOT NULL,\n title TEXT NOT NULL, prompt_template TEXT NOT NULL, target_instance_id TEXT,\n session_preset_json TEXT, display_order INTEGER NOT NULL,\n PRIMARY KEY(story_id, id)\n);\nCREATE INDEX na_story_actions_order_idx ON na_story_actions(story_id, display_order, id);\nCREATE TABLE na_story_documents (\n story_id TEXT NOT NULL REFERENCES na_stories(id) ON DELETE CASCADE, story_path TEXT NOT NULL,\n title TEXT NOT NULL, indexed_sequence INTEGER NOT NULL CHECK(indexed_sequence > 0), display_order INTEGER NOT NULL,\n PRIMARY KEY(story_id, story_path)\n);\nCREATE UNIQUE INDEX na_story_documents_sequence_uq ON na_story_documents(story_id, indexed_sequence);\nCREATE INDEX na_story_documents_page_idx ON na_story_documents(story_id, indexed_sequence, story_path);\nCREATE INDEX na_story_documents_display_idx ON na_story_documents(story_id, display_order, story_path);\nCREATE TABLE na_story_automations (\n id TEXT PRIMARY KEY NOT NULL, story_id TEXT NOT NULL, action_id TEXT NOT NULL,\n schedule_json TEXT NOT NULL, enabled INTEGER NOT NULL, policy_json TEXT NOT NULL,\n schedule_anchor_at TEXT NOT NULL, created_at TEXT NOT NULL, updated_at TEXT NOT NULL,\n CONSTRAINT na_story_automations_action_fk FOREIGN KEY(story_id, action_id)\n REFERENCES na_story_actions(story_id, id) ON DELETE RESTRICT\n);\nCREATE INDEX na_story_automations_story_idx ON na_story_automations(story_id);\nCREATE INDEX na_story_automations_enabled_idx ON na_story_automations(enabled);\nCREATE TABLE na_story_automation_runs (\n id TEXT PRIMARY KEY NOT NULL, automation_id TEXT NOT NULL REFERENCES na_story_automations(id) ON DELETE CASCADE,\n event_type TEXT NOT NULL CHECK(event_type IN ('manual','schedule')),\n status TEXT NOT NULL CHECK(status IN ('queued','dispatching','running','completed','failed','skipped')),\n scheduled_for TEXT NOT NULL, target_instance_id TEXT NOT NULL, ai_session_id TEXT, error_json TEXT,\n queued_at TEXT NOT NULL, started_at TEXT, completed_at TEXT,\n execution_key TEXT NOT NULL, request_fingerprint TEXT NOT NULL, execution_input_json TEXT NOT NULL\n);\nCREATE UNIQUE INDEX na_story_automation_runs_execution_key_uq ON na_story_automation_runs(execution_key);\nCREATE INDEX na_story_automation_runs_automation_time_idx ON na_story_automation_runs(automation_id, queued_at);\nCREATE INDEX na_story_automation_runs_status_idx ON na_story_automation_runs(status, scheduled_for);\nCREATE TABLE na_story_file_mutations (\n id TEXT PRIMARY KEY NOT NULL, story_id TEXT NOT NULL REFERENCES na_stories(id) ON DELETE RESTRICT,\n operation TEXT NOT NULL CHECK(operation IN ('write','rename','delete')), story_path TEXT NOT NULL,\n next_story_path TEXT, title TEXT, temporary_name TEXT, backup_name TEXT,\n phase TEXT NOT NULL CHECK(phase IN ('receiving','prepared','files-staged','database-committed','cleanup')),\n created_at TEXT NOT NULL, updated_at TEXT NOT NULL\n);\nCREATE INDEX na_story_file_mutations_story_idx ON na_story_file_mutations(story_id, created_at);\nCREATE TABLE na_story_deletion_intents (\n story_id TEXT PRIMARY KEY NOT NULL,\n phase TEXT NOT NULL CHECK(phase IN ('prepared','files-staged','database-committed','cleanup')),\n trash_name TEXT, created_at TEXT NOT NULL, updated_at TEXT NOT NULL\n);\n"),wd("0002_p0_state_domains","\nCREATE TABLE na_node_identity (\n singleton_key INTEGER PRIMARY KEY NOT NULL DEFAULT 1 CHECK(singleton_key = 1),\n node_id TEXT NOT NULL UNIQUE, created_at TEXT NOT NULL, updated_at TEXT NOT NULL\n);\nCREATE TABLE na_local_folders (\n id TEXT PRIMARY KEY NOT NULL, node_id TEXT NOT NULL REFERENCES na_node_identity(node_id) ON DELETE RESTRICT ON UPDATE CASCADE,\n name TEXT NOT NULL, path TEXT NOT NULL, labels_json TEXT NOT NULL, created_at TEXT NOT NULL, updated_at TEXT NOT NULL,\n UNIQUE(node_id, path)\n);\nCREATE TABLE na_runtimes (\n id TEXT PRIMARY KEY NOT NULL, node_id TEXT NOT NULL REFERENCES na_node_identity(node_id) ON DELETE RESTRICT ON UPDATE CASCADE,\n name TEXT NOT NULL, type TEXT NOT NULL CHECK(type IN ('docker','kubernetes','local')),\n status TEXT NOT NULL CHECK(status IN ('unknown','online','offline','degraded')), access_strategy TEXT NOT NULL,\n capabilities_json TEXT NOT NULL, labels_json TEXT NOT NULL, created_at TEXT NOT NULL, updated_at TEXT NOT NULL\n);\nCREATE INDEX na_runtimes_node_type_idx ON na_runtimes(node_id, type);\nCREATE TABLE na_instances (\n id TEXT PRIMARY KEY NOT NULL, node_id TEXT NOT NULL REFERENCES na_node_identity(node_id) ON DELETE RESTRICT ON UPDATE CASCADE,\n runtime_id TEXT NOT NULL REFERENCES na_runtimes(id) ON DELETE RESTRICT ON UPDATE CASCADE,\n source_local_folder_id TEXT REFERENCES na_local_folders(id) ON DELETE SET NULL ON UPDATE CASCADE,\n name TEXT NOT NULL, status TEXT NOT NULL, state_revision INTEGER NOT NULL DEFAULT 0 CHECK(state_revision >= 0),\n process_incarnation_id TEXT, registration_credential TEXT, desired_json TEXT NOT NULL,\n created_at TEXT NOT NULL, updated_at TEXT NOT NULL\n);\nCREATE INDEX na_instances_runtime_idx ON na_instances(runtime_id);\nCREATE INDEX na_instances_status_idx ON na_instances(status, updated_at);\nCREATE TABLE na_instance_observations (\n instance_id TEXT PRIMARY KEY NOT NULL REFERENCES na_instances(id) ON DELETE CASCADE ON UPDATE CASCADE,\n health TEXT NOT NULL, connection_status TEXT NOT NULL, ready INTEGER NOT NULL,\n observed_json TEXT NOT NULL, last_heartbeat_at TEXT, updated_at TEXT NOT NULL\n);\nCREATE INDEX na_instance_observations_connection_idx ON na_instance_observations(connection_status, updated_at);\nCREATE TABLE na_models (\n id TEXT PRIMARY KEY NOT NULL, name TEXT NOT NULL, endpoint TEXT NOT NULL, key TEXT NOT NULL, model TEXT NOT NULL,\n app TEXT NOT NULL CHECK(app IN ('codex','claude','opencode')), enabled INTEGER NOT NULL,\n display_order INTEGER NOT NULL, model_names_json TEXT NOT NULL, protocols_json TEXT NOT NULL,\n labels_json TEXT NOT NULL, created_at TEXT NOT NULL, updated_at TEXT NOT NULL\n);\nCREATE INDEX na_models_order_idx ON na_models(display_order, id);\nCREATE TABLE na_instance_model_assignments (\n instance_id TEXT PRIMARY KEY NOT NULL REFERENCES na_instances(id) ON DELETE CASCADE ON UPDATE CASCADE,\n legacy_codex_model_id TEXT REFERENCES na_models(id) ON DELETE RESTRICT ON UPDATE CASCADE,\n legacy_claude_model_id TEXT REFERENCES na_models(id) ON DELETE RESTRICT ON UPDATE CASCADE,\n legacy_opencode_model_id TEXT REFERENCES na_models(id) ON DELETE RESTRICT ON UPDATE CASCADE,\n updated_at TEXT NOT NULL\n);\nCREATE TABLE na_instance_model_entities (\n instance_id TEXT NOT NULL REFERENCES na_instance_model_assignments(instance_id) ON DELETE CASCADE ON UPDATE CASCADE,\n model_id TEXT NOT NULL REFERENCES na_models(id) ON DELETE RESTRICT ON UPDATE CASCADE,\n display_order INTEGER NOT NULL, PRIMARY KEY(instance_id, model_id), UNIQUE(instance_id, display_order)\n);\nCREATE TABLE na_control_plane_pairings (\n key_id TEXT PRIMARY KEY NOT NULL, control_plane_id TEXT NOT NULL UNIQUE, name TEXT, secret TEXT NOT NULL,\n paired_at TEXT NOT NULL, revoked_at TEXT, updated_at TEXT NOT NULL\n);\nCREATE TABLE na_control_plane_connections (\n id TEXT PRIMARY KEY NOT NULL,\n pairing_key_id TEXT NOT NULL REFERENCES na_control_plane_pairings(key_id) ON DELETE RESTRICT ON UPDATE CASCADE,\n name TEXT, normalized_url TEXT NOT NULL UNIQUE, enabled INTEGER NOT NULL, created_at TEXT NOT NULL, updated_at TEXT NOT NULL\n);\nCREATE TABLE na_control_plane_connection_operations (\n id TEXT PRIMARY KEY NOT NULL, kind TEXT NOT NULL,\n phase TEXT NOT NULL CHECK(phase IN ('prepared','remote-accepted','committed','failed')),\n requested_json TEXT NOT NULL, pairing_key_id TEXT, connection_id TEXT, replaced_connections_json TEXT NOT NULL,\n error_json TEXT, created_at TEXT NOT NULL, updated_at TEXT NOT NULL\n);\nCREATE INDEX na_control_plane_connection_operations_phase_idx ON na_control_plane_connection_operations(phase, updated_at);\nCREATE TABLE na_git_credential_payloads (\n credential_id TEXT PRIMARY KEY NOT NULL, revision INTEGER NOT NULL CHECK(revision >= 0),\n public_json TEXT NOT NULL, secret_json TEXT NOT NULL, created_at TEXT NOT NULL, updated_at TEXT NOT NULL\n);\nCREATE TABLE na_git_authorization_sets (\n instance_id TEXT PRIMARY KEY NOT NULL REFERENCES na_instances(id) ON DELETE CASCADE ON UPDATE CASCADE,\n generation INTEGER NOT NULL CHECK(generation >= 0), created_at TEXT NOT NULL, updated_at TEXT NOT NULL\n);\nCREATE TABLE na_git_authorization_members (\n instance_id TEXT NOT NULL REFERENCES na_git_authorization_sets(instance_id) ON DELETE CASCADE ON UPDATE CASCADE,\n credential_id TEXT NOT NULL REFERENCES na_git_credential_payloads(credential_id) ON DELETE RESTRICT ON UPDATE CASCADE,\n display_order INTEGER NOT NULL, PRIMARY KEY(instance_id, credential_id), UNIQUE(instance_id, display_order)\n);\nCREATE TABLE na_git_workspace_provisioning (\n instance_id TEXT PRIMARY KEY NOT NULL REFERENCES na_instances(id) ON DELETE CASCADE ON UPDATE CASCADE,\n status TEXT NOT NULL CHECK(status IN ('pending','consumed')), operation_id TEXT NOT NULL, input_json TEXT,\n created_at TEXT NOT NULL, updated_at TEXT NOT NULL, expires_at TEXT NOT NULL,\n CHECK((status = 'pending' AND input_json IS NOT NULL) OR (status = 'consumed' AND input_json IS NULL))\n);\nCREATE INDEX na_git_workspace_provisioning_expiry_idx ON na_git_workspace_provisioning(expires_at);\n")],bd=a.z.string().trim().min(1).max(160),Sd=a.z.string().datetime(),vd=a.z.string().min(1).max(4096),Nd=a.z.string().trim().url().max(2048),Od=a.z.object({id:bd,keyId:bd,name:a.z.string().trim().min(1).max(160).optional(),secret:vd,pairedAt:Sd,revokedAt:Sd.optional(),updatedAt:Sd}).strip(),zd=a.z.object({id:bd,pairingKeyId:bd,name:a.z.string().trim().min(1).max(160).optional(),url:Nd,enabled:a.z.boolean().default(!0),createdAt:Sd,updatedAt:Sd}).strip(),Cd=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(),Rd=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(),xd=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(),kd=new Set(["nodeId","createdAt","updatedAt","pairingInvites","controlPlanePairings","controlPlaneConnections","remoteControlPlanes"]),Dd=new Set(["id","keyId","name","secret","pairedAt","revokedAt","updatedAt"]),Pd=new Set(["id","pairingKeyId","name","url","enabled","createdAt","updatedAt"]),Ld=new Set(["id","keyId","name","url","secret","pairedAt","updatedAt","active"]);function Md(e,t){console.warn(JSON.stringify({message:e,...t}))}function jd(e,t){return Object.assign(new Error(e,void 0===t?void 0:{cause:t}),{code:"NODE_AGENT_IDENTITY_INVALID"})}function Ud(e,t){return Object.keys(e).filter(e=>!t.has(e))}function Fd(e,t,n){const i=Sd.safeParse(e);return i.success?i.data:(n("invalid node agent identity timestamp was replaced",{field:t}),ae())}function $d(e,t=Md){if(!e||"object"!=typeof e||Array.isArray(e))throw jd("Node agent identity must be a JSON object.");const n=e,i=bd.safeParse(n.nodeId);if(!i.success)throw jd("Node agent identity has an invalid nodeId.",i.error);const s=i.data,o=Ud(n,kd);o.length&&t("unknown node agent identity fields were ignored",{fields:o}),Array.isArray(n.pairingInvites)&&n.pairingInvites.length&&t("persisted node agent pairing invites were discarded",{count:n.pairingInvites.length});const r=Array.isArray(n.remoteControlPlanes)?n.remoteControlPlanes.flatMap(e=>{if(!e||"object"!=typeof e||Array.isArray(e))return[];const n=e,i=Ud(n,Ld);i.length&&t("unknown legacy node agent remote control-plane fields were ignored",{fields:i});const s=Od.safeParse(n);if(!s.success)return t("invalid legacy node agent control-plane pairing was ignored",{issues:s.error.issues}),[];const o=n.url?zd.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,...o?.success?{connection:o.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 o=Ud(e,n);o.length&&t(`unknown node agent ${s} fields were ignored`,{fields:o});const r=i.safeParse(e);return r.success?[r.data]:(t(`invalid node agent ${s} was ignored`,{issues:r.error.issues}),[])}):[];return{nodeId:s,createdAt:Fd(n.createdAt,"createdAt",t),updatedAt:Fd(n.updatedAt,"updatedAt",t),controlPlanePairings:n.controlPlanePairings?a(n.controlPlanePairings,Dd,Od,"control-plane pairing"):r.map(e=>e.pairing),controlPlaneConnections:n.controlPlaneConnections?a(n.controlPlaneConnections,Pd,zd,"control-plane connection"):r.flatMap(e=>e.connection?[e.connection]:[])}}const Hd="1000_import_v0_0_28_p0",qd=d.createHash("sha256").update(JSON.stringify({sourceTag:"v0.0.28",plannerVersion:3,domains:["identity","folders","runtimes","instances","models","assignments","model-environments","git"],transaction:"begin-immediate"})).digest("hex"),Vd=["id","nodeId","name","path","defaultImageSelection","labels","createdAt","updatedAt"],Bd=["id","nodeId","name","type","status","accessStrategy","capabilities","labels","createdAt","updatedAt"],Kd=["id","name","endpoint","key","model","modelNames","protocols","app","enabled","order","labels","createdAt","updatedAt"],Gd=["instanceId","modelEntityIds","codexModelHash","claudeModelHash","opencodeModelHash","updatedAt"],Wd=["id","payload","createdAt","updatedAt"],Xd=["id","instanceId","generation","credentialIds","createdAt","updatedAt"],Yd=["id","instanceId","credentialId","credentialRevision","assignmentRevision","status","authorizedAt","createdAt","updatedAt"],Jd=["id","status","operationId","input","createdAt","updatedAt","expiresAt"];function Qd(e,i,s={}){const o=e.prepare("SELECT checksum FROM na_migration_ledger WHERE id = ?").get(Hd);if(o){if(o.checksum!==qd)throw ll("ledger","Legacy P0 migration checksum mismatch.");return void sl(i,s.rename)}const r=[],c=function(e,i){const s=[],o=new Set,r=(e,o)=>function(e,i,s,o){return t.existsSync(e)?t.readdirSync(e).filter(e=>e.endsWith(".json")).sort().flatMap(r=>{const a=n.join(e,r);let c;try{c=t.readFileSync(a,"utf8")}catch(e){throw ll(a,"Legacy JSON could not be accessed.",e)}const l={filePath:a,value:void 0,digest:d.createHash("sha256").update(c).digest("hex")};s.push(l);try{return l.value=JSON.parse(c),[l]}catch{return i.push({source:a,field:"unreadable-record"}),o?.(a),[]}}):[]}(e,i,s,o);return{...{folders:r(e.localFoldersDir),runtimes:r(e.nodeRuntimesDir),instances:r(e.controlledInstancesDir,e=>o.add(n.basename(e,".json"))),privateConfigs:r(e.instancePrivateConfigsDir),models:r(e.nodeModelsDir),assignments:r(e.modelAssignmentsDir),modelEnvironments:r(e.modelEnvironmentsDir),gitPayloads:r(e.gitCredentialPayloadsDir),gitAssignments:r(e.gitCredentialAssignmentsDir),gitAuthorizations:r(e.gitCredentialAuthorizationSetsDir),gitProvisioning:r(e.gitWorkspaceProvisioningIntentsDir)},allFiles:s,isolatedInstanceIds:o}}(i,r),l=c.allFiles.length>0,u=function(e){let n;try{n=t.lstatSync(e)}catch(t){if("ENOENT"===t.code)return;throw ll(e,"Legacy JSON could not be accessed.",t)}if(!n.isFile())throw ll(e,"Legacy JSON must be a regular file.");return function(e){try{const n=t.readFileSync(e,"utf8");return{filePath:e,value:JSON.parse(n),digest:d.createHash("sha256").update(n).digest("hex")}}catch(t){throw ll(e,"Legacy JSON could not be read.",t)}}(e)}(i.identityPath);if(l&&!u)throw ll(i.identityPath,"Legacy P0 data requires a node identity.");try{const t=u?$d(u.value,(e,t)=>r.push({source:i.identityPath,field:String(t.field||t.fields||"legacy")})):void 0,s=c.folders.map(e=>(dl(e,Vd,r),el(e,rs,Si(e.value)))),o=c.runtimes.map(e=>(dl(e,Bd,r),el(e,Ws.strip(),e.value))),d=new Map(Zd(c.privateConfigs,c.isolatedInstanceIds,r).map(e=>{const t=rl(e.value);return[n.basename(e.filePath,".json"),al(t.instanceCredential??t.registrationToken)]})),l=c.instances.map(e=>{const t=fo(e.value,t=>r.push({source:e.filePath,field:t.field}));if(!t.success)throw tl(e,t.error);return{...t.data,registrationToken:t.data.registrationToken||d.get(t.data.id)}}),p=c.models.flatMap(e=>{const t=rl(e.value);dl(e,Kd,r);const i=el(e,hs,cl(t,["id","name","endpoint","key","model","modelNames","protocols","app","enabled","order","labels","createdAt","updatedAt"]));return n.basename(e.filePath,".json")!==i.id||Ss(i)!==i.id?(r.push({source:e.filePath,field:"identity-or-content-hash"}),[]):[hs.parse({...i,modelNames:i.modelNames.length?i.modelNames:[{name:i.model,order:0}],protocols:i.protocols.length?i.protocols:[(s=i.app,"claude"===s?"anthropic-messages":"opencode"===s?"openai-chat-completions":"openai-responses")]})];var s}),m=Zd(c.assignments,c.isolatedInstanceIds,r).map(e=>{const t=rl(e.value);return dl(e,Gd,r),el(e,ys,cl(t,["instanceId","modelEntityIds","codexModelHash","claudeModelHash","opencodeModelHash","updatedAt"]))});!function(e,t,i,s){const o=new Set(t.map(e=>e.id)),r=new Map(s.map(e=>[e.instanceId,e])),c=new Map(i.map(e=>[e.id,e]));let d=i.reduce((e,t)=>Math.max(e,t.order),0)+100;for(const l of e){const e=n.basename(l.filePath,".json");if(!o.has(e))throw ll(l.filePath,`Legacy model environment references missing instance ${e}.`);if(r.has(e))continue;const u=a.z.record(a.z.string(),a.z.string()).safeParse(l.value);if(!u.success)throw tl(l,u.error);const p=u.data,m=new Set(["OPENAI_API_KEY","OPENAI_BASE_URL","CODEX_MODEL","TASK_HANDOFF_CODEX_BASE_URL","TASK_HANDOFF_CODEX_MODEL","ANTHROPIC_API_KEY","ANTHROPIC_BASE_URL","CLAUDE_MODEL","TASK_HANDOFF_CLAUDE_MODEL"]);if(Object.keys(p).some(e=>!m.has(e)))throw ll(l.filePath,"Legacy model environment contains an unknown field.");const h=[],g={};for(const n of["codex","claude"]){const s=p["codex"===n?"OPENAI_API_KEY":"ANTHROPIC_API_KEY"],o="codex"===n?p.TASK_HANDOFF_CODEX_BASE_URL||p.OPENAI_BASE_URL:p.ANTHROPIC_BASE_URL,r="codex"===n?p.TASK_HANDOFF_CODEX_MODEL||p.CODEX_MODEL:p.TASK_HANDOFF_CLAUDE_MODEL||p.CLAUDE_MODEL;if(!s&&!o&&!r)continue;if(!s||!o||!r)throw ll(l.filePath,`Legacy ${n} model environment is incomplete.`);const a=Ss({app:n,endpoint:o,key:s,model:r});if(!c.has(a)){const l=t.find(t=>t.id===e).updatedAt,u=hs.parse({id:a,name:`Migrated ${"codex"===n?"Codex":"Claude"} model`,endpoint:o,key:s,model:r,app:n,enabled:!0,order:d,labels:{migratedFrom:"instance-model-environment"},createdAt:l,updatedAt:l});d+=100,i.push(u),c.set(a,u)}h.push(a),"codex"===n?g.codexModelHash=a:g.claudeModelHash=a}if(!h.length)throw ll(l.filePath,"Legacy model environment has no complete model configuration.");const f=ys.parse({instanceId:e,modelEntityIds:h,...g,updatedAt:t.find(t=>t.id===e).updatedAt});s.push(f),r.set(e,f)}}(Zd(c.modelEnvironments,c.isolatedInstanceIds,r),l,p,m);const h=c.gitPayloads.map(e=>{const t=rl(e.value);return dl(e,Wd,r),{id:al(t.id),payload:el(e,Xc,t.payload),createdAt:al(t.createdAt),updatedAt:al(t.updatedAt)}}),g=function(e,t){const n=new Map(e.map(e=>[e.instanceId,e]));for(const e of new Set(t.map(e=>e.instanceId))){if(n.has(e))continue;const i=t.filter(t=>t.instanceId===e).sort((e,t)=>e.credentialId.localeCompare(t.credentialId)),s=i.map(e=>e.updatedAt).sort().at(-1);n.set(e,{id:e,instanceId:e,generation:Math.max(0,...i.map(e=>e.assignmentRevision)),credentialIds:i.filter(e=>"revoking"!==e.status&&"revoked"!==e.status).map(e=>e.credentialId),createdAt:s,updatedAt:s})}return[...n.values()].sort((e,t)=>e.instanceId.localeCompare(t.instanceId))}(Zd(c.gitAuthorizations,c.isolatedInstanceIds,r).map(e=>{const t=rl(e.value);dl(e,Xd,r);const n=el(e,Yc,cl(t,["instanceId","generation","credentialIds","updatedAt"]));return{...n,id:n.instanceId,createdAt:al(t.createdAt)}}),Zd(c.gitAssignments,c.isolatedInstanceIds,r).map(e=>{const t=rl(e.value);return dl(e,Yd,r),el(e,Wc,cl(t,["instanceId","credentialId","credentialRevision","assignmentRevision","status","authorizedAt","updatedAt"]))})),f=Zd(c.gitProvisioning,c.isolatedInstanceIds,r).map(e=>(dl(e,Jd,r),function(e){const t=rl(e.value),n={id:al(t.id),createdAt:al(t.createdAt),updatedAt:al(t.updatedAt),expiresAt:al(t.expiresAt)};if("consumed"===t.status)return{...n,status:"consumed",operationId:al(t.operationId)};const i=function(e){const t=od(e),n=od(t?.ref),i=od(t?.clone),s=Array.isArray(t?.credentials)?t.credentials.map(e=>{const t=od(e),n=od(t?.payload),i=function(e){const t=od(e),n=od(t?.scope);return Vc.safeParse({...rd(t,["id","name","kind","secretSet","status","revision","createdAt","updatedAt"]),scope:rd(n,["scheme","host","port","pathPrefix"])})}(n?.credential),s=od(n?.secret);return{...rd(t,["operationId","retention"]),payload:{credential:i.success?i.data:n?.credential,secret:rd(s,"https-token"===s?.kind?["kind","username","token"]:["kind","privateKey","passphrase","pinnedKnownHosts"])}}}):t?.credentials;return sd.safeParse({...rd(t,["operationId","instanceId","remoteUrl"]),ref:rd(n,["type","name","commit"]),clone:rd(i,["depth","submodules","lfs","subdirectory"]),credentials:s})}(t.input);if(!i.success)throw tl(e,i.error);const s=sd.parse(i.data);return{...n,id:s.instanceId,status:"pending",input:s}}(e)));!function(e){const t=e.identity?.nodeId,n=nl("local folder",e.folders.map(e=>e.id)),i=nl("runtime",e.runtimes.map(e=>e.id)),s=nl("instance",e.instances.map(e=>e.id)),o=nl("model",e.models.map(e=>e.id)),r=nl("Git credential payload",e.payloads.map(e=>e.id));nl("model assignment",e.assignments.map(e=>e.instanceId)),nl("Git authorization",e.authorizations.map(e=>e.instanceId)),nl("Git provisioning",e.provisioning.map(e=>e.id));for(const n of[...e.folders,...e.runtimes])if(!t||n.nodeId!==t)throw il("node-identity",n.id,n.nodeId,"Legacy topology record references a different or missing node identity.");for(const s of e.instances){if(!t||s.nodeId!==t)throw il("node-identity",s.id,s.nodeId,"Legacy instance references a different or missing node identity.");if(!i.has(s.runtimeId))throw il("runtime",s.id,s.runtimeId,"Legacy instance references a missing runtime.");if("local-folder"===s.source.type&&s.source.localFolderId&&!n.has(s.source.localFolderId))throw il("local-folder",s.id,s.source.localFolderId,"Legacy instance references a missing local folder.")}for(const t of e.privateConfigInstanceIds)if(!s.has(t))throw il("instance",t,t,"Legacy private config references a missing instance.");for(const t of e.assignments){if(!s.has(t.instanceId))throw il("instance",t.instanceId,t.instanceId,"Legacy model assignment references a missing instance.");for(const e of new Set([...t.modelEntityIds,t.codexModelHash,t.claudeModelHash,t.opencodeModelHash].filter(e=>Boolean(e))))if(!o.has(e))throw il("model",t.instanceId,e,"Legacy model assignment references a missing model.")}for(const t of e.payloads)if(t.id!==t.payload.credential.id)throw il("Git credential payload",t.id,t.payload.credential.id,"Legacy Git credential wrapper and payload ids do not match.");for(const t of e.authorizations){if(!s.has(t.instanceId))throw il("instance",t.instanceId,t.instanceId,"Legacy Git authorization references a missing instance.");for(const e of t.credentialIds)if(!r.has(e))throw il("Git credential payload",t.instanceId,e,"Legacy Git authorization references a missing credential payload.")}for(const t of e.provisioning)if(!s.has(t.id))throw il("instance",t.id,t.id,"Legacy Git provisioning references a missing instance.");if(e.identity){const t=nl("Control Plane pairing",e.identity.controlPlanePairings.map(e=>e.keyId));nl("Control Plane connection",e.identity.controlPlaneConnections.map(e=>e.id));const n=new Set;for(const i of e.identity.controlPlaneConnections){if(!t.has(i.pairingKeyId))throw il("Control Plane pairing",i.id,i.pairingKeyId,"Legacy connection references a missing pairing.");const e=new URL(i.url).toString().replace(/\/$/,"");if(n.has(e))throw il("Control Plane URL",i.id,e,"Legacy connections contain a duplicate normalized URL.");n.add(e)}}}({identity:t,folders:s,runtimes:o,instances:l,privateConfigInstanceIds:[...d.keys()],models:p,assignments:m,payloads:h,authorizations:g,provisioning:f}),e.exec("BEGIN IMMEDIATE");try{const n=new vc(e),i=hc(e),a=bc(e),d=new cd(e);t&&n.writeIdentity(t);for(const e of s)i.localFolders.put(e);for(const e of o)i.runtimes.put(e);for(const e of l)i.instances.put(e);for(const e of p)a.models.put(e);for(const e of m)a.assignments.put(e);for(const e of h)d.putPayload(e);for(const e of g)d.putAuthorization(e);for(const e of f)d.putProvisioning(e);const y={sourceTag:"v0.0.28",counts:{identities:t?1:0,folders:s.length,runtimes:o.length,instances:l.length,models:p.length,assignments:m.length,pairings:t?.controlPlanePairings?.length||0,connections:t?.controlPlaneConnections?.length||0,gitPayloads:h.length,gitAuthorizations:g.length,gitProvisioning:f.length},inputDigest:ol([...u?[u]:[],...c.allFiles]),warningCount:r.length};e.prepare("INSERT INTO na_migration_ledger (id, checksum, applied_at, details) VALUES (?, ?, ?, ?)").run(Hd,qd,(new Date).toISOString(),JSON.stringify(y)),e.exec("COMMIT")}catch(t){throw e.exec("ROLLBACK"),t}}catch(e){if(e&&"object"==typeof e&&"code"in e&&"NODE_AGENT_LEGACY_MIGRATION_FAILED"===e.code)throw e;throw ll("p0","Legacy P0 data failed validation.",e)}sl(i,s.rename);for(const e of r)console.warn(JSON.stringify({message:"legacy node agent field was ignored",...e}))}function Zd(e,t,i){return e.filter(e=>{const s=rl(e.value),o="string"==typeof s.instanceId?s.instanceId:n.basename(e.filePath,".json");return!t.has(o)||(i.push({source:e.filePath,field:"isolated-instance-owner"}),!1)})}function el(e,t,n){const i=t.safeParse(n);if(!i.success)throw tl(e,i.error);return i.data}function tl(e,t){return ll(e.filePath,"Legacy record is missing a required field or has an invalid type.",void 0,{issues:t.issues.map(e=>({path:e.path.join("."),code:e.code}))})}function nl(e,t){const n=new Set;for(const i of t){if(n.has(i))throw ll(e,`Legacy ${e} id is duplicated.`,void 0,{recordId:i});n.add(i)}return n}function il(e,t,n,i){return ll(e,i,void 0,{relation:e,recordId:t,referencedId:n})}function sl(e,n=t.renameSync){const i=[e.identityPath,e.localFoldersDir,e.nodeRuntimesDir,e.controlledInstancesDir,e.nodeModelsDir,e.modelAssignmentsDir,e.gitCredentialPayloadsDir,e.modelEnvironmentsDir,e.gitCredentialAssignmentsDir,e.gitCredentialAuthorizationSetsDir,e.gitWorkspaceProvisioningIntentsDir];for(const e of i){if(!t.existsSync(e))continue;const i=`${e}.migrated-v0.0.28`;let s=i;for(let e=1;t.existsSync(s);e+=1)s=`${i}.${e}`;try{n(e,s)}catch(t){console.warn(JSON.stringify({message:"legacy node agent persistence archive failed",source:e,target:s,error:t instanceof Error?t.message:String(t)}))}}}function ol(e){const t=d.createHash("sha256");for(const i of[...e].sort((e,t)=>e.filePath.localeCompare(t.filePath)))t.update(n.basename(i.filePath)),t.update(i.digest);return t.digest("hex")}function rl(e){if(!e||"object"!=typeof e||Array.isArray(e))throw ll("record","Legacy record must be an object.");return e}function al(e){if("string"!=typeof e||!e)throw ll("record","Legacy record is missing a required string.");return e}function cl(e,t){return Object.fromEntries(t.flatMap(t=>Object.prototype.hasOwnProperty.call(e,t)?[[t,e[t]]]:[]))}function dl(e,t,n){const i=rl(e.value),s=new Set(t);for(const t of Object.keys(i).filter(e=>!s.has(e)).sort())n.push({source:e.filePath,field:t})}function ll(e,t,n,i={}){return Object.assign(new Error(t,void 0===n?void 0:{cause:n}),{code:"NODE_AGENT_LEGACY_MIGRATION_FAILED",statusCode:500,details:{source:e,...i}})}function ul(e,t){return Object.assign(new Error(`Node Agent database ${e} failed: ${t instanceof Error?t.message:String(t)}`,{cause:t}),{code:"NODE_AGENT_DATABASE_STARTUP_FAILED",statusCode:500,details:{phase:e,recovery:"Restore or remove the invalid node-agent.sqlite before restarting the Node Agent."}})}function pl(e,t){const n=e.prepare(t).get();return n?Object.values(n)[0]:void 0}function ml(e){for(const n of[e.databasePath,`${e.databasePath}-wal`,`${e.databasePath}-shm`])t.existsSync(n)&&t.chmodSync(n,384)}function hl(e,i={}){try{!function(e=process.versions.node){const[t,n]=e.split(".").map(Number);if(24!==t||n<15)throw new Error(`Node.js 24.15 or newer within the Node.js 24 release line is required; received ${e}.`)}()}catch(e){throw ul("runtime",e)}let s;t.mkdirSync(n.dirname(e.databasePath),{recursive:!0,mode:448}),t.chmodSync(n.dirname(e.databasePath),448);try{if(s=new w.DatabaseSync(e.databasePath),function(e,t){e.exec("PRAGMA foreign_keys = ON"),e.exec("PRAGMA busy_timeout = 5000"),e.exec("PRAGMA journal_mode = WAL"),e.exec("PRAGMA synchronous = FULL");const n=Number(pl(e,"PRAGMA application_id"));if(0===n)e.exec("PRAGMA application_id = 1414024769");else if(1414024769!==n)throw new Error(`Unexpected application_id ${n}.`);if(1!==Number(pl(e,"PRAGMA foreign_keys")))throw new Error("foreign_keys could not be enabled.");if("wal"!==String(pl(e,"PRAGMA journal_mode")).toLowerCase())throw new Error("WAL could not be enabled.");if(5e3!==Number(pl(e,"PRAGMA busy_timeout")))throw new Error("busy_timeout=5000 could not be enabled.");if(2!==Number(pl(e,"PRAGMA synchronous")))throw new Error("synchronous=FULL could not be enabled.");if("ok"!==String(pl(e,"PRAGMA quick_check")))throw new Error("quick_check failed.");ml(t)}(s,e),function(e){e.exec("CREATE TABLE IF NOT EXISTS na_migration_ledger (\n id TEXT PRIMARY KEY NOT NULL, checksum TEXT NOT NULL, applied_at TEXT NOT NULL, details TEXT NOT NULL\n )"),e.exec("BEGIN IMMEDIATE");try{const t=e.prepare("SELECT checksum FROM na_migration_ledger WHERE id = ?"),n=e.prepare("INSERT INTO na_migration_ledger (id, checksum, applied_at, details) VALUES (?, ?, ?, ?)");for(const i of Td){const s=t.get(i.id);if(s){if(s.checksum!==i.checksum)throw new Error(`Migration checksum mismatch for ${i.id}.`)}else e.exec(i.sql),n.run(i.id,i.checksum,(new Date).toISOString(),JSON.stringify({domain:"node-agent-story"}))}e.exec("COMMIT")}catch(t){throw e.exec("ROLLBACK"),t}}(s),Qd(s,e,i.legacyMigration),"ok"!==String(pl(s,"PRAGMA quick_check")))throw new Error("post-migration quick_check failed.");ml(e);const t=T.drizzle({client:s});let n=!1;return{db:t,client:s,async checkpoint(){n||(s.exec("PRAGMA wal_checkpoint(TRUNCATE)"),ml(e))},async close(){n||(n=!0,s.close())}}}catch(e){try{s?.close()}catch{}throw ul(s?"initialize":"connect",e)}}const gl=a.z.enum(["openai-responses","openai-chat-completions","anthropic-messages"]),fl=a.z.object({protocolVersion:a.z.literal("2026-08-27"),instanceId:a.z.string().trim().min(1).max(120),entities:a.z.array(a.z.object({id:a.z.string().trim().min(1).max(120),endpoint:a.z.string().trim().min(1).max(2048),key:a.z.string().trim().min(1).max(4096),protocols:a.z.array(gl).min(1).max(3),modelNames:a.z.array(a.z.object({name:a.z.string().trim().min(1).max(240),order:a.z.number().int().min(0).max(1e6)}).strip()).min(1).max(256)}).strip()).max(64),updatedAt:a.z.string().datetime()}).strip();function yl(e){if(!e||"object"!=typeof e||Array.isArray(e))return e;const t=e;return{protocolVersion:t.protocolVersion,instanceId:t.instanceId,entities:Array.isArray(t.entities)?t.entities.map(e=>{if(!e||"object"!=typeof e||Array.isArray(e))return e;const t=e;return{id:t.id,endpoint:t.endpoint,key:t.key,protocols:t.protocols,modelNames:Array.isArray(t.modelNames)?t.modelNames.map(e=>{if(!e||"object"!=typeof e||Array.isArray(e))return e;const t=e;return{name:t.name,order:t.order}}):t.modelNames}}):t.entities,updatedAt:t.updatedAt}}class Il{models;assignments;transaction;nodeId;instances;constructor(e,t,n,i){this.nodeId=t,this.instances=n;const s=i||md(hl(e)).model;this.models=s.models,this.assignments=s.assignments,this.transaction=s.transaction.bind(s)}init(){}list(){const e=new Map;for(const t of this.instances.list()){const n=this.assignments.get(t.id);for(const t of new Set([...n?.modelEntityIds||[],n?.codexModelHash,n?.claudeModelHash,n?.opencodeModelHash]))t&&e.set(t,(e.get(t)||0)+1)}return this.models.list().map(t=>this.toPublic(t,e.get(t.id)||0))}create(e){const t=ae(),n=El(e.modelNames,e.model),i={...e,model:n[0].name,modelNames:n,protocols:e.protocols?.length?e.protocols:_l(e.app)},s=Ss(i),o=this.models.get(s),r=hs.parse({...i,id:s,enabled:e.enabled??!0,order:e.order??this.nextOrder(),labels:e.labels||{},createdAt:o?.createdAt||t,updatedAt:t});return this.toPublic(this.models.put(r),this.referenceIds(s).length)}deploy(e){const t=Ss(e);if(e.id!==t)throw Object.assign(new Error(`Model content hash ${t} does not match ${e.id}.`),{statusCode:400,code:"NODE_MODEL_HASH_MISMATCH"});const n=El(e.modelNames,e.model),i=this.models.get(e.id)||this.models.put(hs.parse({...e,model:n[0].name,modelNames:n,protocols:e.protocols?.length?e.protocols:_l(e.app)}));return this.toPublic(i,this.referenceIds(i.id).length)}update(e,t){const n=this.requireModel(e),i=t.modelNames?.length?El(t.modelNames,t.model||n.model):t.model?El(void 0,t.model):El(n.modelNames,n.model),s=t.protocols?.length?t.protocols:n.protocols?.length?n.protocols:_l(t.app||n.app),o=hs.parse({...n,...t,key:t.key?.trim()?t.key:n.key,protocols:s,model:i[0].name,modelNames:i,createdAt:n.createdAt,updatedAt:ae()}),r=Ss(o),a=this.models.put(hs.parse({...o,id:r}));return this.toPublic(a,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);for(const e of t.modelEntityIds)this.validateEntityRef(e);if(void 0!==t.modelSelection.modelEntityIds&&JSON.stringify(t.modelSelection.modelEntityIds)!==JSON.stringify(t.modelEntityIds))throw Object.assign(new Error("Ordered model entity selection does not match its node assignment."),{statusCode:400,code:"NODE_MODEL_SELECTION_MISMATCH"});if(this.validateRef("codex",t.codexModelHash),this.validateRef("claude",t.claudeModelHash),this.validateRef("opencode",t.opencodeModelHash),void 0!==t.modelSelection.codexModelHash&&(t.modelSelection.codexModelHash??void 0)!==t.codexModelHash)throw Object.assign(new Error("Codex model selection does not match its node assignment."),{statusCode:400,code:"NODE_MODEL_SELECTION_MISMATCH"});if(void 0!==t.modelSelection.claudeModelHash&&(t.modelSelection.claudeModelHash??void 0)!==t.claudeModelHash)throw Object.assign(new Error("Claude model selection does not match its node assignment."),{statusCode:400,code:"NODE_MODEL_SELECTION_MISMATCH"});if(void 0!==t.modelSelection.opencodeModelHash&&(t.modelSelection.opencodeModelHash??void 0)!==t.opencodeModelHash)throw Object.assign(new Error("OpenCode model selection does not match its node assignment."),{statusCode:400,code:"NODE_MODEL_SELECTION_MISMATCH"});const i=ys.parse({instanceId:e,modelEntityIds:t.modelEntityIds,codexModelHash:t.codexModelHash,claudeModelHash:t.claudeModelHash,opencodeModelHash:t.opencodeModelHash,updatedAt:ae()});return this.transaction(()=>({assignment:this.assignments.put(i),instance:this.instances.put(po.parse({...n,modelSelection:t.modelSelection,updatedAt:ae()}))}))}resolvedEnvironment(e){const t=this.assignments.get(e);if(!t)return{};const n=e=>t.modelEntityIds.find(t=>this.modelSupportsApp(this.requireModel(t),e));return{...this.environmentForRef("codex",n("codex")||t.codexModelHash),...this.environmentForRef("claude",n("claude")||t.claudeModelHash),...this.environmentForOpenCode(t)}}privateCatalog(e){const t=this.assignments.get(e);return fl.parse({protocolVersion:"2026-08-27",instanceId:e,entities:(t?.modelEntityIds||[]).map(e=>{const t=this.requireModel(e);return this.validateEntityRef(e),{id:t.id,endpoint:t.endpoint,key:t.key,protocols:t.protocols?.length?t.protocols:_l(t.app),modelNames:El(t.modelNames,t.model)}}),updatedAt:t?.updatedAt||ae()})}privateSecretValues(e){return[...new Set(this.privateCatalog(e).entities.map(e=>e.key))]}deleteInstanceMetadata(e){this.assignments.delete(e)}validateRef(e,t){if(!t)return;const n=this.requireModel(t);if(!this.modelSupportsApp(n,e))throw Object.assign(new Error(`Model ${n.id} does not support the ${e} runtime protocol.`),{statusCode:400,code:"NODE_MODEL_APP_MISMATCH"});if(!n.enabled)throw Object.assign(new Error(`Model ${n.id} is disabled.`),{statusCode:409,code:"NODE_MODEL_DISABLED"})}modelSupportsApp(e,t){const n="claude"===t?"anthropic-messages":"opencode"===t?"openai-chat-completions":"openai-responses";return e.protocols?.length?e.protocols.includes(n):e.app===t}validateEntityRef(e){const t=this.requireModel(e);if(!t.enabled)throw Object.assign(new Error(`Model ${t.id} is disabled.`),{statusCode:409,code:"NODE_MODEL_DISABLED"});if(!t.protocols?.length&&!_l(t.app).length)throw Object.assign(new Error(`Model ${t.id} does not expose a supported protocol.`),{statusCode:400,code:"NODE_MODEL_PROTOCOL_UNSUPPORTED"})}environmentForRef(e,t){if(!t)return{};this.validateRef(e,t);const n=this.requireModel(t);return"codex"===e?{OPENAI_API_KEY:n.key,OPENAI_BASE_URL:n.endpoint,TASK_HANDOFF_CODEX_BASE_URL:n.endpoint,TASK_HANDOFF_CODEX_MODEL:n.model}:{ANTHROPIC_API_KEY:n.key,ANTHROPIC_BASE_URL:n.endpoint,TASK_HANDOFF_CLAUDE_MODEL:n.model}}environmentForOpenCode(e){const t=e.modelEntityIds.map(e=>this.requireModel(e)).filter(e=>this.modelSupportsApp(e,"opencode"));if(!t.length)return{};const n=t[0],i=El(n.modelNames,n.model)[0].name,s=Object.fromEntries(t.map(e=>[`task-handoff-${e.id}`,Al(e,El(e.modelNames,e.model).map(e=>e.name))]));if(e.opencodeModelHash){const t=this.requireModel(e.opencodeModelHash);s["task-handoff"]=Al(t,[t.model])}return{TASK_HANDOFF_OPENCODE_CONFIG_CONTENT:JSON.stringify({$schema:"https://opencode.ai/config.json",model:`task-handoff-${n.id}/${i}`,provider:s})}}requireModel(e){const t=this.models.get(e);if(!t)throw Object.assign(new Error(`Model ${e} was not found on node ${this.nodeId}.`),{statusCode:404,code:"NODE_MODEL_NOT_FOUND"});if(Ss(t)!==t.id)throw Object.assign(new Error(`Stored model ${e} does not match its content hash.`),{statusCode:409,code:"NODE_MODEL_HASH_INVALID"});return t}referenceIds(e){return this.instances.list().filter(t=>{const n=this.assignments.get(t.id);return n?.modelEntityIds.includes(e)||n?.codexModelHash===e||n?.claudeModelHash===e||n?.opencodeModelHash===e}).map(e=>e.id)}toPublic(e,t){const{key:n,...i}=e;return fs.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}}function Al(e,t){return{npm:"@ai-sdk/openai-compatible",name:e.name,options:{baseURL:e.endpoint,apiKey:e.key},models:Object.fromEntries(t.map(t=>[t,{name:e.name,variants:Object.fromEntries(["none","minimal","low","medium","high","xhigh","max","ultra"].map(e=>[e,{reasoningEffort:e}]))}]))}}function _l(e){return"claude"===e?["anthropic-messages"]:"opencode"===e?["openai-chat-completions"]:["openai-responses"]}function El(e,t){const n=e?.length?e:[{name:t,order:100}],i=new Set;return n.map(e=>({name:e.name.trim(),order:e.order})).filter(e=>!(!e.name||i.has(e.name)||(i.add(e.name),0))).sort((e,t)=>e.order-t.order||e.name.localeCompare(t.name)).map((e,t)=>({name:e.name,order:100*(t+1)}))}function wl(e,t){if(!e)return!0;const n=b.valid(e),i=b.valid(t);return n&&i?b.gt(i,n):e!==t}function Tl(){return process.env.TASK_HANDOFF_NPM_COMMAND||"npm"}function bl(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 Sl(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,o=n.resolve(e);for(;o!==n.dirname(o);){try{const e=JSON.parse(t.readFileSync(n.join(o,"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}o=n.dirname(o)}return s?{packageName:"@task-handoff/node-agent",currentVersion:s,relatedCurrentVersions:[],installPrefix:i}:void 0}(i):void 0;if(s)return s;const o=(await e(Tl(),["root","--global"])).stdout.trim();if(!o)throw new Error("npm did not return its global module root.");const r=(await e(Tl(),["prefix","--global"])).stdout.trim();if(!n.isAbsolute(r))throw new Error(`npm did not return an absolute global prefix: ${r||"empty"}`);const a=bl(o,"@task-handoff/server"),c=bl(o,"@task-handoff/node-agent");return a?{packageName:"@task-handoff/server",currentVersion:a.version,relatedCurrentVersions:c?[c.version]:[],installPrefix:r}:{packageName:"@task-handoff/node-agent",currentVersion:c?.version,relatedCurrentVersions:[],installPrefix:r}}function vl(e){if(!e||"object"!=typeof e||Array.isArray(e))return e;const t=e,n="string"==typeof t.updatedAt?t.updatedAt:ae(),i=t.target&&"object"==typeof t.target&&!Array.isArray(t.target)?t.target:void 0,s="controlled-instance"===i?.component,o={updating:"updating-node",downloading:"updating-node",installing:"updating-node",restarting:"restarting-node",completed:"succeeded",success:"succeeded",error:"failed"},r=new Set(["queued","updating-node","restarting-node","converging-instances","succeeded","degraded","failed"]),a="string"==typeof t.status?t.status:"queued",c=s?"failed":r.has(a)?a:o[a]||"failed",d="string"==typeof t.toVersion&&t.toVersion?t.toVersion:"unknown",l=Xi.strip().safeParse(t.impact).success?Xi.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||r.has(a)||a in o?"string"==typeof t.error?{code:"NODE_UPDATE_FAILED",message:t.error,retryable:!1}:Gi.strip().safeParse(t.error).success?Gi.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=Ki.strip().safeParse(e);return t.success?[t.data]:[]}):[],rollout:f.success?f.data:g,...u?{error:u}:{},...s?{completedAt:t.completedAt||n}:{}}}class Nl{records;constructor(e){this.records=new Ja(e.updatesDir,{schema:Zi,sanitize:vl})}init(){this.records.init()}list(){return this.records.list().sort((e,t)=>t.createdAt.localeCompare(e.createdAt))}create(e,t){const n=ae();return this.records.put(Zi.parse({id:Xa("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(Zi.parse({...n,...t,id:e,createdAt:n.createdAt,updatedAt:ae()}))}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:ae()});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:ae()});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 o=s.rollout.expectedInstanceIds,r=o.map(e=>i.get(e)),a=r.filter(e=>e?.ready&&"matched"===e.runtimeVersion?.phase&&e.runtimeVersion.actualVersion===s.toVersion).length,c=r.filter(e=>e&&["created","stopped","failed"].includes(e.status||"")&&"failed"!==e.runtimeVersion?.phase).length,d=r.filter(e=>!e||"failed"===e.runtimeVersion?.phase).length,l=Math.max(0,o.length-a-d-c),u=d>0?"degraded":0===l?"succeeded":"converging-instances";this.patch(s.id,{status:u,rollout:{...s.rollout,phase:u,nodeVersion:t,expectedInstanceCount:o.length,matchedInstanceCount:a,pendingInstanceCount:l,failedInstanceCount:d,deferredInstanceCount:s.impact.stoppedInstanceCount+c},..."succeeded"===u||"degraded"===u?{completedAt:ae()}:{}})}}run(e,t){(async()=>{this.patch(e.id,{status:"updating-node",rollout:{...e.rollout,phase:"updating-node"},startedAt:ae(),error:void 0});try{await t(e),this.patch(e.id,{status:"succeeded",completedAt:ae()})}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:ae()})}})()}}class Ol{records;constructor(e){this.records=new Ja(e.environmentTemplatesDir,{schema:zi,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 o=_o(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}`});o.error=_o(e,["code","message","phase"])}return o}(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(zi.parse({...e,status:"failed",error:{code:"ENVIRONMENT_TEMPLATE_CREATION_INTERRUPTED",message:"Environment template creation was interrupted by a node-agent restart.",phase:"recovery"},updatedAt:ae()}))}list(){return this.records.list()}get(e){return this.records.get(e)}put(e){return this.records.put(zi.parse(e))}patch(e,t){return this.records.patch(e,t)}delete(e){return this.records.delete(e)}}const zl=a.z.record(a.z.string().regex(/^[A-Za-z_][A-Za-z0-9_]*$/),a.z.string()),Cl=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:zl,modelCatalog:fl.optional(),codexSettings:Hn.optional(),updatedAt:a.z.string().datetime()}).strict();class Rl{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`)}inspectMaterialized(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:{},o=Cl.parse({version:s.version,instanceId:s.instanceId,instanceCredential:s.instanceCredential??s.registrationToken,environment:s.environment,modelCatalog:void 0===s.modelCatalog?void 0:yl(s.modelCatalog),codexSettings:void 0===s.codexSettings?void 0:(r=s.codexSettings,Hn.parse(function(e){if(!e||"object"!=typeof e||Array.isArray(e))return e;const t=e,n=t.multiAgent,i=!n||"object"!=typeof n||Array.isArray(n)?n:(()=>{const e=n,t=e.defaultModel;return{...void 0===e.enabled?{}:{enabled:e.enabled},...void 0===e.maxConcurrentThreads?{}:{maxConcurrentThreads:e.maxConcurrentThreads},...void 0===t?{}:{defaultModel:!t||"object"!=typeof t||Array.isArray(t)?t:{modelEntityId:t.modelEntityId,modelName:t.modelName}},...void 0===e.defaultReasoningEffort?{}:{defaultReasoningEffort:e.defaultReasoningEffort}}})();return{...void 0===t.modelVerbosity?{}:{modelVerbosity:t.modelVerbosity},...void 0===t.personality?{}:{personality:t.personality},...void 0===n?{}:{multiAgent:i}}}(r))),updatedAt:s.updatedAt});var r;if(o.instanceId!==e)throw Object.assign(new Error(`Private config identity mismatch for instance ${e}.`),{statusCode:409,code:"INSTANCE_PRIVATE_CONFIG_IDENTITY_MISMATCH"});return o}put(e){const n=Cl.parse(e);this.init();const i=this.filePath(n.instanceId);return I.sync(i,`${JSON.stringify(n,null,2)}\n`,{encoding:"utf8",mode:384}),t.chmodSync(i,384),n}materialize(e,t,n,i,s){if(!t)throw Object.assign(new Error(`Instance ${e} does not have a long-lived credential.`),{statusCode:409,code:"INSTANCE_PRIVATE_CONFIG_CREDENTIAL_MISSING"});return this.put({version:1,instanceId:e,instanceCredential:t,environment:n,...i?{modelCatalog:i}:{},...s?{codexSettings:s}:{},updatedAt:(new Date).toISOString()})}delete(e){t.rmSync(this.filePath(e),{force:!0})}}const xl=a.z.object({id:a.z.string().trim().min(1).max(120),status:a.z.literal("pending"),input:sd,createdAt:a.z.string().datetime(),updatedAt:a.z.string().datetime(),expiresAt:a.z.string().datetime()}).strict();class kl{repository;workspaceProvisioningTtlMs;workspaceProvisioningCleanupTimer;constructor(e,t={}){this.workspaceProvisioningTtlMs=t.workspaceProvisioningTtlMs??864e5,this.repository=t.repository||md(hl(e)).git}init(){this.repository.deleteExpiredProvisioning((new Date).toISOString()),this.scheduleWorkspaceProvisioningCleanup()}putPayload(e){const t=Xc.parse(e),n=this.repository.getPayload(t.credential.id);if(n&&n.payload.credential.revision>t.credential.revision)throw i=t.credential.id,Object.assign(new Error(`Refusing stale payload revision for ${i}.`),{code:"GIT_CREDENTIAL_REVISION_STALE",statusCode:409});var i;if(n&&n.payload.credential.revision===t.credential.revision&&JSON.stringify(n.payload)!==JSON.stringify(t))throw function(e,t){return Object.assign(new Error(`Refusing conflicting payload revision for ${t}.`),{code:"GIT_CREDENTIAL_REVISION_CONFLICT",statusCode:409})}(0,t.credential.id);const s=(new Date).toISOString();return this.repository.putPayload({id:t.credential.id,payload:t,createdAt:n?.createdAt||s,updatedAt:s}).payload}getPayload(e){return this.repository.getPayload(e)?.payload}putAuthorizationSet(e){const t=Yc.parse(e),n=this.repository.getAuthorization(t.instanceId),i=(new Date).toISOString();return this.publicAuthorizationSet(this.repository.putAuthorizationCas({id:t.instanceId,...t,createdAt:n?.createdAt||i}))}getAuthorizationSet(e){const t=this.repository.getAuthorization(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=ad(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.repository.listAuthorizations().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.repository.deletePayload(e)}collectUnreferencedPayloads(){return this.repository.collectUnreferencedPayloads()}removeInstance(e){const t=this.repository.deleteAuthorization(e)?1:0;return this.repository.deleteProvisioning(e),this.scheduleWorkspaceProvisioningCleanup(),t}putWorkspaceProvisioning(e){const t=sd.parse(e);if(!Dl(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.repository.getProvisioning(t.instanceId);if("consumed"===n?.status&&n.operationId===t.operationId)return t;const i=(new Date).toISOString(),s=xl.parse(this.repository.putProvisioning({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.repository.getProvisioning(e);if(t&&"pending"===t.status)return!Dl(t.input)||Date.parse(t.expiresAt)<=Date.now()?(this.repository.deleteProvisioning(e),void this.scheduleWorkspaceProvisioningCleanup()):t.input}removeWorkspaceProvisioning(e){const t=this.repository.deleteProvisioning(e);return this.scheduleWorkspaceProvisioningCleanup(),t}discardPendingWorkspaceProvisioning(e){const t=this.repository.getProvisioning(e);return!(!t||"pending"!==t.status)&&this.removeWorkspaceProvisioning(e)}completeWorkspaceProvisioning(e,t){const n=(new Date).toISOString(),i=this.repository.consumeProvisioning(e,t,n,new Date(Date.now()+6048e5).toISOString());return this.scheduleWorkspaceProvisioningCleanup(),i}workspaceProvisioningStatus(e){const t=this.repository.getProvisioning(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.repository.listProvisioning().map(e=>Date.parse(e.expiresAt)));Number.isFinite(e)&&(this.workspaceProvisioningCleanupTimer=setTimeout(()=>{this.workspaceProvisioningCleanupTimer=void 0;const e=Date.now();this.repository.deleteExpiredProvisioning(new Date(e).toISOString()),this.scheduleWorkspaceProvisioningCleanup()},Math.min(2147483647,Math.max(0,e-Date.now()))),this.workspaceProvisioningCleanupTimer.unref?.())}publicAuthorizationSet(e){const{id:t,createdAt:n,...i}=e;return Yc.parse(i)}}function Dl(e){return e.credentials.length>0&&e.credentials.every(e=>"operation-only"===e.retention)}const Pl=function(e,t=process.env,n=e){let i;return()=>{const s=t.TASK_HANDOFF_VERSION?.trim();return s||(i||=R(e,t,n),i)}}("@task-handoff/node-agent",process.env,"@task-handoff/control-plane");function Ll(){return Pl()}function Ml(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 jl(e){const t=Ll();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:Ml(t,e)}}function Ul(e,t,n=!0){if(!n){const n=Ll(),i=e.runtimeVersion;return"matched"===i?.phase&&i.desiredVersion===n&&i.actualVersion===t?i:jl(t)}const i=Ll(),s=e.runtimeVersion;if(!s||s.desiredVersion!==i)return jl(t);const o="INSTANCE_RUNTIME_VERSION_MISMATCH"!==s.error?.code?s.error:t===i?void 0:Ml(i,t);return Wi.parse({...s,desiredVersion:i,...t?{actualVersion:t}:{actualVersion:void 0},..."pending"===s.phase?{error:o||(t!==i?Ml(i,t):void 0)}:{}})}const Fl="runtime_local_host",$l="task-handoff.node-agent.builtin";function Hl(e){const t={...e};return delete t[$l],t}function ql(e){return"local-folder"===e.type?cs.parse({mode:"local-bind",path:"/workspace",readOnly:!1}):cs.parse({mode:"git-clone",path:"/workspace",readOnly:!1})}function Vl(e){const t=as.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 ps.parse({id:n,name:"string"==typeof e.sourceSnapshot.name?e.sourceSnapshot.name:e.name,source:t,defaultImageSelection:e.imageSelection,defaultNodeId:e.nodeId,workspacePolicy:ql(t),labels:{},createdAt:e.createdAt,updatedAt:e.updatedAt})}function Bl(e,t){throw Object.assign(new Error(t),{statusCode:403,code:e})}function Kl(e,t){e!==Pn&&console.warn(JSON.stringify({message:"protocol version mismatch",peer:t,expectedProtocolVersion:Pn,actualProtocolVersion:e||"missing",errorCode:"PROTOCOL_VERSION_MISMATCH"}))}function Gl(e){return"none"!==e.capabilities.artifactKind}function Wl(e={}){return{...e,requiresImage:!1,supportsControlledInstanceApi:!0,supportsContainerLifecycle:!1,supportsAppSessions:!0,supportsHostSessions:!0,artifactKind:"none",isolation:"none"}}class Xl{onStored;records;constructor(e){this.records=e}init(){}setOnStored(e){this.onStored=e}put(e){const t=this.records.put(po.parse(e));return this.onStored?.(t),t}putObservation(e){const t=this.records.putObservation(po.parse(e));return this.onStored?.(t),t}get(e){return this.records.get(e)}list(){return this.records.list()}delete(e){return this.records.delete(e)}}class Yl{nodeId;paths;persistence;localFolders;nodeRuntimes;controlledInstances;environmentTemplates;instancePrivateConfigs;modelRegistry;gitCredentials;updateJobs;node;listenerPort;containerUrlOverride;platform;constructor(e,t,n,i,s,o,r){this.paths=e,this.nodeId=t;const a=r||md(hl(e));this.persistence=a,a.topology.nodeIdentity.ensure(t,ae()),this.localFolders=a.topology.localFolders,this.nodeRuntimes=a.topology.runtimes,this.instancePrivateConfigs=new Rl(e),this.controlledInstances=new Xl(a.topology.instances),this.environmentTemplates=new Ol(e),this.gitCredentials=new kl(e,{repository:a.git}),this.modelRegistry=new Il(e,t,{has:e=>Boolean(this.controlledInstances.get(e)),list:()=>this.listInstances(),require:e=>this.requireInstance(e),put:e=>this.controlledInstances.put(e)},a.model),this.updateJobs=new Nl(e),this.listenerPort=s,this.platform=o,this.containerUrlOverride=i;const c=ae();this.node=Gs.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:c,updatedAt:c})}init(){for(const e of this.localFolders.list())this.localFolders.put(e);if(this.instancePrivateConfigs.init(),this.controlledInstances.init(),this.environmentTemplates.init(),this.gitCredentials.init(),this.modelRegistry.init(),this.updateJobs.init(),this.updateJobs.reconcileRollouts(this.controlledInstances.list(),Ll(),{processStarted:!0}),!this.nodeRuntimes.get("runtime_local_docker")){const e=ae();this.nodeRuntimes.put(Ws.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(Fl),t=ae();this.nodeRuntimes.put(Ws.parse({id:Fl,nodeId:this.nodeId,name:"Local Runtime",type:"local",status:e?.status||"unknown",accessStrategy:"node-proxy",capabilities:Wl(e?.capabilities),labels:{...e?.labels,[$l]:"true"},createdAt:e?.createdAt||t,updatedAt:e?.updatedAt||t}))}for(const e of this.nodeRuntimes.list())e.nodeId!==this.nodeId&&this.nodeRuntimes.put(Ws.parse({...e,nodeId:this.nodeId,updatedAt:ae()}));for(const e of this.localFolders.list())e.nodeId!==this.nodeId&&this.localFolders.put(rs.parse({...e,nodeId:this.nodeId,updatedAt:ae()}));this.normalizeInstanceRuntimeVersions()}normalizeInstanceRuntimeVersions(){for(const e of this.controlledInstances.list()){const t=jl(e.build?.packageVersion||e.instanceVersion),n=Gl(this.requireRuntime(e.runtimeId)),i=["created","stopped","failed"].includes(e.status),s=n&&e.runtimeVersion?.desiredVersion===t.desiredVersion?e.runtimeVersion:void 0,o=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(po.parse({...e,ready:!1,runtimeVersion:o,updatedAt:ae()}))}}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=ae()}runningInstanceCount(){const e=new Set(["created","stopped","failed"]);return this.listInstances().filter(t=>!e.has(t.status)).length}createLocalFolder(e){const t=ae(),i=pa(e.path),s=rs.parse({...e,name:e.name.trim()||n.basename(i),path:i,id:e.id||Xa("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(rs.parse({...i,name:t.name.trim()||n.basename(i.path),updatedAt:ae()}))}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=ae(),n=Ws.parse({...e,id:e.id||Xa("runtime"),nodeId:this.nodeId,accessStrategy:e.accessStrategy||(i=e.type,"docker"===i?"direct-port":"node-proxy"),capabilities:e.capabilities||{},labels:Hl(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[$l]){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=Ws.parse({...n,...t,id:n.id,nodeId:this.nodeId,accessStrategy:t.accessStrategy||n.accessStrategy,capabilities:t.capabilities||n.capabilities,labels:t.labels?Hl(t.labels):n.labels,createdAt:n.createdAt,updatedAt:ae()});return this.nodeRuntimes.put(i)}deleteRuntime(e){if("true"===this.requireRuntime(e).labels[$l]){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=Ws.parse({...n,...e,id:n.id,nodeId:this.nodeId,createdAt:n.createdAt,updatedAt:ae()});return this.nodeRuntimes.put(t)}):this.nodeRuntimes.put(Ws.parse({...n,status:"unknown",updatedAt:ae()}))}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=fo(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 ${Pn}: ${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 po.parse({...e,status:"starting",ready:!1,updatedAt:n});case"stop-requested":return po.parse({...e,status:"stopping",ready:!1,updatedAt:n});case"stop-failed":return"stopping"!==e.status?e:po.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 po.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 po.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 po.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 po.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=fo(e);return t.success?[t.data]:[]})}resolvedAssignedModelEnvironment(e){return this.modelRegistry.resolvedEnvironment(e)}createInstance(e){const t=this.requireRuntime(e.runtimeId),i=ae(),s=e.id||Xa("inst"),o=function(e){const t=as.parse(e);return"local-folder"===t.type?t:as.parse({...t,auth:{type:"none"}})}(e.source),r=e.environmentSource||(e.imageSelection?{type:"image",imageSelection:e.imageSelection}:void 0);if("template"===r?.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"===r?.type?this.environmentTemplates.get(r.environmentTemplateId):void 0;if("template"===r?.type&&(!a||"ready"!==a.status)){const e=new Error(`Environment template ${r.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)&&(!r||"image"===r.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"!==o.type){const e=new Error("Localhost runtime currently supports local folder sources only.");throw Object.assign(e,{statusCode:400,code:"LOCAL_RUNTIME_REQUIRES_LOCAL_FOLDER"}),e}if("local"===t.type&&this.listInstances().some(e=>"local"===this.requireRuntime(e.runtimeId).type)){const e=new Error("A localhost instance already exists on this node.");throw Object.assign(e,{statusCode:409,code:"LOCAL_RUNTIME_INSTANCE_EXISTS"}),e}const c=a?Ms.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?Ms.parse(e.image):void 0,d="local"===t.type&&"local-folder"===o.type?n.resolve(o.path):void 0,l=po.parse({id:s,name:e.name||`instance-${s.replace(/^inst_?/,"").slice(0,6)}`,source:o,sourceSnapshot:e.sourceSnapshot||{},modelSelection:e.modelSelection,projectId:e.projectId,nodeId:this.nodeId,runtimeId:t.id,imageSelection:"image"===r?.type?r.imageSelection:void 0,environmentSource:r,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"!==r?.type?{phase:"checking-image",requestedReference:c.requestedReference,generation:0,startedAt:i,updatedAt:i}:void 0,status:c&&"docker"===t.type&&"template"!==r?.type?"provisioning":"created",health:"unknown",connectionStatus:"unknown",agentStatus:"unknown",targetStatus:"unknown",uiAccessStatus:"unknown",controlMode:"controlled",ready:!1,runtimeVersion:jl(),capabilities:{},config:{autoImportAgentConfigs:e.config?.autoImportAgentConfigs??!0,codexConfigEnabled:e.config?.codexConfigEnabled??!0,codexHomeMode:e.config?.codexHomeMode??("local"===t.type?"taskhandoff":"default"),defaultCodexPermissionMode:e.config?.defaultCodexPermissionMode??("docker"===t.type?"full-access":"ask"),...e.config?.codexSettings?{codexSettings:e.config.codexSettings}:{},aiSessionHistoryLimit:e.config?.aiSessionHistoryLimit??50,aiSessionAttachmentRetentionDays:e.config?.aiSessionAttachmentRetentionDays??30,aiSessionMaxFileAttachmentBytes:e.config?.aiSessionMaxFileAttachmentBytes??he},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:Ya(),createdAt:i,updatedAt:i}),u=this.persistence.transactionSync(()=>{let t=this.controlledInstances.put(l);const n=e.modelSelection;return n&&Object.values(n).some(e=>Array.isArray(e)?e.length>0:Boolean(e))&&(t=this.modelRegistry.assign(s,{modelSelection:n,modelEntityIds:n.modelEntityIds,codexModelHash:n.codexModelHash,claudeModelHash:n.claudeModelHash,opencodeModelHash:n.opencodeModelHash}).instance),e.gitWorkspaceProvisioning?.credentials.every(e=>"operation-only"===e.retention)&&this.gitCredentials.putWorkspaceProvisioning(e.gitWorkspaceProvisioning),t});return this.instancePrivateConfigs.materialize(u.id,u.registrationToken,this.resolvedAssignedModelEnvironment(u.id),this.modelRegistry.privateCatalog(u.id),u.config.codexSettings),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=ad(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=Eo.parse(t),s=ae(),o=this.controlledInstances.get(e);if(!o){const t=new Error(`Instance ${e} was not found on node ${this.nodeId}.`);throw Object.assign(t,{statusCode:404,code:"NODE_INSTANCE_NOT_FOUND"}),t}if(this.validateInstanceReport(o,i,n),i.processIncarnationId&&i.processIncarnationId===o.processIncarnationId)return o;Kl(i.protocolVersion,`Instance ${e}`);const r=i.build?.packageVersion||i.instanceVersion,a=Gl(this.requireRuntime(o.runtimeId)),c=Ul(o,r,a),d=po.parse({...o,status:"registered",health:r===Ll()?"ok":"degraded",ready:!a&&r===Ll(),connectionStatus:"online",agentStatus:"online",targetStatus:o.targetStatus,uiAccessStatus:o.uiAccessStatus,controlMode:i.controlMode,protocolVersion:i.protocolVersion,instanceVersion:i.instanceVersion,build:i.build,runtimeVersion:c,processIncarnationId:i.processIncarnationId||o.processIncarnationId,capabilities:i.capabilities,appInventory:i.appInventory,workspace:i.workspace,target:o.target,registrationToken:o.registrationToken||i.registrationToken,lastHeartbeatAt:s,updatedAt:s});return this.controlledInstances.putObservation(d)}heartbeatInstance(e,t,n){const i=this.requireInstance(e);this.validateInstanceToken(i,n);const s=wo.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.`),Kl(s.protocolVersion,`Instance ${e}`);const o=ae(),r=i.target,a=i.targetStatus,c=Ul(i,s.build?.packageVersion||i.build?.packageVersion||i.instanceVersion,Gl(this.requireRuntime(i.runtimeId))),d=s.health||i.health,l="running"===(s.status||i.status)&&"failed"!==d,u=po.parse({...i,...s,target:r,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:o,updatedAt:o});return this.controlledInstances.putObservation(u)}validateInstanceReport(e,t,n){this.validateInstanceToken(e,n||t.registrationToken),t.instanceId&&t.instanceId!==e.id&&Bl("INSTANCE_ID_MISMATCH",`Instance ${t.instanceId} cannot register as ${e.id}.`),t.nodeId&&t.nodeId!==this.nodeId&&Bl("INSTANCE_NODE_MISMATCH",`Instance ${e.id} belongs to node ${this.nodeId}.`),t.runtimeId&&t.runtimeId!==e.runtimeId&&Bl("INSTANCE_RUNTIME_MISMATCH",`Instance ${e.id} belongs to runtime ${e.runtimeId}.`),t.imageSelection&&t.imageSelection.imageId!==e.imageSelection?.imageId&&Bl("INSTANCE_IMAGE_MISMATCH",`Instance ${e.id} belongs to image ${e.imageSelection?.imageId}.`)}validateInstanceToken(e,t){e.registrationToken&&t===e.registrationToken||Bl("INSTANCE_REGISTRATION_TOKEN_INVALID",`Invalid registration token for instance ${e.id}.`)}authenticateInstance(e,t){const n=this.requireInstance(e);return this.validateInstanceToken(n,t),n}context(e,t=this.resolvedAssignedModelEnvironment(e.id)){const n=t,i=e.imageSnapshot||Ms.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}),s=this.instancePrivateConfigs.materialize(e.id,e.registrationToken,n,this.modelRegistry.privateCatalog(e.id),e.config.codexSettings),o=this.gitWorkspaceProvisioningFor(e);return{project:Vl(e),image:i,node:this.node,runtime:this.requireRuntime(e.runtimeId),instance:e,nodeAgentUrl:this.containerUrl,modelEnv:n,privateConfigPath:this.instancePrivateConfigs.filePath(s.instanceId),...o?{gitWorkspaceProvisioning:o,completeGitWorkspaceProvisioning:()=>this.gitCredentials.completeWorkspaceProvisioning(e.id,o.operationId)}:{}}}}async function Jl(e,t){const n=function(e){const t=tu(e),n=[],i=t.pathname.split("/").filter(Boolean).at(-1)||"";return ru(n,Zl(t.toString(),/^v\d+$/.test(i)?"models":"v1/models")),ru(n,new URL("/v1/models",t.origin).toString()),ru(n,new URL("/models",t.origin).toString()),n}(t.endpoint),i=Date.now();let s;for(const o of n){const n=await nu(e,o,{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 su("MODEL_DISCOVERY_FAILED",n.status);const r=await iu(n,"MODEL_DISCOVERY_RESPONSE_INVALID"),a=Array.isArray(r.data)?r.data:void 0;if(!a)throw ou("MODEL_DISCOVERY_RESPONSE_INVALID","The model endpoint returned an invalid model list.",502);return{models:au(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 ou("MODEL_DISCOVERY_UNSUPPORTED","No compatible model-list endpoint was found for this endpoint.",502,s)}async function Ql(e,t){const n=Date.now(),i=t.protocol||("claude"===t.app?"anthropic-messages":"opencode"===t.app?"openai-chat-completions":"openai-responses"),s="openai-responses"===i?await nu(e,eu(t.endpoint,"responses"),{method:"POST",headers:{accept:"application/json",authorization:`Bearer ${t.key}`,"content-type":"application/json"},body:JSON.stringify({model:t.model,input:"Reply with OK.",max_output_tokens:32,stream:!1})}):"openai-chat-completions"===i?await nu(e,eu(t.endpoint,"chat/completions"),{method:"POST",headers:{accept:"application/json",authorization:`Bearer ${t.key}`,"content-type":"application/json"},body:JSON.stringify({model:t.model,messages:[{role:"user",content:"Reply with OK."}],max_tokens:32,stream:!1})}):await nu(e,function(e){const t=tu(e);if(/\/messages\/?$/.test(t.pathname))return t.toString();const n=t.pathname.split("/").filter(Boolean).at(-1)||"";return Zl(t.toString(),/^v\d+$/.test(n)?"messages":"v1/messages")}(t.endpoint),{method:"POST",headers:{accept:"application/json","anthropic-version":"2023-06-01","content-type":"application/json","x-api-key":t.key},body:JSON.stringify({model:t.model,max_tokens:8,messages:[{role:"user",content:"Reply with OK."}]})});if(!s.ok)throw su("MODEL_TEST_FAILED",s.status);if((await iu(s,"MODEL_TEST_RESPONSE_INVALID")).error)throw ou("MODEL_TEST_RESPONSE_INVALID","The model endpoint returned an error payload.",502);return{success:!0,latencyMs:Date.now()-n}}function Zl(e,t){const n=tu(e);return n.pathname=`${n.pathname.replace(/\/+$/,"")}/${t.replace(/^\/+/,"")}`,n.search="",n.hash="",n.toString()}function eu(e,t){const n=tu(e);return n.pathname.replace(/\/+$/,"").endsWith(`/${t}`)?n.toString():Zl(n.toString(),t)}function tu(e){let t;try{t=new URL(e.trim())}catch{throw ou("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 ou("MODEL_ENDPOINT_INVALID","The model endpoint must be an HTTP or HTTPS URL without embedded credentials.",400);return t}async function nu(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 ou(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 iu(e,t){const n=await e.text();if(n.length>1e6)throw ou(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 ou(t,"The model endpoint returned invalid JSON.",502)}}function su(e,t){return ou(e,401===t||403===t?"The model endpoint rejected the API key.":"The model endpoint rejected the request.",502,t)}function ou(e,t,n,i){return Object.assign(new Error(t),{code:e,statusCode:n,...i?{details:{upstreamStatus:i}}:{}})}function ru(e,t){e.includes(t)||e.push(t)}function au(e){const t=new Set;return e.filter(e=>!t.has(e.id)&&(t.add(e.id),!0))}const cu=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(),du=cu.extend({model:a.z.string().trim().min(1).max(240),app:a.z.enum(["codex","claude","opencode"]).optional(),protocol:a.z.enum(["openai-responses","openai-chat-completions","anthropic-messages"]).optional()}).strict().refine(e=>Boolean(e.protocol||e.app),{message:"A model protocol is required.",path:["protocol"]});class lu{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:o}=this.store.resolve(e,i);if("unique"!==s.status||"ssh-key"!==o?.secret.kind)return{status:s.status};const r=`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 pu("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:o.secret.passphrase||""};await mu("ssh-add",["-"],o.secret.privateKey,s);const c=await pu("ssh-add",["-L"],s);t.rmSync(u,{force:!0});const d=Date.now();return this.invocations.set(r,{instanceId:e,remoteUrl:i,credentialId:o.credential.id,credentialRevision:o.credential.revision,socketPath:l,agentPid:p,directory:a,idleExpiresAt:d+this.idleTtlMs,absoluteExpiresAt:d+this.maxTtlMs}),this.scheduleCleanup(),{status:"ok",invocationId:r,publicIdentity:c,pinnedKnownHosts:o.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 uu("GIT_CREDENTIAL_SSH_INVOCATION_INVALID",404);const{match:s,payload:o}=this.store.resolve(e,i.remoteUrl);if("unique"!==s.status||"ssh-key"!==o?.secret.kind||o.credential.id!==i.credentialId||o.credential.revision!==i.credentialRevision)throw this.release(t,e),uu("GIT_CREDENTIAL_SSH_INVOCATION_REVOKED",403);const r=Buffer.from(n,"base64");if(r.length<5||r.length>1048576||r.readUInt32BE(0)!==r.length-4)throw uu("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 o=m.createConnection(e),r=[];let a=0,c=!1;const d=(e,t)=>{c||(c=!0,o.destroy(),e?s(e):i(t))};o.setTimeout(n),o.once("timeout",()=>d(new Error("Managed Git SSH agent exchange timed out."))),o.once("error",e=>d(e)),o.once("end",()=>d(new Error("Managed Git SSH agent closed before returning a complete frame."))),o.once("close",()=>d(new Error("Managed Git SSH agent closed before returning a complete frame."))),o.on("data",e=>{r.push(e);const t=Buffer.concat(r);!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))}),o.once("connect",()=>o.write(t,e=>{e&&d(e)}))})}(i.socketPath,r,a);return{frame:e.toString("base64")}}catch{throw this.release(t,e),uu("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 uu(e,t){return Object.assign(new Error("Managed Git broker request was rejected."),{code:e,statusCode:t})}function pu(e,t,n=process.env){return mu(e,t,void 0,n)}function mu(e,t,n,i){return new Promise((s,o)=>{const r=l.spawn(e,t,{shell:!1,env:i,stdio:[void 0===n?"ignore":"pipe","pipe","pipe"]}),a=[];r.stdout.on("data",e=>a.push(e)),r.once("error",()=>o(new Error(`Managed Git SSH broker could not start ${e}.`))),r.once("close",t=>0===t?s(Buffer.concat(a).toString("utf8")):o(new Error(`Managed Git SSH broker command ${e} failed.`))),void 0!==n&&r.stdin.end(n)})}const hu=a.z.object({credentialId:a.z.string().trim().min(1).max(120)}).strict(),gu=a.z.object({id:a.z.string().trim().min(1).max(120)}).strict(),fu=gu.extend({invocationId:a.z.string().trim().min(1).max(120)}).strict();function yu(e){const t=e.authorization;return"string"==typeof t&&t.startsWith("Bearer ")?t.slice(7).trim():void 0}const Iu=a.z.object({maxIdleAiSessions:a.z.number().int().min(1).max(50).default(5)}).strict(),Au=a.z.string().trim().min(1).max(1024).refine(e=>!e.startsWith("/")&&!e.includes("\\")&&e.split("/").every(e=>e.length>0&&"."!==e&&".."!==e),"Story paths must be normalized relative POSIX paths."),_u=a.z.string().regex(/^[a-f0-9]{64}$/),Eu=a.z.object({title:a.z.string().trim().min(1).max(240),storyPath:Au,revision:_u}).strict(),wu=a.z.object({agent:be.optional(),mode:tt.optional(),permissionMode:nt.optional(),modelSelection:ht.optional(),reasoningEffort:gt.optional(),cwdFolderId:a.z.string().trim().min(1).max(120).optional(),gitSelection:ft.optional()}).strict(),Tu=a.z.object({id:a.z.string().trim().min(1).max(120),title:a.z.string().trim().min(1).max(120),promptTemplate:a.z.string().trim().min(1).max(32e3),targetInstanceId:a.z.string().trim().min(1).max(120).optional(),sessionPreset:wu.optional()}).strict(),bu=Tu.omit({id:!0}).strict(),Su=bu.extend({id:Tu.shape.id.optional()}).strict(),vu=a.z.discriminatedUnion("scheduleKind",[a.z.object({scheduleKind:a.z.literal("interval"),intervalMs:a.z.number().int().min(6e4)}).strict(),a.z.object({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({scheduleKind:a.z.literal("weekly"),weekdays:a.z.array(a.z.number().int().min(0).max(6)).min(1).max(7).refine(e=>new Set(e).size===e.length,"Weekdays must be unique."),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({scheduleKind:a.z.literal("monthly"),dayOfMonth:a.z.number().int().min(-3).max(31).refine(e=>0!==e,"Day of month must not be zero."),timeOfDay:a.z.string().regex(/^([01]\d|2[0-3]):[0-5]\d$/),timezone:a.z.string().trim().min(1).max(120)}).strict()]),Nu=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(),Ou=a.z.object({id:a.z.string().trim().min(1).max(120),storyId:ue,actionId:Tu.shape.id,schedule:vu,enabled:a.z.boolean().default(!0),policy:Nu.default({maxConcurrentRuns:1,whenBusy:"skip"}),createdAt:a.z.string().datetime(),updatedAt:a.z.string().datetime()}).strict(),zu=Ou.omit({id:!0,createdAt:!0,updatedAt:!0}).strict(),Cu=a.z.object({action:Tu,automation:zu.omit({storyId:!0,actionId:!0}).strict()}).strict(),Ru=a.z.object({actionId:Ou.shape.actionId.optional(),schedule:vu.optional(),enabled:a.z.boolean().optional(),policy:Nu.optional()}).strict().refine(e=>Object.keys(e).length>0,"At least one Automation field is required."),xu=a.z.object({code:a.z.string().trim().min(1).max(120),message:a.z.string().trim().min(1).max(2e3)}).strict(),ku=a.z.enum(["queued","dispatching","running","completed","failed","skipped"]),Du=a.z.object({id:a.z.string().trim().min(1).max(160),automationId:Ou.shape.id,eventType:a.z.enum(["manual","schedule"]),status:ku,scheduledFor:a.z.string().datetime(),targetInstanceId:a.z.string().trim().min(1).max(120),aiSessionId:a.z.string().trim().min(1).max(120).optional(),error:xu.optional(),queuedAt:a.z.string().datetime(),startedAt:a.z.string().datetime().optional(),completedAt:a.z.string().datetime().optional()}).strict(),Pu=a.z.enum(["disabled","blocked","scheduled","running","error"]),Lu=a.z.object({automation:Ou,effectiveStatus:Pu,blockedReason:xu.optional(),nextRunAt:a.z.string().datetime().optional(),currentRuns:a.z.array(Du).max(20).default([]),lastRun:Du.optional()}).strict(),Mu=a.z.object({automations:a.z.array(Lu).default([])}).strict(),ju=a.z.object({runs:a.z.array(Du).max(120).default([])}).strict(),Uu=a.z.object({clientRequestId:a.z.string().trim().min(1).max(160)}).strict(),Fu="story.automation.changed";a.z.object({storyId:ue,automationId:Ou.shape.id,change:a.z.enum(["created","updated","deleted","status","run"]),status:Lu.optional(),run:Du.optional()}).strict();const $u=a.z.object({id:ue,ownerNodeId:a.z.string().trim().min(1).max(120),title:a.z.string().trim().min(1).max(240),description:a.z.string().trim().max(4e3).optional(),documents:a.z.array(Eu).max(500).default([]),actions:a.z.array(Tu).max(50).default([]),createdAt:a.z.string().datetime(),updatedAt:a.z.string().datetime(),archivedAt:a.z.string().datetime().optional()}).strict();a.z.object({stories:a.z.array($u).default([])}).strict();const Hu=a.z.object({title:$u.shape.title,description:$u.shape.description,actions:a.z.array(bu).max(50).optional(),maxIdleAiSessions:Iu.shape.maxIdleAiSessions.optional()}).strict(),qu=a.z.object({title:$u.shape.title.optional(),description:$u.shape.description.nullable().optional(),actions:a.z.array(Su).max(50).optional(),maxIdleAiSessions:Iu.shape.maxIdleAiSessions.optional()}).strict().refine(e=>Object.keys(e).length>0,"At least one Story field is required."),Vu=a.z.object({title:Eu.shape.title.optional(),storyPath:Au.optional()}).strict().refine(e=>Object.keys(e).length>0,"At least one document field is required."),Bu=a.z.object({storyPaths:a.z.array(Au).max(500)}).strict();a.z.object({storyPath:Au,title:Eu.shape.title.optional(),expectedRevision:_u.optional()}).strict();const Ku=a.z.object({documents:a.z.array(Eu).max(500)}).strict(),Gu=a.z.union([a.z.number(),a.z.string().regex(/^\d+$/).transform(Number)]),Wu=a.z.object({page:Gu.pipe(a.z.number().int().min(1).max(500)).default(1),pageSize:Gu.pipe(a.z.number().int().min(1).max(100)).default(20)}).strict(),Xu=a.z.object({title:Eu.shape.title,storyPath:Au}).strict(),Yu=a.z.object({page:a.z.number().int().min(1).max(500),pageSize:a.z.number().int().min(1).max(100),totalItems:a.z.number().int().nonnegative(),totalPages:a.z.number().int().nonnegative(),hasMore:a.z.boolean()}).strict(),Ju=a.z.object({storyCreatedAt:$u.shape.createdAt,documents:a.z.array(Xu).max(100),pagination:Yu}).strict();a.z.object({storyCreatedAt:$u.shape.createdAt,documents:a.z.array(Xu.strip()).max(100),pagination:Yu.strip()}).strip(),a.z.object({storyPath:Au,revision:_u,content:a.z.string(),size:a.z.number().int().nonnegative()}).strict(),a.z.object({storyPaths:a.z.array(Au).min(1).max(20),destinationPath:a.z.string().trim().min(1).max(4096)}).strict(),a.z.object({storyPath:Au,title:Eu.shape.title.optional(),sourcePath:a.z.string().trim().min(1).max(4096),expectedRevision:_u.optional()}).strict();const Qu=a.z.object({storyPath:Au,path:a.z.string().trim().min(1).max(4096).optional(),revision:_u.optional(),error:a.z.object({code:a.z.string().trim().min(1).max(120),message:a.z.string().trim().min(1).max(2e3)}).strict().optional()}).strict();a.z.object({items:a.z.array(Qu).min(1).max(20)}).strict(),a.z.object({storyId:ue,nodeId:a.z.string().trim().min(1).max(120),change:a.z.enum(["created","updated","archived","restored","deleted","content.written","document.updated","document.reordered","document.deleted"]).optional(),storyPath:Au.optional()}).strict();const Zu=a.z.object({storyId:ue}).strict(),ep=Zu.extend({storyPath:a.z.string().min(1).max(2048)}).strict(),tp=Zu.extend({automationId:a.z.string().trim().min(1).max(120)}).strict(),np=a.z.object({id:a.z.string().trim().min(1).max(120),sessionId:a.z.string().trim().min(1).max(120)}).strict(),ip=a.z.object({storyPath:Au}).strict(),sp=ip.extend({title:a.z.string().trim().min(1).max(240).optional(),expectedRevision:a.z.string().regex(/^[a-f0-9]{64}$/).optional()}).strict();function op(e){const t=e.authorization;return"string"==typeof t&&t.startsWith("Bearer ")?t.slice(7).trim():void 0}async function rp(e,t,n,i,s){const o=e.authenticateInstance(n,s).aiSessions.sessions.find(e=>e.id===i);if(!o)throw Object.assign(new Error("AI Session was not found in the authoritative instance snapshot."),{code:"AI_SESSION_NOT_FOUND",statusCode:404});if(!o.storyId)throw Object.assign(new Error("AI Session is not assigned to a Story."),{code:"STORY_CONTEXT_REQUIRED",statusCode:409});return await t.get(o.storyId)||(()=>{throw Object.assign(new Error("Story was not found."),{code:"STORY_NOT_FOUND",statusCode:404})})()}function ap(e,t,n,i){return e.header("content-type","application/octet-stream"),e.header("content-length",String(i)),e.header("x-story-revision",n),e.send(t)}class cp{tails=new Map;accepting=!0;async acquire(e){if(!this.accepting)throw Object.assign(new Error("Story storage is shutting down."),{code:"STORY_STORAGE_QUIESCING",statusCode:503});const t=this.tails.get(e)??Promise.resolve();let n;const i=new Promise(e=>{n=e}),s=t.catch(()=>{}).then(()=>i);this.tails.set(e,s),await t.catch(()=>{});let o=!1;return()=>{o||(o=!0,n(),s.finally(()=>{this.tails.get(e)===s&&this.tails.delete(e)}))}}async run(e,t){const n=await this.acquire(e);try{return await t()}finally{n()}}stopAccepting(){this.accepting=!1}async drain(){await Promise.all([...this.tails.values()])}pendingStoryIds(){return[...this.tails.keys()]}}class dp{coordinator;paths;ownerNodeId;repository;maxFileBytes;onChange;constructor(e,t,n,i=33554432,s){this.paths=e,this.ownerNodeId=t,this.repository=n,this.maxFileBytes=i,this.onChange=s,this.coordinator=new cp}async init(){t.mkdirSync(this.paths.storyMutationsDir,{recursive:!0,mode:448}),t.mkdirSync(this.paths.storyTrashDir,{recursive:!0,mode:448}),t.chmodSync(this.paths.storyMutationsDir,448),t.chmodSync(this.paths.storyTrashDir,448),await this.recoverFileMutations()}setOnChange(e){this.onChange=e}async list(){const e=await this.repository.stories.list();return Promise.all(e.map(e=>this.project(e)))}async get(e){const t=await this.repository.stories.get(e);return t?this.project(t):void 0}async require(e){const t=await this.repository.stories.get(e);if(!t)throw lp("STORY_NOT_FOUND","Story was not found.",404);return t}async exists(e){return Boolean(await this.repository.stories.get(e))}async automationContext(e){const t=await this.repository.stories.get(e);if(!t)return;if(await this.repository.deletionIntents.get(e))throw lp("STORY_DELETING","Story is being deleted.",409);const n=(await this.repository.actions.list(e)).map(({storyId:e,displayOrder:t,sessionPreset:n,...i})=>Tu.parse({...i,sessionPreset:n||void 0}));return{id:t.id,archivedAt:t.archivedAt||void 0,actions:n}}async create(e){const t=Hu.parse(e),n=(new Date).toISOString(),i=await this.repository.transaction(async e=>{const i=await e.stories.insert({id:Xa("story"),title:t.title,description:t.description,createdAt:n,updatedAt:n,maxIdleAiSessions:t.maxIdleAiSessions??5,nextDocumentSequence:1}),s=(t.actions||[]).map((e,t)=>({storyId:i.id,id:Xa("story_action"),title:e.title,promptTemplate:e.promptTemplate,targetInstanceId:e.targetInstanceId,sessionPreset:e.sessionPreset,displayOrder:t}));return await e.actions.replace(i.id,s),i}),s=await this.project(i);return this.onChange?.("created",s),s}async retentionSettings(e){return Iu.parse({maxIdleAiSessions:(await this.require(e)).maxIdleAiSessions})}async update(e,t,n=!0){const i=qu.parse(t),s=(new Date).toISOString(),o=await this.repository.transaction(async t=>{if(!await t.stories.get(e))throw lp("STORY_NOT_FOUND","Story was not found.",404);if(await t.deletionIntents.get(e))throw lp("STORY_DELETING","Story is being deleted.",409);if(void 0!==i.actions){const n=await t.actions.list(e),s=new Set(i.actions.flatMap(e=>e.id?[e.id]:[])),o=n.map(e=>e.id).filter(e=>!s.has(e)),r=await t.automations.referencingActions(e,o);if(r.length)throw lp("STORY_ACTION_AUTOMATION_IN_USE","Story Action is referenced by an Automation.",409,{automationIds:r.map(e=>e.id)});await t.actions.replace(e,i.actions.map((t,n)=>({storyId:e,id:t.id||Xa("story_action"),title:t.title,promptTemplate:t.promptTemplate,targetInstanceId:t.targetInstanceId,sessionPreset:t.sessionPreset,displayOrder:n})))}return t.stories.update(e,{...void 0!==i.title?{title:i.title}:{},...void 0!==i.description?{description:i.description||null}:{},...void 0!==i.maxIdleAiSessions?{maxIdleAiSessions:i.maxIdleAiSessions}:{},updatedAt:s})}),r=await this.project(o);return n&&this.onChange?.("updated",r),r}async archive(e){return this.setArchived(e,!0)}async restore(e){return this.setArchived(e,!1)}async setArchived(e,t){await this.require(e);const n=(new Date).toISOString(),i=await this.repository.stories.update(e,{archivedAt:t?n:null,updatedAt:n}),s=await this.project(i);return this.onChange?.(t?"archived":"restored",s),s}async deleteRecord(e){const t=await this.get(e);if(!t)return!1;const n=await this.repository.stories.delete(e);return n&&this.onChange?.("deleted",t),n}notifyDeleted(e){this.onChange?.("deleted",e)}notifyUpdated(e){this.onChange?.("updated",e)}async listContent(e){const t=await this.require(e);return(await this.project(t)).documents}async pageContent(e,t,n){const i=await this.require(e),{items:s,totalItems:o}=await this.repository.documents.page(e,t,n),r=Math.ceil(o/n);return{storyCreatedAt:i.createdAt,documents:s,pagination:{page:t,pageSize:n,totalItems:o,totalPages:r,hasMore:t*n<o}}}async readContent(e,n){const i=await this.coordinator.acquire(e);try{await this.require(e);const s=Au.parse(n);if(!await this.repository.documents.get(e,s))throw lp("STORY_CONTENT_NOT_INDEXED","Story content is not indexed.",404);const o=this.openRegularFileWithinRoot(e,s),r=t.createReadStream("",{fd:o.fd,autoClose:!0});let a=!1;const c=()=>{a||(a=!0,i())};return r.once("close",c),r.once("error",c),{stream:r,size:o.size,revision:o.revision}}catch(t){if(i(),"ENOENT"===t.code)throw await this.removeMissingDocument(e,n),lp("STORY_CONTENT_NOT_FOUND","Story content file was not found.",404);throw t}}async writeContent(e,i){return this.coordinator.run(e,async()=>{if((await this.require(e)).archivedAt)throw lp("STORY_ARCHIVED","Archived Story content is read-only.",409);const s=Au.parse(i.storyPath),o=await this.repository.documents.get(e,s);if(o){if(!i.expectedRevision)throw lp("STORY_REVISION_REQUIRED","expectedRevision is required when replacing Story content.",409);const n=this.openRegularFileWithinRoot(e,s);if(t.closeSync(n.fd),n.revision!==i.expectedRevision)throw lp("STORY_REVISION_CONFLICT","Story content changed since it was read.",409)}else if(!i.title?.trim())throw lp("STORY_CONTENT_TITLE_REQUIRED","A title is required for new Story content.",400);this.ensureStoryParent(e,s);const r=Xa("story_file_mutation"),a=this.filePath(e,s),c=`${a}.${r}.tmp`,d=`${a}.${r}.bak`,l=(new Date).toISOString();if(!o&&t.existsSync(a))throw lp("STORY_PATH_CONFLICT","Story path already exists on disk.",409);await this.repository.fileMutations.insert({id:r,storyId:e,operation:"write",storyPath:s,title:i.title?.trim(),temporaryName:c,backupName:d,phase:"receiving",createdAt:l,updatedAt:l});let u=0,p=!1;try{const l=new h.Transform({transform:(e,t,n)=>{u+=e.byteLength,n(u>this.maxFileBytes?lp("STORY_FILE_TOO_LARGE","Story content exceeds the node limit.",413):null,e)}});await f.pipeline(i.stream,l,t.createWriteStream(c,{flags:"wx",mode:384})),this.fsyncFile(c),await this.repository.fileMutations.update(r,{phase:"prepared",updatedAt:(new Date).toISOString()}),o&&t.renameSync(a,d),t.renameSync(c,a),this.fsyncDirectory(n.dirname(a)),await this.repository.fileMutations.update(r,{phase:"files-staged",updatedAt:(new Date).toISOString()}),await this.repository.transaction(async t=>{const n=await t.stories.get(e);if(!n)throw lp("STORY_NOT_FOUND","Story was not found.",404);if(o)await t.documents.update(e,s,{title:i.title?.trim()||o.title});else{const o=await t.documents.list(e);await t.documents.insert({storyId:e,storyPath:s,title:i.title.trim(),indexedSequence:n.nextDocumentSequence,displayOrder:o.length}),await t.stories.update(e,{nextDocumentSequence:n.nextDocumentSequence+1,updatedAt:(new Date).toISOString()})}o&&await t.stories.update(e,{updatedAt:(new Date).toISOString()}),await t.fileMutations.update(r,{phase:"database-committed",updatedAt:(new Date).toISOString()})}),p=!0,t.rmSync(d,{force:!0}),await this.repository.fileMutations.update(r,{phase:"cleanup",updatedAt:(new Date).toISOString()}),await this.repository.fileMutations.delete(r);const m=this.openRegularFileWithinRoot(e,s);t.closeSync(m.fd);const g=await this.get(e);return g&&this.onChange?.("content.written",g),{storyPath:s,revision:m.revision,size:u}}catch(e){throw p||await this.rollbackFileMutation(r,a,c,d,Boolean(o)),e}})}async updateDocument(e,i,s){return this.coordinator.run(e,async()=>{if((await this.require(e)).archivedAt)throw lp("STORY_ARCHIVED","Archived Story content is read-only.",409);const o=Au.parse(i),r=await this.repository.documents.get(e,o);if(!r)throw lp("STORY_CONTENT_NOT_INDEXED","Story content is not indexed.",404);const a=s.storyPath?Au.parse(s.storyPath):o;if(a!==o&&await this.repository.documents.get(e,a))throw lp("STORY_PATH_CONFLICT","Story path is already indexed.",409);if(a===o)await this.repository.transaction(async t=>{await t.documents.update(e,o,{title:s.title?.trim()||r.title}),await t.stories.update(e,{updatedAt:(new Date).toISOString()})});else{this.openAndClose(e,o),this.ensureStoryParent(e,a);const i=this.filePath(e,o),c=this.filePath(e,a);if(t.existsSync(c))throw lp("STORY_PATH_CONFLICT","Story path already exists on disk.",409);const d=Xa("story_file_mutation"),l=(new Date).toISOString();await this.repository.fileMutations.insert({id:d,storyId:e,operation:"rename",storyPath:o,nextStoryPath:a,title:s.title?.trim(),temporaryName:i,backupName:c,phase:"prepared",createdAt:l,updatedAt:l});let u=!1;try{t.renameSync(i,c),this.fsyncDirectory(n.dirname(i)),n.dirname(i)!==n.dirname(c)&&this.fsyncDirectory(n.dirname(c)),await this.repository.fileMutations.update(d,{phase:"files-staged",updatedAt:(new Date).toISOString()}),await this.repository.transaction(async t=>{await t.documents.replacePath(e,o,{...r,storyPath:a,title:s.title?.trim()||r.title}),await t.stories.update(e,{updatedAt:(new Date).toISOString()}),await t.fileMutations.update(d,{phase:"database-committed",updatedAt:(new Date).toISOString()})}),u=!0,await this.repository.fileMutations.update(d,{phase:"cleanup",updatedAt:(new Date).toISOString()}),await this.repository.fileMutations.delete(d)}catch(e){throw u||(t.existsSync(c)&&!t.existsSync(i)&&t.renameSync(c,i),await this.repository.fileMutations.delete(d)),e}}const c=await this.get(e);return this.onChange?.("document.updated",c),c})}async reorderDocuments(e,t){const{storyPaths:n}=Bu.parse(t),i=(await this.repository.documents.list(e)).map(e=>e.storyPath);if(n.length!==i.length||new Set(n).size!==n.length||i.some(e=>!n.includes(e)))throw lp("STORY_DOCUMENT_ORDER_INVALID","Document order must contain every indexed storyPath exactly once.",400);await this.repository.transaction(async t=>{await t.documents.reorder(e,n),await t.stories.update(e,{updatedAt:(new Date).toISOString()})});const s=await this.get(e);return this.onChange?.("document.reordered",s),s}async deleteDocument(e,i){return this.coordinator.run(e,async()=>{if((await this.require(e)).archivedAt)throw lp("STORY_ARCHIVED","Archived Story content is read-only.",409);const s=Au.parse(i);if(!await this.repository.documents.get(e,s))return!1;const o=this.filePath(e,s),r=`${o}.${Xa("story_file_mutation")}.deleted`,a=Xa("story_file_mutation"),c=(new Date).toISOString();await this.repository.fileMutations.insert({id:a,storyId:e,operation:"delete",storyPath:s,backupName:r,phase:"prepared",createdAt:c,updatedAt:c});let d=!1;try{this.openAndClose(e,s),t.renameSync(o,r),this.fsyncDirectory(n.dirname(o)),await this.repository.fileMutations.update(a,{phase:"files-staged",updatedAt:(new Date).toISOString()}),await this.repository.transaction(async t=>{await t.documents.delete(e,s),await t.stories.update(e,{updatedAt:(new Date).toISOString()}),await t.fileMutations.update(a,{phase:"database-committed",updatedAt:(new Date).toISOString()})}),d=!0,t.rmSync(r,{force:!0}),await this.repository.fileMutations.update(a,{phase:"cleanup",updatedAt:(new Date).toISOString()}),await this.repository.fileMutations.delete(a)}catch(e){throw d||(t.existsSync(r)&&!t.existsSync(o)&&t.renameSync(r,o),await this.repository.fileMutations.delete(a)),e}const l=await this.get(e);return l&&this.onChange?.("document.deleted",l),!0})}stopAccepting(){this.coordinator.stopAccepting()}drain(){return this.coordinator.drain()}async project(e){const n=(await this.repository.actions.list(e.id)).map(({storyId:e,displayOrder:t,sessionPreset:n,...i})=>Tu.parse({...i,sessionPreset:n||void 0})),i=await this.repository.documents.list(e.id),s=[];for(const n of i)try{const i=this.openRegularFileWithinRoot(e.id,n.storyPath);t.closeSync(i.fd),s.push({title:n.title,storyPath:n.storyPath,revision:i.revision})}catch(t){if("ENOENT"!==t.code)throw t;await this.removeMissingDocument(e.id,n.storyPath)}return $u.parse({id:e.id,ownerNodeId:this.ownerNodeId,title:e.title,description:e.description||void 0,actions:n,documents:s,createdAt:e.createdAt,updatedAt:e.updatedAt,archivedAt:e.archivedAt||void 0})}storyRoot(e){return n.resolve(this.paths.storyContentDir,$u.shape.id.parse(e))}filePath(e,t){const i=this.storyRoot(e),s=n.resolve(i,...Au.parse(t).split("/"));if(s===i||!s.startsWith(`${i}${n.sep}`))throw lp("STORY_PATH_OUTSIDE_ROOT","Story path is outside the Story directory.",400);return s}ensureStoryParent(e,i){const s=this.filePath(e,i);try{const e=t.lstatSync(this.paths.storyContentDir);if(e.isSymbolicLink()||!e.isDirectory())throw lp("STORY_PATH_UNSAFE","Story content root must be a real directory.",409)}catch(e){if("ENOENT"!==e.code)throw e;t.mkdirSync(this.paths.storyContentDir,{recursive:!0,mode:448})}t.chmodSync(this.paths.storyContentDir,448);let o=this.paths.storyContentDir;for(const e of n.relative(this.paths.storyContentDir,n.dirname(s)).split(n.sep).filter(Boolean)){o=n.join(o,e);try{const e=t.lstatSync(o);if(e.isSymbolicLink()||!e.isDirectory())throw lp("STORY_PATH_UNSAFE","Story path parent must be a real directory.",409)}catch(e){if("ENOENT"!==e.code)throw e;t.mkdirSync(o,{mode:448})}t.chmodSync(o,448)}}openRegularFileWithinRoot(e,i){const s=this.filePath(e,i);this.assertExistingParentsSafe(this.storyRoot(e),n.dirname(s));const o="number"==typeof t.constants.O_NOFOLLOW?t.constants.O_NOFOLLOW:0;if(!o)throw lp("STORY_NOFOLLOW_UNAVAILABLE","Safe no-follow file access is unavailable on this platform.",500);const r=t.openSync(s,t.constants.O_RDONLY|o);try{const e=t.fstatSync(r);if(!e.isFile())throw lp("STORY_CONTENT_NOT_FILE","Story content must be a regular file.",409);if(e.size>this.maxFileBytes)throw lp("STORY_FILE_TOO_LARGE","Story content exceeds the node limit.",413);const n=d.createHash("sha256"),i=Buffer.allocUnsafe(65536);let s=0;for(;s<e.size;){const o=t.readSync(r,i,0,Math.min(i.length,e.size-s),s);if(!o)break;n.update(i.subarray(0,o)),s+=o}return{fd:r,size:e.size,revision:n.digest("hex")}}catch(e){throw t.closeSync(r),e}}assertExistingParentsSafe(e,i){const s=n.relative(this.paths.storyContentDir,i);let o=this.paths.storyContentDir;for(const e of s.split(n.sep).filter(Boolean)){o=n.join(o,e);const i=t.lstatSync(o);if(i.isSymbolicLink()||!i.isDirectory())throw lp("STORY_PATH_UNSAFE","Story path parent must be a real directory.",409)}if(!i.startsWith(e))throw lp("STORY_PATH_OUTSIDE_ROOT","Story path is outside the Story directory.",400)}openAndClose(e,n){const i=this.openRegularFileWithinRoot(e,n);t.closeSync(i.fd)}fsyncFile(e){const n=t.openSync(e,"r");try{t.fsyncSync(n)}finally{t.closeSync(n)}}fsyncDirectory(e){if("win32"===process.platform)return;const n=t.openSync(e,"r");try{t.fsyncSync(n)}finally{t.closeSync(n)}}async removeMissingDocument(e,t){if(!await this.repository.documents.get(e,t))return;await this.repository.transaction(async n=>{await n.documents.delete(e,t),await n.stories.update(e,{updatedAt:(new Date).toISOString()})});const n=await this.get(e);n&&this.onChange?.("document.deleted",n)}async rollbackFileMutation(e,n,i,s,o){t.rmSync(i,{force:!0}),o&&t.existsSync(s)?(t.rmSync(n,{force:!0}),t.renameSync(s,n)):o||t.rmSync(n,{force:!0}),await this.repository.fileMutations.delete(e)}async recoverFileMutations(){for(const e of await this.repository.fileMutations.list())await this.coordinator.run(e.storyId,async()=>{const n=this.filePath(e.storyId,e.nextStoryPath||e.storyPath);if("database-committed"===e.phase||"cleanup"===e.phase)"write"===e.operation?(e.temporaryName&&t.rmSync(e.temporaryName,{force:!0}),e.backupName&&t.rmSync(e.backupName,{force:!0})):"delete"===e.operation&&e.backupName&&t.rmSync(e.backupName,{force:!0});else if("write"===e.operation){const i=Boolean(e.temporaryName&&t.existsSync(e.temporaryName)),s=Boolean(await this.repository.documents.get(e.storyId,e.storyPath));e.backupName&&t.existsSync(e.backupName)?(t.rmSync(n,{force:!0}),t.renameSync(e.backupName,n)):s||"files-staged"!==e.phase&&("prepared"!==e.phase||i)||t.rmSync(n,{force:!0}),e.temporaryName&&t.rmSync(e.temporaryName,{force:!0})}else"rename"===e.operation&&e.temporaryName&&t.existsSync(n)&&!t.existsSync(e.temporaryName)?t.renameSync(n,e.temporaryName):"delete"===e.operation&&e.backupName&&t.existsSync(e.backupName)&&!t.existsSync(n)&&t.renameSync(e.backupName,n);await this.repository.fileMutations.delete(e.id)})}}function lp(e,t,n,i){return Object.assign(new Error(t),{code:e,statusCode:n,...void 0===i?{}:{details:i}})}const up=a.z.object({storyId:a.z.string().trim().min(1).max(120),actionId:a.z.string().trim().min(1).max(120),targetInstanceId:a.z.string().trim().min(1).max(120),prompt:a.z.string().trim().min(1).max(32e3),sessionPreset:wu.optional(),cwd:a.z.string().trim().min(1).max(4096)}).strict(),pp=vu,mp=Nu,hp=xu,gp=Du.extend({executionKey:a.z.string().trim().min(1).max(160),requestFingerprint:a.z.string().regex(/^[a-f0-9]{64}$/),executionInput:up}).strict(),fp=new Set(["completed","failed","skipped"]),yp={queued:["dispatching","skipped"],dispatching:["running","failed"],running:["completed","failed"],completed:[],failed:[],skipped:[]};class Ip{repository;now;constructor(e,t=()=>new Date){this.repository=e,this.now=t}async init(){}async list(e){return(await this.repository.automations.list(e)).map(Ap)}async stored(e){const t=await this.repository.automations.get(e);return t?function(e){return{...Ap(e),scheduleAnchorAt:e.scheduleAnchorAt}}(t):void 0}async get(e){const t=await this.repository.automations.get(e);return t?Ap(t):void 0}async create(e){const t=zu.parse(e),n=this.now().toISOString();return Ap(await this.repository.automations.insert({id:Xa("story_automation"),storyId:t.storyId,actionId:t.actionId,schedule:pp.parse(t.schedule),enabled:t.enabled,policy:mp.parse(t.policy),scheduleAnchorAt:n,createdAt:n,updatedAt:n}))}async update(e,t){const n=Ru.parse(t),i=await this.repository.automations.get(e);if(!i)return;const s=this.now().toISOString(),o=void 0!==n.schedule||!0===n.enabled&&!i.enabled,r=await this.repository.automations.update(e,{...n,...o?{scheduleAnchorAt:s}:{},updatedAt:s});return r?Ap(r):void 0}referencingActions(e,t){return this.repository.automations.referencingActions(e,[...t])}async hasActiveRuns(e){return(await this.repository.runs.list(e)).some(e=>!fp.has(e.status))}activeRunsForStory(e){return this.repository.runs.activeForStory(e).then(e=>e.map(_p))}async delete(e){if(!await this.repository.automations.get(e))return!1;if(await this.hasActiveRuns(e))throw wp("STORY_AUTOMATION_RUN_ACTIVE","Automation has a non-terminal run.",409);return this.repository.automations.delete(e)}async deleteForStory(e){if((await this.activeRunsForStory(e)).length)throw wp("STORY_AUTOMATION_RUN_ACTIVE","Story has a non-terminal Automation run.",409);await this.repository.automations.deleteForStory(e)}async createRun(e){const t=up.parse(e.executionInput);return this.repository.transaction(async n=>{const i=await n.runs.byExecutionKey(e.executionKey);if(i)return _p(i);const s=await n.runs.insert({...e,executionInput:t,id:Xa("story_automation_run"),status:"queued",targetInstanceId:t.targetInstanceId,queuedAt:this.now().toISOString()});return await n.runs.trimTerminal(e.automationId,100),_p(s)})}async transition(e,t,n={}){return this.repository.transaction(async i=>{const s=await i.runs.get(e);if(!s)throw wp("STORY_AUTOMATION_RUN_NOT_FOUND","Automation run was not found.",404);const o=_p(s);if(o.status===t)return o;if(!yp[o.status].includes(t))throw wp("STORY_AUTOMATION_RUN_TRANSITION_INVALID",`Cannot transition run from ${o.status} to ${t}.`,409);const r=this.now().toISOString(),a=await i.runs.update(e,{...n,status:t,..."dispatching"===t?{startedAt:r}:{},...fp.has(t)?{completedAt:r}:{}});return await i.runs.trimTerminal(o.automationId,100),_p(a)})}async runsFor(e){return(await this.repository.runs.list(e)).map(Ep)}async run(e){const t=await this.repository.runs.get(e);return t?Ep(t):void 0}async runByExecutionKey(e){const t=await this.repository.runs.byExecutionKey(e);return t?_p(t):void 0}async pendingRuns(){return(await this.repository.runs.pending()).map(_p)}}function Ap(e){return Ou.parse({id:e.id,storyId:e.storyId,actionId:e.actionId,schedule:pp.parse(e.schedule),enabled:e.enabled,policy:mp.parse(e.policy),createdAt:e.createdAt,updatedAt:e.updatedAt})}function _p(e){return gp.parse({...e,aiSessionId:e.aiSessionId||void 0,startedAt:e.startedAt||void 0,completedAt:e.completedAt||void 0,error:e.error?hp.parse(e.error):void 0,executionInput:up.parse(e.executionInput)})}function Ep(e){const{executionKey:t,requestFingerprint:n,executionInput:i,...s}=_p(e);return Du.parse(s)}function wp(e,t,n){return Object.assign(new Error(t),{code:e,statusCode:n})}class Tp{state;stories;automations;scheduler;repository;constructor(e,t,n,i,s){this.state=e,this.stories=t,this.automations=n,this.scheduler=i,this.repository=s}async init(){t.mkdirSync(this.state.paths.storyTrashDir,{recursive:!0,mode:448});for(const e of await this.repository.deletionIntents.list()){const i=await this.repository.stories.get(e.storyId),s=this.storyRoot(e.storyId),o=e.trashName?n.join(this.state.paths.storyTrashDir,e.trashName):void 0;i?o&&t.existsSync(o)&&!t.existsSync(s)&&t.renameSync(o,s):o&&t.rmSync(o,{recursive:!0,force:!0}),await this.repository.deletionIntents.delete(e.storyId)}}async update(e,t){const n=qu.parse(t),i=await this.stories.update(e,n);return await this.scheduler.refresh(),i}async createAutomationWithAction(e,t){const n=Cu.parse(t),i=await this.stories.automationContext(e);if(!i)throw bp("STORY_NOT_FOUND","Story was not found.",404);if(i.archivedAt)throw bp("STORY_ARCHIVED","Archived Story cannot create an Automation.",409);if(i.actions.some(e=>e.id===n.action.id))throw bp("STORY_ACTION_ID_CONFLICT","Story Action id already exists.",409);const s={storyId:e,actionId:n.action.id,...n.automation};await this.scheduler.validateCreate(s,{...i,actions:[...i.actions,n.action]});let o="";await this.repository.transaction(async t=>{await t.actions.replace(e,[...i.actions,n.action].map((t,n)=>({storyId:e,id:t.id,title:t.title,promptTemplate:t.promptTemplate,targetInstanceId:t.targetInstanceId,sessionPreset:t.sessionPreset,displayOrder:n}))),await t.stories.update(e,{updatedAt:(new Date).toISOString()}),o=(await this.automations.create(s)).id});const r=await this.stories.get(e);return r&&this.stories.notifyUpdated(r),this.scheduler.activateCreated(o)}async archive(e){const t=await this.stories.archive(e);return await this.scheduler.refresh(),t}async restore(e){const t=await this.stories.restore(e);return await this.scheduler.refresh(),t}async delete(e){return this.stories.coordinator.run(e,async()=>{const t=await this.stories.get(e);return!!t&&(await this.assertStoryCanBeDeleted(e),this.deleteCoordinated(t))})}async assertStoryCanBeDeleted(e){const t=this.state.listInstances().flatMap(t=>t.aiSessions.sessions.filter(t=>t.storyId===e).map(e=>({instanceId:t.id,aiSessionId:e.id})));if(t.length)throw bp("STORY_IN_USE","Story is still referenced by an AI Session.",409,{sessions:t});const n=await this.automations.activeRunsForStory(e);if(n.length)throw bp("STORY_AUTOMATION_RUN_ACTIVE","Story has a non-terminal Automation run.",409,{runIds:n.map(e=>e.id)})}async deleteCoordinated(e){const i=e.id;await this.scheduler.clearStory(i);const s=this.storyRoot(i),o=`${i}-${Date.now()}-${Math.random().toString(16).slice(2)}`,r=n.join(this.state.paths.storyTrashDir,o),a=(new Date).toISOString();await this.repository.deletionIntents.put({storyId:i,phase:"prepared",trashName:null,createdAt:a,updatedAt:a});try{let c=!1;return t.existsSync(s)&&(t.renameSync(s,r),this.fsyncDirectory(n.dirname(s)),this.fsyncDirectory(n.dirname(r)),c=!0),await this.repository.deletionIntents.put({storyId:i,phase:"files-staged",trashName:c?o:null,createdAt:a,updatedAt:(new Date).toISOString()}),await this.repository.transaction(async e=>{const t=await e.runs.activeForStory(i);if(t.length)throw bp("STORY_AUTOMATION_RUN_ACTIVE","Story has a non-terminal Automation run.",409,{runIds:t.map(e=>e.id)});await e.automations.deleteForStory(i),await e.stories.delete(i),await e.deletionIntents.put({storyId:i,phase:"database-committed",trashName:c?o:null,createdAt:a,updatedAt:(new Date).toISOString()})}),c&&t.rmSync(r,{recursive:!0,force:!0}),await this.repository.deletionIntents.put({storyId:i,phase:"cleanup",trashName:c?o:null,createdAt:a,updatedAt:(new Date).toISOString()}),await this.repository.deletionIntents.delete(i),this.stories.notifyDeleted(e),!0}catch(e){throw await this.repository.stories.get(i)&&(t.existsSync(r)&&!t.existsSync(s)&&t.renameSync(r,s),await this.repository.deletionIntents.delete(i)),e}}storyRoot(e){return n.join(this.state.paths.storyContentDir,ue.parse(e))}fsyncDirectory(e){if("win32"===process.platform)return;const n=t.openSync(e,"r");try{t.fsyncSync(n)}finally{t.closeSync(n)}}}function bp(e,t,n,i){return Object.assign(new Error(t),{code:e,statusCode:n,details:i})}class Sp{timers=new Map;running=new Map;queued=new Map;lastStartedAt=new Map;accepting=!0;adapter;maxQueuedPerJob;now;constructor(e,t=100,n=Date.now){this.adapter=e,this.maxQueuedPerJob=t,this.now=n}start(){this.accepting=!0}setTimer(e,t){const n=this.timers.get(e);n&&clearTimeout(n),this.timers.set(e,t)}clearTimer(e){const t=this.timers.get(e);t&&clearTimeout(t),this.timers.delete(e)}clearQueued(e,t="job-disabled"){const n=this.queued.get(e);if(n){for(const e of n)this.adapter.skipped(e.event,t);this.queued.delete(e)}}submit(e,t,n){if(!this.accepting)return this.adapter.skipped(t,"scheduler-stopped"),"skipped";const i=this.now(),s=this.lastStartedAt.get(e);if(n.cooldownMs&&void 0!==s&&i-s<n.cooldownMs)return this.adapter.skipped(t,"cooldown"),"skipped";if((this.running.get(e)??0)>=n.maxConcurrentRuns){if("skip"===n.whenBusy)return this.adapter.skipped(t,"busy"),"skipped";const i=this.queued.get(e)??[];return i.length>=this.maxQueuedPerJob?(this.adapter.skipped(t,"queue-full"),"skipped"):(i.push({event:t,policy:n}),this.queued.set(e,i),"queued")}return this.begin(e,t,n),"started"}stop(){this.accepting=!1;for(const e of this.timers.values())clearTimeout(e);this.timers.clear();for(const e of this.queued.values())for(const t of e)this.adapter.skipped(t.event,"scheduler-stopped");this.queued.clear()}begin(e,t,n){this.running.set(e,(this.running.get(e)??0)+1),this.lastStartedAt.set(e,this.now());const i=()=>{const t=(this.running.get(e)??1)-1;t>0?this.running.set(e,t):this.running.delete(e),this.drain(e)};this.adapter.execute(t).then(i,i)}drain(e){if(!this.accepting)return;const t=this.queued.get(e);if(!t?.length)return;const n=t[0];(this.running.get(e)??0)>=n.policy.maxConcurrentRuns||(t.shift(),t.length||this.queued.delete(e),this.begin(e,n.event,n.policy))}}function vp(e,t){return new Date(Date.UTC(e,t+1,0)).getUTCDate()}function Np(e,t,n,i,s,o){return S.CronExpressionParser.parse(`0 ${i} ${n} ${e} ${t} *`,{currentDate:o,strict:!0,tz:s}).next().toDate()}function Op(e,t,n){return`sch_${d.createHash("sha256").update(`${e}\0${t}\0${n}`).digest("hex").slice(0,32)}`}a.z.object({agent:be,cwd:mt,cwdFolderId:a.z.string().trim().min(1).max(120).optional(),gitSelection:ft.optional(),message:a.z.string().trim().min(1).max(32e3),permissionMode:nt.optional(),clientRequestId:a.z.string().trim().min(1).max(160),modelSelection:ht.optional(),reasoningEffort:gt.optional(),storyId:ue}).strict();const zp=a.z.object({disposition:a.z.enum(["created","already-created"]),aiSessionId:a.z.string().trim().min(1).max(120)}).strict();class Cp{runtime;nextRunAt=new Map;completion=new Map;registeredAutomationIds=new Set;backgroundMutations=new Set;state;stories;automations;fetchImpl;resolveInstanceWeb;publish;now;constructor(e,t,n,i,s,o,r=()=>new Date){this.state=e,this.stories=t,this.automations=n,this.fetchImpl=i,this.resolveInstanceWeb=s,this.publish=o,this.now=r,this.runtime=new Sp({execute:({runId:e})=>this.executeRun(e),skipped:({runId:e},t)=>this.trackMutation(this.skipRun(e,t))})}async start(){this.runtime.stop(),this.runtime.start(),this.nextRunAt.clear(),this.registeredAutomationIds.clear();for(const e of await this.automations.list())await this.register(e);for(const e of await this.automations.pendingRuns())await this.resume(e);await this.reconcileInstances()}async stop(){this.runtime.stop(),this.nextRunAt.clear(),await Promise.allSettled([...this.backgroundMutations])}async refresh(){for(const e of this.registeredAutomationIds)this.runtime.clearTimer(e);this.registeredAutomationIds.clear(),this.nextRunAt.clear();for(const e of await this.automations.list())e.enabled&&!await this.blockedReason(e)||this.runtime.clearQueued(e.id),await this.register(e)}async clearStory(e){for(const t of await this.automations.list(e))this.runtime.clearTimer(t.id),this.runtime.clearQueued(t.id),this.registeredAutomationIds.delete(t.id),this.nextRunAt.delete(t.id)}async status(e){const t=await this.requireAutomation(e),n=await this.automations.runsFor(e),i=n.filter(e=>!xp(e.status)),s=await this.blockedReason(t),o=n.find(e=>xp(e.status)),r=t.enabled?s?"blocked":i.length?"running":"failed"===o?.status?"error":"scheduled":"disabled";return Lu.parse({automation:t,effectiveStatus:r,blockedReason:s,nextRunAt:this.nextRunAt.get(e),currentRuns:i.slice(0,20),lastRun:o})}async list(e){return Promise.all((await this.automations.list(e)).map(e=>this.status(e.id)))}async create(e){const t=await this.validateInput(e),n=await this.automations.create(t);return await this.register(n),await this.publishStatus(n.id,"created"),this.status(n.id)}async validateCreate(e,t){const n=zu.parse(e);return await this.validateReferences({...n,id:"validation",createdAt:this.now().toISOString(),updatedAt:this.now().toISOString()},t),n}async activateCreated(e){const t=await this.requireAutomation(e);return await this.register(t),await this.publishStatus(e,"created"),this.status(e)}async update(e,t){const n={...await this.requireAutomation(e),...t};if(await this.validateReferences(n),await this.automations.update(e,t))return await this.refresh(),await this.publishStatus(e,"updated"),this.status(e)}setEnabled(e,t){return this.update(e,{enabled:t})}async delete(e){const t=await this.requireAutomation(e),n=await this.automations.delete(e);return n&&(this.runtime.clearTimer(e),this.nextRunAt.delete(e),this.publish?.(Fu,{storyId:t.storyId,automationId:e,change:"deleted"},{nodeId:this.state.node.id})),n}async manualRun(e,t){const n=await this.requireAutomation(e),i=this.now().toISOString(),s=Op(e,"manual",t.clientRequestId),o=await this.automations.runByExecutionKey(s);if(o)return this.automations.run(o.id);const r=await this.prepareRun(n,"manual",i,s);return this.runtime.submit(e,{runId:r.id},n.policy),this.automations.run(r.id)}async runs(e){return await this.requireAutomation(e),this.automations.runsFor(e)}async reconcileInstances(e){for(const t of(await this.automations.pendingRuns()).filter(e=>"running"===e.status&&e.aiSessionId)){if(e&&t.targetInstanceId!==e)continue;const n=this.state.listInstances().find(e=>e.id===t.targetInstanceId),i=n?.aiSessions.sessions.find(e=>e.id===t.aiSessionId);if(!i&&e!==t.targetInstanceId)continue;if(i&&"idle"!==i.status&&"failed"!==i.status)continue;const s="failed"===i?.status?"failed":"completed",o="failed"===s?{code:"AI_SESSION_FAILED",message:"The automated AI Session failed."}:void 0,r=await this.automations.transition(t.id,s,o?{error:o}:{});this.resolveCompletion(t.id),await this.publishRun(r),await this.publishStatus(t.automationId,"status")}}async register(e){if(!e.enabled||await this.blockedReason(e))return;const t=await this.automations.stored(e.id);if(!t)return;const n=function(e){const t=e.schedule;if("interval"===t.scheduleKind)return{type:"interval",intervalMs:t.intervalMs};if("daily"===t.scheduleKind)return{type:"daily",timeOfDay:t.timeOfDay,timezone:t.timezone};if("weekly"===t.scheduleKind)return{type:"weekly",weekdays:t.weekdays,timeOfDay:t.timeOfDay,timezone:t.timezone};if("monthly"===t.scheduleKind)return{type:"monthly",dayOfMonth:t.dayOfMonth,timeOfDay:t.timeOfDay,timezone:t.timezone};throw new Error(`Unsupported Story automation schedule kind: ${t.schedule.scheduleKind}`)}(e),i=function(e,t,n=t){if("interval"===e.type){const i=Math.max(0,t.getTime()-n.getTime()),s=Math.floor(i/e.intervalMs)+1;return new Date(n.getTime()+s*e.intervalMs)}const[i,s]=e.timeOfDay.split(":").map(Number);if("monthly"===e.type&&e.dayOfMonth<0)return function(e,t,n,i,s){const o=function(e,t){const n=new Intl.DateTimeFormat("en-US",{timeZone:t,year:"numeric",month:"2-digit",day:"2-digit"}).formatToParts(e),i=e=>Number(n.find(t=>t.type===e)?.value);return{year:i("year"),month:i("month")-1,day:i("day")}}(s,i),r=[];for(let a=0;a<12;a+=1){const c=new Date(Date.UTC(o.year,o.month+a,1)),d=c.getUTCFullYear(),l=c.getUTCMonth(),u=vp(d,l)+e+1;r.push(Np(u,l+1,t,n,i,s))}return r.sort((e,t)=>e.getTime()-t.getTime()),r[0]}(e.dayOfMonth,i,s,e.timezone,t);const o="weekly"===e.type?[...new Set(e.weekdays)].sort((e,t)=>e-t).join(","):"*",r="monthly"===e.type?String(e.dayOfMonth):"*";return S.CronExpressionParser.parse(`0 ${s} ${i} ${r} * ${o}`,{currentDate:t,strict:!0,tz:e.timezone}).next().toDate()}(n,this.now(),new Date(t.scheduleAnchorAt));this.nextRunAt.set(e.id,i.toISOString()),this.registeredAutomationIds.add(e.id);const s=setTimeout(()=>{this.trackMutation(this.handleTimer(e.id,i))},Math.max(1,i.getTime()-this.now().getTime()));s.unref?.(),this.runtime.setTimer(e.id,s)}async handleTimer(e,t){const n=await this.automations.get(e);if(!n?.enabled||await this.blockedReason(n))return;const i=t.toISOString();try{const e=await this.prepareRun(n,"schedule",i,Op(n.id,"schedule",i));this.runtime.submit(n.id,{runId:e.id},n.policy)}catch{await this.publishStatus(n.id,"status")}await this.register(n),await this.publishStatus(n.id,"status")}async prepareRun(e,t,n,i){const s=await this.executionInput(e),o=Rp(s,i);return this.automations.createRun({automationId:e.id,eventType:t,scheduledFor:n,executionKey:i,requestFingerprint:(r=o,d.createHash("sha256").update(JSON.stringify(r)).digest("hex")),executionInput:s});var r}async resume(e){const t=await this.automations.get(e.automationId);t&&(e.status,this.runtime.submit(t.id,{runId:e.id},t.policy))}async executeRun(e){let t=(await this.automations.pendingRuns()).find(t=>t.id===e);if(t){if("queued"===t.status&&(t=await this.automations.transition(t.id,"dispatching")),"dispatching"===t.status)try{const e=this.state.requireInstance(t.targetInstanceId);if(!e.registrationToken)throw Pp("STORY_AUTOMATION_INSTANCE_CREDENTIAL_MISSING","Target instance has no registration credential.",503);const n=`${await this.resolveInstanceWeb(e)}/api/internal/node-agent/story-automation/ai-sessions`;let i;try{i=await this.fetchImpl(n,{method:"POST",headers:{"content-type":"application/json",authorization:`Bearer ${e.registrationToken}`},body:JSON.stringify(Rp(t.executionInput,t.executionKey))})}catch{return void await this.publishStatus(t.automationId,"status")}const s=await i.json().catch(()=>({}));if(!i.ok)throw Pp(s.error?.code||"STORY_AUTOMATION_DISPATCH_FAILED",s.error?.message||`Target instance returned HTTP ${i.status}.`,i.status);const o=zp.parse(s.data);t=await this.automations.transition(t.id,"running",{aiSessionId:o.aiSessionId}),await this.publishRun(t)}catch(e){const n=await this.automations.transition(t.id,"failed",{error:kp(e)});return await this.publishRun(n),void await this.publishStatus(t.automationId,"status")}await this.completionFor(t.id).promise}}async skipRun(e,t){const n=await this.automations.run(e);if(!n||"queued"!==n.status)return;const i=await this.automations.transition(e,"skipped",{error:{code:`STORY_AUTOMATION_${t.replaceAll("-","_").toUpperCase()}`,message:Dp(t)}});await this.publishRun(i)}async executionInput(e,t){const n=t?.id===e.storyId?t:await this.stories.automationContext(e.storyId);if(!n)throw Pp("STORY_NOT_FOUND","Story was not found.",404);if(n.archivedAt)throw Pp("STORY_ARCHIVED","Archived Story cannot run Automation.",409);const i=n.actions.find(t=>t.id===e.actionId);if(!i)throw Pp("STORY_ACTION_NOT_FOUND","Story Action was not found.",404);if(!i.targetInstanceId)throw Pp("STORY_ACTION_TARGET_REQUIRED","Automated Story Action requires a target instance.",409);const s=this.state.requireInstance(i.targetInstanceId);return{storyId:n.id,actionId:i.id,targetInstanceId:s.id,prompt:i.promptTemplate,sessionPreset:i.sessionPreset,cwd:this.runtimeCwd(s,i.sessionPreset?.cwdFolderId)}}runtimeCwd(e,t){if(!t)return e.runtime.workspacePath||e.workspace.path||"/workspace";const i=this.state.localFolders.get(t);if(!i)throw Pp("NODE_LOCAL_FOLDER_NOT_FOUND","Story Action working folder was not found.",404);if("local"===this.state.requireRuntime(e.runtimeId).type)return n.resolve(i.path);if("local-folder"!==e.source.type)throw Pp("AI_SESSION_CWD_UNAVAILABLE","Working folder is unavailable for this instance source.",409);const s=n.relative(n.resolve(e.source.path),n.resolve(i.path));if(".."===s||s.startsWith(`..${n.sep}`)||n.isAbsolute(s))throw Pp("AI_SESSION_CWD_OUTSIDE_WORKSPACE","Working folder is outside the instance workspace.",409);const o=e.runtime.workspacePath||e.workspace.path||"/workspace";return s?n.posix.join(o,...s.split(n.sep)):o}async validateInput(e){const t=zu.parse(e);return await this.validateReferences({...t,id:"validation",createdAt:this.now().toISOString(),updatedAt:this.now().toISOString()}),t}async validateReferences(e,t){await this.executionInput(e,t)}async blockedReason(e){try{return void await this.executionInput(e)}catch(e){const t=kp(e);return["STORY_ARCHIVED","STORY_DELETING","STORY_NOT_FOUND","STORY_ACTION_NOT_FOUND","STORY_ACTION_TARGET_REQUIRED","NODE_INSTANCE_NOT_FOUND","STORY_NODE_MISMATCH"].includes(t.code)?t:void 0}}async requireAutomation(e){const t=await this.automations.get(e);if(!t)throw Pp("STORY_AUTOMATION_NOT_FOUND","Story Automation was not found.",404);return t}completionFor(e){const t=this.completion.get(e);if(t)return t;let n;const i={promise:new Promise(e=>{n=e}),resolve:n};return this.completion.set(e,i),i}resolveCompletion(e){this.completion.get(e)?.resolve(),this.completion.delete(e)}trackMutation(e){return this.backgroundMutations.add(e),e.finally(()=>this.backgroundMutations.delete(e)),e}async publishRun(e){const t=await this.automations.run(e.id),n=await this.automations.get(e.automationId);t&&n&&this.publish?.(Fu,{storyId:n.storyId,automationId:n.id,change:"run",run:t},{nodeId:this.state.node.id,instanceId:e.targetInstanceId})}async publishStatus(e,t){const n=await this.status(e);this.publish?.(Fu,{storyId:n.automation.storyId,automationId:e,change:t,status:n},{nodeId:this.state.node.id})}}function Rp(e,t){const n=e.sessionPreset;return{agent:n?.agent||"codex",cwd:{type:"runtime-path",path:e.cwd},cwdFolderId:n?.cwdFolderId,gitSelection:n?.gitSelection,message:e.prompt,permissionMode:n?.permissionMode||"ask",clientRequestId:t,modelSelection:n?.modelSelection,reasoningEffort:n?.reasoningEffort,storyId:e.storyId}}function xp(e){return"completed"===e||"failed"===e||"skipped"===e}function kp(e){const t=e&&"object"==typeof e?e:void 0;return{code:"string"==typeof t?.code?t.code:"STORY_AUTOMATION_FAILED",message:"string"==typeof t?.message?t.message:String(e)}}function Dp(e){return{cooldown:"Skipped by cooldown policy.",busy:"Skipped because the concurrency limit was reached.","queue-full":"Skipped because the queue is full.","scheduler-stopped":"Skipped because the scheduler stopped.","job-disabled":"Skipped because the Automation was disabled or blocked."}[e]}function Pp(e,t,n){return Object.assign(new Error(t),{code:e,statusCode:n})}class Lp{closed=new Set;pending=new Set;reconciliation;state;stories;fetchImpl;resolveInstanceWeb;warn;constructor(e,t,n,i,s){this.state=e,this.stories=t,this.fetchImpl=n,this.resolveInstanceWeb=i,this.warn=s}reconcile(){if(this.reconciliation)return this.reconciliation;const e=this.reconcileOnce().finally(()=>{this.reconciliation===e&&(this.reconciliation=void 0)});return this.reconciliation=e,e}async reconcileOnce(){const e=new Map,t=new Set,n=[];for(const n of this.state.listInstances()){if(!n.registrationToken)continue;let i;try{i=await this.fetchImpl(`${await this.resolveInstanceWeb(n)}/api/internal/node-agent/ai-sessions/idle-retention`,{headers:{authorization:`Bearer ${n.registrationToken}`}})}catch(e){this.warn({instanceId:n.id,error:e instanceof Error?e.message:String(e)},"could not inspect Story idle sessions");continue}if(!i.ok)continue;const s=await i.json().catch(()=>({}));if(Array.isArray(s.data))for(const i of s.data){if(!i||"object"!=typeof i)continue;const s=i;if("string"!=typeof s.sessionId||"string"!=typeof s.storyId||"idle"!==s.status)continue;if(void 0===jp(s))continue;if(!await this.stories.exists(s.storyId))continue;const o=`${n.id}:${s.sessionId}`;if(t.add(o),this.closed.has(o))continue;const r=e.get(s.storyId)||[];r.push({instance:n,sessionId:s.sessionId,storyId:s.storyId,status:"idle",completedAt:s.completedAt,updatedAt:s.updatedAt}),e.set(s.storyId,r)}}for(const[t,i]of e){const e=(await this.stories.retentionSettings(t)).maxIdleAiSessions;for(;i.length>e;){i.sort((e,t)=>jp(e)-jp(t)||`${e.instance.id}:${e.sessionId}`.localeCompare(`${t.instance.id}:${t.sessionId}`));const e=i.shift(),s=`${e.instance.id}:${e.sessionId}`;this.pending.has(s)||(this.pending.add(s),n.push(this.close(e,s).catch(n=>{this.warn({storyId:t,instanceId:e.instance.id,sessionId:e.sessionId,error:n instanceof Error?n.message:String(n)},"Story idle Session retention close failed"),setTimeout(()=>{this.reconcile()},5e3).unref?.()})))}}await Promise.all(n);for(const e of this.closed)t.has(e)||this.closed.delete(e)}async close(e,t){try{if(!await this.isUnchangedCandidate(e))return;const n=await this.fetchImpl(`${await this.resolveInstanceWeb(e.instance)}/api/internal/node-agent/ai-sessions/${encodeURIComponent(e.sessionId)}/close`,{method:"POST",headers:{"content-type":"application/json",authorization:`Bearer ${e.instance.registrationToken}`},body:JSON.stringify({clientRequestId:d.randomUUID()})});if(204===n.status)return;if(!n.ok)throw new Error(`HTTP ${n.status}`);this.closed.add(t)}finally{this.pending.delete(t)}}async isUnchangedCandidate(e){const t=await this.fetchImpl(`${await this.resolveInstanceWeb(e.instance)}/api/internal/node-agent/ai-sessions/idle-retention`,{headers:{authorization:`Bearer ${e.instance.registrationToken}`}});if(!t.ok)throw new Error(`HTTP ${t.status}`);const n=await t.json().catch(()=>({}));if(!Array.isArray(n.data))return!1;const i=n.data.find(t=>{if(!t||"object"!=typeof t)return!1;const n=t;return n.sessionId===e.sessionId&&n.storyId===e.storyId&&"idle"===n.status});return void 0!==i&&jp(i)===jp(e)}}class Mp{closed=new Set;pending=new Set;reconciliation;state;fetchImpl;resolveInstanceWeb;warn;constructor(e,t,n,i){this.state=e,this.fetchImpl=t,this.resolveInstanceWeb=n,this.warn=i}reconcile(){if(this.reconciliation)return this.reconciliation;const e=this.reconcileOnce().finally(()=>{this.reconciliation===e&&(this.reconciliation=void 0)});return this.reconciliation=e,e}async reconcileOnce(){const e=new Map,t=new Set,n=[];for(const n of this.state.listInstances()){if(!n.registrationToken)continue;let i;try{i=await this.fetchImpl(`${await this.resolveInstanceWeb(n)}/api/internal/node-agent/ai-sessions/instance-idle-retention`,{headers:{authorization:`Bearer ${n.registrationToken}`}})}catch(e){this.warn({instanceId:n.id,error:e instanceof Error?e.message:String(e)},"could not inspect instance idle sessions");continue}if(!i.ok)continue;const s=await i.json().catch(()=>({}));if(Array.isArray(s.data))for(const i of s.data){if(!i||"object"!=typeof i)continue;const s=i;if("string"!=typeof s.sessionId||"idle"!==s.status)continue;if(void 0===jp(s))continue;const o=`${n.id}:${s.sessionId}`;if(t.add(o),this.closed.has(o))continue;const r=e.get(n.id)||[];r.push({instance:n,sessionId:s.sessionId,status:"idle",completedAt:s.completedAt,updatedAt:s.updatedAt}),e.set(n.id,r)}}for(const[t,i]of e)for(;i.length>100;){i.sort((e,t)=>jp(e)-jp(t)||`${e.instance.id}:${e.sessionId}`.localeCompare(`${t.instance.id}:${t.sessionId}`));const e=i.shift(),s=`${e.instance.id}:${e.sessionId}`;this.pending.has(s)||(this.pending.add(s),n.push(this.close(e,s).catch(n=>{this.warn({instanceId:t,sessionId:e.sessionId,error:n instanceof Error?n.message:String(n)},"Instance idle Session retention close failed"),setTimeout(()=>{this.reconcile()},5e3).unref?.()})))}await Promise.all(n);for(const e of this.closed)t.has(e)||this.closed.delete(e)}async close(e,t){try{const n=await this.fetchImpl(`${await this.resolveInstanceWeb(e.instance)}/api/internal/node-agent/ai-sessions/${encodeURIComponent(e.sessionId)}/close`,{method:"POST",headers:{"content-type":"application/json",authorization:`Bearer ${e.instance.registrationToken}`},body:JSON.stringify({clientRequestId:d.randomUUID()})});if(204===n.status)return;if(!n.ok)throw new Error(`HTTP ${n.status}`);this.closed.add(t)}finally{this.pending.delete(t)}}}function jp(e){return Up(e.completedAt)??Up(e.updatedAt)}function Up(e){const t=e?Date.parse(e):Number.NEGATIVE_INFINITY;return Number.isFinite(t)?t:void 0}const Fp=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(),$p=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:pi.optional(),labels:a.z.record(a.z.string(),a.z.string()).default({})}).strict(),Hp=a.z.object({name:a.z.string().trim().max(160)}).strict(),qp=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(),Vp=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:pi.optional(),environmentSource:mi.optional(),projectId:a.z.string().trim().min(1).max(120).optional(),image:Ms.optional(),source:as,sourceSnapshot:a.z.record(a.z.string(),a.z.unknown()).default({}),config:a.z.object({autoImportAgentConfigs:a.z.boolean().optional(),codexConfigEnabled:a.z.boolean().optional(),codexHomeMode:a.z.enum(["default","taskhandoff"]).optional(),defaultCodexPermissionMode:nt.optional(),codexSettings:Hn.optional(),aiSessionHistoryLimit:a.z.number().int().min(1).max(500).optional(),aiSessionAttachmentRetentionDays:a.z.number().int().min(0).max(365).optional(),aiSessionMaxFileAttachmentBytes:a.z.number().int().positive().max(ge).optional()}).strict().optional(),modelSelection:po.shape.modelSelection,gitWorkspaceProvisioning:sd.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."})}),Bp=a.z.object({name:a.z.string().trim().min(1).max(160).optional(),config:a.z.object({autoImportAgentConfigs:a.z.boolean().optional(),codexConfigEnabled:a.z.boolean().optional(),codexHomeMode:a.z.enum(["default","taskhandoff"]).optional(),defaultCodexPermissionMode:nt.optional(),codexSettings:Hn.optional(),aiSessionHistoryLimit:a.z.number().int().min(1).max(500).optional(),aiSessionAttachmentRetentionDays:a.z.number().int().min(0).max(365).optional(),aiSessionMaxFileAttachmentBytes:a.z.number().int().positive().max(ge).optional()}).strict().optional(),modelSelection:po.shape.modelSelection.optional()}).strict(),Kp=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(),Gp=Kp.omit({id:!0}).partial().strict();function Wp(e){const t=e.authorization;return"string"==typeof t&&t.startsWith("Bearer ")?t.slice(7).trim():void 0}class Xp{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 Yp=a.z.object({gitWorkspaceProvisioning:sd.optional()}).strict().default({});class Jp{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=ae();return this.state.controlledInstances.put(po.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 o=this.provisionGeneration(e,n,t).finally(()=>{this.inFlight.get(i)===o&&this.inFlight.delete(i)});return this.inFlight.set(i,o),o}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,o=0,r=!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||(r=!0,o=n.sequence,this.publishTerminalOutput(e,t,n))},this.abortController.signal);if(await a,s)throw s.error;if(this.stopped)return;r&&this.publishFinished(e,t,o+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(po.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:ae()},updatedAt:ae()}));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;r&&this.publishFinished(e,t,o+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(po.parse({...n,status:"failed",health:"failed",imageProvisioning:{...n.imageProvisioning,phase:"failed",error:i,updatedAt:ae()},updatedAt:ae()})),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(po.parse({...s,status:"starting"===s.status?"starting":"provisioning",imageProvisioning:{...s.imageProvisioning,phase:n,error:void 0,updatedAt:ae()},updatedAt:ae()})),this.options.sync())};await(this.options.runInstanceOperation?.(e,s)??s())}eventBase(e,t){return{instanceId:e.id,generation:t,requestedReference:e.imageProvisioning.requestedReference,observedAt:ae()}}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(Us,{...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(Fs,{...this.eventBase(e,t),sequence:1e3*n,outcome:i},e.id)}}const Qp=a.z.object({name:a.z.string().trim().min(1).max(160)}).strict();function Zp(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 em{templateOperations=new Xp;store;docker;requireInstanceValue;requireRuntimeValue;runInstanceOperationValue;privateSecretValues;isImageReferencedValue;constructor(e,t,n,i,s,o,r=()=>!1){this.store=e,this.docker=t,this.requireInstanceValue=n,this.requireRuntimeValue=i,this.runInstanceOperationValue=s,this.privateSecretValues=o,this.isImageReferencedValue=r}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=Qp.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 o=ae(),r=Xa("envtpl"),a=`task-handoff/environment-template:${r.toLowerCase().replace(/[^a-z0-9_.-]/g,"-")}`;return this.store.put(zi.parse({id:r,name:n.name,sourceInstanceId:i.id,nodeId:i.nodeId,internalTag:a,status:"creating",createdAt:o,updatedAt:o})),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.privateSecretValues(n);await this.docker.inspectContainerConfigSecurity(n.runtime.containerName,s),e=await this.docker.commitEnvironmentTemplate(n.runtime.containerName,n.runtime.containerId,a),t=!0;const o=await this.docker.inspectEnvironmentTemplateImage(a);return await this.docker.inspectImageConfigSecurity(a,s),this.store.put(zi.parse({...this.require(r),...o,status:"ready",error:void 0,updatedAt:ae()}))}catch(n){return t&&(await this.docker.untagEnvironmentTemplate(a,e).catch(()=>!1),e&&await this.docker.garbageCollectEnvironmentTemplateImage(e).catch(()=>!1)),this.store.put(zi.parse({...this.require(r),status:"failed",error:Zp(n,"ENVIRONMENT_TEMPLATE_CREATE_FAILED","commit"),updatedAt:ae()}))}})}async delete(e){return this.runTemplateOperation(e,async()=>{const t=this.require(e);this.store.put(zi.parse({...t,status:"deleting",error:void 0,updatedAt:ae()}));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(zi.parse({...t,status:"failed",error:Zp(e,"ENVIRONMENT_TEMPLATE_DELETE_FAILED","delete"),updatedAt:ae()})),e}})}async releaseUnusedImage(e){return!this.store.list().some(t=>t.imageId===e)&&!this.isImageReferencedValue(e)&&this.docker.garbageCollectEnvironmentTemplateImage(e)}}const tm=new Set(["content-encoding","content-length","transfer-encoding"]),nm=67108864;function im(e){return Object.fromEntries([...e.entries()].filter(([e])=>!tm.has(e.toLowerCase())))}function sm(e){return e.bodyBase64?Buffer.from(e.bodyBase64,"base64"):e.body}function om(){const e=Number(process.env.TASK_HANDOFF_INSTANCE_PROXY_MAX_RESPONSE_BYTES);return Number.isSafeInteger(e)&&e>0?e:67108864}const rm="x-task-handoff-trace-id";function am(e){return e.startsWith("/")?e:`/${e}`}function cm(e,t){return e.code(502).send({error:{code:"INSTANCE_PROXY_RESPONSE_TOO_LARGE",message:`Instance response exceeds ${t} bytes.`}})}async function dm(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 lm(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 um(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 lm(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 lm(e,"endpoint must be an origin-only http://127.0.0.1:<port> URL");return i.origin}const pm=a.z.object({version:a.z.literal(1),externalListener:to}).strict();function mm(e){return"all-ipv4"===e?"0.0.0.0":"127.0.0.1"}function hm(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 gm(e){const t=mm(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 fm{app;state;settings;sockets=new Set;config;source;status="error";error;onActiveListener;validateUpdate;synchronizeUpdate;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.validateUpdate=e.validateUpdate,this.synchronizeUpdate=e.synchronizeUpdate,this.app.server.on("connection",e=>{this.sockets.add(e),e.once("close",()=>this.sockets.delete(e))})}current(){return no.parse({...this.config,host:mm(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:mm(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 ${mm(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=io.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&&!this.synchronizeUpdate)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});await(this.validateUpdate?.(t))}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 ${mm(t.bindScope)}:${t.port}: ${e instanceof Error?e.message:String(e)}`),{statusCode:409,code:"NODE_AGENT_LISTENER_BIND_FAILED"})}this.state.setListenerPort(t.port);try{await(this.synchronizeUpdate?.(t))}catch(e){throw await this.stop(),await this.restore(n),await Promise.resolve(this.synchronizeUpdate?.(n.config)).catch(e=>{this.app.log.error({error:e instanceof Error?e.message:String(e)},"node agent listener instance endpoint rollback failed")}),Object.assign(new Error(`Failed to switch controlled instances to node agent port ${t.port}: ${e instanceof Error?e.message:String(e)}`),{statusCode:409,code:"NODE_AGENT_LISTENER_INSTANCE_SYNC_FAILED"})}try{this.settings.put({version:1,externalListener:t})}catch(e){throw await this.stop(),await this.restore(n),await Promise.resolve(this.synchronizeUpdate?.(n.config)).catch(e=>{this.app.log.error({error:e instanceof Error?e.message:String(e)},"node agent listener persistence rollback failed")}),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;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:mm(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 ym="TASK_HANDOFF_NODE_AGENT_V1",Im="/api/node-tunnel";function Am(e=""){return d.createHash("sha256").update(e).digest("hex")}function _m(e,t){return d.createHmac("sha256",e).update(function(e){return[ym,e.keyId,e.method.toUpperCase(),e.pathWithQuery,e.timestamp,e.nonce,e.bodySha256].join("\n")}(t)).digest("hex")}function Em(e){const t=e.timestamp||(new Date).toISOString(),n=e.nonce||d.randomBytes(18).toString("base64url"),i=Am(e.body||""),s=_m(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 wm{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 o=Date.parse(t.timestamp);if(!Number.isFinite(o)||Math.abs(this.nowMs()-o)>6e4)throw Object.assign(new Error("Node agent HMAC timestamp is outside the allowed window."),{statusCode:401,code:"NODE_AGENT_HMAC_TIMESTAMP_INVALID"});if(!t.nonce)throw Object.assign(new Error("Node agent HMAC nonce is missing."),{statusCode:401,code:"NODE_AGENT_HMAC_NONCE_MISSING"});this.pruneNonces();const r=`${t.nodeId}:${t.keyId}:${t.nonce}`;if(this.usedNonces.has(r))throw Object.assign(new Error("Node agent HMAC nonce was already used."),{statusCode:401,code:"NODE_AGENT_HMAC_NONCE_REPLAY"});const a=Am(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,_m(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(r,o+6e4+1),t.keyId}pruneNonces(){const e=this.nowMs();for(const[t,n]of this.usedNonces)n<=e&&this.usedNonces.delete(t)}}function Tm(e,t){console.warn(JSON.stringify({message:e,...t}))}class bm{repository;logger;constructor(e,t,n={}){const i=t&&"readIdentity"in t?t:void 0,s=i?n:t||n;this.repository=i||md(hl(e)).access,this.logger=s.logger||Tm}read(){const e=this.repository.readIdentity();return e?$d(e,this.logger):void 0}init(){}write(e){const t=$d({...e,updatedAt:ae()},this.logger);return this.repository.writeIdentity(t)}}class Sm{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 vm{store;repository;pairingInvites=new Sm;controlPlaneConnectionOperations=new Map;constructor(e,t){this.repository=t||md(hl(e)).access,this.store=new bm(e,this.repository),this.store.init(),this.recoverControlPlaneConnectionOperations()}async runControlPlaneConnectionOperation(e,t){const n=e.replace(/\/$/,""),i=this.controlPlaneConnectionOperations.get(n)||Promise.resolve();let s;const o=new Promise(e=>{s=e});this.controlPlaneConnectionOperations.set(n,o),await i;try{return await t()}finally{s(),this.controlPlaneConnectionOperations.get(n)===o&&this.controlPlaneConnectionOperations.delete(n)}}resolveNodeId(e){if(e?.trim())return this.writeNodeId(e.trim()),e.trim();const t=this.store.read();if(t?.nodeId)return t.nodeId;const n=Xa("node");return this.writeNodeId(n),n}createPairingInvite(e){const t=ae(),n=new Date(Date.now()+(e.expiresInMs||6e5)).toISOString(),i=Ya(),s={tokenHash:Am(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=Am(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=ae(),o={id:e.controlPlaneId||Xa("cp"),keyId:Xa("key"),...e.controlPlaneName||i.controlPlaneName?{name:e.controlPlaneName||i.controlPlaneName}:{},secret:Ya(),pairedAt:s,updatedAt:s};return this.store.write({...t,controlPlanePairings:[...(t.controlPlanePairings||[]).filter(e=>e.id!==o.id),o]}),o}stageControlPlaneConnection(e){const{pairing:t,connection:n}=this.createControlPlaneConnection(e),i=this.store.read()||this.newIdentity(),s=n.url.replace(/\/$/,""),o=(i.controlPlaneConnections||[]).filter(e=>e.id===n.id||e.url.replace(/\/$/,"")===s),r={operationId:Xa("connection_operation"),pairing:t,connection:n,replacedConnections:o},a=ae();return this.repository.transaction(()=>{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]}),this.repository.putOperation({id:r.operationId,kind:"create-connection",phase:"prepared",requested:r,pairingKeyId:t.keyId,connectionId:n.id,replacedConnections:o,createdAt:a,updatedAt:a})}),r}markControlPlaneConnectionRemoteAccepted(e){const t=this.repository.listOperations().find(t=>t.id===e.operationId);if(!t)throw Object.assign(new Error("Control-plane connection operation was not found."),{code:"NODE_AGENT_CONNECTION_OPERATION_NOT_FOUND",statusCode:409});this.repository.putOperation({...t,phase:"remote-accepted",updatedAt:ae()})}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}:{}},o=new Set((n.controlPlaneConnections||[]).map(e=>e.pairingKeyId)),r=new Set(e.replacedConnections.map(e=>e.pairingKeyId));return this.repository.transaction(()=>{this.store.write({...n,controlPlanePairings:[...(n.controlPlanePairings||[]).filter(e=>e.keyId!==i.keyId&&(!r.has(e.keyId)||o.has(e.keyId))),i],controlPlaneConnections:[...(n.controlPlaneConnections||[]).filter(e=>e.id!==s.id),s]});const t=this.repository.listOperations().find(t=>t.id===e.operationId);t&&this.repository.putOperation({...t,phase:"committed",updatedAt:ae()}),this.repository.deleteOperation(e.operationId)}),{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.repository.transaction(()=>{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]}),this.repository.deleteOperation(e.operationId)})}recoverControlPlaneConnectionOperations(){for(const e of this.repository.listOperations(["prepared","remote-accepted"])){const t=e.requested;t?.pairing?.keyId&&t?.connection?.id?"remote-accepted"===e.phase?(this.repository.putOperation({...e,phase:"committed",updatedAt:ae()}),this.repository.deleteOperation(e.id)):this.rollbackControlPlaneConnection(t):this.repository.putOperation({...e,phase:"failed",error:{code:"NODE_AGENT_CONNECTION_OPERATION_INVALID"},updatedAt:ae()})}}createControlPlaneConnection(e){const t=ae(),n={id:Xa("cp"),keyId:Xa("key"),...e.name?{name:e.name}:{},secret:Ya(),pairedAt:t,updatedAt:t};return{pairing:n,connection:{id:Xa("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=ae();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),o=n&&s.find(e=>e.keyId===n.pairingKeyId);if(o)return{keyId:o.keyId,secret:o.secret}}const o=[...s].sort((e,t)=>t.updatedAt.localeCompare(e.updatedAt))[0];return o?{keyId:o.keyId,secret:o.secret}:void 0}newIdentity(){return{nodeId:this.resolveNodeId(),createdAt:ae(),updatedAt:ae(),controlPlanePairings:[],controlPlaneConnections:[]}}writeNodeId(e){const t=this.store.read();this.store.write({...t||{createdAt:ae()},nodeId:e,updatedAt:ae(),controlPlanePairings:t?.controlPlanePairings||[],controlPlaneConnections:t?.controlPlaneConnections||[]})}}const Nm=a.z.string().trim().min(1).max(160);const Om=es.strict();function zm(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 Cm{preflights=new Map;options;applying=!1;constructor(e){this.options=e}async check(e){const t=Ji.parse(e),n=zm(this.options.listInstances()),i=await Sl(this.options.runCommand,this.options.moduleDir),s=this.options.currentRuntimeVersion(),o=this.options.managedUpdateSupport?.(i)||{supported:!0};if(!o.supported)return Qi.parse({source:"npm",channel:t.channel,currentVersion:i.currentVersion||s,availableVersion:i.currentVersion||s||"unavailable",impact:n,updateAvailable:!1,supported:!1,reason:o.reason||"Managed updates are unavailable on this node.",checkedAt:(new Date).toISOString()});const r="@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(Tl(),["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 o=JSON.parse(s.stdout);if("string"!=typeof o)throw new Error(`npm did not resolve ${t}@${i} to one version.`);return o}(e.runCommand,t,e.channel);if(!n)return function(e){return Qi.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:ae()})}({channel:e.channel,currentVersion:e.currentVersion,impact:e.impact});const i=wl(e.currentVersion,n)||(e.relatedCurrentVersions||[]).some(e=>wl(e,n)),s=i?await async function(e,t,n){const i=await e(Tl(),["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 Qi.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:ae()})}({channel:t.channel,currentVersion:i.currentVersion||s,runCommand:this.options.runCommand,packageName:i.packageName,relatedCurrentVersions:r,impact:n});if(!a.updateAvailable)return a;const c={...a,runtimeArtifacts:await this.options.resolveRuntimeArtifacts(a.availableVersion),preflightToken:Ya()};return this.preflights.set(c.preflightToken,{result:c,expiresAt:Date.now()+6e5}),c}async apply(e){const i=Om.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 o=this.options.jobs.create(this.options.nodeId,e),{worker:r,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")],o=s.find(i),r=n.resolve(e,"..","..","..","..","scripts","node-update-worker.cts");return o?{worker:o,packaged:!0,expectedWorker:s[0]}:i(r)?{worker:r,packaged:!1,expectedWorker:s[0]}:{worker:void 0,packaged:!1,expectedWorker:s[0]}}(this.options.moduleDir);if(!r)throw this.options.jobs.patch(o.id,{status:"failed",rollout:{...o.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-${o.id}`,"--collect","--property=Type=exec",...a?[r]:[process.execPath,r],"--job-file",this.options.jobs.records.filePath(o.id),"--target-version",o.toVersion,"--npm-command",Tl(),"--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(o.id,{status:"failed",rollout:{...o.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(o)}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 Sl(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(zm(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 Rm=new Set(["provisioning","starting","registering","registered","running"]);function xm(e){return Rm.has(e.status)&&!Ma(e)}function km(e){return po.parse({...e,health:"unknown",connectionStatus:"offline",agentStatus:"offline",targetStatus:"unknown",uiAccessStatus:"unknown",target:{...e.target,status:"unknown"},updatedAt:ae()})}class Dm{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)&&!Ma(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),o=this.options.crashStableWindowMs??3e4,r=s&&i-s.lastExitAt<o?s.attempt+1:1;this.unexpectedExitRetries.set(e,{attempt:r,lastExitAt:i});const a=this.options.retryBaseDelayMs??1e3,c=1===r?0:Math.min(this.options.retryMaxDelayMs??3e4,a*2**Math.min(r-2,10)),d=t instanceof Error?t.message:String(t);this.restoreErrors.set(e,{message:d,attempt:r,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(Rm.has(t.status)||"failed"===t.status)&&(!e||e.nextAttemptAt<=(this.options.nowMs?.()??Date.now()))}return"docker"===n.type&&xm(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),o=(s?.attempt??0)+1,r=this.options.retryBaseDelayMs??1e3,a=Math.min(this.options.retryMaxDelayMs??3e4,r*2**Math.min(o-1,10)),c=(this.options.nowMs?.()??Date.now())+a;this.restoreErrors.set(n.id,{message:i,attempt:o,nextAttemptAt:c}),s?.message===i&&s.attempt===o||this.options.warn({instanceId:n.id,action:"restore",runtimeId:n.runtimeId,error:i,attempt:o,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(Rm.has(e.status)||"failed"===e.status)&&(!t||t.nextAttemptAt<=(this.options.nowMs?.()??Date.now()))}return"docker"===t.type&&xm(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)&&!Ma(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(km(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:Rm.has(s.status)||"failed"===s.status?Math.min(e,i.nextAttemptAt):e},Number.POSITIVE_INFINITY),i=Math.min(this.options.intervalMs??1e4,Math.max(0,n-e));this.timer=setTimeout(()=>{this.timer=void 0,this.runAndContinue()},i),this.timer.unref?.()}requestCycle(e=0){if(this.started&&!this.stopped){if(this.activeCycle)return this.cycleRequested=!0,void(this.cycleRequestDelayMs=void 0===this.cycleRequestDelayMs?e:Math.min(this.cycleRequestDelayMs,e));this.timer&&clearTimeout(this.timer),this.timer=setTimeout(()=>{this.timer=void 0,this.runAndContinue()},e),this.timer.unref?.()}}}const Pm=new Set(["DELETE","GET","HEAD","PATCH","POST","PUT","OPTIONS"]);function Lm(e){return"string"==typeof e&&Pm.has(e.toUpperCase())?e.toUpperCase():"GET"}function Mm(e,t){const n=new URL(t.tunnelUrl);n.searchParams.set("nodeId",t.nodeId);const i=t.secret?Em({nodeId:t.nodeId,keyId:t.keyId,secret:t.secret,method:"GET",pathWithQuery:`${n.pathname}${n.search}`}):{},s=new p(n,{headers:i}),o=new Map,r=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 o=e.startsWith("/")?e:`/${e}`;return{...s,...t.secret&&t.keyId?Em({nodeId:t.nodeId,keyId:t.keyId,secret:t.secret,method:n,pathWithQuery:`/api/node-agent${o}`,body:i}):t.token?{authorization:`Bearer ${t.token}`}:{}}},u=e=>t.secret?Em({nodeId:t.nodeId,keyId:t.keyId,secret:t.secret,method:"GET",pathWithQuery:`${e.pathname}${e.search}`}):{},m=(e,t,n)=>{const i=o.get(e);o.delete(e),i?.upstream&&L(i.upstream,t,n),i?.tunnel&&L(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 o.keys())m(e,1001,"Reverse tunnel disconnected.");for(const[e,t]of r)r.delete(e),t.controller.abort(),L(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:"",o="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=Lm(a.method);let m;try{m=ni(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 r.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}`)})(o),{method:d,headers:l(o,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{r.delete(i)}}),I.on("close",()=>{f.abort(),r.delete(i)}),void I.on("error",()=>f.abort())}if("control-plane.http.cancel"===g.type){const e="string"==typeof g.streamId?g.streamId:"",t=r.get(e);if(!t)return;return r.delete(e),t.controller.abort(),void L(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 r=l(t,"GET",void 0),a=i?.length?new p(d(t),i,{headers:r}):new p(d(t),{headers:r}),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)});o.set(e,{upstream:a,tunnel:m,close:(e=1e3,t="")=>{L(a,e,t),L(m,e,t)}}),a.on("open",()=>{s.send(JSON.stringify({type:"node-agent.websocket.open",streamId:e,protocol:a.protocol}))}),j(m,a,{pendingFrameLimit:256,upstreamOpenTimeoutMs:1e4,onClientClose:()=>{o.delete(e)},onClientError:t=>{o.delete(e),s.send(JSON.stringify({type:"node-agent.websocket.error",streamId:e,message:t instanceof Error?t.message:String(t)}))},onUpstreamClose:(t,n)=>{o.delete(e);const i=P(t),r=D(n);s.send(JSON.stringify({type:"node-agent.websocket.close",streamId:e,...void 0===i?{}:{code:i},...r?{reason:r}:{}}))},onUpstreamError:t=>{o.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:{},o="string"==typeof g.route&&g.route.startsWith("/")?g.route:"/health",r=i.headers&&"object"==typeof i.headers?i.headers:{},c=Lm(i.method);let d;try{d=ni(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${o}`,headers:l(o,c,d,r),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,g.aiSessionHierarchy)})(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 jm(e,t){return Number.isFinite(e)&&Number(e)>0?Number(e):t}function Um(e){if(!e.length)return;const t=[...e].sort((e,t)=>e-t);return t[Math.ceil(.95*t.length)-1]}function Fm(e){return e.unref?.(),e}class $m{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=jm(e.connectTimeoutMs,1e4),this.handshakeTimeoutMs=jm(e.handshakeTimeoutMs,1e4),this.heartbeatIntervalMs=jm(e.heartbeatIntervalMs,25e3),this.heartbeatTimeoutMs=jm(e.heartbeatTimeoutMs,15e3),this.heartbeatMissThreshold=Math.max(1,Math.floor(jm(e.heartbeatMissThreshold,2))),this.stableThresholdMs=jm(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=Fm(this.setTimeoutFn(()=>this.timeout("connect"),this.connectTimeoutMs))}opened(){this.stopped||(this.clearTimer("connectTimer"),this.setPhase("handshaking"),this.handshakeTimer=Fm(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=Fm(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:Um(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=Fm(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 Hm(e){const t=new URL(Im,e);return t.protocol="https:"===t.protocol?"wss:":"ws:",t.toString()}const qm=new Set(["linux","darwin","win32","freebsd","openbsd","aix","sunos"]);function Vm(e){return qm.has(e)?e:"unknown"}function Bm(e){return!0===e.managedArtifacts}class Km{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:Vm(this.platform),...t?{serverVersion:t}:{}}}}}catch(t){return{status:"offline",capabilities:{...e.capabilities,daemon:{status:"offline",hostPlatform:Vm(this.platform),error:t instanceof Error?t.message:String(t)}}}}}}class Gm{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(Bm)}async stopAll(){await(this.local.stopAll?.())}}const Wm="task-handoff.local-process-nonce",Xm=1e3,Ym=1e4,Jm=2e3;function Qm(e,t){try{e?.(t)}catch{}}function Zm(e){return e.runtime.port?`http://127.0.0.1:${e.runtime.port}`:void 0}async function eh(e,t){try{const n=await fetch(`${e}/api/internal/node-agent/process-identity`,{headers:{authorization:`Bearer ${t}`},signal:AbortSignal.timeout(Xm)});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 th(e,t){if($.processStartIdentity(e)!==t)return!1;try{process.kill(e,"SIGTERM")}catch{return!0}const n=Date.now()+Ym;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()+Jm;for(;Date.now()<i;){try{process.kill(e,0)}catch{return!0}await new Promise(e=>setTimeout(e,50))}return!1}function nh(e,t){return Object.assign(new Error(t),{statusCode:503,code:"LOCAL_INSTANCE_STOP_UNCONFIRMED",instanceId:e.id})}async function ih(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 sh=ih;function oh(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 rh(e,t=1e4,n=2e3,i){if(await oh(e,t))return;Qm(i,{stage:"graceful-timeout",pid:e.pid,timeoutMs:t});let s=!1;if(null===e.exitCode&&null===e.signalCode&&(e.kill("SIGKILL"),s=!0,Qm(i,{stage:"force-signal-sent",pid:e.pid,signal:"SIGKILL"})),!await oh(e,n))throw Qm(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&&Qm(i,{stage:"force-exit-confirmed",pid:e.pid,signal:"SIGKILL"})}class ah{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},o=e=>{try{this.onUnexpectedExitError?.(e,s)}catch{}};try{Promise.resolve(this.onUnexpectedExit?.(s)).catch(o)}catch(e){o(e)}}}),t.unref()}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"),Qm(n,{stage:"graceful-signal-sent",pid:t.pid,signal:"SIGTERM"})),this.children.delete(e.id),void await rh(t,Ym,Jm,n)}const i=await async function(e){const t=Zm(e),n=e.runtime.labels?.[Wm];if(!t||!n||!e.registrationToken)return;const i=await eh(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(Xm)})).ok?i:void 0}catch{return}}(e);if(i){const t=Zm(e),n=Date.now()+Ym;for(;t&&Date.now()<n;){if(!await eh(t,e.registrationToken))return;await new Promise(e=>setTimeout(e,50))}const s=t?await eh(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 th(s.pid,s.startIdentity))return;throw nh(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 G(e)}(this.lockPath),o=await async function(e){const t=Zm(e);if(t)try{const[n,i]=await Promise.all([fetch(`${t}/api/instance/status`,{signal:AbortSignal.timeout(Xm)}),fetch(`${t}/api/diagnostics`,{signal:AbortSignal.timeout(Xm)})]);if(!n.ok||!i.ok)return;const s=await n.json(),o=await i.json(),r=o.data?.runtime?.pid;if(s.data?.id!==e.id||"controlled"!==s.data.controlMode||"number"!=typeof r||!Number.isInteger(r)||r<=0)return;const a=$.processStartIdentity(r);return a?{pid:r,startIdentity:a}:void 0}catch{return}}(e);if(o){if(await th(o.pid,o.startIdentity))return;throw nh(e,`Legacy controlled instance ${e.id} did not exit after termination.`)}if(s?.instanceId===e.id&&Y(s))throw nh(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 o=Date.now()+s;for(;Date.now()<o;){if(null!==n.exitCode||null!==n.signalCode)return!1;const s=await eh(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"),Qm(e,{stage:"graceful-signal-sent",pid:t.pid,signal:"SIGTERM"}))}this.children.clear(),await Promise.all(e.map(e=>rh(e,Ym,Jm,this.lifecycleReporters.get(e))))}}async function ch(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 dh{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,o,r){this.runCommand=e,this.paths=t,this.nodeAgentUrl=n,this.commandOverride=i,this.lockPath=s,this.processSupervisor=new ah(s,o,r)}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,o=!!s&&await ih(s),r="allocate"===process.env.TASK_HANDOFF_LOCAL_INSTANCE_PORT_CONFLICT;if(s&&!o&&!r)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&&o?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 sh(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"),m=(e.instance.config?.codexConfigEnabled??1)&&"taskhandoff"===(e.instance.config?.codexHomeMode??"taskhandoff")?n.join(u,"configs","codex"):void 0;t.mkdirSync(p,{recursive:!0,mode:448}),m&&t.mkdirSync(m,{recursive:!0,mode:448}),t.chmodSync(u,448),t.chmodSync(p,448),m&&t.chmodSync(m,448);const[h,...g]=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),f=[...g,"--host","127.0.0.1","--port",String(a)],y=d.randomUUID(),I=n.join(p,"controlled-instance.out.log"),A=n.join(p,"controlled-instance.err.log");Ea(I),Ea(A);const _=t.mkdtempSync(function(e,t=process.platform,i=c.tmpdir()){const s="darwin"===t?"/private/tmp":i,o=d.createHash("sha256").update(e).digest("hex").slice(0,12);return n.join(s,`th-git-${o}-`)}(e.instance.id));t.chmodSync(_,448);const E=t.openSync(I,"a",384),w=t.openSync(A,"a",384),T=l.spawn(h,f,{cwd:i,detached:!1,stdio:["ignore",E,w],env:{...process.env,TASK_HANDOFF_CONTROL_MODE:"controlled",TASK_HANDOFF_RUNTIME_KIND:"local",TASK_HANDOFF_CONTROLLED_INSTANCE_VERSION:Ll(),...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:y,TASK_HANDOFF_WORKSPACE:i,TASK_HANDOFF_WORKSPACE_MODE:"local-bind",TASK_HANDOFF_DATA_DIR:u,TASK_HANDOFF_INSTANCE_PRIVATE_CONFIG_PATH:e.privateConfigPath||"",TASK_HANDOFF_LOG_DIR:p,TASK_HANDOFF_APP_SESSION_PERSIST:"1",TASK_HANDOFF_CODEX_APP_SERVER:process.env.TASK_HANDOFF_CODEX_APP_SERVER||"1",TASK_HANDOFF_WEB_PORT:String(a),TASK_HANDOFF_WEB_HOST:"127.0.0.1",TASK_HANDOFF_GIT_CREDENTIAL_SOCKET:n.join(_,"broker.sock"),...e.modelEnv||{},CODEX_HOME:m}});t.closeSync(E),t.closeSync(w);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)})}(T)}catch(e){t.rmSync(_,{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=${h} cwd=${i} error=${s}\n`)}catch{}throw Object.assign(new Error(`Controlled instance process could not start with command ${h} in ${i}: ${s}`),{statusCode:500,code:"LOCAL_INSTANCE_PROCESS_SPAWN_FAILED"})}const b=n.join(p,"controlled-instance.lifecycle.log");this.processSupervisor.track(e.instance.id,T,e=>{t.appendFileSync(b,`[${(new Date).toISOString()}] shutdown stage=${e.stage} pid=${e.pid??""} signal=${e.signal??""} timeoutMs=${e.timeoutMs??""}\n`)}),T.on("error",e=>{try{t.appendFileSync(b,`[${(new Date).toISOString()}] process error pid=${T.pid??""} error=${e.message}\n`)}catch{}}),T.once("exit",(e,n)=>{t.rmSync(_,{recursive:!0,force:!0});try{t.appendFileSync(b,`[${(new Date).toISOString()}] exited pid=${T.pid??""} code=${e??""} signal=${n??""}\n`)}catch{}});const S=`http://127.0.0.1:${a}`,v=T.pid?$.processStartIdentity(T.pid):void 0;if(!(T.pid&&e.instance.registrationToken&&await this.processSupervisor.waitUntilHealthy(S,{instanceId:e.instance.id,pid:T.pid,processNonce:y,startIdentity:v},T,e.instance.registrationToken)&&this.processSupervisor.markReady(e.instance.id,T)))throw this.processSupervisor.release(e.instance.id,T),null===T.exitCode&&null===T.signalCode&&T.kill("SIGTERM"),await rh(T),Object.assign(new Error(`Controlled instance process did not become ready for instance ${e.instance.id} on ${S}.`),{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:S,api:`${S}/api`},workspace:{mode:"local-bind",status:"pending",path:i},runtime:{kind:"local",workspacePath:i,pid:T.pid,port:a,labels:{...e.instance.runtime.labels,"task-handoff.runtime-kind":"local",[Wm]:y}}}}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),wi.parse({instanceId:e.instance.id,containerDeleted:!0,completed:!0,deletedVolumes:[],retainedVolumes:[],volumeResults:[]})}async check(e){const[t,n]=await Promise.all([ch(this.runCommand,"codex"),ch(this.runCommand,"claude")]);return{status:"online",capabilities:Wl({...e.capabilities,apps:{terminal:!0,codex:t,claude:n}})}}async stopAll(){await this.processSupervisor.stopAll()}}const lh=["codex","claude"],uh=5e3,ph=$.processStartIdentity(process.pid);function mh(e){const t=process.env[e]?.trim();return t||void 0}function hh(e){const t=e.authorization;return"string"==typeof t&&t.startsWith("Bearer ")?t.slice(7).trim():void 0}function gh(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 fh(e){return!e.ip&&!e.socket.remoteAddress&&!e.socket.remoteFamily}async function yh(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 Ih(e,t,n,i){const s=new AbortController,o=setTimeout(()=>s.abort(),i);try{return await e(t,{...n,signal:s.signal})}finally{clearTimeout(o)}}async function Ah(e,t,n,i=async e=>um(e)){if(!t.registrationToken)return"unavailable";const s=Wn.parse({nodeAgentUrl:n}),o=await Ih(e,`${await i(t)}/api/internal/node-agent-connection`,{method:"PUT",headers:{"content-type":"application/json",authorization:`Bearer ${t.registrationToken}`},body:JSON.stringify(s)},5e3);if(404===o.status)return"unsupported";if(!o.ok)throw Object.assign(new Error(`Controlled instance rejected the node-agent connection update (HTTP ${o.status}).`),{code:"NODE_AGENT_CONNECTION_UPDATE_FAILED",statusCode:o.status});return"applied"}async function _h(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 o=await s(t),r=Number(process.env.TASK_HANDOFF_CONFIG_AUTO_IMPORT_TIMEOUT_MS||uh);for(const s of lh)try{const a=await Ih(e,`${o}/api/config-sync/import/${encodeURIComponent(s)}`,{method:"POST"},Number.isFinite(r)&&r>0?r:uh);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 Eh(e,t,n,i,s=async e=>um(e)){const o=t.requireInstance(n),r=t.resolvedAssignedModelEnvironment(n),a=t.modelRegistry.privateCatalog(n);if(t.instancePrivateConfigs.materialize(o.id,o.registrationToken,r,a,o.config.codexSettings),"reachable"!==o.targetStatus)return!1;let c;try{c=await Ih(e,`${await s(o)}/api/internal/model-environment`,{method:"PUT",headers:{"content-type":"application/json",authorization:`Bearer ${o.registrationToken}`},body:JSON.stringify(r)},uh)}catch(e){return i?.({instanceId:n,targetWeb:o.target.web,error:e instanceof Error?e.message:String(e)},"node instance model environment live sync deferred"),!1}if(!c.ok)return i?.({instanceId:n,targetWeb:o.target.web,statusCode:c.status},"node instance model environment live sync deferred"),!1;if(!Xn(o.capabilities).features.privateModelCatalog)return!0;try{const t=await Ih(e,`${await s(o)}/api/internal/model-catalog`,{method:"PUT",headers:{"content-type":"application/json",authorization:`Bearer ${o.registrationToken}`},body:JSON.stringify(a)},uh);t.ok||404===t.status||i?.({instanceId:n,statusCode:t.status},"node instance model catalog live sync deferred")}catch(e){i?.({instanceId:n,error:e instanceof Error?e.message:String(e)},"node instance model catalog live sync deferred")}return!0}async function wh(e,t,n,i,s,o,r="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:r,runtimeId:c.runtimeId,imageId:c.imageSelection?.imageId,imagePhase:c.imageProvisioning.phase},"node instance start queued until image provisioning completes"),e.controlledInstances.put(po.parse({...c,status:"starting",updatedAt:ae()}));s.diagnostic({instanceId:i,action:"start",reason:r,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=po.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:ae()}),m=u.target?.web?await yh(n,p,o):"unknown";"docker"===e.requireRuntime(d.runtimeId).type&&"reachable"===m&&Ah(n,p,e.containerUrl,o).then(t=>{s.diagnostic({instanceId:i,action:"node-agent-connection.sync",reason:r,syncStatus:t,nodeAgentUrl:e.containerUrl},"node instance connection endpoint synchronized")}).catch(e=>{s.warn({instanceId:i,action:"node-agent-connection.sync",reason:r,error:e instanceof Error?e.message:String(e)},"node instance connection endpoint sync deferred")});const h=e.applyInstanceLifecycle(i,{type:"runtime-lifecycle-completed",baseline:d,observation:{...u,target:u.target?{...u.target,status:m}:void 0,workspace:u.workspace?{error:void 0,...u.workspace}:void 0,targetStatus:m,uiAccessStatus:m}});return s.diagnostic({instanceId:i,action:"start",reason:r,status:h.status,connectionStatus:h.connectionStatus,targetStatus:h.targetStatus,targetWeb:h.target.web,containerName:h.runtime.containerName},"node instance start completed"),h}async function Th(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=Aa(e.dataDir),m=await async function(e){return hl(e)}(u);try{const f=md(m),y=e.remoteSecret||process.env.TASK_HANDOFF_NODE_AGENT_REMOTE_SECRET,I=e.remoteKeyId||process.env.TASK_HANDOFF_NODE_AGENT_REMOTE_KEY_ID,A=new vm(u,f.access),_=A.resolveNodeId(e.nodeId||process.env.TASK_HANDOFF_NODE_ID),E=e.connectionMode||("local-ipc"===process.env.TASK_HANDOFF_NODE_AGENT_CONNECTION_MODE?"local-ipc":"local-loopback"),w=e.ipcPath||process.env.TASK_HANDOFF_NODE_AGENT_IPC_PATH||Ta(u.dataDir),T="local-ipc"===E?`ipc://${encodeURIComponent(w)}`:d,b=e.platform||process.platform,S=e.arch||process.arch,v=new Yl(u,_,d,l,c,b,f);v.node.connectionMode=E,v.node.controlEndpoint=T,v.node.endpoint=T,v.init();const N=new dp(u,_,f);await N.init();const z=new Ip(f);await z.init();const C=e.dockerCommandRunner||zo,R=new Ro(C,e.dockerTerminalCommandRunner),k=new Ho(C,{publishHost:"127.0.0.1",imageService:R});let D;const P=new Gm(new Km(k,C,b,S),new dh(e.dockerCommandRunner||zo,u,()=>v.localNodeAgentUrl,function(){const e=process.env.TASK_HANDOFF_LOCAL_CONTROLLED_COMMAND_ARGV?.trim();if(!e){const e=process.env.TASK_HANDOFF_LOCAL_CONTROLLED_COMMAND?.trim();return e?e.split(/\s+/):void 0}let t;try{t=JSON.parse(e)}catch{throw Object.assign(new Error("TASK_HANDOFF_LOCAL_CONTROLLED_COMMAND_ARGV must be valid JSON."),{code:"LOCAL_CONTROLLED_COMMAND_INVALID"})}if(!Array.isArray(t)||!t.length||t.some(e=>"string"!=typeof e||!e))throw Object.assign(new Error("TASK_HANDOFF_LOCAL_CONTROLLED_COMMAND_ARGV must be a non-empty string array."),{code:"LOCAL_CONTROLLED_COMMAND_INVALID"});return t}(),e.localControlledInstanceLockPath||process.env.TASK_HANDOFF_LOCAL_CONTROLLED_INSTANCE_LOCK_PATH,e=>D.handleUnexpectedLocalExit(e.instanceId,new Error(`Local controlled instance exited unexpectedly (pid=${e.pid??"unknown"}, code=${e.code??"none"}, signal=${e.signal??"none"}).`)),(e,t)=>te.log.error({error:e,instanceId:t.instanceId,pid:t.pid},"local controlled instance exit recovery failed"))),L=async e=>um(e,await P.forRuntime(v.requireRuntime(e.runtimeId)).resolveInstanceWeb(v.context(e))),M=e.updateCommandRunner||e.dockerCommandRunner||zo,U=e.fetchImpl||fetch,F=new Lp(v,N,U,L,(e,t)=>te.log.warn(e,t)),$=new Mp(v,U,L,(e,t)=>te.log.warn(e,t)),H=new Map,q=new Map,V=e=>{if("endpoint-unreachable"!==e.targetStatus||"online"!==e.connectionStatus||"online"!==e.agentStatus||!e.target.web||q.has(e.id))return;const t=e.processIncarnationId,n=(async()=>{if("reachable"!==await yh(U,e,L))return;const n=v.requireInstance(e.id);n.processIncarnationId===t&&"online"===n.connectionStatus&&"online"===n.agentStatus&&(v.controlledInstances.put(po.parse({...n,target:{...n.target,status:"reachable"},targetStatus:"reachable",uiAccessStatus:"reachable",updatedAt:ae()})),le.syncNow())})().catch(t=>{te.log.debug({instanceId:e.id,error:t},"node instance endpoint reconciliation probe failed")}).finally(()=>{q.delete(e.id)});q.set(e.id,n)},B=async e=>{const t=v.requireInstance(e);if(!Xn(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(H.get(e)===s)return!0;let o;try{o=await Ih(U,`${await L(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}:{}})},uh)}catch(t){return Ae.warn({instanceId:e,error:t instanceof Error?t.message:String(t)},"node instance AI session persistence settings live sync deferred"),!1}return o.ok?(H.set(e,s),!0):(Ae.warn({instanceId:e,statusCode:o.status},"node instance AI session persistence settings live sync deferred"),!1)},K=async e=>{const t=v.requireInstance(e);if(v.instancePrivateConfigs.materialize(t.id,t.registrationToken,v.resolvedAssignedModelEnvironment(e),v.modelRegistry.privateCatalog(e),t.config.codexSettings),!t.config.codexSettings)return!0;if(!Xn(t.capabilities).features.codexManagedSettings||"reachable"!==t.targetStatus||!t.registrationToken)return!1;try{const n=await Ih(U,`${await L(t)}/api/internal/codex-settings`,{method:"PUT",headers:{"content-type":"application/json",authorization:`Bearer ${t.registrationToken}`},body:JSON.stringify(t.config.codexSettings||{})},uh);return!!n.ok||(Ae.warn({instanceId:e,statusCode:n.status},"node instance Codex settings live sync deferred"),!1)}catch(t){return Ae.warn({instanceId:e,error:t instanceof Error?t.message:String(t)},"node instance Codex settings live sync deferred"),!1}},G=new xa({cacheDir:n.join(u.dataDir,"runtime-artifacts"),fetchImpl:U}),W=e.resolveRuntimeArtifactRelease||((e,t,n)=>ka(e,t,n,U)),X=async(t,n,i)=>{const s=await n.artifactTarget(i);if(e.resolveRuntimeArtifact)return e.resolveRuntimeArtifact(t,s.platform,s.arch);const o=await W(t,s.platform,s.arch);if(o.identity.launcherAbi>s.launcherAbi)throw Object.assign(new Error(`Runtime requires launcher ABI ${o.identity.launcherAbi}, but ${s.platform}-${s.arch} provides ABI ${s.launcherAbi}.`),{code:"INSTANCE_BASE_RUNTIME_INCOMPATIBLE",retryable:!1});return G.resolve(o.identity,o.source)},Y=e=>P.forRuntime(v.requireRuntime(e.runtimeId)),J=e=>{const t=Y(e);return Bm(t)?t:void 0},Q=e=>{const t=J(e);if(t)return t;throw Object.assign(new Error(`Runtime for instance ${e.id} does not use managed artifacts.`),{code:"INSTANCE_RUNTIME_ARTIFACT_UNMANAGED",retryable:!1})},Z=e=>Boolean(J(e)),ee=(e,t)=>{const n=v.context(e);return X(t,Q(e),n)},te=o({logger:e.logger??!0}),ne=new wa(u,{logger:(e,t)=>te.log.warn(t,e)}),ie=()=>v.listInstances().map(e=>e.id),se=()=>{try{ne.run(ie())}catch(e){te.log.warn({error:e},"node-agent persistence maintenance failed")}},oe=()=>{try{ne.capNodeAgentLogs(),ne.capActiveInstanceLogs(ie())}catch(e){te.log.warn({error:e},"node-agent open log maintenance failed")}};se();const re=setInterval(()=>{se()},216e5);re.unref();const ce=setInterval(()=>{oe()},6e4);ce.unref();const de={requests:0,active:0,completed:0,aborted:0,limitRejected:0,responseBytes:0,totalDurationMs:0,maxResponseBytes:om()};te.decorate("nodeAgentState",v),te.decorate("nodeAgentIdentityService",A),await te.register(r,{options:x});const le=new Gr(v,i,{logger:te.log,safetyIntervalMs:Number(process.env.TASK_HANDOFF_EVENT_CONNECTION_SAFETY_INTERVAL_MS)||void 0}),pe=new Da(v.controlledInstances,Ll,{isInstalled:async(e,t)=>{const n=await ee(e,t),i=await Q(e).inspectRuntime(v.context(e),n.identity);if(i&&e.runtime.labels["task-handoff.bootstrap-backup"]){const t=v.requireInstance(e.id),n={...t.runtime.labels};delete n["task-handoff.bootstrap-backup"],v.controlledInstances.put(po.parse({...t,runtime:{...t.runtime,labels:n},updatedAt:ae()}))}return i},beginDrain:async e=>{try{const t=await async function(e,t,n=async e=>um(e)){const i=await n(t);if(t.registrationToken&&(await Ih(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 Ih(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 o=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]:[]}),r=await Promise.all(o.map(async t=>{try{const n=await Ih(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:o.length,failures:r.filter(e=>Boolean(e))}}(U,e,L);t.failures.length?te.log.warn({instanceId:e.id,requested:t.requested,failures:t.failures},"runtime convergence could not stop every app session"):te.log.info({instanceId:e.id,requested:t.requested},"runtime convergence requested app session drain")}catch(t){te.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=>um(e)){return!!t.registrationToken&&(await Ih(e,`${await n(t)}/api/internal/node-agent/resume`,{method:"POST",headers:{authorization:`Bearer ${t.registrationToken}`}},5e3)).ok}(U,e,L)&&te.log.info({instanceId:e.id},"runtime convergence released app session drain")}catch(t){te.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=Q(e);await n.installRuntime(v.context(e),await ee(e,t))},restart:async e=>{const t=Y(e),n=v.applyInstanceLifecycle(e.id,{type:"convergence-restart-requested"}),i=await t.restart(v.context(n)),s=po.parse({...n,...i,target:i.target?{...n.target,...i.target}:n.target,runtime:i.runtime?{...n.runtime,...i.runtime}:n.runtime,updatedAt:ae()}),o=await yh(U,s,L);v.applyInstanceLifecycle(e.id,{type:"runtime-lifecycle-completed",baseline:n,observation:{...i,target:i.target?{...i.target,status:o}:void 0,targetStatus:o,uiAccessStatus:o}})},onForcedDrain:e=>te.log.warn({instanceId:e.id},"runtime convergence drain deadline reached; restarting instance")},{drainTimeoutMs:Number(process.env.TASK_HANDOFF_RUNTIME_DRAIN_TIMEOUT_MS)||void 0,verificationTimeoutMs:Number(process.env.TASK_HANDOFF_RUNTIME_VERIFY_TIMEOUT_MS)||void 0,maxAttempts:Number(process.env.TASK_HANDOFF_RUNTIME_MAX_ATTEMPTS)||void 0});v.controlledInstances.setOnStored(e=>{le.publishInstanceLifecycle(e),v.updateJobs.reconcileRollouts(v.listInstances(),Ll())}),le.start(),te.decorate("nodeAgentEventForwarder",le);const me=new Cp(v,N,z,U,L,(e,t,n)=>le.publish(e,t,n)),he=new Tp(v,N,z,me,f);await he.init(),await me.start(),N.setOnChange((e,t)=>{le.publish("story.changed",{storyId:t.id,nodeId:t.ownerNodeId,change:e},{nodeId:t.ownerNodeId}),F.reconcile()});const ge=new na(C,()=>v.listInstances().filter(e=>"docker"===v.requireRuntime(e.runtimeId).type),e=>le.publish("instance.metrics.snapshot",e,{instanceId:e.instanceId}));ge.start(),te.decorate("nodeAgentRuntimeMetrics",ge);const fe=(g=process.env.TASK_HANDOFF_DIAGNOSTIC_LOGS,["1","true","yes","on"].includes(String(g||"").trim().toLowerCase())),ye=new wm(A,_,y,I),Ie=(e,t)=>{fe&&te.log.info(e,t)},Ae={diagnostic:Ie,warn:(e,t)=>te.log.warn(e,t)},_e=new Xp,Ee=new em(v.environmentTemplates,k,e=>v.requireInstance(e),e=>v.requireRuntime(e),(e,t)=>_e.run(e,t),e=>[e.registrationToken,...v.modelRegistry.privateSecretValues(e.id)].filter(e=>Boolean(e)),e=>v.listInstances().some(t=>t.environmentTemplateOrigin?.imageId===e)),we=(e,t,n)=>{const i=n&&"object"==typeof n&&!Array.isArray(n)?n.protocolVersion:void 0;if("string"!=typeof i||i===Pn)return n;const s=({field:n,action:s})=>te.log.warn({instanceId:e,report:t,protocolVersion:i,expectedProtocolVersion:Pn,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"}),{..._o(n,i),imageSelection:bi(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 _o(e,n)}(n,s)},Te=async(e,t,n=()=>!0,i)=>{try{if(!n())return v.requireInstance(e);let s=v.requireInstance(e);"failed"===s.runtimeVersion?.phase&&Z(s)&&(s=v.controlledInstances.put(po.parse({...s,ready:!1,runtimeVersion:jl(Pa(s)),updatedAt:ae()})));const o=v.requireRuntime(s.runtimeId);await wh(v,P,U,e,Ae,L,t,i);const r=v.requireInstance(e);if("docker"===o.type&&r.imageProvisioning&&"ready"!==r.imageProvisioning.phase)return le.syncNow(),r;if(!n())return v.requireInstance(e);D.markRestored(e);let a=v.requireInstance(e);if(Z(a)){try{a=await pe.schedule(e,{startRequested:!0})}catch(n){a=v.requireInstance(e),Ae.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&&Ae.warn({instanceId:e,action:"runtime.converge",reason:t,error:a.runtimeVersion.error},"node instance started with pending runtime convergence")}return"docker"===o.type&&"reachable"===a.targetStatus&&Ah(U,a,v.containerUrl,L).then(n=>{Ae.diagnostic({instanceId:e,action:"node-agent-connection.sync",reason:t,syncStatus:n,nodeAgentUrl:v.containerUrl},"node instance connection endpoint synchronized after runtime convergence")}).catch(n=>{Ae.warn({instanceId:e,action:"node-agent-connection.sync",reason:t,error:n instanceof Error?n.message:String(n)},"node instance connection endpoint sync after runtime convergence deferred")}),n()?(await _h(U,a,"start",Ae,L),le.syncNow(),a):v.requireInstance(e)}catch(n){throw v.applyInstanceLifecycle(e,{type:"start-failed",error:n}),le.syncNow(),Ae.warn({instanceId:e,action:"start",reason:t,error:n instanceof Error?n.message:String(n)},"node instance start failed"),n}},be=new Jp(v,R,{sync:()=>le.syncNow(),diagnostic:Ae.diagnostic,warn:Ae.warn,publish:(e,t,n)=>le.publish(e,t,{instanceId:n}),runInstanceOperation:(e,t)=>_e.run(e,t)}),Se=e=>{const t=_e.intent(e.id);be.provision(e,async()=>{await Te(e.id,"image-ready",()=>_e.isIntentCurrent(e.id,t),_e.signal(e.id,t)).catch(()=>{})})};D=new Dm({state:v,runtimeAdapters:P,convergence:pe,restoreInstance:e=>wh(v,P,U,e,Ae,L,"restore"),autoImport:e=>_h(U,e,"start",Ae,L),provisionImage:Se,stopImageProvisioning:()=>be.stop(),usesManagedArtifact:Z,warn:Ae.warn,error:(e,t)=>te.log.error(e,t),runInstanceOperation:(e,t)=>_e.run(e,t)});const ve=async e=>{const t=new Map;for(const e of P.managedAdapters()){const n=await e.artifactTarget();t.set(`${n.platform}-${n.arch}`,{adapter:e})}for(const e of v.listInstances()){const n=J(e);if(!n)continue;const i=v.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})=>X(e,t,n)))).sort((e,t)=>`${e.identity.platform}/${e.identity.arch}`.localeCompare(`${t.identity.platform}/${t.identity.arch}`))},Ne=new Cm({nodeId:_,jobs:v.updateJobs,runCommand:M,currentRuntimeVersion:Ll,listInstances:()=>v.listInstances(),resolveRuntimeArtifacts:async e=>(await ve(e)).map(e=>e.identity),moduleDir:("undefined"==typeof document?require("url").pathToFileURL(__filename).href:O&&"SCRIPT"===O.tagName.toUpperCase()&&O.src||new URL("cli.js",document.baseURI).href)?n.dirname(s.fileURLToPath("undefined"==typeof document?require("url").pathToFileURL(__filename).href:O&&"SCRIPT"===O.tagName.toUpperCase()&&O.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 te.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);(fe||i.statusCode>=500)&&(i.statusCode>=500?te.log.error.bind(te.log):te.log.warn.bind(te.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,...i.details?{details:i.details}:{},...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}:{}}})}),te.addHook("preHandler",async e=>{const t=ye.verify(e);if(t){if(A.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(fh(e)){if(i&&hh(e.headers)!==i){const e=new Error("Invalid node agent token.");throw Object.assign(e,{statusCode:401,code:"NODE_AGENT_UNAUTHORIZED"}),e}}else if("/api/node-agent/pairing/complete"!==e.url.split("?")[0]&&!function(e){const t=e.split("?")[0];return/^\/api\/node-agent\/instances\/[^/]+\/(register|heartbeat)$/.test(t)||/^\/api\/node-agent\/instances\/[^/]+\/git-credentials\//.test(t)||/^\/api\/node-agent\/instances\/[^/]+\/ai-sessions\/[^/]+\/story-content(?:\/|$)/.test(t)}(e.url)){if(ye.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 gh(e.ip)||gh(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&&hh(e.headers)!==i){const e=new Error("Invalid node agent token.");throw Object.assign(e,{statusCode:401,code:"NODE_AGENT_UNAUTHORIZED"}),e}}}),te.addHook("onClose",async()=>{N.stopAccepting(),f.stopAccepting();const e=Number(process.env.TASK_HANDOFF_STORY_DRAIN_DIAGNOSTIC_MS)||3e4,t=setTimeout(()=>{te.log.warn({pendingStoryIds:N.coordinator.pendingStoryIds()},"Story storage drain deadline reached; waiting for accepted operations and preserving recovery intents")},e);t.unref();try{await me.stop(),clearInterval(re),clearInterval(ce),ge.stop(),le.stop(),await D.stop(),await N.drain(),await f.close()}finally{clearTimeout(t)}}),te.decorate("nodeAgentRestoreManagedInstances",()=>D.restoreManagedInstances()),te.decorate("nodeAgentRecoverManagedInstances",()=>D.recoverManagedInstances()),te.decorate("nodeAgentStartRecoverySupervisor",()=>D.start()),te.get("/api/node-agent/health",async()=>{return{data:{ok:!0,role:"node-agent",process:{pid:process.pid,...ph?{startIdentity:ph}:{}},listener:{host:"127.0.0.1",port:v.currentListenerPort},nodeId:_,platform:Vm(b),arch:process.arch,protocolVersion:Pn,capabilities:{modelEndpointProbe:!0,managedModels:{multiEntityAssignment:!0,privateModelCatalog:!0},aiSessionHistoryLimit:!0,aiSessionAttachmentRetention:!0,aiSessionFileAttachmentLimit:!0,codexManagedSettings:!0,folderPlaces:!0,localFolderNameUpdate:!0,managedGitCredentials:{registry:!0,runtimeBroker:!0,workspaceProvisioning:{docker:!0,kubernetes:!1,local:!1}},stories:{enabled:!0,agentTools:!0,sessionRetention:!0,maxFileBytes:33554432,maxBatchPaths:20}},build:(e="node-agent",{component:e,packageName:"@task-handoff/node-agent",packageVersion:Ll(),protocolVersion:Pn,buildId:mh("TASK_HANDOFF_BUILD_ID"),builtAt:mh("TASK_HANDOFF_BUILT_AT"),gitCommit:mh("TASK_HANDOFF_GIT_COMMIT"),imageRef:mh("TASK_HANDOFF_IMAGE_REF"),imageDigest:mh("TASK_HANDOFF_IMAGE_DIGEST")}),instanceProxy:{...de},eventTransport:le.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)}))}(te,e=>{if(!fh(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(!te.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 te.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)}))}(te,Ne,v.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(Cd.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(Rd.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=Nm.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=Nm.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,o)=>{const r=xd.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(/\/$/,"")}(r.controlPlaneUrl);return n.runControlPlaneConnectionOperation(a,async()=>{const e=n.stageControlPlaneConnection({url:a,...r.controlPlaneName?{name:r.controlPlaneName}:{},enabled:!1!==r.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:r.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}n.markControlPlaneConnectionRemoteAccepted(e);const d=n.commitControlPlaneConnection(e,{name:r.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 o.code(201).send({data:{pairing:n.listControlPlanePairings().find(e=>e.keyId===d.pairing.keyId),connection:d.connection,tunnel:{status:u,...l?{error:l}:{}}}})})})}(te,{identity:A,nodeId:_,nodeName:()=>v.node.name,fetchImpl:U,reverseTunnels:()=>te.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(Kp.parse(e.body))})),e.patch("/api/node-agent/runtimes/:id",async e=>({data:t.updateRuntime(e.params.id,Gp.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(qp.parse(e.query))})),e.post("/api/node-agent/local-folders",async(e,n)=>n.code(201).send({data:t.createLocalFolder($p.parse(e.body))})),e.patch("/api/node-agent/local-folders/:id",async e=>({data:t.updateLocalFolder(e.params.id,Hp.parse(e.body))})),e.delete("/api/node-agent/local-folders/:id",async e=>({data:{deleted:t.deleteLocalFolder(e.params.id)}}))}(te,{listRuntimes:()=>v.nodeRuntimes.list(),createRuntime:e=>v.createRuntime(e),updateRuntime:(e,t)=>v.updateRuntime(e,t),deleteRuntime:e=>v.deleteRuntime(e),checkRuntime:async e=>{const t=v.requireRuntime(e);return v.checkRuntime(e,P.forRuntime(t))},listLocalFolders:()=>v.localFolders.list(),listFolderPlaces:ga,listFolderTree:ya,createLocalFolder:e=>v.createLocalFolder(e),updateLocalFolder:(e,t)=>v.updateLocalFolder(e,t),deleteLocalFolder:e=>v.localFolders.delete(e)}),function(e,t,n,i){e.get("/api/node-agent/models",async()=>({data:t.list()})),e.post("/api/node-agent/models",async(e,n)=>n.code(201).send({data:t.create(Es.parse(e.body))})),e.post("/api/node-agent/models/discover",async e=>{const n=cu.parse(e.body);return{data:await Jl(i,{...n,key:t.resolveProbeKey(n.existingModelId,n.key)})}}),e.post("/api/node-agent/models/test",async e=>{const n=du.parse(e.body);return{data:await Ql(i,{...n,key:t.resolveProbeKey(n.existingModelId,n.key)})}}),e.put("/api/node-agent/models/:id/deploy",async e=>{const n=e.params.id,i=Ts.parse(e.body);if(i.id!==n)throw Object.assign(new Error(`Model payload id ${i.id} does not match route id ${n}.`),{statusCode:400,code:"NODE_MODEL_ID_MISMATCH"});return{data:t.deploy(i)}}),e.patch("/api/node-agent/models/:id",async e=>({data:t.update(e.params.id,ws.parse(e.body))})),e.delete("/api/node-agent/models/:id",async e=>({data:{deleted:t.delete(e.params.id)}})),e.put("/api/node-agent/instances/:id/model-assignment",async e=>{const i=e.params.id,s=e.body&&"object"==typeof e.body&&!Array.isArray(e.body)&&Object.prototype.hasOwnProperty.call(e.body,"modelEntityIds"),o=t.assign(i,bs.parse(e.body));if(await n(i),s)return{data:o};const{modelEntityIds:r,...a}=o.assignment;return{data:{...o,assignment:a}}})}(te,v.modelRegistry,e=>Eh(U,v,e,Ae.warn,L),U),function(e,t){const n=new lu(t.gitCredentials);e.addHook("onClose",async()=>n.close()),e.put("/api/node-agent/git-credentials/:credentialId",async e=>{const n=hu.parse(e.params),i=Xc.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(hu.parse(e.params).credentialId)}})),e.get("/api/node-agent/instances/:id/git-credential-authorizations",async e=>{const{id:n}=gu.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}=gu.parse(e.params);t.requireInstance(n);const i=Yc.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}=gu.parse(e.params);t.authenticateInstance(i,yu(e.headers));const s=Jc.parse(e.body);return{data:Qc.parse(n.resolveHttps(i,s.remoteUrl))}}),e.post("/api/node-agent/instances/:id/git-credentials/ssh/prepare",async e=>{const{id:i}=gu.parse(e.params);t.authenticateInstance(i,yu(e.headers));const s=Zc.parse(e.body);return{data:ed.parse(await n.prepareSsh(i,s.remoteUrl))}}),e.post("/api/node-agent/instances/:id/git-credentials/ssh/agent",async e=>{const{id:i}=gu.parse(e.params);t.authenticateInstance(i,yu(e.headers));const s=td.parse(e.body);return{data:nd.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}=fu.parse(e.params);return t.authenticateInstance(i,yu(e.headers)),{data:{deleted:n.release(s,i)}}})}(te,v),function(e,t,n,i={}){if(e.hasContentTypeParser("application/octet-stream")||e.addContentTypeParser("application/octet-stream",(e,t,n)=>n(null,t)),e.get("/api/node-agent/stories",async()=>({data:{stories:await n.list()}})),e.post("/api/node-agent/stories",async(e,t)=>{const s=await n.create(Hu.parse(e.body));return i.onRetentionSettingsChanged?.(),t.code(201).send({data:s})}),e.get("/api/node-agent/stories/:storyId",async e=>{const{storyId:t}=Zu.parse(e.params);return{data:await n.get(t)||(()=>{throw Object.assign(new Error("Story was not found."),{code:"STORY_NOT_FOUND",statusCode:404})})()}}),e.patch("/api/node-agent/stories/:storyId",async e=>{const{storyId:t}=Zu.parse(e.params),s=qu.parse(e.body),o=i.commands?await i.commands.update(t,s):await n.update(t,s);return void 0!==s.maxIdleAiSessions&&i.onRetentionSettingsChanged?.(),{data:o}}),e.get("/api/node-agent/stories/:storyId/settings",async e=>{const{storyId:t}=Zu.parse(e.params);return{data:await n.retentionSettings(t)}}),e.post("/api/node-agent/stories/:storyId/archive",async e=>({data:i.commands?await i.commands.archive(Zu.parse(e.params).storyId):await n.archive(Zu.parse(e.params).storyId)})),e.post("/api/node-agent/stories/:storyId/restore",async e=>({data:i.commands?await i.commands.restore(Zu.parse(e.params).storyId):await n.restore(Zu.parse(e.params).storyId)})),e.delete("/api/node-agent/stories/:storyId",async e=>{const{storyId:t}=Zu.parse(e.params);if(!i.commands)throw Object.assign(new Error("Story command service is unavailable."),{code:"STORY_COMMAND_UNAVAILABLE",statusCode:503});return{data:{deleted:await i.commands.delete(t)}}}),i.scheduler){const t=i.scheduler,s=async(e,n)=>{const i=await t.status(n);if(i.automation.storyId!==e)throw Object.assign(new Error("Story Automation belongs to another Story."),{code:"STORY_AUTOMATION_STORY_MISMATCH",statusCode:409});return i};e.get("/api/node-agent/stories/:storyId/automations",async e=>{const{storyId:i}=Zu.parse(e.params);return await n.require(i),{data:Mu.parse({automations:await t.list(i)})}}),e.post("/api/node-agent/stories/:storyId/automations",async(e,n)=>{const{storyId:i}=Zu.parse(e.params),s=zu.parse(e.body);if(s.storyId!==i)throw Object.assign(new Error("Automation storyId does not match the route."),{code:"STORY_AUTOMATION_STORY_MISMATCH",statusCode:409});return n.code(201).send({data:Lu.parse(await t.create(s))})}),e.post("/api/node-agent/stories/:storyId/automations/with-action",async(e,t)=>{const{storyId:n}=Zu.parse(e.params);if(!i.commands)throw Object.assign(new Error("Story command service is unavailable."),{code:"STORY_COMMAND_UNAVAILABLE",statusCode:503});const s=Cu.parse(e.body);return t.code(201).send({data:Lu.parse(await i.commands.createAutomationWithAction(n,s))})}),e.get("/api/node-agent/stories/:storyId/automations/:automationId",async e=>{const{storyId:t,automationId:n}=tp.parse(e.params);return{data:Lu.parse(await s(t,n))}}),e.patch("/api/node-agent/stories/:storyId/automations/:automationId",async e=>{const{storyId:n,automationId:i}=tp.parse(e.params);return await s(n,i),{data:Lu.parse(await t.update(i,Ru.parse(e.body)))}}),e.delete("/api/node-agent/stories/:storyId/automations/:automationId",async e=>{const{storyId:n,automationId:i}=tp.parse(e.params);return await s(n,i),{data:{deleted:await t.delete(i)}}});for(const n of["enable","disable"])e.post(`/api/node-agent/stories/:storyId/automations/:automationId/${n}`,async e=>{const{storyId:i,automationId:o}=tp.parse(e.params);return await s(i,o),{data:Lu.parse(await t.setEnabled(o,"enable"===n))}});e.post("/api/node-agent/stories/:storyId/automations/:automationId/run",async e=>{const{storyId:n,automationId:i}=tp.parse(e.params);return await s(n,i),{data:await t.manualRun(i,Uu.parse(e.body))}}),e.get("/api/node-agent/stories/:storyId/automations/:automationId/runs",async e=>{const{storyId:n,automationId:i}=tp.parse(e.params);return await s(n,i),{data:ju.parse({runs:await t.runs(i)})}})}e.get("/api/node-agent/stories/:storyId/content",async e=>{const{storyId:t}=Zu.parse(e.params);return{data:Ku.parse({documents:await n.listContent(t)})}}),e.get("/api/node-agent/stories/:storyId/content/file",async(e,t)=>{const{storyId:i}=Zu.parse(e.params),{storyPath:s}=ip.parse(e.query),o=await n.readContent(i,s);return ap(t,o.stream,o.revision,o.size)}),e.put("/api/node-agent/stories/:storyId/content/file",{bodyLimit:33555456},async e=>{const{storyId:t}=Zu.parse(e.params),i=sp.parse(e.query);return{data:await n.writeContent(t,{...i,stream:e.body})}}),e.patch("/api/node-agent/stories/:storyId/documents/:storyPath",async e=>{const t=ep.parse(e.params),i=Au.parse(decodeURIComponent(t.storyPath));return{data:await n.updateDocument(t.storyId,i,Vu.parse(e.body))}}),e.delete("/api/node-agent/stories/:storyId/documents/:storyPath",async e=>{const t=ep.parse(e.params);return{data:{deleted:await n.deleteDocument(t.storyId,Au.parse(decodeURIComponent(t.storyPath)))}}}),e.post("/api/node-agent/stories/:storyId/documents/order",async e=>{const{storyId:t}=Zu.parse(e.params);return{data:await n.reorderDocuments(t,e.body)}}),e.get("/api/node-agent/instances/:id/ai-sessions/:sessionId/story-content",async e=>{const{id:i,sessionId:s}=np.parse(e.params),o=await rp(t,n,i,s,op(e.headers)),{page:r,pageSize:a}=Wu.parse(e.query||{});return{data:Ju.parse(await n.pageContent(o.id,r,a))}}),e.get("/api/node-agent/instances/:id/ai-sessions/:sessionId/story-content/file",async(e,i)=>{const{id:s,sessionId:o}=np.parse(e.params),r=await rp(t,n,s,o,op(e.headers)),{storyPath:a}=ip.parse(e.query),c=await n.readContent(r.id,a);return ap(i,c.stream,c.revision,c.size)}),e.put("/api/node-agent/instances/:id/ai-sessions/:sessionId/story-content/file",{bodyLimit:33555456},async e=>{const{id:i,sessionId:s}=np.parse(e.params),o=await rp(t,n,i,s,op(e.headers)),r=sp.parse(e.query);return{data:await n.writeContent(o.id,{...r,stream:e.body})}}),e.put("/api/node-agent/instances/:id/ai-sessions/:sessionId/story",async e=>{const{id:s,sessionId:o}=np.parse(e.params),r=t.requireInstance(s),c=a.z.object({storyId:ue.nullable()}).strict().parse(e.body||{});if(c.storyId){const e=await n.get(c.storyId);if(!e)throw Object.assign(new Error("Story belongs to another node or was not found."),{code:"STORY_NODE_MISMATCH",statusCode:409});if(e.archivedAt)throw Object.assign(new Error("Archived Story cannot receive new Session associations."),{code:"STORY_ARCHIVED",statusCode:409})}if(!i.fetchImpl||!i.resolveInstanceWeb||!r.registrationToken)throw Object.assign(new Error("Managed instance Session association is unavailable."),{code:"STORY_SESSION_ASSOCIATION_UNAVAILABLE",statusCode:503});const d=await i.resolveInstanceWeb(r),l=await i.fetchImpl(`${d}/api/ai-sessions/${encodeURIComponent(o)}/story`,{method:"PUT",headers:{"content-type":"application/json",authorization:`Bearer ${r.registrationToken}`},body:JSON.stringify(c)}),u=await l.json().catch(()=>({}));if(!l.ok)throw Object.assign(new Error(u.error?.message||"Controlled instance rejected Story association."),{code:u.error?.code||"STORY_SESSION_ASSOCIATION_FAILED",statusCode:l.status});return u})}(te,v,N,{fetchImpl:U,resolveInstanceWeb:L,onRetentionSettingsChanged:()=>F.reconcile(),commands:he,scheduler:me}),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:zi.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)}))}(te,Ee),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(Vp.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,Bp.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),o=t.register(i,Eo.parse(s),Wp(e.headers));return t.afterReport(o,"register"),n.code(201).send({data:o})}),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,wo.parse(i),Wp(e.headers));return t.afterReport(s,"heartbeat"),{data:s}})}(te,{list:()=>v.listInstances(),create:e=>"template"===e.environmentSource?.type?Ee.runTemplateOperation(e.environmentSource.environmentTemplateId,()=>v.createInstance(e)):v.createInstance(e),retryImageProvisioning:e=>be.retry(e),update:(e,t)=>{const n=v.requireInstance(e),i=t.config?.codexSettings?.multiAgent.defaultModel;if(i){const t=v.modelRegistry.privateCatalog(e).entities.find(e=>e.id===i.modelEntityId&&e.protocols.includes("openai-responses"));if(!t?.modelNames.some(e=>e.name===i.modelName))throw Object.assign(new Error("The Codex subagent model must be assigned to this instance."),{statusCode:400,code:"CODEX_SUBAGENT_MODEL_UNAVAILABLE"})}return v.controlledInstances.put(po.parse({...n,...t,...t.config?{config:{...n.config,...t.config}}:{},updatedAt:ae()}))},register:(e,t,n)=>v.registerInstance(e,t,n),heartbeat:(e,t,n)=>v.heartbeatInstance(e,t,n),sanitizeReport:we,afterCreate:e=>{le.syncNow(),e.imageProvisioning&&Se(e)},afterImageRetry:e=>{le.syncNow(),Se(e)},afterUpdate:async e=>{le.syncNow(),await Promise.all([B(e.id),K(e.id)])},afterReport:(e,t)=>{le.syncNow(),me.reconcileInstances("heartbeat"===t?e.id:void 0).catch(t=>te.log.warn({error:t,instanceId:e.id},"Story scheduler reconciliation failed")),V(e),B(e.id),K(e.id),F.reconcile(),$.reconcile(),"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"),!Z(e)||e.ready&&"matched"===e.runtimeVersion?.phase||pe.schedule(e.id).catch(n=>te.log.error({instanceId:e.id,error:n},`runtime convergence after ${t} failed`))}}),te.get("/api/node-agent/events",{websocket:!0},(e,t)=>{const n=e;n.send(JSON.stringify({type:"node-agent.events.connected",nodeId:_,serverTime:(new Date).toISOString()}));const i=t.query,s=le.addOutput(n,{expectsTransientSubscription:"1"===i.aiSessionTransient});n.on("message",e=>{try{const t=JSON.parse(String(e));"subscribe"===t.type&&void 0!==t.aiSessionTransient&&le.setOutputSubscription(n,t.aiSessionTransient,t.eventEnvelopeVersion,t.aiSessionHierarchy)}catch{}}),n.on("close",s),n.on("error",s)}),te.get("/api/node-agent/docker/images",async()=>({data:await tr(e.dockerCommandRunner)})),te.get("/api/node-agent/instances/:id/metrics",async e=>{const t=e.params.id,n=v.requireInstance(t);if("docker"!==v.requireRuntime(n.runtimeId).type){const e=new Error(`Runtime type ${v.requireRuntime(n.runtimeId).type} does not provide resource metrics.`);throw Object.assign(e,{statusCode:409,code:"INSTANCE_METRICS_UNSUPPORTED"}),e}return{data:await ge.snapshot(t)}}),function(e,t,n,i,s,o=new Xp){const r=e=>o.intent(e),a=e=>Promise.resolve(i.cancel(e)).then(()=>({ok:!0}),e=>({ok:!1,error:e})),c=(e,t)=>{if(!o.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=o.signal;return"function"==typeof n?n.call(o,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=Yp.parse(e.body),n=e.params.id,i=r(n);return o.run(n,async()=>(c(n,i),l(n,t.gitWorkspaceProvisioning),s.allowRecovery(n),{data:u(await s.start(n,()=>o.isIntentCurrent(n,i),d(n,i)),t.gitWorkspaceProvisioning)}))}),e.post("/api/node-agent/instances/:id/runtime/reconcile",async e=>{const n=e.params.id;Yp.parse(e.body);const a=r(n);return o.run(n,async()=>{c(n,a);const e=t.requireInstance(n);t.putInstance(po.parse({...e,ready:!1,runtimeVersion:jl(Pa(e)),updatedAt:ae()})),c(n,a);const o=await i.schedule(n,{startRequested:!["created","stopped"].includes(e.status),resumeCancelled:!0});return c(n,a),s.sync(),{data:o}})}),e.post("/api/node-agent/instances/:id/stop",async e=>{const i=e.params.id;t.requireInstance(i),t.discardGitWorkspaceProvisioning(i),o.invalidate(i);const r=a(i);return o.run(i,async()=>{const e=t.requireInstance(i);t.applyLifecycle(i,{type:"stop-requested"});try{await s.suppressRecovery(i);const e=await r;if("error"in e)throw e.error;const o=t.requireInstance(i);s.diagnostic({instanceId:i,action:"stop",runtimeId:o.runtimeId,containerName:o.runtime.containerName},"node instance stop requested"),await n.forRuntime(t.requireRuntime(o.runtimeId)).stop(t.context(o))}catch(n){try{t.applyLifecycle(i,{type:"stop-failed",baseline:e}),s.sync()}finally{s.allowRecovery(i)}throw n}const o=t.applyLifecycle(i,{type:"stop-completed"});return s.completeSuppressedRecovery(i),s.sync(),s.diagnostic({instanceId:i,action:"stop",status:o.status,connectionStatus:o.connectionStatus,containerName:o.runtime.containerName},"node instance stop completed"),{data:o}})}),e.post("/api/node-agent/instances/:id/restart",async e=>{const a=e.params.id,d=Yp.parse(e.body),p=r(a);return o.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(po.parse({...e,runtimeVersion:jl(Pa(e)),updatedAt:ae()}))),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 o=await n.forRuntime(t.requireRuntime(e.runtimeId)).restart(t.context(e));let r=t.applyLifecycle(a,{type:"runtime-lifecycle-completed",baseline:e,observation:{...o,target:o.target?{...e.target,...o.target}:void 0}});s.markRestarted(a),c(a,p);const m=po.parse({...r,updatedAt:ae()}),h=await s.probe(m);return c(a,p),r=t.applyLifecycle(a,{type:"runtime-lifecycle-completed",baseline:r,observation:{target:{...r.target,status:h},targetStatus:h,uiAccessStatus:h}}),await s.autoImport(r),s.sync(),s.diagnostic({instanceId:a,action:"restart",status:r.status,connectionStatus:r.connectionStatus,targetStatus:r.targetStatus,targetWeb:r.target.web,containerName:r.runtime.containerName},"node instance restart completed"),{data:u(r,d.gitWorkspaceProvisioning)}})}),e.post("/api/node-agent/instances/:id/delete",async e=>{const i=e.params.id,r=_i.parse(e.body);t.requireInstance(i),o.invalidate(i);const c=a(i);return o.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(po.parse({...a,status:"deleting",ready:!1,updatedAt:ae()})),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,{}),r);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),o.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(po.parse({...e,updatedAt:ae()})),s.sync()}finally{s.allowRecovery(i)}throw n}})})}(te,{requireInstance:e=>v.requireInstance(e),requireRuntime:e=>v.requireRuntime(e),putInstance:e=>v.controlledInstances.put(e),deleteInstance:e=>v.controlledInstances.delete(e),applyLifecycle:(e,t)=>v.applyInstanceLifecycle(e,t),context:(e,t)=>v.context(e,t),setGitWorkspaceProvisioning:e=>v.setGitWorkspaceProvisioning(e),discardGitWorkspaceProvisioning:e=>v.discardGitWorkspaceProvisioning(e),gitWorkspaceProvisioningStatus:e=>v.gitWorkspaceProvisioningStatus(e)},P,pe,{start:(e,t,n)=>Te(e,"request",t,n),sync:()=>le.syncNow(),isManaged:Z,probe:e=>yh(U,e,L),autoImport:e=>_h(U,e,"restart",Ae,L),markRestarted:e=>D.markRestored(e),allowRecovery:e=>D.allowRecovery(e),suppressRecovery:e=>D.suppressRecovery(e),forgetRecovery:e=>D.forgetInstance(e),completeSuppressedRecovery:e=>D.completeSuppressedOperation(e),deleteMetadata:e=>{H.delete(e),v.modelRegistry.deleteInstanceMetadata(e),v.gitCredentials.removeInstance(e),v.gitCredentials.collectUnreferencedPayloads(),v.discardGitWorkspaceProvisioning(e),v.instancePrivateConfigs.delete(e)},retireInstanceData:e=>{ne.retire(e)},releaseEnvironmentImage:e=>Ee.releaseUnusedImage(e),diagnostic:Ie},_e),function(e,t){const{fetchImpl:n,metrics:i,diagnostic:s}=t;e.post("/api/node-agent/instances/:id/proxy",async(e,i)=>{const o=performance.now(),r=e.params.id,a=Fp.parse(e.body),c=await t.instanceBase(r),d=am(a.path);"POST"===a.method&&"/api/apps/sessions"===d&&await t.syncModelEnvironment(r),s({instanceId:r,action:"proxy",method:a.method,path:d,instanceBase:c},"node instance proxy requested");const l=await dm(n,`${c}${d}`,{method:a.method,headers:{...a.headers},body:sm(a)},{instanceId:r,method:a.method,path:d,diagnostic:s}),u=l.headers.get("content-type")||"application/octet-stream",p=await l.text(),m=performance.now()-o,h=l.headers.get(rm)||a.headers[rm],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(rm,h),s({instanceId:r,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:nm},async(e,o)=>{const r=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()-r,i.responseBytes+=c,i[e]+=1)},p=()=>{a.abort(),d&&u("aborted")};e.raw.once("aborted",p),o.raw.once("close",p);try{const r=e.params.id,l=Fp.parse(e.body),p=await t.instanceBase(r),m=am(l.path);s({instanceId:r,action:"proxy.stream",method:l.method,path:m,instanceBase:p},"node instance streaming proxy requested");const g=await dm(n,`${p}${m}`,{method:l.method,headers:{...l.headers},body:sm(l),signal:a.signal},{instanceId:r,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(),cm(o,i.maxResponseBytes);o.code(g.status);for(const[e,t]of Object.entries(im(g.headers)))o.header(e,t);if(!g.body||"HEAD"===l.method)return u("completed"),o.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")),o.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:nm},async(e,o)=>{const r=e.params.id,a=Fp.parse(e.body),c=await t.instanceBase(r),d=am(a.path);s({instanceId:r,action:"proxy.raw",method:a.method,path:d,instanceBase:c},"node instance raw proxy requested");const l=await dm(n,`${c}${d}`,{method:a.method,headers:{...a.headers},body:sm(a)},{instanceId:r,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(()=>{})),cm(o,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:o}=await s.read();if(e)break;if(i+=o.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(o))}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,cm(o,i.maxResponseBytes)}return s({instanceId:r,action:"proxy.raw",method:a.method,path:d,statusCode:l.status,byteLength:p.length},"node instance raw proxy completed"),{data:{status:l.status,headers:im(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,o=n.params["*"]||"",r=n.url.indexOf("?"),a=r>=0?n.url.slice(r):"";let c;try{const r=await t.instanceBase(i),d=new URL(`/${o}${a}`,`${r}/`);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:`/${o}${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:`/${o}${a}`},"node instance websocket proxy opened")}),c.on("close",()=>{s({instanceId:i,action:"proxy.ws",path:`/${o}${a}`},"node instance websocket proxy closed")}),c.on("error",e=>{s({instanceId:i,action:"proxy.ws",path:`/${o}${a}`,error:e instanceof Error?e.message:String(e)},"node instance websocket proxy failed")}),j(e,c,{upstreamOpenTimeoutMs:1e4})}catch(t){s({instanceId:i,action:"proxy.ws",path:`/${o}${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.")}})}(te,{fetchImpl:U,metrics:de,instanceBase:e=>L(v.requireInstance(e)),syncModelEnvironment:e=>Eh(U,v,e,Ae.warn,L),diagnostic:Ie}),te}catch(e){throw await m.close(),e}var g}async function bh(e){const s=Aa(e.dataDir),o=function(e,i={}){return function(e,i={}){t.mkdirSync(n.dirname(e),{recursive:!0});const s=$.processStartIdentity(process.pid),o={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(V(e),`${JSON.stringify({token:o.token,pid:o.pid,startIdentity:o.startIdentity,startedAt:(new Date).toISOString()})}\n`,{encoding:"utf8",mode:384,flag:"wx"}),J(e,o),{lockPath:e,owner:o,updateDetails:t=>Q(e,o,t),release(){const n=W(e);n?.token===o.token&&t.rmSync(e,{recursive:!0,force:!0})}}}catch(s){if("EEXIST"!==s.code)throw s;const o=W(e);if(Y(o))throw new H(e,o,i.error);if(!o&&(ee(e)||ie(e)<(i.incompleteLockStaleMs??2e3))){if(n+1<5){ne();continue}throw new H(e,void 0,i.error)}const r=d.randomUUID();if(!se(e,r)){if(n+1<5){ne();continue}throw new H(e,W(e),i.error)}const a=W(e);if(Y(a))throw te(B(e)),new H(e,a,i.error);if(o?.token&&a?.token!==o.token){te(B(e));continue}if(!re(e,r))continue;t.rmSync(e,{recursive:!0,force:!0})}const r=W(e);throw new H(e,r,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=(r=e.host,a=e.port,to.parse({bindScope:"0.0.0.0"===r.trim()?"all-ipv4":"loopback",port:a})),d=t.existsSync(s.settingsPath),l=function(e,t){return new Qa(e.settingsPath,()=>({version:1,externalListener:t}),{schema:pm,sanitize:hm})}(s,c);let u=l.get().externalListener;"allocate"===process.env.TASK_HANDOFF_NODE_AGENT_PORT_CONFLICT&&(u=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 gm(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));const p=e=>{if(!o.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 Th(m),g=h.nodeAgentState;if(!g)throw new Error("Node agent state was not initialized.");const f=h.nodeAgentIdentityService;if(!f)throw new Error("Node agent identity service was not initialized.");const y=f.resolveNodeId(e.nodeId||process.env.TASK_HANDOFF_NODE_ID),I=function(e,t,n,i,s){const o=t.token||process.env.TASK_HANDOFF_NODE_AGENT_TOKEN,r=s||new vm(n),a=new Map;let c=!1;const d=(t,n)=>{if(c||n.retry.pending||a.get(t)!==n)return;const s=n.retry.schedule(()=>{c||a.get(t)!==n||n.socket||l(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"))},l=(n,s)=>{let r;s.status=s.lastDisconnectedAt?"reconnecting":"connecting",s.error=void 0,s.failureReason=void 0,s.nextRetryAt=void 0;try{r=Mm(e,{...s.config,nodeId:i,port:()=>e.nodeAgentState.currentListenerPort,token:o})}catch(e){return s.status="failed",s.lastDisconnectedAt=(new Date).toISOString(),s.error=e instanceof Error?e.message:String(e),void d(n,s)}s.socket=r;const l=new $m({connectTimeoutMs:t.connectTimeoutMs,handshakeTimeoutMs:t.handshakeTimeoutMs,heartbeatIntervalMs:t.heartbeatIntervalMs,heartbeatTimeoutMs:t.heartbeatTimeoutMs,heartbeatMissThreshold:t.heartbeatMissThreshold,stableThresholdMs:t.stableThresholdMs,ping:()=>r.ping(),onTimeout:e=>{a.get(n)===s&&s.socket===r&&(s.status="failed",s.failureReason=`Reverse tunnel ${e} timeout.`,s.error=s.failureReason,r.terminate())},onStable:()=>s.retry.reset()});return s.supervisor=l,l.start(),r.on("open",()=>{a.get(n)===s&&s.socket===r&&(s.status="connecting",l.opened())}),r.on("message",t=>{if(a.get(n)!==s||s.socket!==r)return;if(l.activity(),"connected"===s.status)return;let o;try{o=JSON.parse(String(t))}catch{return}const c=o&&"object"==typeof o?o.type:void 0;"control-plane.hello"!==c&&"control-plane.identified"!==c||(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"))}),r.on("pong",()=>l.pong()),r.on("close",(t,o)=>{if(a.get(n)!==s||s.socket!==r)return;l.close(),s.socket=void 0,s.lastDisconnectedAt=(new Date).toISOString();const u=`WebSocket closed${t?` (${t})`:""}${o?`: ${Buffer.isBuffer(o)?o.toString("utf8"):String(o)}`:""}`;s.error=s.failureReason||u,c||(e.log.warn({nodeId:i,tunnelUrl:new URL(s.config.tunnelUrl).origin,code:t,reason:Buffer.isBuffer(o)?o.toString("utf8"):String(o||""),error:s.error,closeOrigin:s.failureReason?"supervisor":"transport"},"node agent reverse tunnel disconnected"),d(n,s))}),r.on("error",e=>{a.get(n)===s&&s.socket===r&&(s.status="failed",s.failureReason=e instanceof Error?e.message:String(e),s.error=s.failureReason,r.terminate())}),r},u=(e,t)=>{const n=a.get(e);n?.retry.cancel(),n?.supervisor?.close();const i={config:t,retry:new qr,status:"connecting"};return a.set(e,i),n?.socket?.close(1e3,"Reverse tunnel reconnecting."),l(e,i)},p=(e,t)=>e.tunnelUrl===t.tunnelUrl&&e.keyId===t.keyId&&e.secret===t.secret;return{connectConfigured:()=>{c=!1;const n=new Map,s=r.resolvedControlPlaneAccess(),o=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=Hm(t.url);n.set(t.id,{tunnelUrl:s,keyId:r.keyId,secret:r.secret}),o.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&&!o.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}),o.add(d)}const l=s.hasPersistedAccess?void 0:function(){const e=process.env.TASK_HANDOFF_CONTROL_PLANE_URL;if(!e)return;const t=new URL(Im,e);return t.protocol="https:"===t.protocol?"wss:":"ws:",t.toString()}();if(l&&!o.has(l)){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:${l}`,{tunnelUrl:l,keyId:e?.keyId,secret:e?.secret})}(e=>{for(const[t,n]of a)e.has(t)||(n.retry.cancel(),n.supervisor?.close(),a.delete(t),n.socket?.close(1e3,"Reverse tunnel configuration removed."));for(const[t,n]of e){const e=a.get(t);e&&p(e.config,n)||u(t,n)}})(n)},state:e=>{const t=a.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:()=>{c=!0;for(const e of a.values())e.retry.cancel(),e.supervisor?.close(),e.socket?.close(1001,"Node agent shutting down.");a.clear()}}}({log:h.log,inject:e=>h.inject(e),nodeAgentEventForwarder:h.nodeAgentEventForwarder,nodeAgentState:g},m,s,y,f);h.decorate("nodeAgentReverseTunnels",I);const A=new fm({app:h,state:g,settings:l,config:u,source:d?"persisted":"bootstrap",onActiveListener:p,validateUpdate:()=>{const e=g.listInstances().filter(e=>!["created","stopped","failed"].includes(e.status)).filter(e=>"reachable"!==e.targetStatus||!Xn(e.capabilities).features.nodeAgentConnectionUpdate);if(e.length)throw Object.assign(new Error(`Cannot change the node agent port while ${e.length} controlled instance(s) cannot switch endpoints live.`),{statusCode:409,code:"NODE_AGENT_LISTENER_LIVE_UPDATE_UNSUPPORTED",details:{instanceIds:e.map(e=>e.id)}})},synchronizeUpdate:async()=>{const t=g.listInstances().filter(e=>!["created","stopped","failed"].includes(e.status));await Promise.all(t.map(t=>{const n="docker"===g.requireRuntime(t.runtimeId).type?g.containerUrl:g.localNodeAgentUrl;return Ah(e.fetchImpl||fetch,t,n).then(e=>{if("applied"!==e)throw new Error(`Controlled instance ${t.id} did not apply the node-agent endpoint update (${e}).`)})}))}});let _;h.decorate("nodeAgentListenerManager",A),function(e){let t=!1;const n=async n=>{if(!t){t=!0,I.closeAll(),_?.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()=>{_?.close(),o.release()});try{await h.ready();const o=e.ipcPath||process.env.TASK_HANDOFF_NODE_AGENT_IPC_PATH||Ta(s.dataDir);_=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 o=i.createServer((t,n)=>{e.server.emit("request",t,n)});return o.on("upgrade",(t,n,i)=>{e.server.emit("upgrade",t,n,i)}),await new Promise((e,t)=>{o.once("error",t),o.listen(s,()=>{o.off("error",t),e()})}),o}(h,o),await A.start(),I.connectConfigured(),h.nodeAgentStartRecoverySupervisor?.()}catch(e){throw await h.close(),e}}catch(e){throw o.release(),e}var r,a}const Sh="task-handoff-node-agent.service",vh=`/etc/systemd/system/${Sh}`,Nh="/etc/task-handoff/node-agent.env",Oh=["@task-handoff/node-agent","@task-handoff/controlled-instance"];function zh(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 Ch(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 Rh={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(!N.stdin.isTTY||!N.stdout.isTTY)return!1;const t=v.createInterface({input:N.stdin,output:N.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 xh(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 kh(e){if("local-ipc"!==e&&"local-loopback"!==e)throw new Error("Connection mode must be local-ipc or local-loopback.");return e}function Dh(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(R("@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",xh,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",kh).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 bh({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",Dh).option("--json","Print raw JSON output").action(async e=>{const n=t.opts(),i=e.ipcPath||n.ipcPath||process.env.TASK_HANDOFF_NODE_AGENT_IPC_PATH,s=e.dataDir||n.dataDir||process.env.TASK_HANDOFF_NODE_AGENT_DATA_DIR,o=e.endpoint?void 0:i||Ta(s||Ia()),r=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 ba(e.ipcPath,"/pairing/invites",{method:"POST",headers:t,body:n}),s=await i.json().catch(()=>({}));if(!i.ok)throw new Error(s.error?.message||`Node agent pairing invite failed with HTTP ${i.status}`);const o="string"==typeof s.data?.joinToken?s.data.joinToken:"";if(!o)throw new Error("Node agent pairing invite response did not include a join token.");return{nodeId:"string"==typeof s.data?.nodeId?s.data.nodeId:"",joinToken:o,expiresAt:"string"==typeof s.data?.expiresAt?s.data.expiresAt:""}}({endpoint:e.endpoint,ipcPath:o,token:e.token,expiresInMs:e.expiresInMs});e.json?console.log(JSON.stringify(r,null,2)):(r.nodeId&&console.log(`Node: ${r.nodeId}`),console.log(`Join token: ${r.joinToken}`),r.expiresAt&&console.log(`Expires: ${r.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,o=e.endpoint?void 0:i||Ta(s||Ia()),r=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 ba(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:o,token:e.token});e.json?console.log(JSON.stringify(r,null,2)):(console.log(`Control Plane: ${String(r?.connection?.url||e.controlPlane)}`),console.log(`Connection: ${String(r?.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=Rh){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(Nh)?t.readText(Nh):"",s=function(e,t){if(e.dataDir?.trim())return n.resolve(e.dataDir.trim());if(t.exists(Nh)){const e=Ch(t.readText(Nh),"TASK_HANDOFF_NODE_AGENT_DATA_DIR");if(e)return n.resolve(e)}return n.resolve(Ia())}(e,{exists:e=>e===Nh&&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 o=Ch(i,"TASK_HANDOFF_NPM_COMMAND")||process.env.TASK_HANDOFF_NPM_COMMAND||"npm";if(t.exists(vh)){const e=t.readText(vh);if(!/^ExecStart=\S*task-handoff-node-agent(?:\s|$)/m.test(e))throw new Error(`Refusing to remove ${Sh} because it is not owned by a standalone Node Agent installation.`);zh(t,"systemctl",["disable","--now",Sh]),t.remove(vh,{force:!0}),zh(t,"systemctl",["daemon-reload"])}zh(t,o,["uninstall","--global",...Oh]),t.remove(Nh,{force:!0}),t.log("TaskHandoff Node Agent service and packages were removed.");const r=!!e.deleteData||!e.keepData&&await t.confirmDeleteData(s);return r?(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:r}}(e)}),await t.parseAsync(process.argv)})().catch(e=>{console.error(e instanceof Error?e.message:String(e)),process.exitCode=1});
1
+ "use strict";var e=require("commander"),t=require("node:fs"),n=require("node:path"),i=require("node:http"),s=require("node:url"),o=require("fastify"),r=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("write-file-atomic"),m=require("ws"),h=require("node:net"),g=require("node:stream"),f=require("node:fs/promises"),y=require("node:stream/promises"),I=require("tar"),A=require("node:async_hooks"),_=require("drizzle-orm"),E=require("drizzle-orm/sqlite-core"),T=require("node:sqlite"),w=require("drizzle-orm/node-sqlite"),b=require("semver"),S=require("cron-parser"),v=require("node:readline/promises"),N=require("node:process"),O="undefined"!=typeof document?document.currentScript:null;function z(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 C(e){if(e)try{return n.dirname(t.realpathSync(e))}catch{return}}function R(e,t=process.env,i=e){const s=t.TASK_HANDOFF_VERSION?.trim();if(s)return s;const o=i.split("/").at(-1),r=process.argv[1]?n.resolve(process.argv[1]):void 0,a=r?n.dirname(r):void 0,c=[C(r),a,process.cwd()].filter(e=>Boolean(e));for(const t of new Set(c)){let i=t;for(;;){const t=z(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(o){const e=z(n.join(t,"packages",o,"package.json"),i);if(e)return e}d||=z(n.join(t,"package.json"));const e=n.dirname(t);if(e===t)break;t=e}}return d||"unknown"}const x={perMessageDeflate:{threshold:256,serverNoContextTakeover:!0,clientNoContextTakeover:!0,concurrencyLimit:4,zlibDeflateOptions:{level:1}}};function k(e){return e.readyState===(e.OPEN??1)}function D(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 P(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 L(e,t,n){e.close(P(t),D(n)||void 0)}function M(e,t,n,i){if(k(e))for(const e of t.splice(0))if(i(e),!n(e))return}function j(e,t,n={}){const i=n.pendingFrameLimit??256,s=n.maxFrameBytes??8388608,o=n.maxTotalBytes??1073741824,r=n.maxBufferedBytes??16777216;let a=!1,c=k(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,r)=>{const a=g(r);return h+=a,n.onFrame?.(i,a),!(a>s||h>o)||(L(e,1009,"WebSocket bridge traffic limit exceeded."),L(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>r)return L(e,1013,"WebSocket bridge consumer is too slow."),L(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 L(e,1011,"WebSocket bridge send failed."),L(t,1011,"WebSocket bridge send failed."),!1}},A=(n,s,o)=>{if(s.length>=i)return L(e,1011,"WebSocket bridge pending frame limit exceeded."),void L(t,1011,"WebSocket bridge pending frame limit exceeded.");const a="upstream"===n?p:m;if((("upstream"===n?t:e).bufferedAmount??0)+a+o.bytes>r)return L(e,1013,"WebSocket bridge consumer is too slow."),void L(t,1013,"WebSocket bridge consumer is too slow.");s.push(o),"upstream"===n?p+=o.bytes:m+=o.bytes};return n.upstreamOpenTimeoutMs&&!c&&(u=setTimeout(()=>{c||a||(L(e,1011,"Upstream websocket did not open."),L(t))},n.upstreamOpenTimeoutMs)),e.on("open",()=>M(e,l,t=>I(e,t),e=>{m-=e.bytes})),t.on("open",()=>{y(),c=!0,n.onUpstreamOpen?.(),M(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)};k(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)};k(e)?I(e,i):A("client",l,i)}),t.on("close",(t,i)=>{y(),n.onUpstreamClose?.(t,i),(c||a||!n.onUpstreamCloseBeforeOpen?.())&&L(e,t,i)}),t.on("error",t=>{n.onUpstreamError?.(t),(c||a||!n.onUpstreamErrorBeforeOpen?.(t))&&L(e)}),e.on("close",(e,i)=>{y(),a=!0,n.onClientClose?.(e,i),L(t,e,i)}),e.on("error",e=>{y(),a=!0,n.onClientError?.(e),L(t,1011,"WebSocket bridge client failed.")}),{close:(n,i)=>{y(),L(t,n,i),L(e,n,i)}}}var U,F,$=function(){if(F)return U;F=1;const e=t,{spawnSync:n}=l;return U={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 H 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 q(e){return n.join(e,"owner.json")}function V(e){return n.join(e,"initializing.json")}function B(e){return n.join(e,"recovering.json")}function K(e){return Number.isInteger(e)&&Number(e)>0}function G(e){try{const n=JSON.parse(t.readFileSync(q(e),"utf8"));if(K(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(!(K(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 W=G;function X(e){if(!K(e))return!1;try{return process.kill(Number(e),0),!0}catch(e){return"EPERM"===e.code}}function Y(e){if(!e||!X(e.pid))return!1;if(!e.startIdentity)return!0;const t=$.processStartIdentity(e.pid);return void 0===t||t===e.startIdentity}function J(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 o=Z(e);if(o?.token!==i.token)throw te(s),new Error(`Process lock initialization was superseded: ${e}`);t.renameSync(s,q(e)),te(V(e))}function Q(e,i,s){const o=W(e);if(o?.token!==i.token)return!1;const r={...i};for(const[e,t]of Object.entries(s))void 0===t?delete r[e]:Object.assign(r,{[e]:t});const a=n.join(e,`.owner-update-${i.token}-${d.randomUUID()}.tmp`);try{if(t.writeFileSync(a,`${JSON.stringify(r,null,2)}\n`,{encoding:"utf8",mode:384,flag:"wx"}),W(e)?.token!==i.token)return!1;t.renameSync(a,q(e));for(const e of Object.keys(i))delete i[e];return Object.assign(i,r),!0}catch(e){if("ENOENT"===e.code)return!1;throw e}finally{te(a)}}function Z(e){try{return JSON.parse(t.readFileSync(V(e),"utf8"))}catch{return}}function ee(e){const t=Z(e);return K(t?.pid)&&Y({pid:t.pid,startIdentity:t.startIdentity})}function te(e){try{t.unlinkSync(e)}catch(e){if("ENOENT"!==e.code)throw e}}function ne(){Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,20)}function ie(e){try{const n=Z(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 se(e,i){try{return t.writeFileSync(B(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=B(e),s=oe(i),o=Date.parse(s?.startedAt||"");if(X(s?.pid)||Number.isFinite(o)&&Date.now()-o<2e3)return!1;const r=n.join(e,`.recovering-${d.randomUUID()}.stale`);try{t.renameSync(i,r)}catch(e){if(["ENOENT","EEXIST"].includes(e.code||""))return!1;throw e}const a=oe(r);if(a?.token===s?.token)return te(r),!0;try{t.linkSync(r,i)}catch(e){if("EEXIST"!==e.code)throw e}finally{te(r)}return!1}(e)&&se(e,i);if("ENOENT"===s.code)return!1;throw s}}function oe(e){try{return JSON.parse(t.readFileSync(e,"utf8"))}catch{return}}function re(e,t){return oe(B(e))?.token===t}function ae(){return(new Date).toISOString()}const ce=6048e5;function de(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 le(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 ue=a.z.string().trim().min(1).max(120),pe=20971520,me=512e3,he=me,ge=pe,fe=41943040,ye="ai.sessions",Ie="ai-session.snapshot",Ae="ai-session.patch",_e="ai-session.removed",Ee="ai-session.message-delta",Te="ai-session.timeline-item",we="ai-session.timeline-item-delta",be=a.z.string().trim().min(1).max(80),Se=a.z.enum(["app-session","ai-session"]),ve=a.z.enum(["image","file"]),Ne={scopeType:a.z.enum(["session","create-request"]),scopeId:a.z.string().trim().min(1).max(160),kind:ve,name:a.z.string().trim().min(1).max(240),mime:a.z.string().trim().min(1).max(120)};a.z.object({...Ne,size:a.z.coerce.number().int().positive().max(pe)}).strict();const Oe=a.z.string().regex(/^cia_[a-f0-9]{24}$/);a.z.object({attachmentId:Oe,...Ne,size:a.z.number().int().positive().max(pe)}).strict(),a.z.object({offset:a.z.coerce.number().int().nonnegative()}).strict(),a.z.object({attachmentId:Oe,offset:a.z.number().int().nonnegative()}),a.z.object({id:Oe,kind:ve,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(pe),expiresAt:a.z.string().datetime()});const ze=a.z.object({id:a.z.string().trim().min(1).max(120),kind:ve,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)}),Ce=a.z.enum(["available","expired","missing"]),Re=ze.extend({contentState:Ce.default("available")}).strict(),xe=a.z.object({id:a.z.string().trim().min(1).max(240),text:a.z.string(),attachments:a.z.array(Re).max(6).default([])}).strict(),ke=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 De=a.z.enum(["thinking","tool","editing","approval","responding","unknown"]),Pe=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(),Le=a.z.enum(["running","completed","failed","waiting"]),Me=a.z.object({id:a.z.string().trim().min(1).max(240),turnId:a.z.string().trim().min(1).max(240)}).strict(),je=Me.extend({type:a.z.literal("user-message"),text:a.z.string(),attachments:a.z.array(Re).max(6).optional()}).strict(),Ue=Me.extend({type:a.z.literal("ai-message"),text:a.z.string()}).strict(),Fe=Me.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:Le.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(),$e=a.z.discriminatedUnion("type",[je,Ue,Fe]);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($e),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($e),generatedAt:a.z.string().datetime()}).strict();const He=a.z.enum(["pending-init","running","interrupted","completed","errored","shutdown","not-found"]),qe=a.z.enum(["started","interacted","interrupted"]),Ve=a.z.object({threadId:a.z.string().trim().min(1).max(240),path:a.z.string().trim().max(4096).optional(),status:He,activity:qe.optional(),message:a.z.string().trim().max(1e3).optional(),updatedAt:a.z.string().datetime()}).strict();function Be(e){return"completed"!==e.status}const Ke=a.z.array(Ve).max(50).transform(e=>e.filter(Be)),Ge=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}),We=a.z.object({send:a.z.boolean().optional(),interrupt:a.z.boolean().optional(),approval:a.z.boolean().optional(),fork:a.z.boolean().optional(),rename:a.z.boolean().optional(),openApp:a.z.boolean().optional(),close:a.z.boolean().optional()}),Xe=a.z.string().trim().min(1).max(240),Ye=a.z.discriminatedUnion("kind",[a.z.object({kind:a.z.literal("fork"),parentProviderSessionId:Xe,throughTurnId:a.z.string().trim().min(1).max(240).optional()}).strict(),a.z.object({kind:a.z.literal("subagent"),parentProviderSessionId:Xe}).strict()]),Je=a.z.preprocess(function(e){if(!e||"object"!=typeof e||Array.isArray(e))return;const t=e;if("fork"===t.kind){const e=Ye.safeParse({kind:"fork",parentProviderSessionId:t.parentProviderSessionId,..."string"==typeof t.throughTurnId?{throughTurnId:t.throughTurnId}:{}});return e.success?e.data:void 0}if("subagent"===t.kind){const e=Ye.safeParse({kind:"subagent",parentProviderSessionId:t.parentProviderSessionId});return e.success?e.data:void 0}},Ye.optional()),Qe=a.z.union([ze.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?pe:me;(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.`})}),ze.extend({source:a.z.object({type:a.z.literal("runtime-path"),path:a.z.string().trim().min(1).max(4096)}).strict()}).strict()]),Ze=ze.extend({sourceType:a.z.enum(["inline","runtime-path"])}).strict(),et=a.z.union([a.z.object({id:a.z.string().trim().min(1).max(120),kind:ve.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:ve,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()]),tt=a.z.enum(["auto","queue","steer","immediate"]),nt=a.z.enum(["ask","auto-review","full-access"]),it=a.z.enum(["review","rename","goal","compact"]);a.z.object({command:it,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:it,value:a.z.string().max(4e3).optional(),turnId:a.z.string().trim().min(1).max(240).optional()}).strict(),a.z.object({title:a.z.string().trim().max(120),expectedTitle:a.z.string().trim().max(240).optional(),clientRequestId:a.z.string().trim().min(1).max(160)}).strict(),a.z.object({disposition:a.z.enum(["renamed","already-named"]),aiSessionId:a.z.string().trim().min(1).max(120),appSessionId:a.z.string().trim().min(1).max(120).optional(),title:a.z.string().trim().max(120)}).strict(),a.z.enum(["skill","app","plugin"]);const st=a.z.object({name:a.z.string().trim().min(1).max(240),path:a.z.string().trim().min(1).max(4096)}),ot=a.z.discriminatedUnion("kind",[st.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(),st.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(),st.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()]),rt=a.z.array(ot).max(20).default([]),at=a.z.enum(["plugin","skill","file","directory","app"]),ct=a.z.object({kind:at,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."})}),dt=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(ct).max(1e3).default([]),diagnostics:a.z.array(dt).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(ct.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 lt=a.z.object({message:a.z.string().trim().min(1).max(2e4),mode:tt.optional(),permissionMode:nt.optional()}),ut=lt.extend({attachments:a.z.array(Qe).max(6).default([]),references:rt}).strict().superRefine((e,t)=>{e.attachments.reduce((e,t)=>e+("inline"===t.source.type?t.size:0),0)>fe&&t.addIssue({code:a.z.ZodIssueCode.custom,path:["attachments"],message:"Inline attachments must be 41943040 bytes or less in total."})}),pt=lt.extend({attachments:a.z.array(et).max(6).default([]),references:rt}).strict(),mt=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(),ht=a.z.object({modelEntityId:a.z.string().trim().min(1).max(120),modelName:a.z.string().trim().min(1).max(240)}).strict(),gt=a.z.enum(["none","minimal","low","medium","high","xhigh","max","ultra"]);ut.extend({agent:be,cwd:mt,cwdFolderId:a.z.string().trim().min(1).max(120).optional(),clientRequestId:a.z.string().trim().min(1).max(160),modelSelection:ht.optional(),reasoningEffort:gt.optional(),storyId:ue.optional()}).strict();const ft=a.z.object({mode:a.z.enum(["current-folder","worktree"]),branch:a.z.string().trim().min(1).max(1024)}).strict();pt.extend({agent:be,cwdFolderId:a.z.string().trim().min(1).max(120).optional(),gitSelection:ft.optional(),clientRequestId:a.z.string().trim().min(1).max(160),modelSelection:ht.optional(),reasoningEffort:gt.optional(),storyId:ue.optional()}).strict(),a.z.object({clientRequestId:a.z.string().trim().min(1).max(160),modelSelection:ht}).strict(),a.z.object({sessionId:a.z.string().trim().min(1).max(120),accepted:a.z.literal(!0)}).strict(),a.z.object({clientRequestId:a.z.string().trim().min(1).max(160),reasoningEffort:gt}).strict(),a.z.object({cwdFolderId:a.z.string().trim().min(1).max(120).optional(),branch:a.z.string().trim().min(1).max(1024)}).strict(),a.z.object({sessionId:a.z.string().trim().min(1).max(120),accepted:a.z.literal(!0)}).strict(),a.z.object({storyId:ue.nullable()}).strict(),a.z.object({sessionId:a.z.string().trim().min(1).max(120),storyId:ue.optional()}).strict(),a.z.object({disposition:a.z.enum(["created","already-created"]),aiSessionId:a.z.string().trim().min(1).max(120),providerSessionId:a.z.string().trim().min(1).max(240),creationSource:a.z.literal("ai-session")}).strict();const yt=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:yt.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:Se}).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:Se}).strict(),a.z.object({disposition:a.z.enum(["cleared","already-cleared"]),aiSessionId:a.z.string().trim().min(1).max(120),clearedSessionIds:a.z.array(a.z.string().trim().min(1).max(120))}).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(Ze).max(6).default([]),references:rt,permissionMode:nt.optional(),status:a.z.enum(["queued","sending","failed"]).default("queued"),createdAt:a.z.string().datetime(),updatedAt:a.z.string().datetime(),error:a.z.string().trim().max(4e3).optional()}).strict(),At=a.z.object({revision:a.z.number().int().min(0).default(0),pendingCount:a.z.number().int().min(0).default(0),items:a.z.array(It).max(100).default([])}).strict().default({revision:0,pendingCount:0,items:[]}),_t=a.z.enum(["control","realtime","adapter-snapshot","transcript-tail","transcript-scan","process-scan","app-session"]),Et=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(),Tt=a.z.object({id:a.z.string().trim().min(1).max(240),providerTurnId:a.z.string().trim().max(240).optional(),source:_t.optional(),userPrompt:a.z.string().trim().optional(),userMessages:a.z.array(xe).max(100).optional(),status:a.z.enum(["queued","running","waiting","completed","failed"]).default("running"),phase:De.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(Et).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(),wt=Tt.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(),bt=a.z.object({id:a.z.string().trim().min(1).max(120),agent:be,creationSource:Se.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:Je,providerMeta:a.z.record(a.z.string(),a.z.unknown()).optional(),modelSelection:ht.optional(),reasoningEffort:gt.optional(),storyId:ue.optional(),appBindingKeys:a.z.array(a.z.string().trim().min(1).max(240)).max(20).optional(),actions:We.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(Tt).max(50).optional(),status:ke.default("running"),phase:De.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:Pe.optional(),toolCallsSinceLastMessage:a.z.number().int().min(0).default(0),subAgents:Ke.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:Ge,queue:At}).strict(),St=bt.pick({id:!0,appBindingKeys:!0,cwd:!0,error:!0,providerMeta:!0,modelSelection:!0,reasoningEffort:!0,queue:!0,subAgents:!0}).strict(),vt=Tt.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(),Nt=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(vt).max(50)}).strict(),Ot=a.z.object({sessionId:a.z.string().trim().min(1).max(120),revision:a.z.string().trim().min(1).max(64),turn:Tt}).strict(),zt=a.z.string().trim().min(1).max(64),Ct=a.z.object({kind:a.z.literal("not-modified"),revision:zt}).strict();a.z.discriminatedUnion("kind",[Ct,a.z.object({kind:a.z.literal("updated"),revision:zt,detail:St}).strict()]),a.z.discriminatedUnion("kind",[Ct,a.z.object({kind:a.z.literal("updated"),revision:zt,index:Nt}).strict()]),a.z.discriminatedUnion("kind",[Ct,a.z.object({kind:a.z.literal("updated"),revision:zt,body:Ot}).strict()]);const Rt=a.z.object({session:bt,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(),xt=Rt.omit({session:!0}).extend({sessionId:a.z.string().trim().min(1).max(120),messageId:a.z.string().trim().min(1).max(240).optional()}).strict();a.z.object({sessionId:a.z.string().trim().min(1).max(120),queueRevision:a.z.number().int().min(0),action:a.z.enum(["retry","remove","edit","reorder"]),queueId:a.z.string().trim().min(1).max(120).optional()}).strict(),a.z.union([xt,Rt.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 xt.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 kt=a.z.object({id:a.z.string().trim().min(1).max(120),agent:be,creationSource:Se,providerSessionId:a.z.string().trim().min(1).max(240),lineage:Je,modelSelection:ht.optional(),reasoningEffort:gt.optional(),storyId: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(kt).max(1e4).default([])}).strict(),a.z.object({items:a.z.array(kt).max(1e4).default([])}).strict(),a.z.object({item:kt,turns:a.z.array(wt).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:Se}).strict();const Dt=Tt.omit({userMessages:!0}),Pt=bt.pick({id:!0,agent:!0,creationSource:!0,appSessionId:!0,appId:!0,providerSessionId:!0,lineage:!0,providerMeta:!0,modelSelection:!0,reasoningEffort:!0,storyId:!0,appBindingKeys:!0,actions:!0,activeTurnId:!0,title:!0,cwd:!0,cwdFolderId:!0,userPrompt:!0,turns:!0,status:!0,phase:!0,summary:!0,lastMessage:!0,lastMessageItemId:!0,currentTool:!0,toolCallsSinceLastMessage:!0,subAgents:!0,queue:!0,startedAt:!0,updatedAt:!0,error:!0}).extend({turns:a.z.array(Dt).max(50).optional(),detailRevision:a.z.string().trim().min(1).max(64).optional(),turnsRevision:a.z.string().trim().min(1).max(64).optional(),latestTurnRef:a.z.object({id:Tt.shape.id,bodyRevision:a.z.string().trim().min(1).max(64)}).strict().optional(),turnCount:a.z.number().int().min(0).optional(),subAgentCount:a.z.number().int().min(0).optional(),lastUserMessageAt:a.z.string().datetime().optional()}).strict(),Lt=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(Pt).default([]),updatedAt:a.z.string().datetime()}).strict(),Mt=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:Lt}).strict();Lt.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 jt=a.z.enum(["provider-event","app-session-created","app-session-updated","app-session-deleted","discovery-scan","control-action","heartbeat-sync","startup"]),Ut=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:jt}).strict(),Ft=a.z.object({meta:Ut,snapshot:Lt}).strict(),$t=a.z.object({meta:Ut,upserted:a.z.array(Pt).default([]),removed:a.z.array(a.z.string().trim().min(1).max(120)).default([])}).strict(),Ht=a.z.object({meta:Ut,sessionIds:a.z.array(a.z.string().trim().min(1).max(120)).default([]),expiresAt:a.z.string().datetime()}).strict(),qt=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(),Vt=qt.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:$e,generatedAt:a.z.string().datetime()}).strict();const Bt=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),field:a.z.literal("output"),delta:a.z.string().min(1),generatedAt:a.z.string().datetime()}).strict(),Kt=Bt.omit({instanceId:!0,nodeId:!0,providerSessionId:!0}).strict();function Gt(e){return Kt.parse({sessionId:e.sessionId,turnId:e.turnId,itemId:e.itemId,field:e.field,delta:e.delta,generatedAt:e.generatedAt})}function Wt(e,t){if(t?.subagents||"subagent"!==e.lineage?.kind)return e;const{lineage:n,...i}=e;return i}function Xt(e,t){return t?.subagents?e:{...e,sessions:e.sessions.map(e=>Wt(e,t))}}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(Ie),payload:Ft}).strict(),a.z.object({type:a.z.literal(Ae),payload:$t}).strict(),a.z.object({type:a.z.literal(_e),payload:Ht}).strict()])).default([])}).strict();const Yt=a.z.object({source:_t,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(),Jt=Yt.extend({type:a.z.literal("snapshot"),agent:a.z.string().trim().min(1).max(80),creationSource:Se.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:Ye.optional(),providerMeta:a.z.record(a.z.string(),a.z.unknown()).optional(),modelSelection:ht.optional(),reasoningEffort:gt.optional(),storyId:ue.optional(),appBindingKeys:a.z.array(a.z.string().trim().min(1).max(240)).max(20).optional(),actions:We.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(Tt).max(50).optional(),status:ke.optional(),phase:De.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:Pe.optional(),toolCallsSinceLastMessage:a.z.number().int().min(0).optional(),subAgents:Ke.optional(),transcriptPath:a.z.string().trim().max(4096).optional(),transcriptSize:a.z.number().int().min(0).optional(),replaceActivity:a.z.boolean().optional()}).strict(),Qt=Yt.extend({type:a.z.literal("event"),sessionId:a.z.string().trim().min(1).max(120),kind:a.z.enum(["lifecycle","send-ack","turn-started","user-message","assistant-message","approval-requested","turn-completed","session-error","tool-activity","sub-agent-activity","context-compaction","model-selection","reasoning-effort"]),modelSelection:ht.optional(),reasoningEffort:gt.optional(),activeTurnId:a.z.string().trim().max(240).optional(),providerTurnId:a.z.string().trim().max(240).optional(),userPrompt:a.z.string().trim().optional(),userMessage:xe.optional(),text:a.z.string().optional(),itemId:a.z.string().trim().max(240).optional(),status:ke.optional(),phase:De.optional(),summary:a.z.string().trim().max(1e3).optional(),error:a.z.string().trim().max(4e3).optional(),currentTool:Pe.nullable().optional(),toolCallsSinceLastMessage:a.z.number().int().min(0).optional(),subAgents:Ke.optional(),contextCompaction:Et.optional(),counters:a.z.object({toolCalls:a.z.number().int().min(0).optional(),edits:a.z.number().int().min(0).optional(),approvals:a.z.number().int().min(0).optional()}).strict().optional()}).strict().superRefine((e,t)=>{if("model-selection"===e.kind?e.modelSelection||t.addIssue({code:"custom",path:["modelSelection"],message:"model-selection events require modelSelection"}):void 0!==e.modelSelection&&t.addIssue({code:"custom",path:["modelSelection"],message:"modelSelection is only valid for model-selection events"}),"reasoning-effort"===e.kind?e.reasoningEffort||t.addIssue({code:"custom",path:["reasoningEffort"],message:"reasoning-effort events require reasoningEffort"}):void 0!==e.reasoningEffort&&t.addIssue({code:"custom",path:["reasoningEffort"],message:"reasoningEffort is only valid for reasoning-effort events"}),"session-error"!==e.kind||e.error||t.addIssue({code:"custom",path:["error"],message:"session-error events require error"}),"context-compaction"===e.kind?e.contextCompaction||t.addIssue({code:"custom",path:["contextCompaction"],message:"context-compaction events require contextCompaction"}):void 0!==e.contextCompaction&&t.addIssue({code:"custom",path:["contextCompaction"],message:"contextCompaction is only valid for context-compaction events"}),"send-ack"!==e.kind&&"user-message"!==e.kind&&void 0!==e.userMessage&&t.addIssue({code:"custom",path:["userMessage"],message:"userMessage is only valid for send-ack and user-message events"}),"sub-agent-activity"===e.kind?e.subAgents||t.addIssue({code:"custom",path:["subAgents"],message:"sub-agent-activity events require subAgents"}):void 0!==e.subAgents&&t.addIssue({code:"custom",path:["subAgents"],message:"subAgents is only valid for sub-agent-activity events"}),"tool-activity"!==e.kind)return void 0!==e.currentTool&&t.addIssue({code:"custom",path:["currentTool"],message:"currentTool is only valid for tool-activity events"}),void(void 0!==e.toolCallsSinceLastMessage&&t.addIssue({code:"custom",path:["toolCallsSinceLastMessage"],message:"toolCallsSinceLastMessage is only valid for tool-activity events"}));"currentTool"in e||t.addIssue({code:"custom",path:["currentTool"],message:"tool-activity events require currentTool"}),void 0===e.toolCallsSinceLastMessage&&t.addIssue({code:"custom",path:["toolCallsSinceLastMessage"],message:"tool-activity events require toolCallsSinceLastMessage"})});a.z.discriminatedUnion("type",[Jt,Qt]);const Zt=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()]),en=a.z.union([Zt,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()]),tn=a.z.object({promptTemplate:a.z.string().trim().min(1).max(2e4)}).strict(),nn=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(),sn=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:en,action:tn,policy:nn.default({maxConcurrentRuns:1,whenBusy:"skip"}),createdAt:a.z.string().datetime(),updatedAt:a.z.string().datetime()}).strict(),on=a.z.object({type:a.z.literal("ai-session"),aiSessionId:a.z.string().trim().min(1).max(160)}).strict(),rn=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:on,localName:a.z.string().trim().min(1).max(160).optional(),createdAt:a.z.string().datetime(),updatedAt:a.z.string().datetime()}).strict(),an=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(),cn=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:on,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(sn).default([]),deployments:a.z.array(rn).default([]),runtime:a.z.array(an).default([]),recentRuns:a.z.array(cn).default([])}).strict();const dn=a.z.object({config:sn,deployment:rn,runtime:an.optional()}).strict();a.z.object({instanceId:a.z.string().trim().min(1).max(160),sessionId:a.z.string().trim().min(1).max(160),mutation:dn.optional()}).strip(),a.z.object({instanceId:a.z.string().trim().min(1).max(160),sessionId:a.z.string().trim().min(1).max(160),configHash:sn.shape.configHash}).strip();const ln=a.z.object({instanceId:a.z.string().trim().min(1).max(160),instanceName:a.z.string().trim().min(1).max(160),deployment:rn,runtime:an.optional()}).strip(),un=cn.extend({instanceName:a.z.string().trim().min(1).max(160).optional()}).strip(),pn=a.z.object({configHash:a.z.string().trim().min(8).max(80),config:sn,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(ln),recentRuns:a.z.array(un)}).strip();a.z.object({updatedAt:a.z.string().datetime(),triggers:a.z.array(pn)}).strip(),a.z.object({name:sn.shape.name,description:sn.shape.description,source:en,action:tn,policy:nn.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 mn=a.z.string().regex(/^\d{4}-\d{2}-\d{2}$/,"Proxy protocol version must use YYYY-MM-DD format."),hn=a.z.string().trim().min(1).max(160).regex(/^[a-zA-Z0-9][a-zA-Z0-9_.:-]*$/),gn=a.z.string().datetime(),fn=a.z.string().trim().min(32).max(4096),yn=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 In=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"})),An=a.z.object({code:In,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(),_n=a.z.enum(["active","revoked"]),En=a.z.object({id:hn,targetNodeId:hn,status:_n,createdBy:hn,expiresAt:gn,revokedAt:gn.optional(),createdAt:gn,updatedAt:gn}).strict();a.z.object({targetNodeId:hn,expiresInSeconds:a.z.number().int().min(60).max(3600).default(600)}).strict(),a.z.object({invite:En,token:a.z.string().trim().min(24).max(512),proxyOrigin:yn,protocolVersion:mn}).strict();const Tn=a.z.enum(["active","revoked"]),wn=a.z.object({id:hn,claimId:hn,sourceControlPlaneId:hn,targetNodeId:hn,bindingKeyId:hn,status:Tn,revision:a.z.number().int().positive(),lastError:An.optional(),revokedAt:gn.optional(),createdAt:gn,updatedAt:gn}).strict();a.z.object({protocolVersion:mn,inviteToken:a.z.string().trim().min(24).max(512).optional(),claimId:hn,sourceControlPlaneId:hn,targetNodeId:hn.optional(),bindingKeyId:hn,credential:fn}).strict(),a.z.object({sourceControlPlaneId:hn,bindingKeyId:hn,credential:fn}).strict();const bn=a.z.object({id:hn,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:gn.optional(),capabilities:a.z.record(a.z.string(),a.z.unknown()).default({})}).strict(),Sn=a.z.object({protocolVersion:mn,binding:wn,streamId:hn,revision:a.z.number().int().nonnegative(),observedAt:gn,target:bn}).strict(),vn=a.z.object({type:a.z.literal("control-plane-proxy.event"),protocolVersion:mn,streamId:hn,bindingId:hn,sourceControlPlaneId:hn,targetNodeId:hn,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:bn,event:a.z.object({type:a.z.string().trim().min(1).max(240),topic:a.z.string().trim().min(1).max(240),createdAt:gn}).strict()}).strict(),Nn=a.z.object({type:a.z.literal("control-plane-proxy.events.ready"),protocolVersion:mn,streamId:hn,bindingId:hn,sourceControlPlaneId:hn,targetNodeId:hn,latestRevision:a.z.number().int().nonnegative(),earliestRetainedRevision:a.z.number().int().nonnegative()}).strict(),On=a.z.object({type:a.z.literal("control-plane-proxy.snapshot-required"),protocolVersion:mn,streamId:hn,bindingId:hn,sourceControlPlaneId:hn,targetNodeId:hn,sinceRevision:a.z.number().int().nonnegative(),latestRevision:a.z.number().int().nonnegative(),earliestRetainedRevision:a.z.number().int().nonnegative(),error:An}).strict();a.z.discriminatedUnion("type",[vn,Nn,On]),a.z.object({protocolVersion:mn,binding:wn,target:Sn.shape.target}).strict(),a.z.object({id:hn,claimId:hn,proxyOrigin:yn,requestedName:a.z.string().trim().min(1).max(160).optional(),sourceControlPlaneId:hn,targetNodeId:hn.optional(),bindingKeyId:hn,credential:fn,status:a.z.enum(["pending","compensation-required"]),createdAt:gn,updatedAt:gn,expiresAt:gn}).strict().omit({credential:!0}),a.z.object({id:hn,nodeId:hn,proxyOrigin:yn,proxyBindingId:hn,targetNodeId:hn,sourceControlPlaneId:hn,bindingKeyId:hn,credential:fn,createdAt:gn,updatedAt:gn}).strict();const zn=a.z.string().trim().min(1).max(120),Cn=a.z.object({selectModelAtCreate:a.z.boolean().default(!1),selectProviderAtCreate:a.z.boolean().default(!1),switchModelWithinProvider:a.z.boolean().default(!1),switchProviderDuringSession:a.z.boolean().default(!1)}).strip().default({selectModelAtCreate:!1,selectProviderAtCreate:!1,switchModelWithinProvider:!1,switchProviderDuringSession:!1}),Rn=a.z.object({selectAtCreate:a.z.boolean().default(!1),updateDuringSession:a.z.boolean().default(!1)}).strip().default({selectAtCreate:!1,updateDuringSession:!1}),xn=a.z.object({subagents:a.z.boolean().default(!1)}).strip().default({subagents:!1}),kn=a.z.object({agent:zn,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),rename:a.z.boolean().default(!1),approvalDecisions:a.z.array(a.z.enum(["allow","deny","skip"])).max(3).default([])}).passthrough(),permissionModes:a.z.array(a.z.enum(["ask","auto-review","full-access"])).max(3).default([]),timeline:a.z.object({sessionRead:a.z.boolean().default(!1),turnRead:a.z.boolean().default(!1),liveItems:a.z.boolean().default(!1)}).passthrough(),modelSelection:Cn.optional(),reasoningEffort:Rn.optional(),hierarchy:xn.optional()}).passthrough(),Dn=a.z.array(kn).max(100).default([]),Pn="2026-09-17",Ln=new Set(["2026-08-01","2026-08-16","2026-08-17","2026-08-20",Pn]),Mn=a.z.string().regex(/^\d{4}-\d{2}-\d{2}$/,"Protocol version must use YYYY-MM-DD format."),jn=a.z.string().trim().min(1).max(120),Un=a.z.enum(["low","medium","high"]),Fn=a.z.enum(["none","friendly","pragmatic"]),$n=a.z.object({modelEntityId:a.z.string().trim().min(1).max(120),modelName:a.z.string().trim().min(1).max(240)}).strict(),Hn=a.z.object({modelVerbosity:Un.optional(),personality:Fn.optional(),multiAgent:a.z.object({enabled:a.z.boolean().default(!0),maxConcurrentThreads:a.z.number().int().min(1).max(64).optional(),defaultModel:$n.optional(),defaultReasoningEffort:gt.optional()}).strict().default({enabled:!0})}).strict();function qn(){return{features:{appRuntime:!1,tty:!1,gui:!1,browser:!1,browserTunnel:!1,screenshots:!1,logs:!1,aiSessionWorkspaceSelection:!1,aiSessionWorkspaceCheckout:!1,aiSessionPersistenceSettings:!1,privateModelCatalog:!1,codexManagedSettings:!1,nodeAgentConnectionUpdate:!1,gitCliCredentialBroker:!1,gitCredentialProxy:!1,aiSessionTimeline:{sessionReadAgents:[],turnReadAgents:[],liveItemAgents:[]},aiSessionConversationAttachments:{metadataAgents:[],contentAgents:[],uploadAgents:[],retentionSettings:!1,fileSizeLimitSettings:!1},aiSessionProviders:[]}}}const Vn=a.z.object({sessionReadAgents:a.z.array(jn).max(100).default([]),turnReadAgents:a.z.array(jn).max(100).default([]),liveItemAgents:a.z.array(jn).max(100).default([])}).passthrough(),Bn=a.z.object({metadataAgents:a.z.array(jn).max(100).default([]),contentAgents:a.z.array(jn).max(100).default([]),uploadAgents:a.z.array(jn).max(100).default([]),retentionSettings:a.z.boolean().default(!1),fileSizeLimitSettings:a.z.boolean().default(!1)}).passthrough(),Kn=a.z.object({appRuntime:a.z.boolean().default(!1),tty:a.z.boolean().default(!1),gui:a.z.boolean().default(!1),browser:a.z.boolean().default(!1),browserTunnel:a.z.boolean().optional(),screenshots:a.z.boolean().default(!1),logs:a.z.boolean().default(!1),aiSessionWorkspaceSelection:a.z.boolean().default(!1),aiSessionWorkspaceCheckout:a.z.boolean().optional(),aiSessionPersistenceSettings:a.z.boolean().default(!1),privateModelCatalog:a.z.boolean().optional(),codexManagedSettings:a.z.boolean().optional(),nodeAgentConnectionUpdate:a.z.boolean().optional(),gitCliCredentialBroker:a.z.boolean().optional(),gitCredentialProxy:a.z.boolean().optional(),aiSessionTimeline:Vn.default(function(){return{sessionReadAgents:[],turnReadAgents:[],liveItemAgents:[]}}),aiSessionConversationAttachments:Bn.optional(),aiSessionProviders:Dn.optional()}).passthrough(),Gn=a.z.object({features:Kn.default(function(){return{appRuntime:!1,tty:!1,gui:!1,browser:!1,browserTunnel:!1,screenshots:!1,logs:!1,aiSessionWorkspaceSelection:!1,aiSessionWorkspaceCheckout:!1,aiSessionPersistenceSettings:!1,privateModelCatalog:!1,codexManagedSettings:!1,nodeAgentConnectionUpdate:!1,gitCliCredentialBroker:!1,gitCredentialProxy:!1,aiSessionTimeline:{sessionReadAgents:[],turnReadAgents:[],liveItemAgents:[]},aiSessionConversationAttachments:{metadataAgents:[],contentAgents:[],uploadAgents:[],retentionSettings:!1,fileSizeLimitSettings:!1},aiSessionProviders:[]}})}).passthrough(),Wn=a.z.object({nodeAgentUrl:a.z.string().trim().url().max(2048).refine(e=>{const t=new URL(e);return/^https?:$/.test(t.protocol)&&!t.username&&!t.password&&"/"===t.pathname&&!t.search&&!t.hash},"Node agent URL must be an HTTP(S) origin.")}).strict();function Xn(e){const t={features:{appRuntime:!1,tty:!1,gui:!1,browser:!1,browserTunnel:!1,screenshots:!1,logs:!1,aiSessionWorkspaceSelection:!1,aiSessionWorkspaceCheckout:!1,aiSessionPersistenceSettings:!1,privateModelCatalog:!1,codexManagedSettings:!1,nodeAgentConnectionUpdate:!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,o={appRuntime:!1,tty:!1,gui:!1,browser:!1,browserTunnel:!1,screenshots:!1,logs:!1,aiSessionWorkspaceSelection:!1,aiSessionWorkspaceCheckout:!1,aiSessionPersistenceSettings:!1,privateModelCatalog:!1,codexManagedSettings:!1,nodeAgentConnectionUpdate:!1,gitCliCredentialBroker:!1,gitCredentialProxy:!1,aiSessionTimeline:{sessionReadAgents:[],turnReadAgents:[],liveItemAgents:[]},aiSessionConversationAttachments:{metadataAgents:[],contentAgents:[],uploadAgents:[],retentionSettings:!1,fileSizeLimitSettings:!1},aiSessionProviders:[]};for(const e of["appRuntime","tty","gui","browser","browserTunnel","screenshots","logs","aiSessionWorkspaceSelection","aiSessionWorkspaceCheckout","aiSessionPersistenceSettings","privateModelCatalog","codexManagedSettings","nodeAgentConnectionUpdate","gitCliCredentialBroker","gitCredentialProxy"]){const t=a.z.boolean().safeParse(s[e]);t.success&&(o[e]=t.data)}const r=Vn.safeParse(s.aiSessionTimeline);r.success&&(o.aiSessionTimeline=r.data);const c=Bn.safeParse(s.aiSessionConversationAttachments);c.success&&(o.aiSessionConversationAttachments=c.data);const d=Dn.safeParse(s.aiSessionProviders);return d.success&&(o.aiSessionProviders=d.data),Gn.parse({...n,features:{...s,...o}})}function Yn(e){return Xn(e).features.aiSessionConversationAttachments}const Jn=a.z.string().trim().min(1).max(120).regex(/^[a-zA-Z0-9][a-zA-Z0-9_.:-]*$/),Qn=a.z.string().datetime(),Zn=a.z.record(a.z.string(),a.z.string()).default({}),ei=a.z.record(a.z.string(),a.z.string()).default({}),ti=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 ni(e){if(null==e)return;const t=ti.parse(e);return"utf8"===t.encoding?t.data:Buffer.from(t.data,"base64")}const ii=/^[A-Za-z0-9_][A-Za-z0-9_.-]{0,127}$/,si=/^sha256:([a-fA-F0-9]{64})$/,oi=/^(?:localhost|[a-z0-9](?:[a-z0-9.-]*[a-z0-9])?)(?::[1-9][0-9]{0,4})?$/,ri=/^[a-z0-9]+(?:(?:[._]|__|-+)[a-z0-9]+)*$/;function ai(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),o=i?si.exec(i):void 0;if(i&&!o)throw new Error("Docker image digest must use sha256 followed by 64 hexadecimal characters.");const r=s.lastIndexOf("/"),a=s.lastIndexOf(":"),c=a>r,d=c?s.slice(a+1):void 0,l=c?s.slice(0,a):s;if(d&&!ii.test(d))throw new Error("Docker image tag is invalid.");if(!d&&!o)throw new Error("Docker image reference must include an explicit tag or sha256 digest.");const u=l.split("/");if(!u.length||u.some(e=>!e))throw new Error("Docker image repository path is invalid.");const p=u.length>1&&(u[0].includes(".")||u[0].includes(":")||"localhost"===u[0]),m=p?u.slice(1):u;if(p&&!oi.test(u[0].toLowerCase()))throw new Error("Docker image registry host or port is invalid.");if(!m.length||m.some(e=>!ri.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=o?`sha256:${o[1].toLowerCase()}`:void 0;return`${h}${d?`:${d}`:""}${g?`@${g}`:""}`}function ci(e){const t=ai(e),n=t.indexOf("@"),i=-1===n?void 0:t.slice(n+1),s=-1===n?t:t.slice(0,n),o=s.lastIndexOf("/"),r=s.lastIndexOf(":"),a=r>o;return{reference:t,repository:a?s.slice(0,r):s,tag:a?s.slice(r+1):void 0,digest:i}}const di=a.z.string().trim().min(1).max(512).transform((e,t)=>{try{return ai(e)}catch(e){return t.addIssue({code:"custom",message:e instanceof Error?e.message:String(e)}),a.z.NEVER}}),li=a.z.string().trim().transform((e,t)=>{const n=si.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)}),ui=a.z.object({modelEntityIds:a.z.array(Jn).max(64).transform(e=>[...new Set(e)]).optional(),codexModelHash:Jn.nullable().optional(),claudeModelHash:Jn.nullable().optional(),opencodeModelHash:Jn.nullable().optional()}).strict().default({}),pi=a.z.object({imageId:Jn,tag:a.z.string().trim().min(1).max(128).regex(ii).optional()}).strict(),mi=a.z.discriminatedUnion("type",[a.z.object({type:a.z.literal("image"),imageSelection:pi}).strict(),a.z.object({type:a.z.literal("template"),environmentTemplateId:Jn}).strict()]),hi=a.z.enum(["creating","ready","failed","deleting"]),gi=a.z.enum(["linux","darwin","win32","freebsd","openbsd","aix","sunos","unknown"]),fi=a.z.enum(["x64","arm64","arm","ia32","ppc64","s390x","riscv64","unknown"]),yi=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(),Ii=a.z.object({templateId:Jn,nodeId:Jn,imageId:li,name:a.z.string().trim().min(1).max(160),platform:gi,architecture:fi}).strict(),Ai=a.z.enum(["data","agent-home","workspace"]),_i=a.z.object({deleteVolumes:a.z.boolean()}).strict(),Ei=a.z.object({role:Ai,name:a.z.string().trim().min(1).max(255),mountPath:a.z.string().trim().startsWith("/").max(4096),status:a.z.enum(["deleted","retained","missing","failed"]),error:a.z.object({code:a.z.string().trim().min(1).max(120),message:a.z.string().trim().min(1).max(2048)}).strict().optional()}).strict(),Ti=a.z.object({instanceId:Jn,containerDeleted:a.z.boolean(),completed:a.z.boolean(),deletedVolumes:a.z.array(Ei),retainedVolumes:a.z.array(Ei),volumeResults:a.z.array(Ei)}).strict(),wi={img_default:"market_taskhandoff_browser",img_codex:"market_taskhandoff_codex",img_ai:"market_taskhandoff_ai"};function bi(e,t){if(e&&"object"==typeof e&&!Array.isArray(e)){const t=e;return{imageId:"string"==typeof t.imageId&&wi[t.imageId]||t.imageId,..."string"==typeof t.tag?{tag:t.tag}:{}}}if("string"==typeof t)return{imageId:wi[t]||t}}function Si(e){if(!e||"object"!=typeof e||Array.isArray(e))return e;const t=e,{defaultImageId:n,...i}=t;return{...i,defaultImageSelection:bi(t.defaultImageSelection,n)}}const vi=a.z.object({id:Jn,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(),Ni=a.z.object({code:a.z.enum(["APP_CATALOG_INVALID"]),message:a.z.string().trim().min(1).max(500)}).strict(),Oi=a.z.object({items:a.z.array(vi).max(256),observedAt:Qn,issues:a.z.array(Ni).max(32).default([])}).strict(),zi=a.z.object({id:Jn,name:a.z.string().trim().min(1).max(160),sourceInstanceId:Jn,nodeId:Jn,imageId:li.optional(),internalTag:a.z.string().trim().min(1).max(512).optional(),platform:gi.optional(),architecture:fi.optional(),sizeBytes:a.z.number().int().nonnegative().optional(),status:hi,error:yi.optional(),createdAt:Qn,updatedAt:Qn}).strict().superRefine((e,t)=>{if("ready"===e.status)for(const n of["imageId","internalTag","platform","architecture","sizeBytes"])void 0===e[n]&&t.addIssue({code:"custom",path:[n],message:`Ready environment template requires ${n}.`});"failed"!==e.status||e.error||t.addIssue({code:"custom",path:["error"],message:"Failed environment template requires an error diagnostic."})}),Ci=a.z.enum(["apt","dnf","brew","npm"]),Ri=a.z.enum(["user","passwordless-sudo","root"]),xi=a.z.object({platform:gi,arch:fi,installers:a.z.array(Ci).max(8),privilege:Ri,installerAccess:a.z.object({npmGlobalWritable:a.z.boolean().optional()}).strict().optional()}).strict(),ki=a.z.enum(["installed","not-installed","broken","unsupported"]),Di=a.z.enum(["recipe","bundled","external","none"]),Pi=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(),Li=a.z.object({id:Jn,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:ki,managementSource:Di,version:a.z.string().trim().max(120).optional(),canInstall:a.z.boolean(),canUninstall:a.z.boolean(),installReason:Pi.optional(),uninstallReason:Pi.optional(),activeJobId:Jn.optional()}).strict(),Mi=a.z.enum(["install","uninstall"]),ji=a.z.enum(["queued","running","succeeded","failed","cancelled","interrupted"]),Ui=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"]}),Fi=a.z.object({executable:a.z.string().trim().min(1).max(4096),args:a.z.array(a.z.string().max(4096)).max(128)}).strict(),$i=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(Jn).max(64).optional()}).strict(),Hi=a.z.object({id:Jn,requestId:Jn.optional(),appId:Jn,operation:Mi,state:ji,phase:a.z.string().trim().min(1).max(120).optional(),progress:Ui.optional(),command:Fi.optional(),logTail:a.z.string().max(32768).optional(),logTruncated:a.z.boolean().optional(),error:$i.optional(),requestedAt:Qn,startedAt:Qn.optional(),finishedAt:Qn.optional(),updatedAt:Qn}).strict(),qi=a.z.object({streamId:Jn,sequence:a.z.number().int().nonnegative(),capabilities:xi,apps:a.z.array(Li).max(256),activeJobs:a.z.array(Hi).max(256),recentJobs:a.z.array(Hi).max(256),observedAt:Qn}).strict();a.z.object({requestId:Jn.optional()}).strict(),a.z.object({job:Hi}).strict(),a.z.object({type:a.z.literal("app-management"),streamId:Jn,sequence:a.z.number().int().nonnegative(),observedAt:Qn,job:Hi.optional(),snapshot:qi.optional()}).strict().refine(e=>void 0!==e.job||void 0!==e.snapshot,{message:"An app management event requires a job or snapshot."});const Vi=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:Mn.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:Mn,build:Vi.extend({component:a.z.literal("control-plane"),packageVersion:a.z.string().trim().min(1).max(80)}).loose(),serverTime:Qn}).loose()}).loose();const Bi=a.z.enum(["stable","beta","alpha"]),Ki=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(),Gi=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(),Wi=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:Qn.optional(),matchedAt:Qn.optional(),error:Gi.optional()}).strict(),Xi=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(Jn).max(1024).default([]),stoppedInstanceIds:a.z.array(Jn).max(1024).default([]),activeInstanceIds:a.z.array(Jn).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(Jn).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(),Ji=a.z.object({channel:Bi.default("stable")}).strict(),Qi=a.z.object({source:a.z.literal("npm"),channel:Bi,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(Ki).default([]),impact:Xi,updateAvailable:a.z.boolean(),supported:a.z.boolean().default(!0),reason:a.z.string().trim().max(2048).optional(),checkedAt:Qn,preflightToken:a.z.string().trim().min(16).max(240).optional()}).strict(),Zi=a.z.object({id:Jn,nodeId:Jn,source:a.z.literal("npm"),channel:Bi,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(Ki).default([]),impact:Xi,rollout:Yi,status:a.z.enum(["queued","updating-node","restarting-node","converging-instances","succeeded","degraded","failed"]),error:Gi.optional(),startedAt:Qn.optional(),completedAt:Qn.optional(),createdAt:Qn,updatedAt:Qn}).strict(),es=a.z.object({channel:Bi,targetVersion:a.z.string().trim().min(1).max(240),preflightToken:a.z.string().trim().min(16).max(240)}).strict(),ts=a.z.object({type:a.z.enum(["branch","tag"]),name:a.z.string().trim().min(1).max(240)}).strict(),ns=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(),is=a.z.discriminatedUnion("type",[ts,ns]),ss=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(),os=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:Jn,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:is.default({type:"branch",name:"main"}),auth:ss.default({type:"none"}),clone:os.default({submodules:!1,lfs:!1,subdirectory:""}),defaultImageSelection:pi.optional(),labels:Zn,createdAt:Qn,updatedAt:Qn}).strict();const rs=a.z.object({id:Jn,nodeId:Jn,name:a.z.string().trim().min(1).max(160),path:a.z.string().trim().min(1).max(4096),defaultImageSelection:pi.optional(),labels:Zn,createdAt:Qn,updatedAt:Qn}).strict(),as=a.z.discriminatedUnion("type",[a.z.object({type:a.z.literal("git-repository"),repositoryId:Jn.optional(),url:a.z.string().trim().min(1).max(2048),provider:a.z.string().trim().max(80).optional(),ref:is.default({type:"branch",name:"main"}),auth:ss.default({type:"none"}),clone:os.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:is.default({type:"branch",name:"main"}),auth:ss.default({type:"none"}),clone:os.default({submodules:!1,lfs:!1,subdirectory:""})}).strict(),a.z.object({type:a.z.literal("local-folder"),localFolderId:Jn.optional(),path:a.z.string().trim().min(1).max(4096),ownerNodeId:Jn.optional()}).strict()]),cs=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(),ds=a.z.enum(["codex","claude","opencode"]),ls=a.z.enum(["openai-responses","openai-chat-completions","anthropic-messages"]),us=a.z.object({name:a.z.string().trim().min(1).max(240),order:a.z.number().int().min(0).max(1e6).default(0)}).strict(),ps=a.z.object({id:Jn,name:a.z.string().trim().min(1).max(160),source:as,defaultImageSelection:pi.optional(),defaultNodeId:Jn.optional(),workspacePolicy:cs,labels:Zn,createdAt:Qn,updatedAt:Qn}).strict(),ms=a.z.object({id:Jn,name:a.z.string().trim().min(1).max(160),endpoint:a.z.string().trim().min(1).max(2048),key:a.z.string().trim().min(1).max(4096),model:a.z.string().trim().min(1).max(240),modelNames:a.z.array(us).max(256).default([]),protocols:a.z.array(ls).max(3).default([]),app:ds,enabled:a.z.boolean().default(!0),order:a.z.number().int().min(0).max(1e6).default(0),labels:Zn,createdAt:Qn,updatedAt:Qn}).strict(),hs=ms,gs=ms.omit({key:!0}).extend({keyPreview:a.z.string().trim().min(1).max(160),keySet:a.z.boolean()}).strict(),fs=gs.extend({referenceCount:a.z.number().int().min(0)}).strict(),ys=a.z.object({instanceId:Jn,modelEntityIds:a.z.array(Jn).max(64).transform(e=>[...new Set(e)]).optional(),codexModelHash:Jn.optional(),claudeModelHash:Jn.optional(),opencodeModelHash:Jn.optional(),updatedAt:Qn}).strict().transform(e=>({...e,modelEntityIds:e.modelEntityIds?.length?e.modelEntityIds:[...new Set([e.codexModelHash,e.claudeModelHash,e.opencodeModelHash].filter(e=>Boolean(e)))]})),Is=a.z.discriminatedUnion("type",[a.z.object({type:a.z.literal("control-plane"),name:ms.shape.name,enabled:ms.shape.enabled,order:ms.shape.order}).strict(),a.z.object({type:a.z.literal("node"),nodeId:Jn,name:ms.shape.name,enabled:ms.shape.enabled,order:ms.shape.order,referenceCount:a.z.number().int().min(0)}).strict()]),As=a.z.object({id:Jn,model:gs,locations:a.z.array(Is).min(1),referenceCount:a.z.number().int().min(0).default(0)}).strict(),_s=a.z.object({nodeId:Jn,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(As),nodeDiagnostics:a.z.array(_s).default([]),updatedAt:Qn}).strict();const Es=ms.omit({id:!0,createdAt:!0,updatedAt:!0}).strict(),Ts=Es.partial().strict(),ws=ms,bs=a.z.object({modelSelection:ui,modelEntityIds:a.z.array(Jn).max(64).transform(e=>[...new Set(e)]).optional(),codexModelHash:Jn.optional(),claudeModelHash:Jn.optional(),opencodeModelHash:Jn.optional()}).strict().transform(e=>({...e,modelEntityIds:e.modelEntityIds||e.modelSelection.modelEntityIds||[...new Set([e.codexModelHash,e.claudeModelHash,e.opencodeModelHash].filter(e=>Boolean(e)))]}));function Ss(e){const t={app:ds.parse(e.app),endpoint:ms.shape.endpoint.parse(e.endpoint),key:ms.shape.key.parse(e.key),model:ms.shape.model.parse(e.model)};return`mdl_${d.createHash("sha256").update(JSON.stringify(t)).digest("hex")}`}const vs=a.z.enum(["market","custom"]),Ns=a.z.enum(["active","deprecated","yanked"]),Os=a.z.discriminatedUnion("kind",[a.z.object({kind:a.z.literal("builtin"),key:a.z.string().trim().min(1).max(120)}).strict(),a.z.object({kind:a.z.literal("remote"),url:a.z.string().trim().url().max(2048),mediaType:a.z.enum(["image/png","image/jpeg","image/webp"]).optional(),digest:li.optional()}).strict()]),zs=a.z.array(a.z.string().trim().min(1).max(80)).default([]),Cs=a.z.array(a.z.string().trim().min(1).max(120)).default([]),Rs=a.z.record(a.z.string().trim().min(2).max(35),a.z.string().trim().min(1).max(4096)),xs=a.z.object({os:a.z.string().trim().min(1).max(40),architecture:a.z.string().trim().min(1).max(40),digest:li.optional(),downloadSizeBytes:a.z.number().int().positive().optional(),unpackedSizeBytes:a.z.number().int().positive().optional()}).strict(),ks=a.z.object({name:a.z.string().trim().min(1).max(128).regex(ii),version:a.z.string().trim().min(1).max(160).optional(),reference:di,manifestDigest:li.optional(),publishedAt:Qn.optional(),platforms:a.z.array(xs).default([]),status:Ns.default("active")}).strict(),Ds=a.z.object({id:Jn,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:Rs.optional(),cover:Os.optional(),repository:a.z.string().trim().min(1).max(512),defaultTag:a.z.string().trim().min(1).max(128).regex(ii),tags:a.z.array(ks).min(1),capabilities:zs,optionalApps:Cs,defaultEnv:ei,labels:Zn,status:Ns.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:Mn,catalogId:Jn,revision:a.z.string().trim().min(1).max(240),source:a.z.enum(["embedded","remote","cache"]),generatedAt:Qn,expiresAt:Qn.optional(),items:a.z.array(Ds)}).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:Qn,error:a.z.string().trim().max(4096).optional()}).strict(),a.z.object({id:Jn,origin:a.z.literal("custom"),name:a.z.string().trim().min(1).max(160),description:a.z.string().trim().max(4096).optional(),localizedDescriptions:Rs.optional(),cover:Os.optional(),reference:di,repository:a.z.string().trim().min(1).max(512),tag:a.z.string().trim().min(1).max(128).regex(ii).optional(),pullPolicy:a.z.literal("if-not-present").default("if-not-present"),capabilities:zs,optionalApps:Cs,defaultEnv:ei,labels:Zn,createdAt:Qn,updatedAt:Qn}).strict();const Ps=a.z.object({name:a.z.string().trim().min(1).max(128).regex(ii),version:a.z.string().trim().min(1).max(160).optional(),reference:di,manifestDigest:li.optional(),status:Ns}).strict(),Ls=a.z.object({id:Jn,origin:vs,name:a.z.string().trim().min(1).max(160),description:a.z.string().trim().max(4096).optional(),localizedDescriptions:Rs.optional(),cover:Os,repository:a.z.string().trim().min(1).max(512),tag:a.z.string().trim().min(1).max(128).regex(ii).optional(),availableTags:a.z.array(Ps),reference:di,digest:li.optional(),downloadSizeBytes:a.z.number().int().positive().optional(),unpackedSizeBytes:a.z.number().int().positive().optional(),capabilities:zs,optionalApps:Cs,defaultEnv:ei,labels:Zn,readOnly:a.z.boolean(),lifecycleStatus:Ns.optional(),market:a.z.object({catalogId:Jn,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(),Ms=a.z.object({id:Jn,origin:vs,name:a.z.string().trim().min(1).max(160),description:a.z.string().trim().max(4096).optional(),localizedDescriptions:Rs.optional(),cover:Os.optional(),repository:a.z.string().trim().min(1).max(512),tag:a.z.string().trim().min(1).max(128).regex(ii).optional(),requestedReference:di,resolvedDigest:li.optional(),resolvedReference:di.optional(),downloadSizeBytes:a.z.number().int().positive().optional(),pullPolicy:a.z.literal("if-not-present").default("if-not-present"),capabilities:zs,optionalApps:Cs,defaultEnv:ei,labels:Zn,market:a.z.object({catalogId:Jn,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:Qn,updatedAt:Qn}).strict(),js=a.z.object({phase:a.z.enum(["checking-image","pulling-image","resolving-image","ready","failed"]),requestedReference:di,generation:a.z.number().int().nonnegative().default(0),error:a.z.string().trim().max(4096).optional(),startedAt:Qn,updatedAt:Qn}).strict(),Us="image.pull.terminal.output",Fs="image.pull.terminal.finished",$s=a.z.object({instanceId:Jn,generation:a.z.number().int().nonnegative(),requestedReference:di,sequence:a.z.number().int().nonnegative(),observedAt:Qn}).strict(),Hs=$s.extend({data:a.z.string().min(1).max(65536),replay:a.z.boolean().optional()}).strict(),qs=$s.extend({outcome:a.z.enum(["succeeded","failed"])}).strict();$s.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 Vs=a.z.discriminatedUnion("kind",[a.z.object({kind:a.z.literal("direct")}).strict(),a.z.object({kind:a.z.literal("control-plane-proxy"),proxyId:Jn,proxyBindingId:Jn,targetNodeId:Jn}).strict()]),Bs=a.z.object({pingRttMs:a.z.number().nonnegative().optional(),pingRttP95Ms:a.z.number().nonnegative().optional(),consecutiveReconnects:a.z.number().int().nonnegative(),nextRetryAt:Qn.optional()}).strict();a.z.object({nodeId:Jn,inviteId:Jn.optional()}).strict(),a.z.discriminatedUnion("status",[a.z.object({id:Jn,status:a.z.literal("pending")}).strict(),a.z.object({id:Jn,status:a.z.literal("completed"),nodeId:Jn}).strict()]);const Ks=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:Qn.optional(),target:bn.optional(),lastError:An.optional(),updatedAt:Qn}).strict(),Gs=a.z.object({id:Jn,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:Vs.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:Jn.optional(),secret:a.z.string().trim().max(4096).optional(),pairedAt:Qn.optional(),pairing:a.z.object({status:a.z.enum(["pending","paired","expired"]).default("pending"),joinToken:a.z.string().trim().max(4096).optional(),expiresAt:Qn.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:Ks.optional(),appInventory:Oi.optional(),labels:Zn,lastSeenAt:Qn.optional(),createdAt:Qn,updatedAt:Qn}).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:Jn,status:a.z.enum(["unknown","online","offline","degraded"]),health:a.z.enum(["unknown","ok","degraded","failed"]),lastSeenAt:Qn.nullable(),connectionPhase:a.z.enum(["connecting","handshaking","healthy","reconnecting","suspect","offline"]).nullable(),connectionDiagnostics:Bs.nullable(),proxyState:Ks.nullable()}).strict();const Ws=a.z.object({id:Jn,nodeId:Jn,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:Zn,createdAt:Qn,updatedAt:Qn}).strict(),Xs=a.z.object({instanceId:Jn,runtimeKind:a.z.literal("docker"),state:a.z.enum(["pending","available","stopped","unavailable"]),sampledAt:Qn,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(),Ys=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(),Js=a.z.object({multiEntityAssignment:a.z.boolean().default(!1),privateModelCatalog:a.z.boolean().default(!1)}).strip(),Qs=a.z.object({enabled:a.z.boolean().default(!1),agentTools:a.z.boolean().default(!1),sessionRetention:a.z.boolean().default(!1),maxFileBytes:a.z.number().int().positive().default(33554432),maxBatchPaths:a.z.number().int().min(1).max(100).default(20)}).strip(),Zs=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:Ys.optional(),managedModels:Js.optional(),stories:Qs.optional(),codexManagedSettings:a.z.boolean().optional()}).strip(),eo=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:Qn.optional(),lastCongestedAt:Qn.optional()}).strip();a.z.object({ok:a.z.boolean().optional(),role:a.z.string().optional(),nodeId:Jn.optional(),platform:gi.optional(),arch:fi.optional(),protocolVersion:Mn.optional(),capabilities:Zs.optional(),build:Vi.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:eo.optional(),serverTime:Qn.optional()}).strip();const to=a.z.object({bindScope:a.z.enum(["loopback","all-ipv4"]),port:a.z.number().int().min(1).max(65535)}).strict(),no=to.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(),io=to;a.z.object({nodeId:Jn,joinToken:a.z.string().trim().min(1),expiresAt:Qn}).passthrough(),a.z.object({nodeId:Jn,keyId:Jn,secret:a.z.string().regex(/^[A-Za-z0-9_-]{32,128}$/),pairedAt:Qn}).strict();const so=a.z.object({id:Jn,keyId:Jn,name:a.z.string().trim().min(1).max(160).optional(),pairedAt:Qn,updatedAt:Qn,current:a.z.boolean()}).passthrough();a.z.object({keyId:Jn,revoked:a.z.literal(!0),revokedAt:Qn}).strict(),a.z.object({id:Jn,pairingKeyId:Jn,url:a.z.string().trim().min(1).max(2048),name:a.z.string().trim().min(1).max(160).optional(),enabled:a.z.boolean(),createdAt:Qn,updatedAt:Qn,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:Qn.optional(),lastConnectedAt:Qn.optional(),lastDisconnectedAt:Qn.optional(),error:a.z.string().optional()}).passthrough(),a.z.object({pairing:so,connection:a.z.object({id:Jn,pairingKeyId:Jn,url:a.z.string().trim().min(1).max(2048),name:a.z.string().trim().min(1).max(160).optional(),enabled:a.z.boolean(),createdAt:Qn,updatedAt:Qn}).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 oo=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:Ls,status:a.z.enum(["available","pull-required","unknown"]),localImage:oo.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 ro=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(ro)}).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 ao=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(),co=a.z.object({...ao.shape}).strict(),lo=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"}),uo=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(),po=a.z.object({id:Jn,name:a.z.string().trim().min(1).max(160),projectId:Jn.optional(),source:as,sourceSnapshot:a.z.record(a.z.string(),a.z.unknown()).default({}),modelSelection:ui,nodeId:Jn,runtimeId:Jn,imageSelection:pi.optional(),environmentSource:mi.optional(),environmentTemplateOrigin:Ii.optional(),imageSnapshot:Ms.optional(),imageProvisioning:js.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:Mn.optional(),instanceVersion:a.z.string().trim().max(80).optional(),build:Vi.optional(),runtimeVersion:Wi.optional(),ready:a.z.boolean().default(!1),capabilities:Gn.default(qn),appInventory:Oi.optional(),config:a.z.object({autoImportAgentConfigs:a.z.boolean().default(!0),codexConfigEnabled:a.z.boolean().default(!0),codexHomeMode:a.z.enum(["default","taskhandoff"]).default("taskhandoff"),defaultCodexPermissionMode:nt.default("ask"),codexSettings:Hn.optional(),aiSessionHistoryLimit:a.z.number().int().min(1).max(500).default(50),aiSessionAttachmentRetentionDays:a.z.number().int().min(0).max(365).default(30),aiSessionMaxFileAttachmentBytes:a.z.number().int().positive().max(ge).default(he)}).strict().default({autoImportAgentConfigs:!0,codexConfigEnabled:!0,codexHomeMode:"taskhandoff",defaultCodexPermissionMode:"ask",aiSessionHistoryLimit:50,aiSessionAttachmentRetentionDays:30,aiSessionMaxFileAttachmentBytes:he}),workspace:uo.default({status:"unknown"}),target:ao.default({strategy:"direct-port",status:"unknown"}),access:lo,apps:a.z.object({runningCount:a.z.number().int().min(0).default(0),problemCount:a.z.number().int().min(0).default(0),updatedAt:Qn.optional(),revision:a.z.number().int().min(0).optional()}).strict().default({runningCount:0,problemCount:0}),aiSessions:Lt.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:sn,deployments:a.z.array(rn).default([]),runtime:a.z.array(an).default([])}).strict()).default([]),recentRuns:a.z.array(cn).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:Qn.optional(),createdAt:Qn,updatedAt:Qn}).strict(),mo=a.z.union([po.transform(e=>({instance:e,gitWorkspaceProvisioningOperationId:void 0})),a.z.object({instance:po,gitWorkspaceProvisioningOperationId:Jn.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:yo(t.instance),..."string"==typeof t.gitWorkspaceProvisioningOperationId?{gitWorkspaceProvisioningOperationId:t.gitWorkspaceProvisioningOperationId}:{}}:yo(t)},mo);const ho="instance.lifecycle.snapshot",go=a.z.object({instanceId:po.shape.id,revision:a.z.number().int().min(0),updatedAt:Qn,status:po.shape.status.unwrap(),health:po.shape.health.unwrap(),connectionStatus:po.shape.connectionStatus.unwrap(),accessStatus:a.z.enum(["reachable","endpoint-unreachable"]),imageProvisioning:js.optional(),workspace:uo,runtime:po.shape.runtime.unwrap(),runtimeVersion:Wi.optional(),ready:a.z.boolean(),lastHeartbeatAt:Qn.optional()}).strict();function fo(e,t){return po.safeParse(yo(e,t))}function yo(e,t){if(!e||"object"!=typeof e||Array.isArray(e))return e;const n=e,i=new Set(Object.keys(po.shape)),s={};for(const[e,o]of Object.entries(n))i.has(e)?s[e]=o:t?.({instanceId:"string"==typeof n.id?n.id:void 0,field:e});if(n.capabilities&&"object"==typeof n.capabilities&&!Array.isArray(n.capabilities)){const e={...n.capabilities};Object.prototype.hasOwnProperty.call(e,"apps")&&(t?.({instanceId:"string"==typeof n.id?n.id:void 0,field:"capabilities.apps"}),delete e.apps),s.capabilities=Xn(e)}else s.capabilities=Xn(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=_o(e,["id","name","kind","source","availability","diagnosticCode"]);return!i||"object"!=typeof i||Array.isArray(i)?i:{...i,capabilities:_o(e.capabilities,["automation","supportsCwdSelection"])}}):i.items,issues:Array.isArray(i.issues)?i.issues.map(e=>_o(e,["code","message"])):i.issues},o=Oi.safeParse(s);return o.success?o.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,o=as.options.find(e=>e.shape.type.value===s);if(!o)return e;const r="local-folder"===s?["type","localFolderId","path","ownerNodeId"]:"git-template"===s?["type","url","templateId","ref","auth","clone"]:["type","repositoryId","url","provider","ref","auth","clone"],a=_o(i,r);if("local-folder"!==s){const e=function(e,t,n){const i=e&&"object"==typeof e&&!Array.isArray(e)?e:void 0,s=is.safeParse(_o(i,["type","name","commit"]));if(s.success)return s.data;const o="string"==typeof i?.commit?i.commit.trim():"",r="string"==typeof i?.name?i.name.trim():"",a=o?is.safeParse({type:"commit",commit:o}):r?is.safeParse({type:"tag"===i?.type?"tag":"branch",name:r}):is.safeParse({type:"branch",name:"main"});return a.success?(t?.({instanceId:n,field:"source.ref"}),a.data):void 0}(i.ref,t,n),s=Io(ss,_o(i.auth,["type","secretId"]),"source.auth",t,n),o=Io(os,_o(i.clone,["depth","submodules","lfs","subdirectory"]),"source.clone",t,n);e?a.ref=e:delete a.ref,s?a.auth=s:delete a.auth,o?a.clone=o:delete a.clone}const c=Io(o,a,"source",t,n);return c?(Object.keys(i).some(e=>!r.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=Io(Vi,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=Io(Pt,e,`aiSessions.sessions.${i}`,t,n);return s?[s]:[]}):[],o={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:Qn.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"}),Lt.parse(o)}(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,o)=>{const r=Io(i,e,`${s}.${o}`,t,n);return r?[r]:[]}):[],o=Array.isArray(i.configs)?i.configs.flatMap((e,i)=>{if(!e||"object"!=typeof e||Array.isArray(e))return[];const o=e;Object.keys(o).some(e=>!["configHash","config","deployments","runtime"].includes(e))&&t?.({instanceId:n,field:`triggers.configs.${i}`});const r=function(e,t,n,i){if(!e||"object"!=typeof e||Array.isArray(e))return;const s=e,o=_o(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"];o.source=_o(e,t)}return o.action=_o(s.action,["promptTemplate"]),o.policy=_o(s.policy,["cooldownMs","maxConcurrentRuns","whenBusy"]),Io(sn,o,t,n,i)}(o.config,`triggers.configs.${i}.config`,t,n);return"string"==typeof o.configHash&&r?[{configHash:o.configHash,config:r,deployments:s(o.deployments,rn,`triggers.configs.${i}.deployments`),runtime:s(o.runtime,an,`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:o,recentRuns:s(i.recentRuns,cn,"triggers.recentRuns")}}(n.triggers,t,"string"==typeof n.id?n.id:void 0),s.apps=Io(po.shape.apps.unwrap(),_o(n.apps,["runningCount","problemCount","updatedAt","revision"]),"apps",t,"string"==typeof n.id?n.id:void 0)||{runningCount:0,problemCount:0},s.config=Io(po.shape.config.unwrap(),_o(n.config,["autoImportAgentConfigs","codexConfigEnabled","codexHomeMode","defaultCodexPermissionMode","codexSettings","aiSessionHistoryLimit","aiSessionAttachmentRetentionDays","aiSessionMaxFileAttachmentBytes"]),"config",t,"string"==typeof n.id?n.id:void 0)||{autoImportAgentConfigs:!0,codexConfigEnabled:!0,codexHomeMode:"taskhandoff",defaultCodexPermissionMode:"ask",aiSessionHistoryLimit:50,aiSessionAttachmentRetentionDays:30,aiSessionMaxFileAttachmentBytes:he},s.modelSelection=Io(ui.unwrap(),_o(n.modelSelection,["modelEntityIds","codexModelHash","claudeModelHash","opencodeModelHash"]),"modelSelection",t,"string"==typeof n.id?n.id:void 0)||{},s.imageSnapshot=function(e,t,n,i){if(!e||"object"!=typeof e||Array.isArray(e))return e;const s=e,o=function(e){if(!e||"object"!=typeof e||Array.isArray(e))return e;const t=e,n=new Set(["id","origin","name","description","localizedDescriptions","cover","reference","repository","tag","image","registry","pullPolicy","capabilities","optionalApps","defaultEnv","labels","createdAt","updatedAt"]);for(const e of Object.keys(t))n.has(e);"string"==typeof t.id&&t.id;const i="string"==typeof t.image?t.image:void 0;Object.prototype.hasOwnProperty.call(t,"registry");let s,o="string"==typeof t.reference?t.reference:i;if(o)try{o=ai(o)}catch{if(!o.includes("@")&&o.lastIndexOf(":")<=o.lastIndexOf("/"))try{o=ai(`${o}:latest`)}catch{}}try{s=o?ci(o):void 0}catch{}return{id:t.id,origin:"custom",name:t.name,description:t.description,localizedDescriptions:t.localizedDescriptions,cover:_o(t.cover,["kind","key","url","mediaType","digest"]),reference:s?.reference??o,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:r,...a}=o,c=s.requestedReference??r;let d;try{d="string"==typeof c?ci(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?_o(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 o="string"==typeof n.imageId?{img_default:"market_taskhandoff_browser",img_codex:"market_taskhandoff_codex",img_ai:"market_taskhandoff_ai"}[n.imageId]||n.imageId:void 0,r=_o(n.imageSelection,["imageId","tag"]);s.imageSelection=r||(o?{imageId:o,tag:s.imageSnapshot?.tag}:void 0),s.imageProvisioning=Io(js,_o(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},o=s(i.desiredVersion);if(!o)return void t?.({instanceId:n,field:"runtimeVersion.desiredVersion"});const r=new Set(Wi.shape.phase.options),a="string"==typeof i.phase?i.phase:"pending",c=r.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,o="string"==typeof e.message?e.message.trim().slice(0,4096):"";if(o){const i=new Set(Gi.shape.code.options),r="string"==typeof e.code&&i.has(e.code)?e.code:"INSTANCE_RUNTIME_INSTALL_FAILED";r!==e.code&&t?.({instanceId:n,field:"runtimeVersion.error.code"});const a=s(e.expectedVersion),c=s(e.actualVersion);d={code:r,message:o,...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:o,...s(i.actualVersion)?{actualVersion:s(i.actualVersion)}:{},retryable:!1});const l=s(i.actualVersion),u=Qn.safeParse(i.lastAttemptAt),p=Qn.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:o,...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=Io(uo,n.workspace,"workspace",t,"string"==typeof n.id?n.id:void 0)||{status:"unknown"},s.environmentSource=Io(mi,n.environmentSource,"environmentSource",t,"string"==typeof n.id?n.id:void 0),s.environmentTemplateOrigin=Io(Ii,n.environmentTemplateOrigin,"environmentTemplateOrigin",t,"string"==typeof n.id?n.id:void 0),s.runtime=Io(po.shape.runtime.unwrap(),n.runtime,"runtime",t,"string"==typeof n.id?n.id:void 0)||{labels:{}},s.target=Io(ao,_o(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=Io(lo,_o(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(po.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 Io(e,t,n,i,s){if(!t||"object"!=typeof t||Array.isArray(t))return;let o=structuredClone(t),r=!1;for(let t=0;t<20;t+=1){const t=e.safeParse(o);if(t.success)return r&&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=Ao(o,e.path);if(t&&"object"==typeof t&&!Array.isArray(t))for(const n of e.keys)Object.prototype.hasOwnProperty.call(t,n)&&(delete t[n],a=!0,r=!0)}if(!a){const r=structuredClone(o);let a=!1;for(const e of t.error.issues){if(!e.path.length||"string"!=typeof e.path.at(-1))continue;const t=Ao(r,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(r);if(t.success)return i?.({instanceId:s,field:n}),t.data}break}}i?.({instanceId:s,field:n})}function Ao(e,t){let n=e;for(const e of t){if(!n||"object"!=typeof n)return;n=n[e]}return n}function _o(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 Eo=a.z.object({instanceId:Jn.optional(),projectId:Jn.optional(),source:as.optional(),nodeId:Jn.optional(),runtimeId:Jn.optional(),imageSelection:pi.optional(),instanceVersion:a.z.string().trim().max(80).optional(),protocolVersion:Mn,build:Vi.optional(),controlMode:a.z.enum(["standalone","controlled"]).default("controlled"),capabilities:Gn.default(qn),appInventory:Oi.optional(),target:co.optional(),workspace:uo.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)=>{Ln.has(e.protocolVersion)&&!e.appInventory&&t.addIssue({code:"custom",path:["appInventory"],message:"Current protocol register payload requires appInventory."})}),To=a.z.object({status:po.shape.status.optional(),health:po.shape.health.optional(),protocolVersion:Mn,build:Vi.optional(),capabilities:po.shape.capabilities.optional(),appInventory:Oi.optional(),apps:po.shape.apps.optional(),aiSessions:po.shape.aiSessions.optional(),triggers:po.shape.triggers.optional(),workspace:uo.optional(),target:co.optional(),processIncarnationId:a.z.string().trim().min(1).max(120).optional()}).strict().superRefine((e,t)=>{Ln.has(e.protocolVersion)&&!e.appInventory&&t.addIssue({code:"custom",path:["appInventory"],message:"Current protocol heartbeat payload requires appInventory."})}),wo=a.z.enum(["web","telegram","wechat","dingding","lark"]);function bo(e,t){let n=Oo(t);for(let t=0;t<100;t+=1){const t=e.safeParse(n);if(t.success)return t;const i=So(t.error.issues);let s=!1;for(const e of i){const t=No(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 So(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)=>vo(t)<vo(e)?t:e);n.push(...So(s,[...t,...i.path]))}return n}function vo(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(vo)):1)},0)}function No(e,t){let n=e;for(const e of t){if(!n||"object"!=typeof n)return;n=n[e]}return n}function Oo(e){return Array.isArray(e)?e.map(Oo):e&&"object"==typeof e?Object.getPrototypeOf(e)!==Object.prototype&&null!==Object.getPrototypeOf(e)?e:Object.fromEntries(Object.entries(e).map(([e,t])=>[e,Oo(t)])):e}function zo(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 o=l.spawn(e,t,{stdio:["ignore","pipe","pipe"]}),r=[],a=[];let c=!1;const d=n.timeoutMs?setTimeout(()=>{c=!0,o.kill("SIGKILL")},n.timeoutMs):void 0;let u=!1;const p=()=>{u=!0,o.kill("SIGKILL")},m=()=>{d&&clearTimeout(d),n.signal?.removeEventListener("abort",p)};n.signal?.addEventListener("abort",p,{once:!0}),d?.unref?.(),o.stdout.on("data",e=>r.push(Buffer.from(e))),o.stderr.on("data",e=>a.push(Buffer.from(e))),o.on("error",e=>{m(),s(e)}),o.on("close",t=>{m();const o={stdout:Buffer.concat(r).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:o}),void s(t)}if(u)return void s(Object.assign(new Error(`${e} was aborted.`),{code:"RUNTIME_COMMAND_ABORTED",details:o}));if(0===t)return void i(o);const d=new Error(o.stderr||`${e} exited with code ${t}`);Object.assign(d,{statusCode:502,code:"RUNTIME_EXECUTOR_FAILED",details:o}),s(d)})})}a.z.object({id:Jn,channel:wo,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:Qn,updatedAt:Qn}).strict(),a.z.object({id:Jn,channel:wo,bridgeId:Jn.optional(),chatSessionId:a.z.string().trim().min(1).max(240),userId:a.z.string().trim().max(240).optional(),activeProjectId:Jn.optional(),activeInstanceId:Jn.optional(),activeAiSessionId:a.z.string().trim().min(1).max(120).optional(),lastUsedAt:Qn,createdAt:Qn,updatedAt:Qn}).strict(),a.z.object({source:a.z.object({type:a.z.literal("chat-gateway").default("chat-gateway"),channel:wo,bridgeId:Jn.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(Qe).max(6).default([])}).strict().superRefine((e,t)=>{e.attachments.reduce((e,t)=>e+("inline"===t.source.type?t.size:0),0)>fe&&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:Jn,aiSessionId:a.z.string().trim().min(1).max(120)}).strict().optional()}).strict(),a.z.object({id:Jn,instanceId:Jn,projectId:Jn.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:Qn}).strict();const Co=(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 o=[];let r,a=!1,c=!1;try{r=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,r.kill("SIGKILL")},n.timeoutMs):void 0,l=()=>{c=!0;try{r.kill("SIGKILL")}catch{}};n.signal?.addEventListener("abort",l,{once:!0}),d?.unref?.(),r.onData(e=>{o.push(e),n.onData?.(e)}),r.onExit(({exitCode:t})=>{d&&clearTimeout(d),n.signal?.removeEventListener("abort",l);const r={stdout:o.join(""),stderr:""};a?s(Object.assign(new Error(`${e} timed out after ${n.timeoutMs}ms`),{statusCode:504,code:"RUNTIME_COMMAND_TIMEOUT",details:r})):c?s(Object.assign(new Error(`${e} was aborted.`),{code:"RUNTIME_COMMAND_ABORTED",details:r})):0!==t?s(Object.assign(new Error(r.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:r})):i(r)})});class Ro{inFlight=new Map;runCommand;runTerminalCommand;constructor(e=zo,t){this.runCommand=e,this.runTerminalCommand=t||function(e){return e===zo?Co: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=ai(e),o=this.inFlight.get(s);if(o)return t&&(o.phaseListeners.add(t),o.phase&&t(o.phase)),n&&(o.terminalListeners.add(n),o.terminalTail&&n({sequence:o.terminalSequence,data:o.terminalTail,replay:!0})),this.bindAbort(o,i),o.promise;const r=new Set,a=new Set;t&&r.add(t),n&&a.add(n);const c={promise:Promise.resolve(void 0),controller:new AbortController,abortDisposers:new Set,phaseListeners:r,terminalListeners:a,terminalSequence:0,terminalTail:""};return this.bindAbort(c,i),c.promise=this.ensureOnce(s,e=>{c.phase=e,r.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}),o=!1;s||(t("pulling-image"),await this.runTerminalCommand("docker",["pull",e],{cols:120,rows:40,signal:i,onData:n}),o=!0,s=await this.inspect(e,i)),t("resolving-image");const r=(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=r?.split("@").at(-1)?.toLowerCase();return{requestedReference:e,...c?{resolvedDigest:c}:{},resolvedReference:r||e,pulled:o}}async inspect(e,t){const n=await this.runCommand("docker",["image","inspect",e,"--format","{{json .}}"],{signal:t});return JSON.parse(n.stdout.trim()||"{}")}}function xo(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 ko=new Set(["entrypoint.sh","git-provision.sh","instance-launcher.sh","node-agent-unix-proxy.mjs","runtime-installer.mjs"]);function Do(){const e=("undefined"==typeof document?require("url").pathToFileURL(__filename).href:O&&"SCRIPT"===O.tagName.toUpperCase()&&O.src||new URL("cli.js",document.baseURI).href)?n.dirname(s.fileURLToPath("undefined"==typeof document?require("url").pathToFileURL(__filename).href:O&&"SCRIPT"===O.tagName.toUpperCase()&&O.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]}const Po="/run/task-handoff/bootstrap",Lo=`${Po}/entrypoint.sh`,Mo="/bin/bash",jo=`${Po}/runtime-installer.mjs`,Uo="/opt/task-handoff/instance-runtime";function Fo(e,t){return{role:"runtime",name:`${ir(e)}-runtime`,mountPath:Uo,labels:{"task-handoff.owner":"task-handoff","task-handoff.instance-id":e,"task-handoff.node-id":t,"task-handoff.volume-role":"runtime"}}}function $o(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:o})=>({role:n,name:`${i}-${s}`,mountPath:o,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 Ho=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 qo(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),o=-1===n?"":e.slice(n+1);Ho.has(i)&&s.add(`Config.Env.${i}`),t.some(e=>e&&o.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))(Ho.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 Vo{runCommand;publishHost;images;launcherAssetsDir;nodeAgentContainerIpcPath;portResolutionRetryDelaysMs;constructor(e=zo,t={}){this.runCommand=e,this.images=t.imageService||new Ro(e),this.publishHost=t.publishHost||"127.0.0.1",this.launcherAssetsDir=t.launcherAssetsDir||Do(),this.nodeAgentContainerIpcPath=t.nodeAgentContainerIpcPath,this.portResolutionRetryDelaysMs=t.portResolutionRetryDelaysMs?.length?t.portResolutionRetryDelaysMs:[0,100,250,500,1e3]}async start(e){or(e);const t=e.instance.runtime.containerName||ir(e.instance.id),i=await this.inspectContainerForStart(t);if(i){tr(t,i.id,e.instance.runtime.containerId,"before start","RUNTIME_EXECUTOR_FAILED");const n=i.labels["task-handoff.instance-id"];if(n!==e.instance.id)throw Jo("RUNTIME_EXECUTOR_FAILED",`Docker container ${t} belongs to ${n||"an unknown instance"}, not ${e.instance.id}.`);await this.createRuntimeVolume(e),await this.validatePersistentVolumes(e,i.mounts);try{await this.runCommand("docker",["start",t])}catch(e){throw Jo("RUNTIME_EXECUTOR_FAILED",`Could not start Docker container ${t}.`,e)}return this.resumedContainerResult(e,t,i.id,i.labels)}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",function(e,t,i={}){const s=i.publishHost||"127.0.0.1",o=n.resolve(i.launcherAssetsDir||Do()),r=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=${r}`,"--label",`task-handoff.runtime-id=${a}`,"--label",`task-handoff.image-id=${e.image.id}`,"--label","task-handoff.bootstrap-abi=1","--shm-size","1gb","--security-opt","seccomp=unconfined","--network","bridge","--no-healthcheck","--add-host","host.docker.internal:host-gateway","--tmpfs","/tmp:rw,nosuid,nodev,exec,mode=1777","-p",`${s}::8080`];if(!e.privateConfigPath)throw Object.assign(new Error(`Instance ${e.instance.id} private config was not materialized.`),{statusCode:409,code:"INSTANCE_PRIVATE_CONFIG_MISSING"});c.push("--mount",`type=bind,src=${e.privateConfigPath},dst=/run/task-handoff/instance-private-config.json,readonly`,"--mount",`type=bind,src=${o},dst=${Po},readonly`,"--entrypoint",Mo);const d=i.nodeAgentContainerIpcPath?`/run/task-handoff/node-agent-transport/${n.basename(i.nodeAgentContainerIpcPath)}`:void 0;i.nodeAgentContainerIpcPath&&d&&c.push("--mount",`type=bind,src=${n.dirname(i.nodeAgentContainerIpcPath)},dst=/run/task-handoff/node-agent-transport,readonly`);for(const t of $o(e))c.push("--mount",`type=volume,src=${t.name},dst=${t.mountPath}`);const l=Fo(e.instance.id,e.node?.id||"node_unset");c.push("--mount",`type=volume,src=${l.name},dst=${l.mountPath}`);const u={TASK_HANDOFF_CONTROL_MODE:"controlled",TASK_HANDOFF_NODE_AGENT_URL:d?"http://127.0.0.1:19001":e.nodeAgentUrl||e.node?.endpoint||"",...d?{TASK_HANDOFF_NODE_AGENT_SOCKET_PATH:d}:{},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:r,TASK_HANDOFF_RUNTIME_ID:a,TASK_HANDOFF_IMAGE_ID:e.image.id,TASK_HANDOFF_INSTANCE_LAUNCHER:`${Po}/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(u))sr(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"}`):(sr(c,"TASK_HANDOFF_PROJECT_SOURCE",JSON.stringify(e.project.source)),sr(c,"TASK_HANDOFF_WORKSPACE_POLICY",JSON.stringify(e.project.workspacePolicy)),sr(c,"TASK_HANDOFF_GIT_URL",e.project.source.url),"commit"===e.project.source.ref.type?sr(c,"TASK_HANDOFF_GIT_COMMIT",e.project.source.ref.commit):sr(c,"TASK_HANDOFF_GIT_REF",e.project.source.ref.name),e.project.source.clone?.depth&&sr(c,"TASK_HANDOFF_GIT_DEPTH",String(e.project.source.clone.depth)),sr(c,"TASK_HANDOFF_GIT_SUBMODULES",e.project.source.clone?.submodules?"true":"false"),sr(c,"TASK_HANDOFF_GIT_LFS",e.project.source.clone?.lfs?"true":"false"),e.project.source.clone?.subdirectory&&sr(c,"TASK_HANDOFF_WORKSPACE_SUBDIRECTORY",e.project.source.clone.subdirectory));const p={...e.image.labels["task-handoff.image.profile"]?{TASK_HANDOFF_IMAGE_PROFILE:e.image.labels["task-handoff.image.profile"]}:{},TASK_HANDOFF_IMAGE_CAPABILITIES:e.image.capabilities.join(",")};for(const[t,n]of Object.entries(e.image.defaultEnv))t in p||sr(c,t,n);for(const[e,t]of Object.entries(p))sr(c,e,t);return c.push(i.imageReference||e.instance.environmentTemplateOrigin?.imageId||e.image.resolvedReference||e.image.requestedReference,Lo,"task-handoff","web"),c}(e,t,{publishHost:this.publishHost,launcherAssetsDir:this.launcherAssetsDir,nodeAgentContainerIpcPath:this.nodeAgentContainerIpcPath}))}catch(e){throw Jo("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 Jo("GIT_WORKSPACE_PROVISIONING_MISSING",`Git workspace provisioning input is missing for ${e.instance.id}.`);const s=`${ir(e.instance.id)}-git-provision`,o=t.mkdtempSync(n.join(c.tmpdir(),"task-handoff-git-auth-"));t.chmodSync(o,448);try{await this.runCommand("docker",["rm","-f",s],{timeoutMs:3e4}).catch(()=>({stdout:"",stderr:""})),this.materializeGitProvisioningAuth(o,i);const t=function(e,t,i,s={}){const o=e.gitWorkspaceProvisioning;if(!o||"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 r=n.resolve(s.launcherAssetsDir||Do()),a=$o(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=${r},dst=${Po},readonly`,"--tmpfs","/run/task-handoff/git-runtime:rw,nosuid,nodev,exec,mode=0700"];o.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",o.remoteUrl),d("TASK_HANDOFF_INSTANCE_ID",e.instance.id),"commit"===o.ref.type?d("TASK_HANDOFF_GIT_COMMIT",o.ref.commit):d("TASK_HANDOFF_GIT_REF",o.ref.name),o.clone.depth&&d("TASK_HANDOFF_GIT_DEPTH",String(o.clone.depth)),d("TASK_HANDOFF_GIT_SUBMODULES",o.clone.submodules?"true":"false"),d("TASK_HANDOFF_GIT_LFS",o.clone.lfs?"true":"false"),o.clone.subdirectory&&d("TASK_HANDOFF_WORKSPACE_SUBDIRECTORY",o.clone.subdirectory),c.push("--entrypoint","/bin/bash",e.instance.environmentTemplateOrigin?.imageId||e.image.resolvedReference||e.image.requestedReference,`${Po}/git-provision.sh`),c}(e,s,o,{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 Jo("GIT_WORKSPACE_PROVISIONING_TIMEOUT",`Git workspace provisioning timed out for ${e}.`);if("RUNTIME_COMMAND_ABORTED"===i)return Jo("GIT_WORKSPACE_PROVISIONING_CANCELLED",`Git workspace provisioning was cancelled for ${e}.`);const s=Zo(t)||"",o=s.match(/TASK_HANDOFF_GIT_PROVISIONING_ERROR=([A-Z_]+)/)?.[1];return Jo(`GIT_WORKSPACE_PROVISIONING_${o&&Qo.has(o)?o:"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(o,{recursive:!0,force:!0})}}materializeGitProvisioningAuth(e,i){const s=(e,i,s)=>{const o=n.join(e,i);t.writeFileSync(o,s,{encoding:"utf8",mode:384}),t.chmodSync(o,384)};i.credentials.forEach((i,o)=>{const r=n.join(e,`credential-${o}`);if(t.mkdirSync(r,{recursive:!0,mode:448}),t.chmodSync(r,448),s(r,"scope.json",JSON.stringify(i.payload.credential.scope)),"https-token"===i.payload.secret.kind)return s(r,"username",i.payload.secret.username),void s(r,"token",i.payload.secret.token);s(r,"private-key",i.payload.secret.privateKey),s(r,"known_hosts",i.payload.secret.pinnedKnownHosts),i.payload.secret.passphrase&&s(r,"passphrase",i.payload.secret.passphrase),s(r,"ssh-askpass.sh",`#!/usr/bin/env bash\ncat /run/task-handoff/git-runtime/credential-${o}/passphrase 2>/dev/null || true\n`)})}async inspectContainerConfigSecurity(e,t){qo(await this.runCommand("docker",["inspect","--format","{{json .}}",e]).then(e=>JSON.parse(e.stdout||"{}")).catch(t=>{throw Jo("ENVIRONMENT_TEMPLATE_CONTAINER_INSPECT_FAILED",`Could not inspect Docker container ${e}.`,t)}),t)}async inspectImageConfigSecurity(e,t){qo(await this.runCommand("docker",["image","inspect","--format","{{json .}}",e]).then(e=>JSON.parse(e.stdout||"{}")).catch(e=>{throw Jo("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 Jo("ENVIRONMENT_TEMPLATE_CONTAINER_NOT_FOUND",`Docker container ${e} does not exist.`);tr(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 Jo("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=Wo(n.Os),o=Xo(n.Architecture),r="number"==typeof n.Size?n.Size:Number.NaN;if(!/^sha256:[a-f0-9]{64}$/.test(i)||!s||!o||!Number.isSafeInteger(r)||r<0)throw new Error("Docker image inspection did not return a valid immutable identity.");return{imageId:i,platform:s,architecture:o,sizeBytes:r}}catch(e){throw Jo("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,Yo(n)]),await this.runCommand("docker",["image","rm",e]),n}catch(e){const t=Zo(e)?.toLowerCase()||"";if(t.includes("no such image")||t.includes("no such object"))return;throw Jo("ENVIRONMENT_TEMPLATE_UNTAG_FAILED","Could not remove the environment template tag.",e)}}async garbageCollectEnvironmentTemplateImage(e){try{try{await this.runCommand("docker",["image","rm",Yo(e)])}catch(e){const t=Zo(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=Zo(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 Jo("ENVIRONMENT_TEMPLATE_GC_FAILED","Could not garbage collect the environment template image.",e)}}async createPersistentVolumes(e,t=new Set){const n=Fo(e.instance.id,e.node?.id||"node_unset");for(const i of[...$o(e),n])await this.createVolume(i),await this.validateOwnedVolume(e.instance.id,i,t.has(i.name))}async createRuntimeVolume(e){await this.createVolume(Fo(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 Jo("INSTANCE_VOLUME_CREATE_FAILED",`Could not create managed volume ${e.name}.`,t)}}async validatePersistentVolumes(e,t){for(const n of $o(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=Fo(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 Jo("INSTANCE_VOLUME_INSPECT_FAILED",`Could not inspect managed volume ${t.name}.`,e)}try{const s=JSON.parse(i.stdout||"{}"),o=s.Labels&&"object"==typeof s.Labels&&!Array.isArray(s.Labels)?s.Labels:{},r=s.Name===t.name&&"task-handoff"===o["task-handoff.owner"]&&o["task-handoff.instance-id"]===e&&o["task-handoff.volume-role"]===t.role,a=n&&s.Name===t.name&&0===Object.keys(o).length;if(!r&&!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",o=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":o,"task-handoff.image-id":e.image.id}}}}async resumedContainerResult(e,t,n,i){const s=this.bootstrapResult(e,t,n);return{...s,target:{...s.target,...await this.publishedEndpoint(t)},runtime:{...s.runtime,labels:{...e.instance.runtime.labels,...i}}}}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 Jo("INSTANCE_RUNTIME_ENDPOINT_UNAVAILABLE",`Docker container ${t} does not exist.`);return tr(t,n,e.instance.runtime.containerId,"while resolving its web endpoint","INSTANCE_RUNTIME_ENDPOINT_UNAVAILABLE"),(await this.publishedEndpoint(t)).web}async resolveNodeAgentUrl(e){const t=e.nodeAgentUrl||e.node?.endpoint||"";if(!this.nodeAgentContainerIpcPath)return t;const i=e.instance.runtime.containerName||ir(e.instance.id),s=await this.inspectContainerForStart(i);if(!s)return t;if(tr(i,s.id,e.instance.runtime.containerId,"while resolving its node-agent transport","RUNTIME_EXECUTOR_FAILED"),s.labels["task-handoff.instance-id"]!==e.instance.id)throw Jo("RUNTIME_EXECUTOR_FAILED",`Docker container ${i} does not belong to ${e.instance.id}.`);const o=n.dirname(n.resolve(this.nodeAgentContainerIpcPath));return s.mounts.some(e=>"bind"===e.type&&"/run/task-handoff/node-agent-transport"===e.destination&&n.resolve(e.source||"")===o)?"http://127.0.0.1:19001":t}bootstrapResult(e,t,n){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"}}}}async stop(e){const t=e.instance.runtime.containerName||ir(e.instance.id);try{await this.runCommand("docker",["stop",t])}catch(e){if(!er(e))throw Jo("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){or(e);const n=e.instance.runtime.containerName||ir(e.instance.id),i=await this.inspectContainerId(n);if(!i)throw Jo("INSTANCE_RUNTIME_RESTART_FAILED",`Docker container ${n} does not exist.`);tr(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 Jo("INSTANCE_RUNTIME_RESTART_FAILED",`Docker container identity changed while restarting ${n}.`);return tr(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){tr(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 Jo("RUNTIME_EXECUTOR_FAILED",`Docker container ${n} belongs to ${t||"an unknown instance"}, not ${e.instance.id}.`);for(const t of $o(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(!er(e))throw Jo("RUNTIME_EXECUTOR_FAILED",`Could not delete Docker container ${n}.`,e)}}const o=[];for(const n of $o(e))if(t.deleteVolumes)try{const t=await this.inspectVolumeForDelete(n.name);if(!t){o.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,r=s.has(n.name)&&t.name===n.name&&0===Object.keys(t.labels).length;if(!i&&!r)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]),o.push({role:n.role,name:n.name,mountPath:n.mountPath,status:"deleted"})}catch(e){o.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 o.push({role:n.role,name:n.name,mountPath:n.mountPath,status:"retained"});return await this.deleteRuntimeVolume(e),Ti.parse({instanceId:e.instance.id,containerDeleted:!0,completed:o.every(e=>"failed"!==e.status),deletedVolumes:o.filter(e=>"deleted"===e.status||"missing"===e.status),retainedVolumes:o.filter(e=>"retained"===e.status),volumeResults:o})}async deleteRuntimeVolume(e){const t=Fo(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 Jo("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 Jo("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=Zo(e)?.toLowerCase()||"";return t.includes("no such volume")||t.includes("no such object")}(t))return;throw Jo("INSTANCE_VOLUME_INSPECT_FAILED",`Could not inspect managed volume ${e}.`,t)}}async installRuntime(e){const t=await this.installRuntimeRelease(e);tr(e.containerName,t,e.expectedContainerId,"before runtime restart","INSTANCE_RUNTIME_RESTART_FAILED");try{await this.runCommand("docker",["restart",t])}catch(t){throw Jo("INSTANCE_RUNTIME_RESTART_FAILED",`Could not restart Docker container ${e.containerName}.`,t)}const n=await this.inspectContainerId(e.containerName);if(!n||n!==t)throw Jo("INSTANCE_RUNTIME_RESTART_FAILED",`Docker container identity changed while updating ${e.containerName}.`);return tr(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 Jo("INSTANCE_RUNTIME_INSTALL_FAILED",`Docker container ${e.containerName} does not exist.`);tr(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",jo,"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 Jo("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 Jo("INSTANCE_RUNTIME_INSTALL_FAILED",`Docker container identity changed while installing ${e.containerName}.`);return tr(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",jo,"verify-active"]).catch(()=>{});if(!n?.stdout)return{containerId:t};try{const e=bo(Ki,JSON.parse(n.stdout));return e.success?{containerId:t,...e.data}:{containerId:t}}catch{return{containerId:t}}}async inspectRuntimeTarget(e){let t,n;if(e){const i=await this.runCommand("docker",["inspect","--format","{{json .}}",e]).then(e=>JSON.parse(e.stdout.trim()||"{}")).catch(()=>{});if(t=i?.Platform,"string"==typeof i?.Image&&i.Image){const e=await this.runCommand("docker",["image","inspect","--format","{{json .}}",i.Image]).then(e=>JSON.parse(e.stdout.trim()||"{}")).catch(()=>{});t=e?.Os||t,n=e?.Architecture}}if(!t||!n){const e=await this.runCommand("docker",["info","--format","{{json .}}"]).then(e=>JSON.parse(e.stdout.trim()||"{}")).catch(e=>{throw Jo("INSTANCE_BASE_RUNTIME_INCOMPATIBLE","Could not inspect the Docker runtime target.",e)});t||=e.OSType,n||=e.Architecture}const i=Wo(t),s=Xo(n);if(!i||!s)throw Jo("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 Jo("INSTANCE_RUNTIME_INSTALL_FAILED",`Docker container ${t} does not exist.`);if(tr(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 Jo("INSTANCE_RUNTIME_INSTALL_FAILED",`Docker container ${t} does not expose its immutable image identity.`);const s="/run/task-handoff/runtime-rescue-artifact.tar.gz",o=[`test -r ${Lo}`,`test -r ${Po}/instance-launcher.sh`,`test -r ${jo}`,`install -d -o root -g root -m 0755 ${Uo} ${Uo}/releases ${Uo}/staging ${Uo}/incoming`,`chown -R root:root ${Uo}`,`chmod -R go-w ${Uo}`,`node ${jo} 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",Mo,i.image,"-ceu",o,"task-handoff-runtime-rescue",s,e.identity.version,e.identity.sha256,e.identity.platform,e.identity.arch,String(e.identity.launcherAbi)])}catch(n){throw Jo("INSTANCE_RUNTIME_INSTALL_FAILED",`Could not rescue controlled-instance ${e.identity.version} in stopped container ${t}.`,n)}const r=await this.inspectContainerForStart(t);if(!r)throw Jo("INSTANCE_RUNTIME_INSTALL_FAILED",`Docker container ${t} disappeared during runtime install recovery.`);if(tr(t,r.id,i.id,"after runtime install recovery","INSTANCE_RUNTIME_INSTALL_FAILED"),r.running)throw Jo("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 Jo("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Docker container ${e} does not exist.`);tr(e,n,t,"before runtime launcher install","INSTANCE_BASE_RUNTIME_INCOMPATIBLE");try{await this.runCommand("docker",["exec","--user","0",n,"bash","-ceu",`test -r ${Lo}; test -r ${Po}/instance-launcher.sh; test -r ${jo}; 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 Jo("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Could not install the runtime launcher in ${e}.`,t)}const i=await this.inspectContainerId(e);if(i!==n)throw Jo("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Docker container identity changed while installing the runtime launcher in ${e}.`);tr(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(er(t))return;throw Jo("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(er(t))return;throw Jo("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]:[],o=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:o,labels:n,mounts:i}}catch(t){throw Jo("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 Go(s);try{const n=Bo((await this.runCommand("docker",["port",e,t])).stdout);if(n)return n}catch(e){n=e}try{const n=Ko((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 Jo("RUNTIME_EXECUTOR_FAILED",`Docker container ${e} does not publish ${t}.`);throw Jo("RUNTIME_EXECUTOR_FAILED",`Could not resolve the published port for Docker container ${e}.`,n)}}function Bo(e){const t=e.split(/\r?\n/).find(Boolean);return t?.match(/:(\d+)$/)?.[1]}function Ko(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 Go(e){return new Promise(t=>setTimeout(t,e))}function Wo(e){return"linux"===e||"darwin"===e?e:"windows"===e||"win32"===e?"win32":void 0}function Xo(e){return"amd64"===e||"x86_64"===e||"x64"===e?"x64":"arm64"===e||"aarch64"===e?"arm64":void 0}function Yo(e){return`task-handoff/environment-image:${e.replace(/^sha256:/,"")}`}function Jo(e,t,n){const i=Zo(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 Qo=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 Zo(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 er(e){const t=Zo(e)?.toLowerCase()||"";return t.includes("no such container")||t.includes("no such object")}function tr(e,t,n,i,s){if(n&&t!==n)throw Jo(s,`Docker container ${e} identity mismatch ${i}: expected ${n}, got ${t}.`)}async function nr(e=zo){return async function(e=zo){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||"",o="<none>"!==n&&"<none>"!==i?`${n}:${i}`:s,r="<none>"!==n&&t.Digest&&"<none>"!==t.Digest?[`${n}@${t.Digest}`]:[];return{repository:n,tag:i,id:s,createdSince:t.CreatedSince,size:t.Size,sizeBytes:xo(t.Size),reference:o,repoDigests:r}}).filter(e=>Boolean(e.reference))}(e)}function ir(e){return`task-handoff-${e.replace(/[^a-zA-Z0-9_.-]/g,"-")}`}function sr(e,t,n){e.push("-e",`${t}=${n}`)}function or(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 rr="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 ar="app-session.snapshot",cr="app-session.patch",dr="app-session.removed",lr=a.z.enum(["created","starting","running","stopping","stopped","exited","failed","closed","terminated","unknown"]),ur=a.z.enum(["tty","vnc","web"]);a.z.object({mode:ur,url:a.z.string().trim().min(1).max(4096),token:a.z.string().trim().min(1).max(512),expiresAt:a.z.string().datetime()}).strict(),a.z.object({revoked:a.z.boolean()}).strict();const pr=new Set(["stopped","failed","exited","closed","terminated"]),mr=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(),hr=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:lr.default("unknown"),bindings:a.z.array(mr).max(40).default([]),workspace:a.z.object({cwd:a.z.string().trim().max(4096).optional()}).strict().optional(),createdAt:a.z.string().datetime().optional(),updatedAt:a.z.string().datetime().optional()})),gr=a.z.object({runningCount:a.z.number().int().min(0).default(0),problemCount:a.z.number().int().min(0).default(0),sessions:a.z.array(hr).default([]),updatedAt:a.z.string().datetime()}).strict(),fr=a.z.object({streamId:a.z.string().trim().min(1).max(240),revision:a.z.number().int().min(0),lastEventAt:a.z.string().datetime(),snapshot:gr}).strict();gr.pick({runningCount:!0,problemCount:!0,updatedAt:!0}).extend({revision:a.z.number().int().min(0).optional()});const yr=a.z.enum(["app-session-created","app-session-updated","app-session-deleted","app-session-recovered","control-action","heartbeat-sync","startup"]),Ir=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:yr}).strict(),Ar=a.z.object({meta:Ir,snapshot:gr}).strict(),_r=a.z.object({meta:Ir,session:hr}).strict(),Er=a.z.object({meta:Ir,sessionId:a.z.string().trim().min(1).max(160),tombstone:hr.optional(),expiresAt:a.z.string().datetime().optional()}).strict();function Tr(e,t=(new Date).toISOString()){const n=e.map(e=>function(e){const t=br("string"==typeof e.status?e.status:void 0),n="string"==typeof e.id?e.id:"",i=function(e){const t=zr(e.workspace),n=zr(e.tty),i=zr(e.launch),s=zr(e.ai),o=zr(s.claude),r=Cr(t.cwd)||Cr(n.cwd)||Cr(o.cwd)||Cr(i.cwd);return r?{cwd:r}:void 0}(e),{workspace:s,...o}=e;return hr.parse({...o,status:t,bindings:Or([...(r=e.bindings,Array.isArray(r)?r.flatMap(e=>{const t=mr.safeParse(e);return t.success?[t.data]:[]}):[]),...n?[{type:"app-session",id:n}]:[],...Nr(e)]),...i?{workspace:i}:{}});var r}(e));return gr.parse({runningCount:n.filter(e=>"running"===e.status).length,problemCount:n.filter(e=>"failed"===e.status).length,sessions:n,updatedAt:t})}function wr(e,t=(new Date).toISOString()){return Tr(e.filter(e=>Sr("string"==typeof e.status?e.status:void 0)),t)}function br(e){const t=(e||"unknown").trim().toLowerCase();return"ended"===t?"closed":"terminating"===t?"stopping":lr.options.includes(t)?t:"unknown"}function Sr(e){return!pr.has(br(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 Nr(e){const t=zr(e.ai),n=zr(t.claude),i=zr(t.appServer),s=zr(e.launch),o=[],r=Cr(zr(s.aiSessionResume).providerSessionId),a="codex"===e.appId||"claude"===e.appId||"opencode"===e.appId?e.appId:void 0;a&&r&&o.push({type:"provider-session",agent:a,id:r});const c=Cr(n.short);c&&o.push({type:"adapter-key",adapter:"claude",agent:"claude",id:`short:${c}`,key:`short:${c}`});const d=Cr(n.providerSessionId);d&&o.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=Cr(t.activeThreadId);for(const e of[...new Set([u,...l].filter(Boolean))])o.push({type:"provider-session",agent:"codex",id:e});const p=Cr(i.socketPath);return p&&o.push({type:"adapter-key",adapter:"codex-app-server",agent:"codex",id:`socket:${p}`,key:`socket:${p}`}),o}function Or(e){const t=new Map;for(const n of e)t.set(vr(n),n);return[...t.values()]}function zr(e){return e&&"object"==typeof e&&!Array.isArray(e)?e:{}}function Cr(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(ar),payload:Ar}).strict(),a.z.object({type:a.z.literal(cr),payload:_r}).strict(),a.z.object({type:a.z.literal(dr),payload:Er}).strict()])).default([])}).strict();const Rr="2026-08-25",xr=a.z.object({nodeId:a.z.string().optional(),instanceId:a.z.string().optional()}).passthrough(),kr=a.z.object({v:a.z.literal(1),id:a.z.string().min(1),seq:a.z.number().finite(),type:a.z.string().min(1),topic:a.z.string().min(1),createdAt:a.z.string().datetime(),payload:a.z.unknown(),replay:a.z.literal(!0).optional(),scope:xr.optional()}).passthrough(),Dr=a.z.object({v:a.z.literal(Rr),id:a.z.string().min(1),type:a.z.string().min(1),createdAt:a.z.string().datetime(),payload:a.z.unknown(),topic:a.z.string().min(1).optional(),replay:a.z.literal(!0).optional(),scope:xr.optional()}).passthrough();function Pr(e){return e.startsWith("ai-session.")||e.startsWith("ai.session.")?"ai.sessions":e.startsWith("app-session.")?"app.sessions":e.startsWith("app.management")?"apps":e.startsWith("trigger.")?"triggers":e.startsWith("instance.")?"instances":e.startsWith("node.")?"nodes":e.startsWith("project.")?"projects":e.startsWith("model.")?"models":e.startsWith("image.")?"images":e.startsWith("market.")?"market":e.startsWith("story.")?"stories":"system"}a.z.discriminatedUnion("v",[kr,Dr]),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 Lr=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([])}),Mr=a.z.enum(["ai.sessions","app.sessions"]),jr=a.z.object({topic:Mr,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(),Ur=a.z.object({protocolVersion:a.z.literal(1),streams:a.z.array(jr)}).strict();function Fr(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 $r{retryNumber=0;random;constructor(e=Math.random){this.random=e}get attempts(){return this.retryNumber}next(){return this.retryNumber+=1,{attempt:this.retryNumber,delay:Fr(this.retryNumber,this.random)}}reset(){this.retryNumber=0}}class Hr{backoff;timer;constructor(e=Math.random){this.backoff=new $r(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 qr extends Hr{}function Vr(e,t=6e4){const n=[];for(let i=0;i<e.length;i+=t)n.push(e.slice(i,i+t));return n}const Br=262144,Kr=4194304;class Gr{sockets=new Map;socketUrls=new Map;retries=new Map;outputs=new Set;outputSubscriptions=new Map;outputEnvelopeVersions=new Map;outputHierarchy=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;stopped=!1;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 m(e,t)),this.setIntervalFn=n.setIntervalFn||setInterval,this.clearIntervalFn=n.clearIntervalFn||clearInterval,this.setTimeoutFn=n.setTimeoutFn||setTimeout,this.clearTimeoutFn=n.clearTimeoutFn||clearTimeout}start(){this.stopped=!1,this.sync(),this.timer=this.setIntervalFn(()=>{this.safetyReconciliations+=1,this.sync()},this.safetyIntervalMs)}stop(){this.stopped=!0,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.outputHierarchy.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?Lr.parse({}):void 0),this.outputEnvelopeVersions.set(e,1),this.outputHierarchy.set(e,xn.parse(void 0)),t.expectsTransientSubscription||void 0===t.legacyFallbackMs||(n=this.setTimeoutFn(()=>{n=void 0,this.outputs.has(e)&&void 0===this.outputSubscriptions.get(e)&&(this.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.outputHierarchy.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.stopped||this.syncNow()};e.on("close",s),e.on("error",s);for(const t of this.state.listInstances()){const n=Wr(t);n?this.sendForwarded(e,this.createEvent(ho,n,{instanceId:t.id})):this.logger?.warn?.({instanceId:t.id},"instance.lifecycle.snapshot.invalid")}for(const[t,n]of this.imagePullTerminalByInstance)Vr(n.tail).forEach((i,s)=>this.sendForwarded(e,this.createEvent(Us,{...n.output,sequence:n.output.sequence+s,data:i,...0===s?{replay:!0}:{}},{instanceId:t}))),n.finished&&this.sendForwarded(e,this.createEvent(Fs,n.finished,{instanceId:t}));return(t.expectsTransientSubscription||void 0===t.legacyFallbackMs)&&(this.replaySessionAuthority(e),this.syncNow()),s}setOutputSubscription(e,t,n,i){if(!this.outputs.has(e))return!1;const s=Lr.safeParse(t),o=xn.safeParse(i);if(!s.success||!o.success)return!1;this.outputSubscriptions.set(e,s.data),this.outputEnvelopeVersions.set(e,n===Rr?Rr:1),this.outputHierarchy.set(e,o.data),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===Us){const e=bo(Hs,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,o=n.replay||!s?n.data:`${i.tail}${n.data}`.slice(-262144);return void this.imagePullTerminalByInstance.set(n.instanceId,{output:n,tail:o})}if(e===Fs){const e=bo(qs,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(ho,function(e){return go.parse(Xr(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:Pr(e),createdAt:(new Date).toISOString(),payload:t,scope:n}}sendForwarded(e,t){const n=Jr(t),i=n?function(e,t){return t?.subagents||e.type===_e?e:e.type===Ie?{...e,payload:{...e.payload,snapshot:Xt(e.payload.snapshot,t)}}:{...e,payload:{...e.payload,upserted:e.payload.upserted.map(e=>Wt(e,t))}}}(n,this.outputHierarchy.get(e)):void 0,s=i&&i.payload!==t.payload?{...t,payload:i.payload}:t,o=t.type===Ee?qt.safeParse(t.payload):void 0,r=t.type===we?Bt.safeParse(t.payload):void 0,a=this.outputEnvelopeVersions.get(e)===Rr?function(e,t,n={}){const i=e.scope?n.publicScope&&e.scope.instanceId?{instanceId:e.scope.instanceId}:e.scope:void 0;return{v:Rr,id:e.id,type:e.type,createdAt:e.createdAt,payload:void 0===n.payload?e.payload:n.payload,...e.topic!==Pr(e.type)?{topic:e.topic}:{},...e.replay?{replay:!0}:{},...i&&Object.keys(i).length?{scope:i}:{}}}(s,0,{...o?.success?{payload:(c=o.data,Vt.parse({sessionId:c.sessionId,turnId:c.turnId,itemId:c.itemId,delta:c.delta,generatedAt:c.generatedAt}))}:{},...r?.success?{payload:Gt(r.data)}:{}}):s;var c;const d=JSON.stringify({type:"node-agent.event.forwarded",event:a});this.sendOutput(e,d,s)}sendOutput(e,t,n){const i=Buffer.byteLength(t,"utf8"),s=n?.topic===rr?"app-session":n?.topic===ye?"ai-session":void 0,o=s?{...this.outputDiagnostics.get(e),instanceId:n.scope?.instanceId,eventType:n.type,...Yr(n.payload)}:void 0;if(e.readyState!==m.OPEN)return o&&this.logger?.warn?.({...o,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&&Qr(n)&&i>Kr){if(n.type!==Ie&&this.deferAiSessionAuthority(e,n))return!0;this.observeEventTransportCongestion(e,!1,i),o&&this.logger?.warn?.({...o,bufferedAmount:e.bufferedAmount,bytes:i,maxBytes:Kr,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),o&&this.logger?.warn?.({...o,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),o&&this.logger?.info?.({...o,bufferedAmount:e.bufferedAmount,bytes:i,outcome:"queued"},`${s}.event.output.queued`),!0}catch(t){o&&this.logger?.warn?.({...o,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(!Qr(t))return!1;const n=t.scope?.instanceId;return!!n&&(!!this.pendingAiSessionAuthorityByOutput.get(e)?.has(n)||e.bufferedAmount>=Br)}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=Jr(e);return n?n.payload.meta.streamId!==t.streamId||n.payload.meta.revision!==t.revision?void 0:Ft.parse({meta:n.payload.meta,snapshot:t.snapshot}):void 0}(t,i);if(!s)return!1;const o=this.pendingAiSessionAuthorityByOutput.get(e)||new Map;return o.set(n,{...t,type:Ie,topic:ye,payload:s}),this.pendingAiSessionAuthorityByOutput.set(e,o),this.observeEventTransportCongestion(e,!0),this.logger?.info?.({...this.outputDiagnostics.get(e),instanceId:n,eventType:t.type,...Yr(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!==m.OPEN)return void this.pendingAiSessionAuthorityByOutput.delete(e);const[n,i]=t.entries().next().value;e.bufferedAmount>=Br?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)),o=this.eventTransportCongestion;this.eventTransportCongestion={congestedSince:o?.recoveredAt?i:o?.congestedSince||i,lastCongestedAt:i,peakBufferedBytes:Math.max(o?.recoveredAt?0:o?.peakBufferedBytes||0,s),coalescedEvents:(o?.recoveredAt?0:o?.coalescedEvents||0)+(t?1:0),oversizedEvents:(o?.recoveredAt?0:o?.oversizedEvents||0)+(n>0?1:0),peakEventBytes:Math.max(o?.recoveredAt?0:o?.peakEventBytes||0,n)}}eventTransportIsCongested(){return!![...this.pendingAiSessionAuthorityByOutput.values()].some(e=>e.size>0)||[...this.outputs].some(e=>e.readyState===m.OPEN&&e.bufferedAmount>=Br)}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===m.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=Zr(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 qr,url:t}),i.readyState===m.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:Pr(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===Ee){const e=function(e,t){const n=Vt.safeParse(e);return n.success?qt.parse({instanceId:t,...n.data}):qt.parse(e)}(n.payload,t);return{...n,payload:e,scope:{...n.scope,instanceId:t}}}if(n.type===we){const e=function(e,t){const n=Kt.safeParse(e);return n.success?Bt.parse({instanceId:t,...n.data}):Bt.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=bo(Ur,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!==m.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:Rr,aiSessionHierarchy:{subagents:!0},topics:[ye,"app.sessions","apps","instances"]}));const i=n.some(t=>t.messageDeltas.allInstances||t.messageDeltas.instanceIds.includes(e)),s=n.some(e=>e.timelineAllSessions),o=[...new Set(n.flatMap(t=>t.timelineSessions.filter(t=>t.instanceId===e).map(e=>e.sessionId)))],r=n.map(e=>e.replaySince).filter(e=>Boolean(e)).sort()[0];t.send(JSON.stringify({v:1,type:"subscribe",eventEnvelopeVersion:Rr,aiSessionHierarchy:{subagents:!0},topics:[Ie,Ae,_e,...i?[Ee]:[],...s||o.length?[Te,we]:[],"app.sessions","apps","instances"],aiSessionTransient:{...r?{replaySince:r}:{},messageDeltas:{allInstances:i,instanceIds:[]},timelineAllSessions:s,timelineSessions:o.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&&"ai-session.timeline-item-delta"!==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&&Zr(t);if(!n||!this.outputs.size)return;const i=this.retries.get(e)??{timer:new qr};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!==ye)return;if(t.type===Ee||t.type===Te||t.type===we)return;const n=Jr(t);if(n){const t=function(e,t){const{meta:n}=t.payload;if(t.type===Ie)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:Mt.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===Ae){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()],o=Lt.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:Mt.parse({streamId:n.streamId,revision:n.revision,lastEventAt:n.generatedAt,snapshot:o})}}(this.aiSessionProjectionByInstance.get(e),n);"applied"!==t.kind&&"duplicate"!==t.kind&&"stale"!==t.kind||this.aiSessionProjectionByInstance.set(e,t.projection)}const i=Yr(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!==rr)return;const n=function(e){const t=e.type===ar?Ar:e.type===cr?_r:e.type===dr?Er:void 0;if(!t)return;const n=bo(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===ar)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:fr.parse({streamId:n.streamId,revision:n.revision,lastEventAt:n.generatedAt,snapshot:wr(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===cr){const e=i.findIndex(e=>e.id===t.payload.session.id);Sr(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=Tr(i,n.generatedAt);return{kind:"applied",projection:fr.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=Yr(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===m.OPEN){this.sessionAuthorityReplayedOutputs.add(e);for(const[t,n]of this.sessionStreamsHelloByInstance){const i=n.streams.map(e=>{const n=e.topic===ye?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(Ie,{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(ar,{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 Wr(e){const t=go.safeParse(Xr(e));return t.success?t.data:void 0}function Xr(e){return{instanceId:e.id,revision:e.stateRevision,updatedAt:e.updatedAt,status:e.status,health:e.health,connectionStatus:e.connectionStatus,accessStatus:"online"===e.connectionStatus||"online"===e.agentStatus?"reachable":"endpoint-unreachable",imageProvisioning:e.imageProvisioning,workspace:e.workspace,runtime:e.runtime,runtimeVersion:e.runtimeVersion,ready:e.ready,lastHeartbeatAt:e.lastHeartbeatAt}}function Yr(e){const t=e&&"object"==typeof e&&!Array.isArray(e)?e:{},n=t.meta&&"object"==typeof t.meta&&!Array.isArray(t.meta)?t.meta:{};return{streamId:"string"==typeof n.streamId?n.streamId:void 0,revision:"number"==typeof n.revision?n.revision:void 0,traceId:"string"==typeof n.traceId?n.traceId:void 0}}function Jr(e){const t=e.type===Ie?Ft:e.type===Ae?$t:e.type===_e?Ht:void 0;if(!t)return;const n=bo(t,e.payload);return n.success?{type:e.type,payload:n.data}:void 0}function Qr(e){return e.topic===ye&&(e.type===Ie||e.type===Ae||e.type===_e)}function Zr(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.searchParams.set("aiSessionHierarchy","subagents"),e.protocol="https:"===e.protocol?"wss:":"ws:",e.toString()}catch{return}}const ea=new Set(["provisioning","starting","registering","registered","running","unhealthy"]),ta=JSON.stringify({id:"{{.ID}}",name:"{{.Name}}",cpu:"{{.CPUPerc}}",memory:"{{.MemUsage}}",memoryPercent:"{{.MemPerc}}",network:"{{.NetIO}}",blockIo:"{{.BlockIO}}",pids:"{{.PIDs}}"});class na{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(!ea.has(t.status))return ca(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=ia(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,ia(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=>ea.has(e.status)&&(e.runtime.containerId||e.runtime.containerName));for(const t of e.filter(e=>ea.has(e.status)&&!e.runtime.containerId&&!e.runtime.containerName))this.update(da(t.id));for(const t of e.filter(e=>!ea.has(e.status)))this.update(ca(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",ta,...n],{timeoutMs:5e3});this.applyDockerOutput(t,e.stdout,i)}catch(e){if(1===t.length)return void this.update(la(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",ta,t],{timeoutMs:5e3});this.applyDockerOutput([e],n.stdout,i)}catch(t){this.update(la(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=aa(e.id),o=aa(e.name),r=s||o;if(!r)continue;const a=sa(aa(e.memory)),c=sa(aa(e.network)),d=sa(aa(e.blockIo)),l=Xs.parse({instanceId:r,runtimeKind:"docker",state:"available",sampledAt:t,cpu:oa(e.cpu,"usagePercent"),memory:a?{usageBytes:a[0],...void 0!==a[1]?{limitBytes:a[1]}:{},...oa(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:ra(e.pids)});s&&n.set(s,l),o&&n.set(o,l)}return n}(t,n);for(const t of e){const e=[t.runtime.containerId,t.runtime.containerName].filter(Boolean),s=[...i.entries()].find(([t])=>e.some(e=>e===t||e.startsWith(t)||t.startsWith(e)))?.[1];this.update(s?{...s,instanceId:t.id}:la(t.id,n,"Container metrics were not returned by Docker."))}}update(e){const t=Xs.parse(e);this.snapshots.set(t.instanceId,t),this.publish?.(t)}}function ia(e){return[e.status,e.runtime.containerId||"",e.runtime.containerName||""].join("\0")}function sa(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"),o="b"===i[0]?"":i[0],r=o?"kmgtpe".indexOf(o)+1:0;return Math.round(n*(s?1024:1e3)**r)}(e||""));return void 0===t?void 0:[t,n]}function oa(e,t){const n=Number(aa(e).replace(/%$/,""));return Number.isFinite(n)&&n>=0?{[t]:n}:void 0}function ra(e){const t=Number(aa(e));return Number.isFinite(t)&&t>=0?t:void 0}function aa(e){return"string"==typeof e||"number"==typeof e?String(e).trim():""}function ca(e){return{instanceId:e,runtimeKind:"docker",state:"stopped",sampledAt:(new Date).toISOString()}}function da(e){return{instanceId:e,runtimeKind:"docker",state:"pending",sampledAt:(new Date).toISOString()}}function la(e,t,n){return{instanceId:e,runtimeKind:"docker",state:"unavailable",sampledAt:t,error:n.slice(0,2048)}}function ua(e,t,n){return Object.assign(new Error(e),{statusCode:t,code:n})}function pa(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 ua(`Folder ${i} was not found.`,404,"NODE_FOLDER_PATH_NOT_FOUND");throw ua(`Folder ${i} is not accessible.`,403,"NODE_FOLDER_PATH_UNREADABLE")}if(!s.isDirectory())throw ua(`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 ua(`Folder ${i} is not accessible.`,403,"NODE_FOLDER_PATH_UNREADABLE")}return i}function ma(e){try{return t.statSync(e).isDirectory()}catch{return!1}}function ha(){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(ma)}function ga(){const e=n.resolve(c.homedir()),t=ha().map(e=>n.resolve(e));return[...ma(e)?[{kind:"home",name:n.basename(e)||e,path:e}]:[],...t.map(e=>({kind:"root",name:e,path:e}))]}function fa(e,i){let s;try{s=t.statSync(e)}catch{return}if(!s.isDirectory())return;const o=n.resolve(e),r=n.basename(o)||o;let a=[];try{a=i>0?t.readdirSync(o,{withFileTypes:!0}):[]}catch{a=[]}const c=i>0?a.filter(e=>e.isDirectory()||e.isSymbolicLink()&&ma(n.join(o,e.name))).sort((e,t)=>e.name.localeCompare(t.name)).slice(0,80).flatMap(e=>{const t=fa(n.join(o,e.name),i-1);return t?[t]:[]}):[];return{name:r,path:o,children:c}}function ya(e){return(e.path?[pa(e.path)]:ha()).flatMap(t=>{const n=fa(t,e.depth);return n?[n]:[]})}function Ia(){return process.env.TASK_HANDOFF_NODE_AGENT_DATA_DIR||n.join(c.homedir(),".config","task-handoff","node-agent")}function Aa(e=Ia()){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"),dockerBootstrapDir:n.join(t,"docker-bootstrap"),logsDir:n.join(t,"logs"),databasePath:n.join(t,"node-agent.sqlite"),storyRegistryDir:n.join(t,"story-registry"),storyAutomationsDir:n.join(t,"story-automations"),storyContentDir:n.join(t,"stories"),storyMutationsDir:n.join(t,".story-mutations"),storyTrashDir:n.join(t,".story-trash")}}function _a(e,t){const i=n.extname(e);return`${i?e.slice(0,-i.length):e}.${t}${i}`}function Ea(e,n=10485760,i=2){if(!t.existsSync(e))return!1;const s=t.lstatSync(e);if(!s.isFile()||s.isSymbolicLink()||s.size<=n)return!1;if(i>0){!function(e,n){if(!(n<=0)){t.rmSync(_a(e,n),{force:!0});for(let i=n-1;i>=1;i-=1){const n=_a(e,i);t.existsSync(n)&&t.renameSync(n,_a(e,i+1))}}}(e,i);const s=function(e,n){const i=t.statSync(e),s=Math.min(i.size,n),o=Buffer.allocUnsafe(s),r=t.openSync(e,"r");let a=0;try{for(;a<s;){const e=t.readSync(r,o,a,s-a,i.size-s+a);if(0===e)break;a+=e}}finally{t.closeSync(r)}return a===s?o:o.subarray(0,a)}(e,n);t.writeFileSync(_a(e,1),s,{mode:384})}return t.truncateSync(e,0),t.chmodSync(e,384),!0}class Ta{logsDir;localInstancesRoot;localInstancesTrashRoot;privateConfigsDir;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"),this.privateConfigsDir=e.instancePrivateConfigsDir}run(e){this.capNodeAgentLogs();const n=new Set(e);if(this.removeOrphanPrivateConfigs(n),t.existsSync(this.localInstancesRoot)){le(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??ce,s=[];for(const o of t.readdirSync(e.trashRoot,{withFileTypes:!0})){const r=de(e.trashRoot,o.name);try{const e=Number(o.name.split("-",1)[0]);if(!Number.isFinite(e)||e+i>n)continue;const a=t.lstatSync(r);a.isSymbolicLink()?t.unlinkSync(r):a.isDirectory()?t.rmSync(r,{recursive:!0,force:!0}):t.unlinkSync(r),s.push(r)}catch(t){e.logger?.("retired persistence entry cleanup failed",{path:r,error:t instanceof Error?t.message:String(t)})}}return s}({trashRoot:this.localInstancesTrashRoot,retentionMs:this.options.retentionMs??ce,nowMs:this.now(),logger:this.options.logger})}capActiveInstanceLogs(e){for(const t of e)this.capControlledInstanceLogs(t)}capNodeAgentLogs(){const e=[];for(const t of["node-agent.out.log","node-agent.err.log"]){const i=n.join(this.logsDir,t);try{Ea(i)&&e.push(i)}catch(e){this.options.logger?.("node-agent log rotation failed",{filePath:i,error:e instanceof Error?e.message:String(e)})}}return e}capControlledInstanceLogs(e){const t=n.resolve(this.localInstancesRoot,e);if(n.dirname(t)!==n.resolve(this.localInstancesRoot))return[];const i=n.join(t,"logs"),s=[];for(const t of["controlled-instance.out.log","controlled-instance.err.log"]){const o=n.join(i,t);try{Ea(o)&&s.push(o)}catch(t){this.options.logger?.("controlled instance log rotation failed",{instanceId:e,filePath:o,error:t instanceof Error?t.message:String(t)})}}return s}retire(e){try{return function(e){const n=de(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}`);le(e.trashRoot);const s=e.nowMs??Date.now();let o=0,r=`${s}-${e.entryName}`;for(;t.existsSync(de(e.trashRoot,r));)o+=1,r=`${s}-${o}-${e.entryName}`;const a=de(e.trashRoot,r);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)})}}removeOrphanPrivateConfigs(e){if(t.existsSync(this.privateConfigsDir))for(const i of t.readdirSync(this.privateConfigsDir,{withFileTypes:!0})){if(!i.isFile()||!i.name.endsWith(".json"))continue;const s=i.name.slice(0,-5);if(e.has(s))continue;const o=n.join(this.privateConfigsDir,i.name);try{(this.options.removeFile||(e=>t.rmSync(e,{force:!0})))(o)}catch(e){this.options.logger?.("orphan instance private config cleanup failed",{instanceId:s,filePath:o,error:e instanceof Error?e.message:String(e)})}}}now(){return this.options.now?.()??Date.now()}}function wa(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`)}function ba(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}}}async function Sa(e,t,n={}){const s=n.method||"GET",o="string"==typeof n.body||n.body instanceof Buffer?n.body:void 0===n.body||null===n.body?void 0:String(n.body),r=new Headers(n.headers||{});return void 0===o||r.has("content-length")||r.set("content-length",String(Buffer.byteLength(o))),new Promise((a,c)=>{const d=i.request({socketPath:e,method:s,path:`/api/node-agent${t}`,headers:Object.fromEntries(r.entries())},e=>{const t=e.statusCode||500;a(new Response("HEAD"!==s&&204!==t&&205!==t&&304!==t?g.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!==o&&d.write(o),d.end()})}const va="runtime-manifest.json";class Na extends Error{code;retryable;constructor(e,t,n){super(t,void 0===n?.cause?void 0:{cause:n.cause}),this.name="RuntimeArtifactError",this.code=e,this.retryable=n?.retryable??!1}}async function Oa(e,t=""){const i=[],s=await f.readdir(n.join(e,t),{withFileTypes:!0});for(const o of s){const s=t?n.posix.join(t,o.name):o.name;if(!t&&s===va)continue;const r=n.join(e,...s.split("/"));if(o.isDirectory()){i.push(...await Oa(e,s));continue}if(o.isSymbolicLink()){const t=await f.readlink(r);if(n.isAbsolute(t))throw new Na("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload symlink is absolute: ${s}`);const o=n.resolve(n.dirname(r),t),a=n.relative(n.resolve(e),o);if(!a||".."===a||a.startsWith(`..${n.sep}`)||n.isAbsolute(a))throw new Na("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload symlink escapes the artifact: ${s}`);if(!await f.lstat(o).catch(()=>{}))throw new Na("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload symlink is broken: ${s}`);i.push({absolutePath:r,relativePath:s,kind:"symlink",target:t,size:Buffer.byteLength(t)});continue}if(!o.isFile())throw new Na("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload contains unsupported entry: ${s}`);const a=await f.lstat(r);i.push({absolutePath:r,relativePath:s,kind:"file",size:a.size})}return i}async function za(e){const n=(await Oa(e)).sort((e,t)=>function(e,t){return Buffer.compare(Buffer.from(e,"utf8"),Buffer.from(t,"utf8"))}(e.relativePath,t.relativePath)),i=d.createHash("sha256");for(const e of n){if(i.update("file"===e.kind?"F":"L","ascii"),i.update(Buffer.from(e.relativePath,"utf8")),i.update(Buffer.from([0])),i.update(Buffer.from(String(e.size),"ascii")),i.update(Buffer.from([0])),"file"===e.kind)for await(const n of t.createReadStream(e.absolutePath))i.update(n);else i.update(Buffer.from(e.target,"utf8"));i.update(Buffer.from([0]))}return i.digest("hex")}function Ca(e){for(const[t,n]of[["version",e.version],["platform",e.platform],["arch",e.arch]])if(!/^[0-9A-Za-z._-]+$/.test(n))throw new Na("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Invalid runtime artifact ${t}: ${n}`);return`${e.version}-${e.platform}-${e.arch}`}function Ra(e,t){return`${Ca(e)}-${e.sha256}-${t}`}async function xa(e){const n=d.createHash("sha256");for await(const i of t.createReadStream(e))n.update(i);return n.digest("hex")}class ka{#e;#t;#n=new Map;constructor(e){this.#e=e.cacheDir,this.#t=e.fetchImpl??fetch}resolve(e,t){const n=Ki.parse(e);if(!/^[a-f0-9]{64}$/.test(t.archiveSha256))throw new Na("INSTANCE_RUNTIME_ARTIFACT_INVALID","Runtime archive SHA-256 is invalid.");if((t.archiveUrl?1:0)+(t.archivePath?1:0)!=1)throw new Na("INSTANCE_RUNTIME_ARTIFACT_INVALID","Runtime artifact source must specify exactly one archive location.");const i=Ra(n,t.archiveSha256),s=this.#n.get(i);if(s)return s;const o=this.#i(n,t).finally(()=>this.#n.delete(i));return this.#n.set(i,o),o}async#i(e,i){if(!/^[a-f0-9]{64}$/.test(i.archiveSha256))throw new Na("INSTANCE_RUNTIME_ARTIFACT_INVALID","Runtime archive SHA-256 is invalid.");const s=Ra(e,i.archiveSha256),o=n.join(this.#e,"archives"),r=n.join(o,`${s}.tar.gz`);if(await f.mkdir(o,{recursive:!0}),await this.#s(r,e,i.archiveSha256))return{identity:e,archivePath:r,cacheHit:!0};await f.rm(r,{force:!0});const a=n.join(o,`.${s}.${d.randomUUID()}.part`);try{const n=await f.open(a,"wx");if(i.archivePath)await y.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 Na("INSTANCE_RUNTIME_ARTIFACT_UNAVAILABLE",`Runtime artifact download failed with HTTP ${e.status}.`,{retryable:e.status>=500});await y.pipeline(e.body,n.createWriteStream())}if(await xa(a)!==i.archiveSha256)throw new Na("INSTANCE_RUNTIME_ARTIFACT_INVALID","Downloaded runtime archive SHA-256 does not match release metadata.");return await this.#o(a,e),await f.rename(a,r),{identity:e,archivePath:r,cacheHit:!1}}catch(e){if(e instanceof Na)throw e;throw new Na("INSTANCE_RUNTIME_ARTIFACT_UNAVAILABLE","Could not download runtime artifact.",{cause:e,retryable:!0})}finally{await f.rm(a,{force:!0})}}async#s(e,t,n){try{return await xa(e)===n&&(await this.#o(e,t),!0)}catch{return!1}}async#o(e,t){const i=n.join(this.#e,"validation",`${Ca(t)}-${d.randomUUID()}`);try{await async function(e,t){await f.mkdir(t,{recursive:!0});try{await I.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 Na("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 Na("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime archive contains unsupported entry type ${s??"unknown"}: ${e}`);return!0}})}catch(e){throw new Na("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 f.readFile(n.join(e,va),"utf8"))}catch(e){throw new Na("INSTANCE_RUNTIME_ARTIFACT_INVALID","Runtime artifact manifest is missing or invalid JSON.",{cause:e})}const i=bo(Ki,t);if(!i.success)throw new Na("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 Na("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 Na("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Unsupported runtime artifact format ${s.formatVersion}.`);if(i?.platform&&"universal"!==s.platform&&s.platform!==i.platform)throw new Na("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 Na("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 Na("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Runtime requires launcher ABI ${s.launcherAbi}, but the base runtime provides ${i.launcherAbi}.`);const o=function(e,t){if(!e||e.includes("\\")||n.posix.isAbsolute(e))throw new Na("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 Na("INSTANCE_RUNTIME_ARTIFACT_INVALID",`${t} escapes the runtime root.`);return i}(s.entrypoint,"Runtime entrypoint"),r=await f.lstat(n.join(e,...o.split("/"))).catch(()=>{});if(!r?.isFile())throw new Na("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime entrypoint is missing: ${o}`);const a=await za(e);if(a!==s.sha256)throw new Na("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 f.rm(i,{recursive:!0,force:!0})}}}async function Da(e,t,i,s=fetch){if("linux"!==t||!["x64","arm64"].includes(i))throw new Na("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Managed controlled-instance updates require a Linux x64 or arm64 target, received ${t}/${i}.`);const o=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,o]=await Promise.all([f.readFile(n.join(i,`${t}.manifest.json`),"utf8"),f.readFile(n.join(i,`${t}.tar.gz.sha256`),"utf8")]),r=bo(Ki,JSON.parse(s));if(!r.success||r.data.version!==e||"linux"!==r.data.platform||"universal"!==r.data.arch)throw new Na("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Bundled controlled-instance ${e} has an invalid Linux manifest.`);const a=o.trim().split(/\s+/)[0]?.toLowerCase();if(!a||!/^[a-f0-9]{64}$/.test(a))throw new Na("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Bundled controlled-instance ${e} has an invalid archive checksum.`);return{identity:r.data,source:{archivePath:n.join(i,`${t}.tar.gz`),archiveSha256:a}}}catch(t){if("ENOENT"===t.code)return;if(t instanceof Na)throw t;throw new Na("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Could not read bundled controlled-instance ${e}.`,{cause:t})}}(e);if(o)return o;const r=`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}/${r}.manifest.json`,d=`${a}/${r}.tar.gz`,l=`${a}/${r}.tar.gz.sha256`,[u,p]=await Promise.all([s(c),s(l)]).catch(t=>{throw new Na("INSTANCE_RUNTIME_ARTIFACT_UNAVAILABLE",`Could not read release metadata for controlled-instance ${e}.`,{cause:t,retryable:!0})});if(!u.ok||!p.ok)throw new Na("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 Na("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Release manifest for controlled-instance ${e} is not valid JSON.`,{cause:t})}const h=bo(Ki,m);if(!h.success)throw new Na("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 Na("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Release identity mismatch: requested ${e}-linux-universal, received ${h.data.version}-${h.data.platform}-${h.data.arch}.`);const g=(await p.text()).trim().split(/\s+/)[0]?.toLowerCase();if(!g||!/^[a-f0-9]{64}$/.test(g))throw new Na("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Release checksum for controlled-instance ${e} is invalid.`);return{identity:h.data,source:{archiveUrl:d,archiveSha256:g}}}class Pa{store;desiredVersion;hooks;inFlight=new Map;requests=new Map;cancelled=new Set;now;delay;drainTimeoutMs;drainRequestRetryMs;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.drainRequestRetryMs=function(e){if(!Number.isFinite(e)||e<=0)throw new TypeError("drainRequestRetryMs must be a positive finite number.");return e}(i.drainRequestRetryMs??1e3),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=Va(i.retryBaseDelayMs??1e3,"retryBaseDelayMs"),this.retryMaxDelayMs=Va(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(ja(n))return this.storePhase(n,"pending");const s=n.runtimeVersion?.desiredVersion!==i||t.startRequested||Ua(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 o=La(n),r=o===i&&(await(this.hooks.isInstalled?.(n,i))??!0);if(this.cancelled.has(e))return this.storePhase(this.requireInstance(e),"pending");if(o===i&&r)return this.storeState(n,{desiredVersion:i,actualVersion:o,phase:"matched",attempt:n.runtimeVersion?.attempt||0,matchedAt:this.timestamp()},!Ua(n)&&"failed"!==n.health);if(n=this.storeState(n,function(e,t,n,i=!1){const s=e.runtimeVersion,o=s?.desiredVersion===t&&"matched"!==s.phase;return{desiredVersion:t,...n?{actualVersion:n}:{},phase:"pending",attempt:o?s.attempt:0,error:(o?s.error:void 0)||(n!==t||i?Fa(t,n):$a("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,o,r)),Ua(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{n=this.storePhase(n,"draining");const s=this.now().getTime()+this.drainTimeoutMs;let o=!1;for(;!o;){if(o=!1!==await(this.hooks.beginDrain?.(n)),o){a=!0;break}if(this.cancelled.has(e))return this.storePhase(this.requireInstance(e),"pending");const t=s-this.now().getTime();if(t<=0)break;await this.delay(Math.min(this.drainRequestRetryMs,t)),n=this.requireInstance(e)}if(n=this.requireInstance(e),!o||Ma(n)){const t=Math.max(0,s-this.now().getTime()),i=o&&await this.waitUntil(e,t,e=>!Ma(e));if(n=this.requireInstance(e),!i){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)||Ua(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=>La(e)===i);if(this.cancelled.has(e))return this.storePhase(this.requireInstance(e),"pending");if(!r)throw $a("INSTANCE_RUNTIME_VERIFICATION_FAILED",`Instance ${e} did not register controlled-instance ${i} after restart.`,i,La(this.requireInstance(e)),!0);const d=this.requireInstance(e);if(this.hooks.isInstalled&&!await this.hooks.isInstalled(d,i))throw $a("INSTANCE_RUNTIME_VERIFICATION_FAILED",`Instance ${e} reported controlled-instance ${i}, but its active runtime release is missing.`,i,La(d),!0);return this.storeState(d,{desiredVersion:i,actualVersion:i,phase:"matched",attempt:d.runtimeVersion?.attempt||1,matchedAt:this.timestamp()},!Ua(d)&&"failed"!==d.health)}catch(t){if(this.cancelled.has(e))return this.storePhase(this.requireInstance(e),"pending");s=Ha(t,i,La(this.store.get(e)))}n=this.requireInstance(e);const o=n.runtimeVersion?.attempt||1;if(!s.retryable||c>=this.maxAttempts)return this.storeBatchFailure(n,i,o>=this.maxAttempts&&s.retryable?qa(i,La(n),this.maxAttempts,s):s);n=this.storeState(n,{desiredVersion:i,...La(n)?{actualVersion:La(n)}:{},phase:"pending",attempt:o,lastAttemptAt:this.timestamp(),error:s}),await this.delay(this.retryDelayMs(o))}return this.storeBatchFailure(n,i,qa(i,La(n),this.maxAttempts,n.runtimeVersion?.error))}finally{a&&await(this.hooks.endDrain?.(this.requireInstance(e)))}}storeBatchFailure(e,t,n){const i=La(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=La(e),o=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(),...o?{error:o}:"pending"===t?{error:Fa(i,s)}:{}},"restarting"!==t&&void 0)}storeState(e,t,n){const i=this.store.get(e.id)||e;return this.store.put(po.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 La(e){return e?.build?.packageVersion||e?.instanceVersion}function Ma(e){return e.apps.runningCount>0||e.aiSessions.runningCount>0}function ja(e){return Boolean(e.imageProvisioning&&"ready"!==e.imageProvisioning.phase)}function Ua(e){return["created","stopped","failed"].includes(e.status)}function Fa(e,t){return $a("INSTANCE_RUNTIME_VERSION_MISMATCH",`Expected controlled-instance ${e}, received ${t||"an unknown version"}.`,e,t,!0)}function $a(e,t,n,i,s){return{code:e,message:t,expectedVersion:n,...i?{actualVersion:i}:{},retryable:s}}function Ha(e,t,n){if(e&&"object"==typeof e&&"code"in e&&"message"in e){const i=e,s=Gi.shape.code.safeParse(i.code);if(s.success&&"string"==typeof i.message)return $a(s.data,i.message,t,n,"boolean"!=typeof i.retryable||i.retryable)}return $a("INSTANCE_RUNTIME_INSTALL_FAILED",e instanceof Error?e.message:String(e),t,n,!0)}function qa(e,t,n,i){const s=i?.message?` Last error: ${i.message}`:"";return $a(i?.code||"INSTANCE_RUNTIME_INSTALL_FAILED",`Runtime convergence paused after ${n} attempts and will retry.${s}`,e,t,!0)}function Va(e,t){if(!Number.isFinite(e)||e<0)throw new TypeError(`${t} must be a nonnegative finite number.`);return e}function Ba(e,n=448){t.mkdirSync(e,{recursive:!0,mode:n}),t.chmodSync(e,n)}function Ka(e,i,s={}){const o=s.directoryMode??448,r=s.fileMode??384;Ba(n.dirname(e),o),p.sync(e,`${JSON.stringify(i,null,2)}\n`,{encoding:"utf8",mode:r}),t.chmodSync(e,r)}function Ga(e,t){console.warn(JSON.stringify({message:e,...t}))}function Wa(e){return e&&"object"==typeof e&&"issues"in e?{issues:e.issues}:{error:e instanceof Error?e.message:String(e)}}function Xa(e,n){const i=n.logger||Ga;let s;try{s=JSON.parse(t.readFileSync(e,"utf8"))}catch(t){if(n.rejectInvalid)throw t;return void i("stored JSON could not be read",{filePath:e,...Wa(t)})}if(!n.schema)return s;const o=n.sanitize?n.sanitize(s):s,r=n.schema.safeParse(o);if(r.success)return r.data;if(n.rejectInvalid)throw r.error;const a="strip"in n.schema&&"function"==typeof n.schema.strip?n.schema.strip().safeParse(o):void 0;if(a?.success)return i("unknown stored fields were ignored",{filePath:e,issues:r.error.issues}),a.data;i("stored record failed validation and was isolated",{filePath:e,issues:r.error.issues})}function Ya(e){return`${e}_${d.randomUUID().replace(/-/g,"").slice(0,20)}`}function Ja(){return d.randomBytes(24).toString("base64url")}class Qa{directory;options;permissionsInitialized=!1;constructor(e,t={}){this.directory=e,this.options=t}init(){if(this.permissionsInitialized&&t.existsSync(this.directory))return;Ba(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=Xa(n.join(this.directory,e),this.options);return t?[t]:[]})}get(e){this.init();const n=this.filePath(e);return t.existsSync(n)?Xa(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 Ka(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 Za{filePathValue;defaults;options;constructor(e,t,n={}){this.filePathValue=e,this.defaults=t,this.options=n}init(){Ba(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)?Xa(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 Ka(this.filePathValue,n,this.options),n}}E.sqliteTable("na_migration_ledger",{id:E.text("id").primaryKey(),checksum:E.text("checksum").notNull(),appliedAt:E.text("applied_at").notNull(),details:E.text("details",{mode:"json"}).$type().notNull()});const ec=E.sqliteTable("na_stories",{id:E.text("id").primaryKey(),title:E.text("title").notNull(),description:E.text("description"),createdAt:E.text("created_at").notNull(),updatedAt:E.text("updated_at").notNull(),archivedAt:E.text("archived_at"),maxIdleAiSessions:E.integer("max_idle_ai_sessions").notNull().default(5),nextDocumentSequence:E.integer("next_document_sequence").notNull().default(1)},e=>[E.check("na_stories_max_idle_check",_.sql`${e.maxIdleAiSessions} BETWEEN 1 AND 50`),E.check("na_stories_next_document_sequence_check",_.sql`${e.nextDocumentSequence} > 0`),E.index("na_stories_created_idx").on(e.createdAt)]),tc=E.sqliteTable("na_story_actions",{storyId:E.text("story_id").notNull().references(()=>ec.id,{onDelete:"cascade"}),id:E.text("id").notNull(),title:E.text("title").notNull(),promptTemplate:E.text("prompt_template").notNull(),targetInstanceId:E.text("target_instance_id"),sessionPreset:E.text("session_preset_json",{mode:"json"}).$type(),displayOrder:E.integer("display_order").notNull()},e=>[E.primaryKey({columns:[e.storyId,e.id]}),E.index("na_story_actions_order_idx").on(e.storyId,e.displayOrder,e.id)]),nc=E.sqliteTable("na_story_documents",{storyId:E.text("story_id").notNull().references(()=>ec.id,{onDelete:"cascade"}),storyPath:E.text("story_path").notNull(),title:E.text("title").notNull(),indexedSequence:E.integer("indexed_sequence").notNull(),displayOrder:E.integer("display_order").notNull()},e=>[E.primaryKey({columns:[e.storyId,e.storyPath]}),E.uniqueIndex("na_story_documents_sequence_uq").on(e.storyId,e.indexedSequence),E.index("na_story_documents_page_idx").on(e.storyId,e.indexedSequence,e.storyPath),E.index("na_story_documents_display_idx").on(e.storyId,e.displayOrder,e.storyPath),E.check("na_story_documents_sequence_check",_.sql`${e.indexedSequence} > 0`)]),ic=E.sqliteTable("na_story_automations",{id:E.text("id").primaryKey(),storyId:E.text("story_id").notNull(),actionId:E.text("action_id").notNull(),schedule:E.text("schedule_json",{mode:"json"}).$type().notNull(),enabled:E.integer("enabled",{mode:"boolean"}).notNull(),policy:E.text("policy_json",{mode:"json"}).$type().notNull(),scheduleAnchorAt:E.text("schedule_anchor_at").notNull(),createdAt:E.text("created_at").notNull(),updatedAt:E.text("updated_at").notNull()},e=>[E.foreignKey({columns:[e.storyId,e.actionId],foreignColumns:[tc.storyId,tc.id],name:"na_story_automations_action_fk"}).onDelete("restrict"),E.index("na_story_automations_story_idx").on(e.storyId),E.index("na_story_automations_enabled_idx").on(e.enabled)]),sc=E.sqliteTable("na_story_automation_runs",{id:E.text("id").primaryKey(),automationId:E.text("automation_id").notNull().references(()=>ic.id,{onDelete:"cascade"}),eventType:E.text("event_type",{enum:["manual","schedule"]}).notNull(),status:E.text("status",{enum:["queued","dispatching","running","completed","failed","skipped"]}).notNull(),scheduledFor:E.text("scheduled_for").notNull(),targetInstanceId:E.text("target_instance_id").notNull(),aiSessionId:E.text("ai_session_id"),error:E.text("error_json",{mode:"json"}).$type(),queuedAt:E.text("queued_at").notNull(),startedAt:E.text("started_at"),completedAt:E.text("completed_at"),executionKey:E.text("execution_key").notNull(),requestFingerprint:E.text("request_fingerprint").notNull(),executionInput:E.text("execution_input_json",{mode:"json"}).$type().notNull()},e=>[E.uniqueIndex("na_story_automation_runs_execution_key_uq").on(e.executionKey),E.index("na_story_automation_runs_automation_time_idx").on(e.automationId,e.queuedAt),E.index("na_story_automation_runs_status_idx").on(e.status,e.scheduledFor)]),oc=E.sqliteTable("na_story_file_mutations",{id:E.text("id").primaryKey(),storyId:E.text("story_id").notNull().references(()=>ec.id,{onDelete:"restrict"}),operation:E.text("operation",{enum:["write","rename","delete"]}).notNull(),storyPath:E.text("story_path").notNull(),nextStoryPath:E.text("next_story_path"),title:E.text("title"),temporaryName:E.text("temporary_name"),backupName:E.text("backup_name"),phase:E.text("phase",{enum:["receiving","prepared","files-staged","database-committed","cleanup"]}).notNull(),createdAt:E.text("created_at").notNull(),updatedAt:E.text("updated_at").notNull()},e=>[E.index("na_story_file_mutations_story_idx").on(e.storyId,e.createdAt)]),rc=E.sqliteTable("na_story_deletion_intents",{storyId:E.text("story_id").primaryKey(),phase:E.text("phase",{enum:["prepared","files-staged","database-committed","cleanup"]}).notNull(),trashName:E.text("trash_name"),createdAt:E.text("created_at").notNull(),updatedAt:E.text("updated_at").notNull()}),ac=["health","connectionStatus","agentStatus","targetStatus","uiAccessStatus","ready","protocolVersion","instanceVersion","build","runtimeVersion","capabilities","appInventory","target","access","apps","aiSessions","triggers","runtime","lastHeartbeatAt"];function cc(e){return JSON.stringify(e??null)}function dc(e){return JSON.parse(String(e))}function lc(e,t){if(e.isTransaction)return t();e.exec("BEGIN IMMEDIATE");try{const n=t();return e.exec("COMMIT"),n}catch(t){throw e.exec("ROLLBACK"),t}}class uc{client;constructor(e){this.client=e}get(){return this.client.prepare("SELECT node_id, created_at, updated_at FROM na_node_identity WHERE singleton_key = 1").get()}ensure(e,t){const n=this.get();if(n&&n.node_id!==e)throw _c("NODE_AGENT_IDENTITY_MISMATCH",`Stored node identity ${n.node_id} does not match ${e}.`);return n||this.client.prepare("INSERT INTO na_node_identity (singleton_key, node_id, created_at, updated_at) VALUES (1, ?, ?, ?)").run(e,t,t),this.get()}}class pc{client;constructor(e){this.client=e}list(){return this.client.prepare("SELECT * FROM na_local_folders ORDER BY id").all().map(yc)}get(e){const t=this.client.prepare("SELECT * FROM na_local_folders WHERE id = ?").get(e);return t?yc(t):void 0}put(e){const t=rs.parse(Si(e));return this.client.prepare("INSERT INTO na_local_folders (id, node_id, name, path, labels_json, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT(id) DO UPDATE SET node_id=excluded.node_id, name=excluded.name, path=excluded.path,\n labels_json=excluded.labels_json, updated_at=excluded.updated_at").run(t.id,t.nodeId,t.name,t.path,cc(t.labels),t.createdAt,t.updatedAt),t}delete(e){return Number(this.client.prepare("DELETE FROM na_local_folders WHERE id = ?").run(e).changes)>0}}class mc{client;constructor(e){this.client=e}list(){return this.client.prepare("SELECT * FROM na_runtimes ORDER BY id").all().map(Ic)}get(e){const t=this.client.prepare("SELECT * FROM na_runtimes WHERE id = ?").get(e);return t?Ic(t):void 0}put(e){const t=Ws.parse(e);return this.client.prepare("INSERT INTO na_runtimes (id, node_id, name, type, status, access_strategy, capabilities_json, labels_json, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT(id) DO UPDATE SET node_id=excluded.node_id, name=excluded.name, type=excluded.type,\n status=excluded.status, access_strategy=excluded.access_strategy, capabilities_json=excluded.capabilities_json,\n labels_json=excluded.labels_json, updated_at=excluded.updated_at").run(t.id,t.nodeId,t.name,t.type,t.status,t.accessStrategy,cc(t.capabilities),cc(t.labels),t.createdAt,t.updatedAt),t}delete(e){try{return Number(this.client.prepare("DELETE FROM na_runtimes WHERE id = ?").run(e).changes)>0}catch(t){if(String(t).includes("FOREIGN KEY constraint failed"))throw _c("NODE_RUNTIME_IN_USE",`Runtime ${e} is used by a controlled instance.`,409);throw t}}}class hc{client;constructor(e){this.client=e}list(){return this.client.prepare("SELECT i.*, o.health, o.connection_status, o.ready, o.observed_json,\n o.last_heartbeat_at, o.updated_at AS observation_updated_at\n FROM na_instances i LEFT JOIN na_instance_observations o ON o.instance_id = i.id ORDER BY i.id").all().map(e=>Ac(this.client,e))}get(e){const t=this.client.prepare("SELECT i.*, o.health, o.connection_status, o.ready, o.observed_json,\n o.last_heartbeat_at, o.updated_at AS observation_updated_at\n FROM na_instances i LEFT JOIN na_instance_observations o ON o.instance_id = i.id WHERE i.id = ?").get(e);return t?Ac(this.client,t):void 0}put(e){const t=po.parse(yo(e));return lc(this.client,()=>{const e=this.client.prepare("SELECT state_revision, registration_credential FROM na_instances WHERE id = ?").get(t.id),n=Math.max(t.stateRevision||0,Number(e?.state_revision)||0)+1,i=t.registrationToken||e?.registration_credential,s=function(e){const t={...e};for(const e of ac)delete t[e];for(const e of["id","nodeId","runtimeId","name","status","stateRevision","processIncarnationId","registrationToken","createdAt","updatedAt"])delete t[e];return t}({...t,stateRevision:n}),o=fc(t),r="local-folder"===t.source.type?t.source.localFolderId:void 0;return this.client.prepare("INSERT INTO na_instances\n (id, node_id, runtime_id, source_local_folder_id, name, status, state_revision, process_incarnation_id,\n registration_credential, desired_json, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT(id) DO UPDATE SET node_id=excluded.node_id, runtime_id=excluded.runtime_id,\n source_local_folder_id=excluded.source_local_folder_id, name=excluded.name, status=excluded.status,\n state_revision=excluded.state_revision, process_incarnation_id=excluded.process_incarnation_id,\n registration_credential=excluded.registration_credential, desired_json=excluded.desired_json,\n updated_at=excluded.updated_at").run(t.id,t.nodeId,t.runtimeId,r??null,t.name,t.status,n,t.processIncarnationId??null,i??null,cc(s),t.createdAt,t.updatedAt),this.client.prepare("INSERT INTO na_instance_observations\n (instance_id, health, connection_status, ready, observed_json, last_heartbeat_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT(instance_id) DO UPDATE SET health=excluded.health, connection_status=excluded.connection_status,\n ready=excluded.ready, observed_json=excluded.observed_json, last_heartbeat_at=excluded.last_heartbeat_at,\n updated_at=excluded.updated_at").run(t.id,t.health,t.connectionStatus,t.ready?1:0,cc(o),t.lastHeartbeatAt??null,t.updatedAt),this.get(t.id)})}putObservation(e){const t=po.parse(yo(e));return lc(this.client,()=>{const e=this.client.prepare("SELECT state_revision, registration_credential FROM na_instances WHERE id = ?").get(t.id);if(!e)throw _c("NODE_INSTANCE_NOT_FOUND",`Instance ${t.id} was not found.`,404);const n=Math.max(t.stateRevision||0,Number(e.state_revision)||0)+1,i=t.registrationToken||e.registration_credential;return this.client.prepare("UPDATE na_instances SET status = ?, state_revision = ?, process_incarnation_id = ?,\n registration_credential = ?, updated_at = ? WHERE id = ?").run(t.status,n,t.processIncarnationId??null,i??null,t.updatedAt,t.id),this.client.prepare("INSERT INTO na_instance_observations\n (instance_id, health, connection_status, ready, observed_json, last_heartbeat_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT(instance_id) DO UPDATE SET health=excluded.health, connection_status=excluded.connection_status,\n ready=excluded.ready, observed_json=excluded.observed_json, last_heartbeat_at=excluded.last_heartbeat_at,\n updated_at=excluded.updated_at").run(t.id,t.health,t.connectionStatus,t.ready?1:0,cc(fc(t)),t.lastHeartbeatAt??null,t.updatedAt),this.get(t.id)})}delete(e){return Number(this.client.prepare("DELETE FROM na_instances WHERE id = ?").run(e).changes)>0}}function gc(e){return{nodeIdentity:new uc(e),localFolders:new pc(e),runtimes:new mc(e),instances:new hc(e)}}function fc(e){return Object.fromEntries(ac.flatMap(t=>void 0===e[t]?[]:[[t,e[t]]]))}function yc(e){return rs.parse({id:e.id,nodeId:e.node_id,name:e.name,path:e.path,labels:dc(e.labels_json),createdAt:e.created_at,updatedAt:e.updated_at})}function Ic(e){return Ws.parse({id:e.id,nodeId:e.node_id,name:e.name,type:e.type,status:e.status,accessStrategy:e.access_strategy,capabilities:dc(e.capabilities_json),labels:dc(e.labels_json),createdAt:e.created_at,updatedAt:e.updated_at})}function Ac(e,t){const n=dc(t.desired_json),i=t.observed_json?dc(t.observed_json):{},s=e.prepare("SELECT * FROM na_instance_model_assignments WHERE instance_id = ?").get(String(t.id)),o=s?e.prepare("SELECT model_id FROM na_instance_model_entities WHERE instance_id = ? ORDER BY display_order").all(String(t.id)).map(e=>String(e.model_id)):void 0,r=s?{modelEntityIds:o,...s.legacy_codex_model_id?{codexModelHash:String(s.legacy_codex_model_id)}:{},...s.legacy_claude_model_id?{claudeModelHash:String(s.legacy_claude_model_id)}:{},...s.legacy_opencode_model_id?{opencodeModelHash:String(s.legacy_opencode_model_id)}:{}}:n.modelSelection;return po.parse({...n,...i,modelSelection:r,id:t.id,nodeId:t.node_id,runtimeId:t.runtime_id,name:t.name,status:t.status,stateRevision:t.state_revision,processIncarnationId:t.process_incarnation_id||void 0,registrationToken:t.registration_credential||void 0,health:t.health||"unknown",connectionStatus:t.connection_status||"unknown",ready:Boolean(t.ready),lastHeartbeatAt:t.last_heartbeat_at||void 0,createdAt:t.created_at,updatedAt:t.updated_at})}function _c(e,t,n=409){return Object.assign(new Error(t),{code:e,statusCode:n})}function Ec(e){return JSON.stringify(e??null)}function Tc(e){return JSON.parse(String(e))}class wc{client;constructor(e){this.client=e}list(){return this.client.prepare("SELECT * FROM na_models ORDER BY display_order, id").all().map(vc)}get(e){const t=this.client.prepare("SELECT * FROM na_models WHERE id = ?").get(e);return t?vc(t):void 0}put(e){const t=hs.parse(e);return this.client.prepare("INSERT INTO na_models\n (id, name, endpoint, key, model, app, enabled, display_order, model_names_json, protocols_json, labels_json, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT(id) DO UPDATE SET name=excluded.name, endpoint=excluded.endpoint, key=excluded.key,\n model=excluded.model, app=excluded.app, enabled=excluded.enabled, display_order=excluded.display_order,\n model_names_json=excluded.model_names_json, protocols_json=excluded.protocols_json,\n labels_json=excluded.labels_json, updated_at=excluded.updated_at").run(t.id,t.name,t.endpoint,t.key,t.model,t.app,t.enabled?1:0,t.order,Ec(t.modelNames),Ec(t.protocols),Ec(t.labels),t.createdAt,t.updatedAt),t}delete(e){try{return Number(this.client.prepare("DELETE FROM na_models WHERE id = ?").run(e).changes)>0}catch(t){if(String(t).includes("FOREIGN KEY constraint failed")){const t=this.referenceIds(e);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})}throw t}}referenceIds(e){return this.client.prepare("SELECT DISTINCT instance_id FROM (\n SELECT instance_id FROM na_instance_model_entities WHERE model_id = ?\n UNION ALL SELECT instance_id FROM na_instance_model_assignments WHERE legacy_codex_model_id = ?\n UNION ALL SELECT instance_id FROM na_instance_model_assignments WHERE legacy_claude_model_id = ?\n UNION ALL SELECT instance_id FROM na_instance_model_assignments WHERE legacy_opencode_model_id = ?\n ) ORDER BY instance_id").all(e,e,e,e).map(e=>String(e.instance_id))}}class bc{client;constructor(e){this.client=e}get(e){const t=this.client.prepare("SELECT * FROM na_instance_model_assignments WHERE instance_id = ?").get(e);if(!t)return;const n=this.client.prepare("SELECT model_id FROM na_instance_model_entities WHERE instance_id = ? ORDER BY display_order").all(e).map(e=>String(e.model_id));return ys.parse({instanceId:e,modelEntityIds:n,codexModelHash:t.legacy_codex_model_id||void 0,claudeModelHash:t.legacy_claude_model_id||void 0,opencodeModelHash:t.legacy_opencode_model_id||void 0,updatedAt:t.updated_at})}put(e){const t=ys.parse(e);return this.transaction(()=>{this.client.prepare("INSERT INTO na_instance_model_assignments\n (instance_id, legacy_codex_model_id, legacy_claude_model_id, legacy_opencode_model_id, updated_at)\n VALUES (?, ?, ?, ?, ?)\n ON CONFLICT(instance_id) DO UPDATE SET legacy_codex_model_id=excluded.legacy_codex_model_id,\n legacy_claude_model_id=excluded.legacy_claude_model_id,\n legacy_opencode_model_id=excluded.legacy_opencode_model_id, updated_at=excluded.updated_at").run(t.instanceId,t.codexModelHash??null,t.claudeModelHash??null,t.opencodeModelHash??null,t.updatedAt),this.client.prepare("DELETE FROM na_instance_model_entities WHERE instance_id = ?").run(t.instanceId);const e=this.client.prepare("INSERT INTO na_instance_model_entities (instance_id, model_id, display_order) VALUES (?, ?, ?)");for(const[n,i]of t.modelEntityIds.entries())e.run(t.instanceId,i,n)}),this.get(t.instanceId)}delete(e){return Number(this.client.prepare("DELETE FROM na_instance_model_assignments WHERE instance_id = ?").run(e).changes)>0}transaction(e){if(this.client.isTransaction)return e();this.client.exec("BEGIN IMMEDIATE");try{const t=e();return this.client.exec("COMMIT"),t}catch(e){throw this.client.exec("ROLLBACK"),e}}}function Sc(e){return{models:new wc(e),assignments:new bc(e),transaction(t){if(e.isTransaction)return t();e.exec("BEGIN IMMEDIATE");try{const n=t();return e.exec("COMMIT"),n}catch(t){throw e.exec("ROLLBACK"),t}}}}function vc(e){const t=Tc(e.model_names_json);return hs.parse({id:e.id,name:e.name,endpoint:e.endpoint,key:e.key,model:e.model,modelNames:t,protocols:Tc(e.protocols_json),app:e.app,enabled:Boolean(e.enabled),order:e.display_order,labels:Tc(e.labels_json),createdAt:e.created_at,updatedAt:e.updated_at})}class Nc{client;constructor(e){this.client=e}readIdentity(){const e=this.client.prepare("SELECT node_id, created_at, updated_at FROM na_node_identity WHERE singleton_key = 1").get();if(!e)return;const t=this.client.prepare("SELECT * FROM na_control_plane_pairings ORDER BY updated_at, key_id").all().map(e=>({id:String(e.control_plane_id),keyId:String(e.key_id),...e.name?{name:String(e.name)}:{},secret:String(e.secret),pairedAt:String(e.paired_at),...e.revoked_at?{revokedAt:String(e.revoked_at)}:{},updatedAt:String(e.updated_at)})),n=this.client.prepare("SELECT * FROM na_control_plane_connections ORDER BY updated_at, id").all().map(e=>({id:String(e.id),pairingKeyId:String(e.pairing_key_id),...e.name?{name:String(e.name)}:{},url:String(e.normalized_url),enabled:Boolean(e.enabled),createdAt:String(e.created_at),updatedAt:String(e.updated_at)}));return{nodeId:String(e.node_id),createdAt:String(e.created_at),updatedAt:String(e.updated_at),controlPlanePairings:t,controlPlaneConnections:n}}writeIdentity(e){return this.transaction(()=>{const t=this.readIdentity();if(t&&t.nodeId!==e.nodeId)throw n=`Stored node identity ${t.nodeId} does not match ${e.nodeId}.`,Object.assign(new Error(n),{code:"NODE_AGENT_IDENTITY_MISMATCH",statusCode:409});var n;this.client.prepare("INSERT INTO na_node_identity (singleton_key, node_id, created_at, updated_at) VALUES (1, ?, ?, ?)\n ON CONFLICT(singleton_key) DO UPDATE SET updated_at=excluded.updated_at").run(e.nodeId,e.createdAt,e.updatedAt);const i=(e.controlPlanePairings||[]).map(e=>e.keyId),s=(e.controlPlaneConnections||[]).map(e=>e.id);zc(this.client,"na_control_plane_connections","id",s),zc(this.client,"na_control_plane_pairings","key_id",i);const o=this.client.prepare("INSERT INTO na_control_plane_pairings\n (key_id, control_plane_id, name, secret, paired_at, revoked_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT(key_id) DO UPDATE SET control_plane_id=excluded.control_plane_id, name=excluded.name,\n secret=excluded.secret, paired_at=excluded.paired_at, revoked_at=excluded.revoked_at, updated_at=excluded.updated_at");for(const t of e.controlPlanePairings||[])o.run(t.keyId,t.id,t.name??null,t.secret,t.pairedAt,t.revokedAt??null,t.updatedAt);const r=this.client.prepare("INSERT INTO na_control_plane_connections\n (id, pairing_key_id, name, normalized_url, enabled, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT(id) DO UPDATE SET pairing_key_id=excluded.pairing_key_id, name=excluded.name,\n normalized_url=excluded.normalized_url, enabled=excluded.enabled, updated_at=excluded.updated_at");for(const t of e.controlPlaneConnections||[])r.run(t.id,t.pairingKeyId,t.name??null,Oc(t.url),t.enabled?1:0,t.createdAt,t.updatedAt);return this.readIdentity()})}listOperations(e){return(e?.length?this.client.prepare(`SELECT * FROM na_control_plane_connection_operations WHERE phase IN (${e.map(()=>"?").join(",")}) ORDER BY created_at`).all(...e):this.client.prepare("SELECT * FROM na_control_plane_connection_operations ORDER BY created_at").all()).map(Cc)}putOperation(e){return this.client.prepare("INSERT INTO na_control_plane_connection_operations\n (id, kind, phase, requested_json, pairing_key_id, connection_id, replaced_connections_json, error_json, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT(id) DO UPDATE SET phase=excluded.phase, pairing_key_id=excluded.pairing_key_id,\n connection_id=excluded.connection_id, replaced_connections_json=excluded.replaced_connections_json,\n error_json=excluded.error_json, updated_at=excluded.updated_at").run(e.id,e.kind,e.phase,JSON.stringify(e.requested),e.pairingKeyId??null,e.connectionId??null,JSON.stringify(e.replacedConnections),e.error?JSON.stringify(e.error):null,e.createdAt,e.updatedAt),e}deleteOperation(e){return Number(this.client.prepare("DELETE FROM na_control_plane_connection_operations WHERE id = ?").run(e).changes)>0}transaction(e){if(this.client.isTransaction)return e();this.client.exec("BEGIN IMMEDIATE");try{const t=e();return this.client.exec("COMMIT"),t}catch(e){throw this.client.exec("ROLLBACK"),e}}}function Oc(e){return new URL(e).toString().replace(/\/$/,"")}function zc(e,t,n,i){i.length?e.prepare(`DELETE FROM ${t} WHERE ${n} NOT IN (${i.map(()=>"?").join(",")})`).run(...i):e.exec(`DELETE FROM ${t}`)}function Cc(e){return{id:String(e.id),kind:String(e.kind),phase:e.phase,requested:JSON.parse(String(e.requested_json)),...e.pairing_key_id?{pairingKeyId:String(e.pairing_key_id)}:{},...e.connection_id?{connectionId:String(e.connection_id)}:{},replacedConnections:JSON.parse(String(e.replaced_connections_json)),...e.error_json?{error:JSON.parse(String(e.error_json))}:{},createdAt:String(e.created_at),updatedAt:String(e.updated_at)}}const Rc=a.z.string().trim().min(1).max(120).regex(/^[a-zA-Z0-9][a-zA-Z0-9_.:-]*$/),xc=a.z.string().datetime(),kc=a.z.number().int().nonnegative(),Dc=a.z.enum(["https-token","ssh-key"]),Pc=a.z.enum(["operation-only","instance-retained"]),Lc=a.z.enum(["enabled","disabled"]),Mc=a.z.enum(["pending","synced","deferred","revoking","revoked"]),jc=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 Uc(e){throw new Error(`Invalid Git credential scope: ${e}`)}function Fc(e){const t=e.trim().replace(/^\[|\]$/g,"");(!t||t.includes("*")||/[/?#@\s]/.test(t))&&Uc("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("*"))&&Uc("host is invalid"),e}catch{Uc("host is invalid")}}function $c(e){try{return decodeURIComponent(e)}catch{Uc("path contains invalid percent encoding")}}function Hc(e){const t=e?.trim()||"/";(t.includes("?")||t.includes("#")||t.includes("\\")||t.includes("\0"))&&Uc("path contains an unsupported delimiter");const n=(t.startsWith("/")?t:`/${t}`).split("/").filter(Boolean);for(const e of n){const t=$c(e);("."===t||".."===t||t.includes("/")||t.includes("\\")||t.includes("\0"))&&Uc("path contains an unsafe segment")}return 0===n.length?"/":`/${n.join("/")}/`}function qc(e){const t=jc.parse(e),n="https"===t.scheme?443:22;return jc.parse({scheme:t.scheme,host:Fc(t.host),...void 0===t.port||t.port===n?{}:{port:t.port},pathPrefix:Hc(t.pathPrefix)})}function Vc(e){return Hc(e.replace(/\.git\/?$/,""))}const Bc=a.z.object({id:Rc,name:a.z.string().trim().min(1).max(160),kind:Dc,scope:jc,secretSet:a.z.literal(!0),status:Lc,revision:kc,createdAt:xc,updatedAt:xc}).strict(),Kc=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(),Gc=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(),Wc=a.z.discriminatedUnion("kind",[Kc,Gc]);a.z.object({name:a.z.string().trim().min(1).max(160),scope:jc,secret:Wc}).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{qc(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:jc.optional(),secret:Wc.optional(),status:Lc.optional()}).strict().refine(e=>Object.keys(e).length>0,"At least one credential field must be updated."),a.z.object({items:a.z.array(Bc).max(1e4)}).strict();const Xc=a.z.object({instanceId:Rc,credentialId:Rc,credentialRevision:kc,assignmentRevision:kc,status:Mc,authorizedAt:xc,updatedAt:xc}).strict(),Yc=a.z.object({credential:Bc,secret:Wc}).strict().superRefine((e,t)=>{e.credential.kind!==e.secret.kind&&t.addIssue({code:"custom",path:["secret","kind"],message:"Credential payload kind mismatch."})}),Jc=a.z.object({instanceId:Rc,generation:kc,credentialIds:a.z.array(Rc).max(256).transform(e=>[...new Set(e)].sort()),updatedAt:xc}).strict(),Qc=a.z.object({remoteUrl:a.z.string().trim().min(1).max(4096)}).strict(),Zc=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()]),ed=a.z.object({remoteUrl:a.z.string().trim().min(1).max(4096)}).strict(),td=a.z.discriminatedUnion("status",[a.z.object({status:a.z.literal("ok"),invocationId:Rc,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()]),nd=a.z.object({invocationId:Rc,frame:a.z.string().min(1).max(1048576)}).strict(),id=a.z.object({frame:a.z.string().min(1).max(1048576)}).strict(),sd=a.z.object({operationId:Rc,retention:Pc,payload:Yc}).strict(),od=a.z.object({operationId:Rc,instanceId:Rc,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(sd).max(256).default([])}).strict();function rd(e){return e&&"object"==typeof e&&!Array.isArray(e)?e:void 0}function ad(e,t){if(e)return Object.fromEntries(t.filter(t=>Object.prototype.hasOwnProperty.call(e,t)).map(t=>[t,e[t]]))}function cd(e,t){let n;try{n=function(e){const t=e.trim();if(t&&!t.includes("\0")||Uc("remote is empty or invalid"),/^https?:\/\//i.test(t)||/^ssh:\/\//i.test(t)){let e;Hc(t.replace(/^[a-z][a-z0-9+.-]*:\/\/[^/]+/i,"").split(/[?#]/,1)[0]||"/");try{e=new URL(t)}catch{Uc("remote URL is invalid")}"https:"!==e.protocol&&"ssh:"!==e.protocol&&Uc("remote scheme is unsupported"),(e.password||"https:"===e.protocol&&e.username)&&Uc("HTTPS userinfo is forbidden"),(e.search||e.hash)&&Uc("query and fragment are forbidden");const n="https:"===e.protocol?"https":"ssh",i=e.port?Number(e.port):void 0;return{...qc({scheme:n,host:e.hostname,port:i,pathPrefix:Vc(e.pathname)}),original:t}}/^[a-z][a-z0-9+.-]*:\/\//i.test(t)&&Uc("remote scheme is unsupported");const n=/^(?:([^@/:\s]+)@)?([^/:\s]+):(.+)$/.exec(t);n||Uc("remote must use HTTPS, ssh://, or scp-like SSH syntax");const[,,i,s]=n;return(s.includes("?")||s.includes("#"))&&Uc("query and fragment are forbidden"),{...qc({scheme:"ssh",host:i,pathPrefix:Vc(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=qc(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:qc(e.scope).pathPrefix.length}));if(0===i.length)return{status:"none",remote:n};const s=Math.max(...i.map(e=>e.specificity)),o=i.filter(e=>e.specificity===s).map(e=>e.candidate);if(o.length>1)return{status:"ambiguous",remote:n,credentialIds:o.map(e=>e.id).sort()};const r=o[0];return"ssh-key"===r.kind&&!0!==r.pinnedKnownHosts?{status:"missing-host-key",remote:n,credentialId:r.id}:{status:"unique",remote:n,credential:r}}class dd{client;constructor(e){this.client=e}listPayloads(){return this.client.prepare("SELECT * FROM na_git_credential_payloads ORDER BY credential_id").all().map(ud)}getPayload(e){const t=this.client.prepare("SELECT * FROM na_git_credential_payloads WHERE credential_id = ?").get(e);return t?ud(t):void 0}putPayload(e){const t=Yc.parse(e.payload);return this.client.prepare("INSERT INTO na_git_credential_payloads\n (credential_id, revision, public_json, secret_json, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?)\n ON CONFLICT(credential_id) DO UPDATE SET revision=excluded.revision, public_json=excluded.public_json,\n secret_json=excluded.secret_json, updated_at=excluded.updated_at").run(e.id,t.credential.revision,JSON.stringify(t.credential),JSON.stringify(t.secret),e.createdAt,e.updatedAt),{...e,payload:t}}deletePayload(e){return Number(this.client.prepare("DELETE FROM na_git_credential_payloads WHERE credential_id = ?").run(e).changes)>0}collectUnreferencedPayloads(){return Number(this.client.prepare("DELETE FROM na_git_credential_payloads\n WHERE NOT EXISTS (SELECT 1 FROM na_git_authorization_members m WHERE m.credential_id = na_git_credential_payloads.credential_id)").run().changes)}listAuthorizations(){return this.client.prepare("SELECT * FROM na_git_authorization_sets ORDER BY instance_id").all().map(e=>this.authorizationFromRow(e))}getAuthorization(e){const t=this.client.prepare("SELECT * FROM na_git_authorization_sets WHERE instance_id = ?").get(e);return t?this.authorizationFromRow(t):void 0}putAuthorization(e){const t=Jc.parse({instanceId:e.instanceId,generation:e.generation,credentialIds:e.credentialIds,updatedAt:e.updatedAt});return this.transaction(()=>{this.client.prepare("INSERT INTO na_git_authorization_sets (instance_id, generation, created_at, updated_at)\n VALUES (?, ?, ?, ?) ON CONFLICT(instance_id) DO UPDATE SET generation=excluded.generation, updated_at=excluded.updated_at").run(t.instanceId,t.generation,e.createdAt,t.updatedAt),this.client.prepare("DELETE FROM na_git_authorization_members WHERE instance_id = ?").run(t.instanceId);const n=this.client.prepare("INSERT INTO na_git_authorization_members (instance_id, credential_id, display_order) VALUES (?, ?, ?)");for(const[e,i]of t.credentialIds.entries())n.run(t.instanceId,i,e);return this.getAuthorization(t.instanceId)})}putAuthorizationCas(e){const t=Jc.parse({instanceId:e.instanceId,generation:e.generation,credentialIds:e.credentialIds,updatedAt:e.updatedAt});return this.transaction(()=>{const n=this.getAuthorization(t.instanceId);if(n&&n.generation>t.generation)throw ld("GIT_CREDENTIAL_REVISION_STALE",`Refusing stale authorization set revision for ${t.instanceId}.`);if(n&&n.generation===t.generation){if(JSON.stringify(n.credentialIds)!==JSON.stringify(t.credentialIds))throw ld("GIT_CREDENTIAL_REVISION_CONFLICT",`Refusing conflicting authorization set revision for ${t.instanceId}.`);return n}for(const e of t.credentialIds)if(!this.getPayload(e))throw ld("GIT_CREDENTIAL_PAYLOAD_MISSING",`Credential payload ${e} is not deployed.`);if(n){const e=this.client.prepare("UPDATE na_git_authorization_sets\n SET generation = ?, updated_at = ? WHERE instance_id = ? AND generation < ?").run(t.generation,t.updatedAt,t.instanceId,t.generation).changes;if(1!==Number(e))throw ld("GIT_CREDENTIAL_REVISION_STALE",`Authorization set ${t.instanceId} changed concurrently.`)}else this.client.prepare("INSERT INTO na_git_authorization_sets (instance_id, generation, created_at, updated_at)\n VALUES (?, ?, ?, ?)").run(t.instanceId,t.generation,e.createdAt,t.updatedAt);this.client.prepare("DELETE FROM na_git_authorization_members WHERE instance_id = ?").run(t.instanceId);const i=this.client.prepare("INSERT INTO na_git_authorization_members (instance_id, credential_id, display_order) VALUES (?, ?, ?)");for(const[e,n]of t.credentialIds.entries())i.run(t.instanceId,n,e);return this.getAuthorization(t.instanceId)})}deleteAuthorization(e){return Number(this.client.prepare("DELETE FROM na_git_authorization_sets WHERE instance_id = ?").run(e).changes)>0}listProvisioning(){return this.client.prepare("SELECT * FROM na_git_workspace_provisioning ORDER BY instance_id").all().map(pd)}getProvisioning(e){const t=this.client.prepare("SELECT * FROM na_git_workspace_provisioning WHERE instance_id = ?").get(e);return t?pd(t):void 0}putProvisioning(e){const t="pending"===e.status?e.input.operationId:e.operationId;return this.client.prepare("INSERT INTO na_git_workspace_provisioning\n (instance_id, status, operation_id, input_json, created_at, updated_at, expires_at) VALUES (?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT(instance_id) DO UPDATE SET status=excluded.status, operation_id=excluded.operation_id,\n input_json=excluded.input_json, updated_at=excluded.updated_at, expires_at=excluded.expires_at").run(e.id,e.status,t,"pending"===e.status?JSON.stringify(e.input):null,e.createdAt,e.updatedAt,e.expiresAt),this.getProvisioning(e.id)}deleteProvisioning(e){return Number(this.client.prepare("DELETE FROM na_git_workspace_provisioning WHERE instance_id = ?").run(e).changes)>0}deleteExpiredProvisioning(e){return Number(this.client.prepare("DELETE FROM na_git_workspace_provisioning WHERE expires_at <= ?").run(e).changes)}consumeProvisioning(e,t,n,i){return this.transaction(()=>{const s=this.client.prepare("UPDATE na_git_workspace_provisioning\n SET status = 'consumed', input_json = NULL, updated_at = ?, expires_at = ?\n WHERE instance_id = ? AND operation_id = ? AND status = 'pending'").run(n,i,e,t).changes;if(1===Number(s))return!0;const o=this.getProvisioning(e);return"consumed"===o?.status&&o.operationId===t})}authorizationFromRow(e){const t=this.client.prepare("SELECT credential_id FROM na_git_authorization_members WHERE instance_id = ? ORDER BY display_order").all(String(e.instance_id)).map(e=>String(e.credential_id));return{id:String(e.instance_id),instanceId:String(e.instance_id),generation:Number(e.generation),credentialIds:t,createdAt:String(e.created_at),updatedAt:String(e.updated_at)}}transaction(e){if(this.client.isTransaction)return e();this.client.exec("BEGIN IMMEDIATE");try{const t=e();return this.client.exec("COMMIT"),t}catch(e){throw this.client.exec("ROLLBACK"),e}}}function ld(e,t){return Object.assign(new Error(t),{code:e,statusCode:409})}function ud(e){return{id:String(e.credential_id),payload:Yc.parse({credential:JSON.parse(String(e.public_json)),secret:JSON.parse(String(e.secret_json))}),createdAt:String(e.created_at),updatedAt:String(e.updated_at)}}function pd(e){const t={id:String(e.instance_id),createdAt:String(e.created_at),updatedAt:String(e.updated_at),expiresAt:String(e.expires_at)};return"pending"===e.status?{...t,status:"pending",input:od.parse(JSON.parse(String(e.input_json)))}:{...t,status:"consumed",operationId:String(e.operation_id)}}class md{tail=Promise.resolve();accepting=!0;run(e){if(!this.accepting)return Promise.reject(Td("NODE_AGENT_REPOSITORY_QUIESCING","Node Agent storage is shutting down.",503));const t=this.tail.then(e,e);return this.tail=t.then(()=>{},()=>{}),t}async barrier(){await this.tail}stopAccepting(){this.accepting=!1}}function hd(e){const t=e.db,n=new md,i=new A.AsyncLocalStorage;let s=!1;const o=()=>{if(s)throw Td("NODE_AGENT_REPOSITORY_CLOSED","Node Agent storage is closed.",503)},r=async e=>(o(),i.getStore()||await n.barrier(),e()),a=async e=>(o(),i.getStore()?e():n.run(e));let c;return c={stories:gd(t,r,a),actions:fd(t,r,a),documents:yd(t,r,a),automations:Id(t,r,a),runs:Ad(t,r,a),fileMutations:_d(t,r,a),deletionIntents:Ed(t,r,a),topology:gc(e.client),model:Sc(e.client),access:new Nc(e.client),git:new dd(e.client),transaction:async t=>i.getStore()?t(c):a(async()=>{e.client.exec("BEGIN IMMEDIATE");try{const n=await i.run(!0,()=>t(c));return e.client.exec("COMMIT"),n}catch(t){throw e.client.exec("ROLLBACK"),t}}),transactionSync:t=>{if(o(),e.client.isTransaction)return t(c);e.client.exec("BEGIN IMMEDIATE");try{const n=t(c);return e.client.exec("COMMIT"),n}catch(t){throw e.client.exec("ROLLBACK"),t}},stopAccepting(){n.stopAccepting()},async drain(){await n.barrier()},async checkpoint(){await n.barrier(),await e.checkpoint()},async close(){s||(n.stopAccepting(),await n.barrier(),await e.checkpoint(),s=!0,await e.close())}},c}function gd(e,t,n){return{list:()=>t(()=>e.select().from(ec).orderBy(_.desc(ec.createdAt),_.asc(ec.id))),get:async n=>t(async()=>(await e.select().from(ec).where(_.eq(ec.id,n)).limit(1))[0]),insert:async t=>n(async()=>(await e.insert(ec).values(t),t)),update:async(t,i)=>n(async()=>(await e.update(ec).set(i).where(_.eq(ec.id,t)),(await e.select().from(ec).where(_.eq(ec.id,t)).limit(1))[0])),delete:async t=>n(async()=>Number((await e.delete(ec).where(_.eq(ec.id,t))).changes)>0)}}function fd(e,t,n){return{list:n=>t(()=>e.select().from(tc).where(_.eq(tc.storyId,n)).orderBy(_.asc(tc.displayOrder),_.asc(tc.id))),replace:async(t,i)=>n(async()=>{const n=i.map(e=>e.id);n.length?await e.delete(tc).where(_.and(_.eq(tc.storyId,t),_.notInArray(tc.id,n))):await e.delete(tc).where(_.eq(tc.storyId,t));for(const t of i)await e.insert(tc).values(t).onConflictDoUpdate({target:[tc.storyId,tc.id],set:{title:t.title,promptTemplate:t.promptTemplate,targetInstanceId:t.targetInstanceId,sessionPreset:t.sessionPreset,displayOrder:t.displayOrder}});return i})}}function yd(e,t,n){return{list:n=>t(()=>e.select().from(nc).where(_.eq(nc.storyId,n)).orderBy(_.asc(nc.displayOrder),_.asc(nc.storyPath))),get:async(n,i)=>t(async()=>(await e.select().from(nc).where(_.and(_.eq(nc.storyId,n),_.eq(nc.storyPath,i))).limit(1))[0]),page:async(n,i,s)=>t(async()=>{const t=Number((await e.select({value:_.count()}).from(nc).where(_.eq(nc.storyId,n)))[0]?.value??0);return{items:await e.select({title:nc.title,storyPath:nc.storyPath}).from(nc).where(_.eq(nc.storyId,n)).orderBy(_.desc(nc.indexedSequence),_.asc(nc.storyPath)).limit(s).offset((i-1)*s),totalItems:t}}),insert:async t=>n(async()=>(await e.insert(nc).values(t),t)),update:async(t,i,s)=>n(async()=>{await e.update(nc).set(s).where(_.and(_.eq(nc.storyId,t),_.eq(nc.storyPath,i)))}),replacePath:async(t,i,s)=>n(async()=>{await e.delete(nc).where(_.and(_.eq(nc.storyId,t),_.eq(nc.storyPath,i))),await e.insert(nc).values(s)}),reorder:async(t,i)=>n(async()=>{for(const[n,s]of i.entries())await e.update(nc).set({displayOrder:n}).where(_.and(_.eq(nc.storyId,t),_.eq(nc.storyPath,s)))}),delete:async(t,i)=>n(async()=>Number((await e.delete(nc).where(_.and(_.eq(nc.storyId,t),_.eq(nc.storyPath,i)))).changes)>0)}}function Id(e,t,n){return{list:n=>t(()=>n?e.select().from(ic).where(_.eq(ic.storyId,n)).orderBy(_.asc(ic.createdAt),_.asc(ic.id)):e.select().from(ic).orderBy(_.asc(ic.createdAt),_.asc(ic.id))),get:async n=>t(async()=>(await e.select().from(ic).where(_.eq(ic.id,n)).limit(1))[0]),insert:async t=>n(async()=>(await e.insert(ic).values(t),t)),update:async(t,i)=>n(async()=>(await e.update(ic).set(i).where(_.eq(ic.id,t)),(await e.select().from(ic).where(_.eq(ic.id,t)).limit(1))[0])),referencingActions:async(n,i)=>i.length?t(()=>e.select().from(ic).where(_.and(_.eq(ic.storyId,n),_.inArray(ic.actionId,i)))):[],delete:async t=>n(async()=>Number((await e.delete(ic).where(_.eq(ic.id,t))).changes)>0),deleteForStory:async t=>n(async()=>{await e.delete(ic).where(_.eq(ic.storyId,t))})}}function Ad(e,t,n){const i=["queued","dispatching","running"];return{list:n=>t(()=>e.select().from(sc).where(_.eq(sc.automationId,n)).orderBy(_.desc(sc.queuedAt))),get:async n=>t(async()=>(await e.select().from(sc).where(_.eq(sc.id,n)).limit(1))[0]),byExecutionKey:async n=>t(async()=>(await e.select().from(sc).where(_.eq(sc.executionKey,n)).limit(1))[0]),pending:()=>t(()=>e.select().from(sc).where(_.inArray(sc.status,[...i])).orderBy(_.asc(sc.queuedAt))),activeForStory:async n=>t(()=>e.select({run:sc}).from(sc).innerJoin(ic,_.eq(sc.automationId,ic.id)).where(_.and(_.eq(ic.storyId,n),_.inArray(sc.status,[...i]))).then(e=>e.map(e=>e.run))),insert:async t=>n(async()=>(await e.insert(sc).values(t),t)),update:async(t,i)=>n(async()=>(await e.update(sc).set(i).where(_.eq(sc.id,t)),(await e.select().from(sc).where(_.eq(sc.id,t)).limit(1))[0])),trimTerminal:async(t,i)=>n(async()=>{const n=await e.select({id:sc.id}).from(sc).where(_.and(_.eq(sc.automationId,t),_.inArray(sc.status,["completed","failed","skipped"]))).orderBy(_.desc(sc.queuedAt)).limit(2147483647).offset(i);n.length&&await e.delete(sc).where(_.inArray(sc.id,n.map(e=>e.id)))})}}function _d(e,t,n){return{list:()=>t(()=>e.select().from(oc).orderBy(_.asc(oc.createdAt))),get:async n=>t(async()=>(await e.select().from(oc).where(_.eq(oc.id,n)).limit(1))[0]),insert:async t=>n(async()=>(await e.insert(oc).values(t),t)),update:async(t,i)=>n(async()=>{await e.update(oc).set(i).where(_.eq(oc.id,t))}),delete:async t=>n(async()=>{await e.delete(oc).where(_.eq(oc.id,t))})}}function Ed(e,t,n){return{list:()=>t(()=>e.select().from(rc).orderBy(_.asc(rc.createdAt))),get:async n=>t(async()=>(await e.select().from(rc).where(_.eq(rc.storyId,n)).limit(1))[0]),put:async t=>n(async()=>(await e.insert(rc).values(t).onConflictDoUpdate({target:rc.storyId,set:{phase:t.phase,trashName:t.trashName,updatedAt:t.updatedAt}}),t)),delete:async t=>n(async()=>{await e.delete(rc).where(_.eq(rc.storyId,t))})}}function Td(e,t,n){return Object.assign(new Error(t),{code:e,statusCode:n})}function wd(e,t){return{id:e,sql:t,checksum:d.createHash("sha256").update(t).digest("hex")}}const bd=[wd("0001_story_domain","\nCREATE TABLE na_stories (\n id TEXT PRIMARY KEY NOT NULL, title TEXT NOT NULL, description TEXT,\n created_at TEXT NOT NULL, updated_at TEXT NOT NULL, archived_at TEXT,\n max_idle_ai_sessions INTEGER NOT NULL DEFAULT 5 CHECK(max_idle_ai_sessions BETWEEN 1 AND 50),\n next_document_sequence INTEGER NOT NULL DEFAULT 1 CHECK(next_document_sequence > 0)\n);\nCREATE INDEX na_stories_created_idx ON na_stories(created_at);\nCREATE TABLE na_story_actions (\n story_id TEXT NOT NULL REFERENCES na_stories(id) ON DELETE CASCADE, id TEXT NOT NULL,\n title TEXT NOT NULL, prompt_template TEXT NOT NULL, target_instance_id TEXT,\n session_preset_json TEXT, display_order INTEGER NOT NULL,\n PRIMARY KEY(story_id, id)\n);\nCREATE INDEX na_story_actions_order_idx ON na_story_actions(story_id, display_order, id);\nCREATE TABLE na_story_documents (\n story_id TEXT NOT NULL REFERENCES na_stories(id) ON DELETE CASCADE, story_path TEXT NOT NULL,\n title TEXT NOT NULL, indexed_sequence INTEGER NOT NULL CHECK(indexed_sequence > 0), display_order INTEGER NOT NULL,\n PRIMARY KEY(story_id, story_path)\n);\nCREATE UNIQUE INDEX na_story_documents_sequence_uq ON na_story_documents(story_id, indexed_sequence);\nCREATE INDEX na_story_documents_page_idx ON na_story_documents(story_id, indexed_sequence, story_path);\nCREATE INDEX na_story_documents_display_idx ON na_story_documents(story_id, display_order, story_path);\nCREATE TABLE na_story_automations (\n id TEXT PRIMARY KEY NOT NULL, story_id TEXT NOT NULL, action_id TEXT NOT NULL,\n schedule_json TEXT NOT NULL, enabled INTEGER NOT NULL, policy_json TEXT NOT NULL,\n schedule_anchor_at TEXT NOT NULL, created_at TEXT NOT NULL, updated_at TEXT NOT NULL,\n CONSTRAINT na_story_automations_action_fk FOREIGN KEY(story_id, action_id)\n REFERENCES na_story_actions(story_id, id) ON DELETE RESTRICT\n);\nCREATE INDEX na_story_automations_story_idx ON na_story_automations(story_id);\nCREATE INDEX na_story_automations_enabled_idx ON na_story_automations(enabled);\nCREATE TABLE na_story_automation_runs (\n id TEXT PRIMARY KEY NOT NULL, automation_id TEXT NOT NULL REFERENCES na_story_automations(id) ON DELETE CASCADE,\n event_type TEXT NOT NULL CHECK(event_type IN ('manual','schedule')),\n status TEXT NOT NULL CHECK(status IN ('queued','dispatching','running','completed','failed','skipped')),\n scheduled_for TEXT NOT NULL, target_instance_id TEXT NOT NULL, ai_session_id TEXT, error_json TEXT,\n queued_at TEXT NOT NULL, started_at TEXT, completed_at TEXT,\n execution_key TEXT NOT NULL, request_fingerprint TEXT NOT NULL, execution_input_json TEXT NOT NULL\n);\nCREATE UNIQUE INDEX na_story_automation_runs_execution_key_uq ON na_story_automation_runs(execution_key);\nCREATE INDEX na_story_automation_runs_automation_time_idx ON na_story_automation_runs(automation_id, queued_at);\nCREATE INDEX na_story_automation_runs_status_idx ON na_story_automation_runs(status, scheduled_for);\nCREATE TABLE na_story_file_mutations (\n id TEXT PRIMARY KEY NOT NULL, story_id TEXT NOT NULL REFERENCES na_stories(id) ON DELETE RESTRICT,\n operation TEXT NOT NULL CHECK(operation IN ('write','rename','delete')), story_path TEXT NOT NULL,\n next_story_path TEXT, title TEXT, temporary_name TEXT, backup_name TEXT,\n phase TEXT NOT NULL CHECK(phase IN ('receiving','prepared','files-staged','database-committed','cleanup')),\n created_at TEXT NOT NULL, updated_at TEXT NOT NULL\n);\nCREATE INDEX na_story_file_mutations_story_idx ON na_story_file_mutations(story_id, created_at);\nCREATE TABLE na_story_deletion_intents (\n story_id TEXT PRIMARY KEY NOT NULL,\n phase TEXT NOT NULL CHECK(phase IN ('prepared','files-staged','database-committed','cleanup')),\n trash_name TEXT, created_at TEXT NOT NULL, updated_at TEXT NOT NULL\n);\n"),wd("0002_p0_state_domains","\nCREATE TABLE na_node_identity (\n singleton_key INTEGER PRIMARY KEY NOT NULL DEFAULT 1 CHECK(singleton_key = 1),\n node_id TEXT NOT NULL UNIQUE, created_at TEXT NOT NULL, updated_at TEXT NOT NULL\n);\nCREATE TABLE na_local_folders (\n id TEXT PRIMARY KEY NOT NULL, node_id TEXT NOT NULL REFERENCES na_node_identity(node_id) ON DELETE RESTRICT ON UPDATE CASCADE,\n name TEXT NOT NULL, path TEXT NOT NULL, labels_json TEXT NOT NULL, created_at TEXT NOT NULL, updated_at TEXT NOT NULL,\n UNIQUE(node_id, path)\n);\nCREATE TABLE na_runtimes (\n id TEXT PRIMARY KEY NOT NULL, node_id TEXT NOT NULL REFERENCES na_node_identity(node_id) ON DELETE RESTRICT ON UPDATE CASCADE,\n name TEXT NOT NULL, type TEXT NOT NULL CHECK(type IN ('docker','kubernetes','local')),\n status TEXT NOT NULL CHECK(status IN ('unknown','online','offline','degraded')), access_strategy TEXT NOT NULL,\n capabilities_json TEXT NOT NULL, labels_json TEXT NOT NULL, created_at TEXT NOT NULL, updated_at TEXT NOT NULL\n);\nCREATE INDEX na_runtimes_node_type_idx ON na_runtimes(node_id, type);\nCREATE TABLE na_instances (\n id TEXT PRIMARY KEY NOT NULL, node_id TEXT NOT NULL REFERENCES na_node_identity(node_id) ON DELETE RESTRICT ON UPDATE CASCADE,\n runtime_id TEXT NOT NULL REFERENCES na_runtimes(id) ON DELETE RESTRICT ON UPDATE CASCADE,\n source_local_folder_id TEXT REFERENCES na_local_folders(id) ON DELETE SET NULL ON UPDATE CASCADE,\n name TEXT NOT NULL, status TEXT NOT NULL, state_revision INTEGER NOT NULL DEFAULT 0 CHECK(state_revision >= 0),\n process_incarnation_id TEXT, registration_credential TEXT, desired_json TEXT NOT NULL,\n created_at TEXT NOT NULL, updated_at TEXT NOT NULL\n);\nCREATE INDEX na_instances_runtime_idx ON na_instances(runtime_id);\nCREATE INDEX na_instances_status_idx ON na_instances(status, updated_at);\nCREATE TABLE na_instance_observations (\n instance_id TEXT PRIMARY KEY NOT NULL REFERENCES na_instances(id) ON DELETE CASCADE ON UPDATE CASCADE,\n health TEXT NOT NULL, connection_status TEXT NOT NULL, ready INTEGER NOT NULL,\n observed_json TEXT NOT NULL, last_heartbeat_at TEXT, updated_at TEXT NOT NULL\n);\nCREATE INDEX na_instance_observations_connection_idx ON na_instance_observations(connection_status, updated_at);\nCREATE TABLE na_models (\n id TEXT PRIMARY KEY NOT NULL, name TEXT NOT NULL, endpoint TEXT NOT NULL, key TEXT NOT NULL, model TEXT NOT NULL,\n app TEXT NOT NULL CHECK(app IN ('codex','claude','opencode')), enabled INTEGER NOT NULL,\n display_order INTEGER NOT NULL, model_names_json TEXT NOT NULL, protocols_json TEXT NOT NULL,\n labels_json TEXT NOT NULL, created_at TEXT NOT NULL, updated_at TEXT NOT NULL\n);\nCREATE INDEX na_models_order_idx ON na_models(display_order, id);\nCREATE TABLE na_instance_model_assignments (\n instance_id TEXT PRIMARY KEY NOT NULL REFERENCES na_instances(id) ON DELETE CASCADE ON UPDATE CASCADE,\n legacy_codex_model_id TEXT REFERENCES na_models(id) ON DELETE RESTRICT ON UPDATE CASCADE,\n legacy_claude_model_id TEXT REFERENCES na_models(id) ON DELETE RESTRICT ON UPDATE CASCADE,\n legacy_opencode_model_id TEXT REFERENCES na_models(id) ON DELETE RESTRICT ON UPDATE CASCADE,\n updated_at TEXT NOT NULL\n);\nCREATE TABLE na_instance_model_entities (\n instance_id TEXT NOT NULL REFERENCES na_instance_model_assignments(instance_id) ON DELETE CASCADE ON UPDATE CASCADE,\n model_id TEXT NOT NULL REFERENCES na_models(id) ON DELETE RESTRICT ON UPDATE CASCADE,\n display_order INTEGER NOT NULL, PRIMARY KEY(instance_id, model_id), UNIQUE(instance_id, display_order)\n);\nCREATE TABLE na_control_plane_pairings (\n key_id TEXT PRIMARY KEY NOT NULL, control_plane_id TEXT NOT NULL UNIQUE, name TEXT, secret TEXT NOT NULL,\n paired_at TEXT NOT NULL, revoked_at TEXT, updated_at TEXT NOT NULL\n);\nCREATE TABLE na_control_plane_connections (\n id TEXT PRIMARY KEY NOT NULL,\n pairing_key_id TEXT NOT NULL REFERENCES na_control_plane_pairings(key_id) ON DELETE RESTRICT ON UPDATE CASCADE,\n name TEXT, normalized_url TEXT NOT NULL UNIQUE, enabled INTEGER NOT NULL, created_at TEXT NOT NULL, updated_at TEXT NOT NULL\n);\nCREATE TABLE na_control_plane_connection_operations (\n id TEXT PRIMARY KEY NOT NULL, kind TEXT NOT NULL,\n phase TEXT NOT NULL CHECK(phase IN ('prepared','remote-accepted','committed','failed')),\n requested_json TEXT NOT NULL, pairing_key_id TEXT, connection_id TEXT, replaced_connections_json TEXT NOT NULL,\n error_json TEXT, created_at TEXT NOT NULL, updated_at TEXT NOT NULL\n);\nCREATE INDEX na_control_plane_connection_operations_phase_idx ON na_control_plane_connection_operations(phase, updated_at);\nCREATE TABLE na_git_credential_payloads (\n credential_id TEXT PRIMARY KEY NOT NULL, revision INTEGER NOT NULL CHECK(revision >= 0),\n public_json TEXT NOT NULL, secret_json TEXT NOT NULL, created_at TEXT NOT NULL, updated_at TEXT NOT NULL\n);\nCREATE TABLE na_git_authorization_sets (\n instance_id TEXT PRIMARY KEY NOT NULL REFERENCES na_instances(id) ON DELETE CASCADE ON UPDATE CASCADE,\n generation INTEGER NOT NULL CHECK(generation >= 0), created_at TEXT NOT NULL, updated_at TEXT NOT NULL\n);\nCREATE TABLE na_git_authorization_members (\n instance_id TEXT NOT NULL REFERENCES na_git_authorization_sets(instance_id) ON DELETE CASCADE ON UPDATE CASCADE,\n credential_id TEXT NOT NULL REFERENCES na_git_credential_payloads(credential_id) ON DELETE RESTRICT ON UPDATE CASCADE,\n display_order INTEGER NOT NULL, PRIMARY KEY(instance_id, credential_id), UNIQUE(instance_id, display_order)\n);\nCREATE TABLE na_git_workspace_provisioning (\n instance_id TEXT PRIMARY KEY NOT NULL REFERENCES na_instances(id) ON DELETE CASCADE ON UPDATE CASCADE,\n status TEXT NOT NULL CHECK(status IN ('pending','consumed')), operation_id TEXT NOT NULL, input_json TEXT,\n created_at TEXT NOT NULL, updated_at TEXT NOT NULL, expires_at TEXT NOT NULL,\n CHECK((status = 'pending' AND input_json IS NOT NULL) OR (status = 'consumed' AND input_json IS NULL))\n);\nCREATE INDEX na_git_workspace_provisioning_expiry_idx ON na_git_workspace_provisioning(expires_at);\n")],Sd=a.z.string().trim().min(1).max(160),vd=a.z.string().datetime(),Nd=a.z.string().min(1).max(4096),Od=a.z.string().trim().url().max(2048),zd=a.z.object({id:Sd,keyId:Sd,name:a.z.string().trim().min(1).max(160).optional(),secret:Nd,pairedAt:vd,revokedAt:vd.optional(),updatedAt:vd}).strip(),Cd=a.z.object({id:Sd,pairingKeyId:Sd,name:a.z.string().trim().min(1).max(160).optional(),url:Od,enabled:a.z.boolean().default(!0),createdAt:vd,updatedAt:vd}).strip(),Rd=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(),xd=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(),kd=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(),Dd=new Set(["nodeId","createdAt","updatedAt","pairingInvites","controlPlanePairings","controlPlaneConnections","remoteControlPlanes"]),Pd=new Set(["id","keyId","name","secret","pairedAt","revokedAt","updatedAt"]),Ld=new Set(["id","pairingKeyId","name","url","enabled","createdAt","updatedAt"]),Md=new Set(["id","keyId","name","url","secret","pairedAt","updatedAt","active"]);function jd(e,t){console.warn(JSON.stringify({message:e,...t}))}function Ud(e,t){return Object.assign(new Error(e,void 0===t?void 0:{cause:t}),{code:"NODE_AGENT_IDENTITY_INVALID"})}function Fd(e,t){return Object.keys(e).filter(e=>!t.has(e))}function $d(e,t,n){const i=vd.safeParse(e);return i.success?i.data:(n("invalid node agent identity timestamp was replaced",{field:t}),ae())}function Hd(e,t=jd){if(!e||"object"!=typeof e||Array.isArray(e))throw Ud("Node agent identity must be a JSON object.");const n=e,i=Sd.safeParse(n.nodeId);if(!i.success)throw Ud("Node agent identity has an invalid nodeId.",i.error);const s=i.data,o=Fd(n,Dd);o.length&&t("unknown node agent identity fields were ignored",{fields:o}),Array.isArray(n.pairingInvites)&&n.pairingInvites.length&&t("persisted node agent pairing invites were discarded",{count:n.pairingInvites.length});const r=Array.isArray(n.remoteControlPlanes)?n.remoteControlPlanes.flatMap(e=>{if(!e||"object"!=typeof e||Array.isArray(e))return[];const n=e,i=Fd(n,Md);i.length&&t("unknown legacy node agent remote control-plane fields were ignored",{fields:i});const s=zd.safeParse(n);if(!s.success)return t("invalid legacy node agent control-plane pairing was ignored",{issues:s.error.issues}),[];const o=n.url?Cd.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,...o?.success?{connection:o.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 o=Fd(e,n);o.length&&t(`unknown node agent ${s} fields were ignored`,{fields:o});const r=i.safeParse(e);return r.success?[r.data]:(t(`invalid node agent ${s} was ignored`,{issues:r.error.issues}),[])}):[];return{nodeId:s,createdAt:$d(n.createdAt,"createdAt",t),updatedAt:$d(n.updatedAt,"updatedAt",t),controlPlanePairings:n.controlPlanePairings?a(n.controlPlanePairings,Pd,zd,"control-plane pairing"):r.map(e=>e.pairing),controlPlaneConnections:n.controlPlaneConnections?a(n.controlPlaneConnections,Ld,Cd,"control-plane connection"):r.flatMap(e=>e.connection?[e.connection]:[])}}const qd="1000_import_v0_0_28_p0",Vd=d.createHash("sha256").update(JSON.stringify({sourceTag:"v0.0.28",plannerVersion:3,domains:["identity","folders","runtimes","instances","models","assignments","model-environments","git"],transaction:"begin-immediate"})).digest("hex"),Bd=["id","nodeId","name","path","defaultImageSelection","labels","createdAt","updatedAt"],Kd=["id","nodeId","name","type","status","accessStrategy","capabilities","labels","createdAt","updatedAt"],Gd=["id","name","endpoint","key","model","modelNames","protocols","app","enabled","order","labels","createdAt","updatedAt"],Wd=["instanceId","modelEntityIds","codexModelHash","claudeModelHash","opencodeModelHash","updatedAt"],Xd=["id","payload","createdAt","updatedAt"],Yd=["id","instanceId","generation","credentialIds","createdAt","updatedAt"],Jd=["id","instanceId","credentialId","credentialRevision","assignmentRevision","status","authorizedAt","createdAt","updatedAt"],Qd=["id","status","operationId","input","createdAt","updatedAt","expiresAt"];function Zd(e,i,s={}){const o=e.prepare("SELECT checksum FROM na_migration_ledger WHERE id = ?").get(qd);if(o){if(o.checksum!==Vd)throw ul("ledger","Legacy P0 migration checksum mismatch.");return void ol(i,s.rename)}const r=[],c=function(e,i){const s=[],o=new Set,r=(e,o)=>function(e,i,s,o){return t.existsSync(e)?t.readdirSync(e).filter(e=>e.endsWith(".json")).sort().flatMap(r=>{const a=n.join(e,r);let c;try{c=t.readFileSync(a,"utf8")}catch(e){throw ul(a,"Legacy JSON could not be accessed.",e)}const l={filePath:a,value:void 0,digest:d.createHash("sha256").update(c).digest("hex")};s.push(l);try{return l.value=JSON.parse(c),[l]}catch{return i.push({source:a,field:"unreadable-record"}),o?.(a),[]}}):[]}(e,i,s,o);return{...{folders:r(e.localFoldersDir),runtimes:r(e.nodeRuntimesDir),instances:r(e.controlledInstancesDir,e=>o.add(n.basename(e,".json"))),privateConfigs:r(e.instancePrivateConfigsDir),models:r(e.nodeModelsDir),assignments:r(e.modelAssignmentsDir),modelEnvironments:r(e.modelEnvironmentsDir),gitPayloads:r(e.gitCredentialPayloadsDir),gitAssignments:r(e.gitCredentialAssignmentsDir),gitAuthorizations:r(e.gitCredentialAuthorizationSetsDir),gitProvisioning:r(e.gitWorkspaceProvisioningIntentsDir)},allFiles:s,isolatedInstanceIds:o}}(i,r),l=c.allFiles.length>0,u=function(e){let n;try{n=t.lstatSync(e)}catch(t){if("ENOENT"===t.code)return;throw ul(e,"Legacy JSON could not be accessed.",t)}if(!n.isFile())throw ul(e,"Legacy JSON must be a regular file.");return function(e){try{const n=t.readFileSync(e,"utf8");return{filePath:e,value:JSON.parse(n),digest:d.createHash("sha256").update(n).digest("hex")}}catch(t){throw ul(e,"Legacy JSON could not be read.",t)}}(e)}(i.identityPath);if(l&&!u)throw ul(i.identityPath,"Legacy P0 data requires a node identity.");try{const t=u?Hd(u.value,(e,t)=>r.push({source:i.identityPath,field:String(t.field||t.fields||"legacy")})):void 0,s=c.folders.map(e=>(ll(e,Bd,r),tl(e,rs,Si(e.value)))),o=c.runtimes.map(e=>(ll(e,Kd,r),tl(e,Ws.strip(),e.value))),d=new Map(el(c.privateConfigs,c.isolatedInstanceIds,r).map(e=>{const t=al(e.value);return[n.basename(e.filePath,".json"),cl(t.instanceCredential??t.registrationToken)]})),l=c.instances.map(e=>{const t=fo(e.value,t=>r.push({source:e.filePath,field:t.field}));if(!t.success)throw nl(e,t.error);return{...t.data,registrationToken:t.data.registrationToken||d.get(t.data.id)}}),p=c.models.flatMap(e=>{const t=al(e.value);ll(e,Gd,r);const i=tl(e,hs,dl(t,["id","name","endpoint","key","model","modelNames","protocols","app","enabled","order","labels","createdAt","updatedAt"]));return n.basename(e.filePath,".json")!==i.id||Ss(i)!==i.id?(r.push({source:e.filePath,field:"identity-or-content-hash"}),[]):[hs.parse({...i,modelNames:i.modelNames.length?i.modelNames:[{name:i.model,order:0}],protocols:i.protocols.length?i.protocols:[(s=i.app,"claude"===s?"anthropic-messages":"opencode"===s?"openai-chat-completions":"openai-responses")]})];var s}),m=el(c.assignments,c.isolatedInstanceIds,r).map(e=>{const t=al(e.value);return ll(e,Wd,r),tl(e,ys,dl(t,["instanceId","modelEntityIds","codexModelHash","claudeModelHash","opencodeModelHash","updatedAt"]))});!function(e,t,i,s){const o=new Set(t.map(e=>e.id)),r=new Map(s.map(e=>[e.instanceId,e])),c=new Map(i.map(e=>[e.id,e]));let d=i.reduce((e,t)=>Math.max(e,t.order),0)+100;for(const l of e){const e=n.basename(l.filePath,".json");if(!o.has(e))throw ul(l.filePath,`Legacy model environment references missing instance ${e}.`);if(r.has(e))continue;const u=a.z.record(a.z.string(),a.z.string()).safeParse(l.value);if(!u.success)throw nl(l,u.error);const p=u.data,m=new Set(["OPENAI_API_KEY","OPENAI_BASE_URL","CODEX_MODEL","TASK_HANDOFF_CODEX_BASE_URL","TASK_HANDOFF_CODEX_MODEL","ANTHROPIC_API_KEY","ANTHROPIC_BASE_URL","CLAUDE_MODEL","TASK_HANDOFF_CLAUDE_MODEL"]);if(Object.keys(p).some(e=>!m.has(e)))throw ul(l.filePath,"Legacy model environment contains an unknown field.");const h=[],g={};for(const n of["codex","claude"]){const s=p["codex"===n?"OPENAI_API_KEY":"ANTHROPIC_API_KEY"],o="codex"===n?p.TASK_HANDOFF_CODEX_BASE_URL||p.OPENAI_BASE_URL:p.ANTHROPIC_BASE_URL,r="codex"===n?p.TASK_HANDOFF_CODEX_MODEL||p.CODEX_MODEL:p.TASK_HANDOFF_CLAUDE_MODEL||p.CLAUDE_MODEL;if(!s&&!o&&!r)continue;if(!s||!o||!r)throw ul(l.filePath,`Legacy ${n} model environment is incomplete.`);const a=Ss({app:n,endpoint:o,key:s,model:r});if(!c.has(a)){const l=t.find(t=>t.id===e).updatedAt,u=hs.parse({id:a,name:`Migrated ${"codex"===n?"Codex":"Claude"} model`,endpoint:o,key:s,model:r,app:n,enabled:!0,order:d,labels:{migratedFrom:"instance-model-environment"},createdAt:l,updatedAt:l});d+=100,i.push(u),c.set(a,u)}h.push(a),"codex"===n?g.codexModelHash=a:g.claudeModelHash=a}if(!h.length)throw ul(l.filePath,"Legacy model environment has no complete model configuration.");const f=ys.parse({instanceId:e,modelEntityIds:h,...g,updatedAt:t.find(t=>t.id===e).updatedAt});s.push(f),r.set(e,f)}}(el(c.modelEnvironments,c.isolatedInstanceIds,r),l,p,m);const h=c.gitPayloads.map(e=>{const t=al(e.value);return ll(e,Xd,r),{id:cl(t.id),payload:tl(e,Yc,t.payload),createdAt:cl(t.createdAt),updatedAt:cl(t.updatedAt)}}),g=function(e,t){const n=new Map(e.map(e=>[e.instanceId,e]));for(const e of new Set(t.map(e=>e.instanceId))){if(n.has(e))continue;const i=t.filter(t=>t.instanceId===e).sort((e,t)=>e.credentialId.localeCompare(t.credentialId)),s=i.map(e=>e.updatedAt).sort().at(-1);n.set(e,{id:e,instanceId:e,generation:Math.max(0,...i.map(e=>e.assignmentRevision)),credentialIds:i.filter(e=>"revoking"!==e.status&&"revoked"!==e.status).map(e=>e.credentialId),createdAt:s,updatedAt:s})}return[...n.values()].sort((e,t)=>e.instanceId.localeCompare(t.instanceId))}(el(c.gitAuthorizations,c.isolatedInstanceIds,r).map(e=>{const t=al(e.value);ll(e,Yd,r);const n=tl(e,Jc,dl(t,["instanceId","generation","credentialIds","updatedAt"]));return{...n,id:n.instanceId,createdAt:cl(t.createdAt)}}),el(c.gitAssignments,c.isolatedInstanceIds,r).map(e=>{const t=al(e.value);return ll(e,Jd,r),tl(e,Xc,dl(t,["instanceId","credentialId","credentialRevision","assignmentRevision","status","authorizedAt","updatedAt"]))})),f=el(c.gitProvisioning,c.isolatedInstanceIds,r).map(e=>(ll(e,Qd,r),function(e){const t=al(e.value),n={id:cl(t.id),createdAt:cl(t.createdAt),updatedAt:cl(t.updatedAt),expiresAt:cl(t.expiresAt)};if("consumed"===t.status)return{...n,status:"consumed",operationId:cl(t.operationId)};const i=function(e){const t=rd(e),n=rd(t?.ref),i=rd(t?.clone),s=Array.isArray(t?.credentials)?t.credentials.map(e=>{const t=rd(e),n=rd(t?.payload),i=function(e){const t=rd(e),n=rd(t?.scope);return Bc.safeParse({...ad(t,["id","name","kind","secretSet","status","revision","createdAt","updatedAt"]),scope:ad(n,["scheme","host","port","pathPrefix"])})}(n?.credential),s=rd(n?.secret);return{...ad(t,["operationId","retention"]),payload:{credential:i.success?i.data:n?.credential,secret:ad(s,"https-token"===s?.kind?["kind","username","token"]:["kind","privateKey","passphrase","pinnedKnownHosts"])}}}):t?.credentials;return od.safeParse({...ad(t,["operationId","instanceId","remoteUrl"]),ref:ad(n,["type","name","commit"]),clone:ad(i,["depth","submodules","lfs","subdirectory"]),credentials:s})}(t.input);if(!i.success)throw nl(e,i.error);const s=od.parse(i.data);return{...n,id:s.instanceId,status:"pending",input:s}}(e)));!function(e){const t=e.identity?.nodeId,n=il("local folder",e.folders.map(e=>e.id)),i=il("runtime",e.runtimes.map(e=>e.id)),s=il("instance",e.instances.map(e=>e.id)),o=il("model",e.models.map(e=>e.id)),r=il("Git credential payload",e.payloads.map(e=>e.id));il("model assignment",e.assignments.map(e=>e.instanceId)),il("Git authorization",e.authorizations.map(e=>e.instanceId)),il("Git provisioning",e.provisioning.map(e=>e.id));for(const n of[...e.folders,...e.runtimes])if(!t||n.nodeId!==t)throw sl("node-identity",n.id,n.nodeId,"Legacy topology record references a different or missing node identity.");for(const s of e.instances){if(!t||s.nodeId!==t)throw sl("node-identity",s.id,s.nodeId,"Legacy instance references a different or missing node identity.");if(!i.has(s.runtimeId))throw sl("runtime",s.id,s.runtimeId,"Legacy instance references a missing runtime.");if("local-folder"===s.source.type&&s.source.localFolderId&&!n.has(s.source.localFolderId))throw sl("local-folder",s.id,s.source.localFolderId,"Legacy instance references a missing local folder.")}for(const t of e.privateConfigInstanceIds)if(!s.has(t))throw sl("instance",t,t,"Legacy private config references a missing instance.");for(const t of e.assignments){if(!s.has(t.instanceId))throw sl("instance",t.instanceId,t.instanceId,"Legacy model assignment references a missing instance.");for(const e of new Set([...t.modelEntityIds,t.codexModelHash,t.claudeModelHash,t.opencodeModelHash].filter(e=>Boolean(e))))if(!o.has(e))throw sl("model",t.instanceId,e,"Legacy model assignment references a missing model.")}for(const t of e.payloads)if(t.id!==t.payload.credential.id)throw sl("Git credential payload",t.id,t.payload.credential.id,"Legacy Git credential wrapper and payload ids do not match.");for(const t of e.authorizations){if(!s.has(t.instanceId))throw sl("instance",t.instanceId,t.instanceId,"Legacy Git authorization references a missing instance.");for(const e of t.credentialIds)if(!r.has(e))throw sl("Git credential payload",t.instanceId,e,"Legacy Git authorization references a missing credential payload.")}for(const t of e.provisioning)if(!s.has(t.id))throw sl("instance",t.id,t.id,"Legacy Git provisioning references a missing instance.");if(e.identity){const t=il("Control Plane pairing",e.identity.controlPlanePairings.map(e=>e.keyId));il("Control Plane connection",e.identity.controlPlaneConnections.map(e=>e.id));const n=new Set;for(const i of e.identity.controlPlaneConnections){if(!t.has(i.pairingKeyId))throw sl("Control Plane pairing",i.id,i.pairingKeyId,"Legacy connection references a missing pairing.");const e=new URL(i.url).toString().replace(/\/$/,"");if(n.has(e))throw sl("Control Plane URL",i.id,e,"Legacy connections contain a duplicate normalized URL.");n.add(e)}}}({identity:t,folders:s,runtimes:o,instances:l,privateConfigInstanceIds:[...d.keys()],models:p,assignments:m,payloads:h,authorizations:g,provisioning:f}),e.exec("BEGIN IMMEDIATE");try{const n=new Nc(e),i=gc(e),a=Sc(e),d=new dd(e);t&&n.writeIdentity(t);for(const e of s)i.localFolders.put(e);for(const e of o)i.runtimes.put(e);for(const e of l)i.instances.put(e);for(const e of p)a.models.put(e);for(const e of m)a.assignments.put(e);for(const e of h)d.putPayload(e);for(const e of g)d.putAuthorization(e);for(const e of f)d.putProvisioning(e);const y={sourceTag:"v0.0.28",counts:{identities:t?1:0,folders:s.length,runtimes:o.length,instances:l.length,models:p.length,assignments:m.length,pairings:t?.controlPlanePairings?.length||0,connections:t?.controlPlaneConnections?.length||0,gitPayloads:h.length,gitAuthorizations:g.length,gitProvisioning:f.length},inputDigest:rl([...u?[u]:[],...c.allFiles]),warningCount:r.length};e.prepare("INSERT INTO na_migration_ledger (id, checksum, applied_at, details) VALUES (?, ?, ?, ?)").run(qd,Vd,(new Date).toISOString(),JSON.stringify(y)),e.exec("COMMIT")}catch(t){throw e.exec("ROLLBACK"),t}}catch(e){if(e&&"object"==typeof e&&"code"in e&&"NODE_AGENT_LEGACY_MIGRATION_FAILED"===e.code)throw e;throw ul("p0","Legacy P0 data failed validation.",e)}ol(i,s.rename);for(const e of r)console.warn(JSON.stringify({message:"legacy node agent field was ignored",...e}))}function el(e,t,i){return e.filter(e=>{const s=al(e.value),o="string"==typeof s.instanceId?s.instanceId:n.basename(e.filePath,".json");return!t.has(o)||(i.push({source:e.filePath,field:"isolated-instance-owner"}),!1)})}function tl(e,t,n){const i=t.safeParse(n);if(!i.success)throw nl(e,i.error);return i.data}function nl(e,t){return ul(e.filePath,"Legacy record is missing a required field or has an invalid type.",void 0,{issues:t.issues.map(e=>({path:e.path.join("."),code:e.code}))})}function il(e,t){const n=new Set;for(const i of t){if(n.has(i))throw ul(e,`Legacy ${e} id is duplicated.`,void 0,{recordId:i});n.add(i)}return n}function sl(e,t,n,i){return ul(e,i,void 0,{relation:e,recordId:t,referencedId:n})}function ol(e,n=t.renameSync){const i=[e.identityPath,e.localFoldersDir,e.nodeRuntimesDir,e.controlledInstancesDir,e.nodeModelsDir,e.modelAssignmentsDir,e.gitCredentialPayloadsDir,e.modelEnvironmentsDir,e.gitCredentialAssignmentsDir,e.gitCredentialAuthorizationSetsDir,e.gitWorkspaceProvisioningIntentsDir];for(const e of i){if(!t.existsSync(e))continue;const i=`${e}.migrated-v0.0.28`;let s=i;for(let e=1;t.existsSync(s);e+=1)s=`${i}.${e}`;try{n(e,s)}catch(t){console.warn(JSON.stringify({message:"legacy node agent persistence archive failed",source:e,target:s,error:t instanceof Error?t.message:String(t)}))}}}function rl(e){const t=d.createHash("sha256");for(const i of[...e].sort((e,t)=>e.filePath.localeCompare(t.filePath)))t.update(n.basename(i.filePath)),t.update(i.digest);return t.digest("hex")}function al(e){if(!e||"object"!=typeof e||Array.isArray(e))throw ul("record","Legacy record must be an object.");return e}function cl(e){if("string"!=typeof e||!e)throw ul("record","Legacy record is missing a required string.");return e}function dl(e,t){return Object.fromEntries(t.flatMap(t=>Object.prototype.hasOwnProperty.call(e,t)?[[t,e[t]]]:[]))}function ll(e,t,n){const i=al(e.value),s=new Set(t);for(const t of Object.keys(i).filter(e=>!s.has(e)).sort())n.push({source:e.filePath,field:t})}function ul(e,t,n,i={}){return Object.assign(new Error(t,void 0===n?void 0:{cause:n}),{code:"NODE_AGENT_LEGACY_MIGRATION_FAILED",statusCode:500,details:{source:e,...i}})}function pl(e,t){return Object.assign(new Error(`Node Agent database ${e} failed: ${t instanceof Error?t.message:String(t)}`,{cause:t}),{code:"NODE_AGENT_DATABASE_STARTUP_FAILED",statusCode:500,details:{phase:e,recovery:"Restore or remove the invalid node-agent.sqlite before restarting the Node Agent."}})}function ml(e,t){const n=e.prepare(t).get();return n?Object.values(n)[0]:void 0}function hl(e){for(const n of[e.databasePath,`${e.databasePath}-wal`,`${e.databasePath}-shm`])t.existsSync(n)&&t.chmodSync(n,384)}function gl(e,i={}){try{!function(e=process.versions.node){const[t,n]=e.split(".").map(Number);if(24!==t||n<15)throw new Error(`Node.js 24.15 or newer within the Node.js 24 release line is required; received ${e}.`)}()}catch(e){throw pl("runtime",e)}let s;t.mkdirSync(n.dirname(e.databasePath),{recursive:!0,mode:448}),t.chmodSync(n.dirname(e.databasePath),448);try{if(s=new T.DatabaseSync(e.databasePath),function(e,t){e.exec("PRAGMA foreign_keys = ON"),e.exec("PRAGMA busy_timeout = 5000"),e.exec("PRAGMA journal_mode = WAL"),e.exec("PRAGMA synchronous = FULL");const n=Number(ml(e,"PRAGMA application_id"));if(0===n)e.exec("PRAGMA application_id = 1414024769");else if(1414024769!==n)throw new Error(`Unexpected application_id ${n}.`);if(1!==Number(ml(e,"PRAGMA foreign_keys")))throw new Error("foreign_keys could not be enabled.");if("wal"!==String(ml(e,"PRAGMA journal_mode")).toLowerCase())throw new Error("WAL could not be enabled.");if(5e3!==Number(ml(e,"PRAGMA busy_timeout")))throw new Error("busy_timeout=5000 could not be enabled.");if(2!==Number(ml(e,"PRAGMA synchronous")))throw new Error("synchronous=FULL could not be enabled.");if("ok"!==String(ml(e,"PRAGMA quick_check")))throw new Error("quick_check failed.");hl(t)}(s,e),function(e){e.exec("CREATE TABLE IF NOT EXISTS na_migration_ledger (\n id TEXT PRIMARY KEY NOT NULL, checksum TEXT NOT NULL, applied_at TEXT NOT NULL, details TEXT NOT NULL\n )"),e.exec("BEGIN IMMEDIATE");try{const t=e.prepare("SELECT checksum FROM na_migration_ledger WHERE id = ?"),n=e.prepare("INSERT INTO na_migration_ledger (id, checksum, applied_at, details) VALUES (?, ?, ?, ?)");for(const i of bd){const s=t.get(i.id);if(s){if(s.checksum!==i.checksum)throw new Error(`Migration checksum mismatch for ${i.id}.`)}else e.exec(i.sql),n.run(i.id,i.checksum,(new Date).toISOString(),JSON.stringify({domain:"node-agent-story"}))}e.exec("COMMIT")}catch(t){throw e.exec("ROLLBACK"),t}}(s),Zd(s,e,i.legacyMigration),"ok"!==String(ml(s,"PRAGMA quick_check")))throw new Error("post-migration quick_check failed.");hl(e);const t=w.drizzle({client:s});let n=!1;return{db:t,client:s,async checkpoint(){n||(s.exec("PRAGMA wal_checkpoint(TRUNCATE)"),hl(e))},async close(){n||(n=!0,s.close())}}}catch(e){try{s?.close()}catch{}throw pl(s?"initialize":"connect",e)}}const fl=a.z.enum(["openai-responses","openai-chat-completions","anthropic-messages"]),yl=a.z.object({protocolVersion:a.z.literal("2026-08-27"),instanceId:a.z.string().trim().min(1).max(120),entities:a.z.array(a.z.object({id:a.z.string().trim().min(1).max(120),endpoint:a.z.string().trim().min(1).max(2048),key:a.z.string().trim().min(1).max(4096),protocols:a.z.array(fl).min(1).max(3),modelNames:a.z.array(a.z.object({name:a.z.string().trim().min(1).max(240),order:a.z.number().int().min(0).max(1e6)}).strip()).min(1).max(256)}).strip()).max(64),updatedAt:a.z.string().datetime()}).strip();function Il(e){if(!e||"object"!=typeof e||Array.isArray(e))return e;const t=e;return{protocolVersion:t.protocolVersion,instanceId:t.instanceId,entities:Array.isArray(t.entities)?t.entities.map(e=>{if(!e||"object"!=typeof e||Array.isArray(e))return e;const t=e;return{id:t.id,endpoint:t.endpoint,key:t.key,protocols:t.protocols,modelNames:Array.isArray(t.modelNames)?t.modelNames.map(e=>{if(!e||"object"!=typeof e||Array.isArray(e))return e;const t=e;return{name:t.name,order:t.order}}):t.modelNames}}):t.entities,updatedAt:t.updatedAt}}class Al{models;assignments;transaction;nodeId;instances;constructor(e,t,n,i){this.nodeId=t,this.instances=n;const s=i||hd(gl(e)).model;this.models=s.models,this.assignments=s.assignments,this.transaction=s.transaction.bind(s)}init(){}list(){const e=new Map;for(const t of this.instances.list()){const n=this.assignments.get(t.id);for(const t of new Set([...n?.modelEntityIds||[],n?.codexModelHash,n?.claudeModelHash,n?.opencodeModelHash]))t&&e.set(t,(e.get(t)||0)+1)}return this.models.list().map(t=>this.toPublic(t,e.get(t.id)||0))}create(e){const t=ae(),n=Tl(e.modelNames,e.model),i={...e,model:n[0].name,modelNames:n,protocols:e.protocols?.length?e.protocols:El(e.app)},s=Ss(i),o=this.models.get(s),r=hs.parse({...i,id:s,enabled:e.enabled??!0,order:e.order??this.nextOrder(),labels:e.labels||{},createdAt:o?.createdAt||t,updatedAt:t});return this.toPublic(this.models.put(r),this.referenceIds(s).length)}deploy(e){const t=Ss(e);if(e.id!==t)throw Object.assign(new Error(`Model content hash ${t} does not match ${e.id}.`),{statusCode:400,code:"NODE_MODEL_HASH_MISMATCH"});const n=Tl(e.modelNames,e.model),i=this.models.get(e.id)||this.models.put(hs.parse({...e,model:n[0].name,modelNames:n,protocols:e.protocols?.length?e.protocols:El(e.app)}));return this.toPublic(i,this.referenceIds(i.id).length)}update(e,t){const n=this.requireModel(e),i=t.modelNames?.length?Tl(t.modelNames,t.model||n.model):t.model?Tl(void 0,t.model):Tl(n.modelNames,n.model),s=t.protocols?.length?t.protocols:n.protocols?.length?n.protocols:El(t.app||n.app),o=hs.parse({...n,...t,key:t.key?.trim()?t.key:n.key,protocols:s,model:i[0].name,modelNames:i,createdAt:n.createdAt,updatedAt:ae()}),r=Ss(o),a=this.models.put(hs.parse({...o,id:r}));return this.toPublic(a,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);for(const e of t.modelEntityIds)this.validateEntityRef(e);if(void 0!==t.modelSelection.modelEntityIds&&JSON.stringify(t.modelSelection.modelEntityIds)!==JSON.stringify(t.modelEntityIds))throw Object.assign(new Error("Ordered model entity selection does not match its node assignment."),{statusCode:400,code:"NODE_MODEL_SELECTION_MISMATCH"});if(this.validateRef("codex",t.codexModelHash),this.validateRef("claude",t.claudeModelHash),this.validateRef("opencode",t.opencodeModelHash),void 0!==t.modelSelection.codexModelHash&&(t.modelSelection.codexModelHash??void 0)!==t.codexModelHash)throw Object.assign(new Error("Codex model selection does not match its node assignment."),{statusCode:400,code:"NODE_MODEL_SELECTION_MISMATCH"});if(void 0!==t.modelSelection.claudeModelHash&&(t.modelSelection.claudeModelHash??void 0)!==t.claudeModelHash)throw Object.assign(new Error("Claude model selection does not match its node assignment."),{statusCode:400,code:"NODE_MODEL_SELECTION_MISMATCH"});if(void 0!==t.modelSelection.opencodeModelHash&&(t.modelSelection.opencodeModelHash??void 0)!==t.opencodeModelHash)throw Object.assign(new Error("OpenCode model selection does not match its node assignment."),{statusCode:400,code:"NODE_MODEL_SELECTION_MISMATCH"});const i=ys.parse({instanceId:e,modelEntityIds:t.modelEntityIds,codexModelHash:t.codexModelHash,claudeModelHash:t.claudeModelHash,opencodeModelHash:t.opencodeModelHash,updatedAt:ae()});return this.transaction(()=>({assignment:this.assignments.put(i),instance:this.instances.put(po.parse({...n,modelSelection:t.modelSelection,updatedAt:ae()}))}))}resolvedEnvironment(e){const t=this.assignments.get(e);if(!t)return{};const n=e=>t.modelEntityIds.find(t=>this.modelSupportsApp(this.requireModel(t),e));return{...this.environmentForRef("codex",n("codex")||t.codexModelHash),...this.environmentForRef("claude",n("claude")||t.claudeModelHash),...this.environmentForOpenCode(t)}}privateCatalog(e){const t=this.assignments.get(e);return yl.parse({protocolVersion:"2026-08-27",instanceId:e,entities:(t?.modelEntityIds||[]).map(e=>{const t=this.requireModel(e);return this.validateEntityRef(e),{id:t.id,endpoint:t.endpoint,key:t.key,protocols:t.protocols?.length?t.protocols:El(t.app),modelNames:Tl(t.modelNames,t.model)}}),updatedAt:t?.updatedAt||ae()})}privateSecretValues(e){return[...new Set(this.privateCatalog(e).entities.map(e=>e.key))]}deleteInstanceMetadata(e){this.assignments.delete(e)}validateRef(e,t){if(!t)return;const n=this.requireModel(t);if(!this.modelSupportsApp(n,e))throw Object.assign(new Error(`Model ${n.id} does not support the ${e} runtime protocol.`),{statusCode:400,code:"NODE_MODEL_APP_MISMATCH"});if(!n.enabled)throw Object.assign(new Error(`Model ${n.id} is disabled.`),{statusCode:409,code:"NODE_MODEL_DISABLED"})}modelSupportsApp(e,t){const n="claude"===t?"anthropic-messages":"opencode"===t?"openai-chat-completions":"openai-responses";return e.protocols?.length?e.protocols.includes(n):e.app===t}validateEntityRef(e){const t=this.requireModel(e);if(!t.enabled)throw Object.assign(new Error(`Model ${t.id} is disabled.`),{statusCode:409,code:"NODE_MODEL_DISABLED"});if(!t.protocols?.length&&!El(t.app).length)throw Object.assign(new Error(`Model ${t.id} does not expose a supported protocol.`),{statusCode:400,code:"NODE_MODEL_PROTOCOL_UNSUPPORTED"})}environmentForRef(e,t){if(!t)return{};this.validateRef(e,t);const n=this.requireModel(t);return"codex"===e?{OPENAI_API_KEY:n.key,OPENAI_BASE_URL:n.endpoint,TASK_HANDOFF_CODEX_BASE_URL:n.endpoint,TASK_HANDOFF_CODEX_MODEL:n.model}:{ANTHROPIC_API_KEY:n.key,ANTHROPIC_BASE_URL:n.endpoint,TASK_HANDOFF_CLAUDE_MODEL:n.model}}environmentForOpenCode(e){const t=e.modelEntityIds.map(e=>this.requireModel(e)).filter(e=>this.modelSupportsApp(e,"opencode"));if(!t.length)return{};const n=t[0],i=Tl(n.modelNames,n.model)[0].name,s=Object.fromEntries(t.map(e=>[`task-handoff-${e.id}`,_l(e,Tl(e.modelNames,e.model).map(e=>e.name))]));if(e.opencodeModelHash){const t=this.requireModel(e.opencodeModelHash);s["task-handoff"]=_l(t,[t.model])}return{TASK_HANDOFF_OPENCODE_CONFIG_CONTENT:JSON.stringify({$schema:"https://opencode.ai/config.json",model:`task-handoff-${n.id}/${i}`,provider:s})}}requireModel(e){const t=this.models.get(e);if(!t)throw Object.assign(new Error(`Model ${e} was not found on node ${this.nodeId}.`),{statusCode:404,code:"NODE_MODEL_NOT_FOUND"});if(Ss(t)!==t.id)throw Object.assign(new Error(`Stored model ${e} does not match its content hash.`),{statusCode:409,code:"NODE_MODEL_HASH_INVALID"});return t}referenceIds(e){return this.instances.list().filter(t=>{const n=this.assignments.get(t.id);return n?.modelEntityIds.includes(e)||n?.codexModelHash===e||n?.claudeModelHash===e||n?.opencodeModelHash===e}).map(e=>e.id)}toPublic(e,t){const{key:n,...i}=e;return fs.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}}function _l(e,t){return{npm:"@ai-sdk/openai-compatible",name:e.name,options:{baseURL:e.endpoint,apiKey:e.key},models:Object.fromEntries(t.map(t=>[t,{name:e.name,variants:Object.fromEntries(["none","minimal","low","medium","high","xhigh","max","ultra"].map(e=>[e,{reasoningEffort:e}]))}]))}}function El(e){return"claude"===e?["anthropic-messages"]:"opencode"===e?["openai-chat-completions"]:["openai-responses"]}function Tl(e,t){const n=e?.length?e:[{name:t,order:100}],i=new Set;return n.map(e=>({name:e.name.trim(),order:e.order})).filter(e=>!(!e.name||i.has(e.name)||(i.add(e.name),0))).sort((e,t)=>e.order-t.order||e.name.localeCompare(t.name)).map((e,t)=>({name:e.name,order:100*(t+1)}))}function wl(e,t){if(!e)return!0;const n=b.valid(e),i=b.valid(t);return n&&i?b.gt(i,n):e!==t}function bl(){return process.env.TASK_HANDOFF_NPM_COMMAND||"npm"}function Sl(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 vl(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,o=n.resolve(e);for(;o!==n.dirname(o);){try{const e=JSON.parse(t.readFileSync(n.join(o,"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}o=n.dirname(o)}return s?{packageName:"@task-handoff/node-agent",currentVersion:s,relatedCurrentVersions:[],installPrefix:i}:void 0}(i):void 0;if(s)return s;const o=(await e(bl(),["root","--global"])).stdout.trim();if(!o)throw new Error("npm did not return its global module root.");const r=(await e(bl(),["prefix","--global"])).stdout.trim();if(!n.isAbsolute(r))throw new Error(`npm did not return an absolute global prefix: ${r||"empty"}`);const a=Sl(o,"@task-handoff/server"),c=Sl(o,"@task-handoff/node-agent");return a?{packageName:"@task-handoff/server",currentVersion:a.version,relatedCurrentVersions:c?[c.version]:[],installPrefix:r}:{packageName:"@task-handoff/node-agent",currentVersion:c?.version,relatedCurrentVersions:[],installPrefix:r}}function Nl(e){if(!e||"object"!=typeof e||Array.isArray(e))return e;const t=e,n="string"==typeof t.updatedAt?t.updatedAt:ae(),i=t.target&&"object"==typeof t.target&&!Array.isArray(t.target)?t.target:void 0,s="controlled-instance"===i?.component,o={updating:"updating-node",downloading:"updating-node",installing:"updating-node",restarting:"restarting-node",completed:"succeeded",success:"succeeded",error:"failed"},r=new Set(["queued","updating-node","restarting-node","converging-instances","succeeded","degraded","failed"]),a="string"==typeof t.status?t.status:"queued",c=s?"failed":r.has(a)?a:o[a]||"failed",d="string"==typeof t.toVersion&&t.toVersion?t.toVersion:"unknown",l=Xi.strip().safeParse(t.impact).success?Xi.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||r.has(a)||a in o?"string"==typeof t.error?{code:"NODE_UPDATE_FAILED",message:t.error,retryable:!1}:Gi.strip().safeParse(t.error).success?Gi.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=Ki.strip().safeParse(e);return t.success?[t.data]:[]}):[],rollout:f.success?f.data:g,...u?{error:u}:{},...s?{completedAt:t.completedAt||n}:{}}}class Ol{records;constructor(e){this.records=new Qa(e.updatesDir,{schema:Zi,sanitize:Nl})}init(){this.records.init()}list(){return this.records.list().sort((e,t)=>t.createdAt.localeCompare(e.createdAt))}create(e,t){const n=ae();return this.records.put(Zi.parse({id:Ya("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:[],expectedInstanceCount:0,matchedInstanceCount:0,pendingInstanceCount:0,failedInstanceCount:0,deferredInstanceCount:0},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(Zi.parse({...n,...t,id:e,createdAt:n.createdAt,updatedAt:ae()}))}reconcileServerUpdates(e,t={}){if(t.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:ae()});for(const n of this.list().filter(e=>["updating-node","restarting-node","converging-instances"].includes(e.status)))t.processStarted&&["restarting-node","converging-instances"].includes(n.status)&&e!==n.toVersion?this.patch(n.id,{status:"failed",rollout:{...n.rollout,phase:"failed",nodeVersion:e},error:{code:"NODE_UPDATE_FAILED",message:`Node agent restarted with version ${e}, expected ${n.toVersion}.`,retryable:!1},completedAt:ae()}):e===n.toVersion&&this.patch(n.id,{status:"succeeded",rollout:{...n.rollout,phase:"succeeded",nodeVersion:e,expectedInstanceIds:[],expectedInstanceCount:0,matchedInstanceCount:0,pendingInstanceCount:0,failedInstanceCount:0,deferredInstanceCount:0},error:void 0,completedAt:ae()})}}class zl{records;constructor(e){this.records=new Qa(e.environmentTemplatesDir,{schema:zi,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 o=_o(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}`});o.error=_o(e,["code","message","phase"])}return o}(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(zi.parse({...e,status:"failed",error:{code:"ENVIRONMENT_TEMPLATE_CREATION_INTERRUPTED",message:"Environment template creation was interrupted by a node-agent restart.",phase:"recovery"},updatedAt:ae()}))}list(){return this.records.list()}get(e){return this.records.get(e)}put(e){return this.records.put(zi.parse(e))}patch(e,t){return this.records.patch(e,t)}delete(e){return this.records.delete(e)}}const Cl=a.z.record(a.z.string().regex(/^[A-Za-z_][A-Za-z0-9_]*$/),a.z.string()),Rl=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:Cl,modelCatalog:yl.optional(),codexSettings:Hn.optional(),updatedAt:a.z.string().datetime()}).strict();class xl{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`)}inspectMaterialized(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:{},o=Rl.parse({version:s.version,instanceId:s.instanceId,instanceCredential:s.instanceCredential??s.registrationToken,environment:s.environment,modelCatalog:void 0===s.modelCatalog?void 0:Il(s.modelCatalog),codexSettings:void 0===s.codexSettings?void 0:(r=s.codexSettings,Hn.parse(function(e){if(!e||"object"!=typeof e||Array.isArray(e))return e;const t=e,n=t.multiAgent,i=!n||"object"!=typeof n||Array.isArray(n)?n:(()=>{const e=n,t=e.defaultModel;return{...void 0===e.enabled?{}:{enabled:e.enabled},...void 0===e.maxConcurrentThreads?{}:{maxConcurrentThreads:e.maxConcurrentThreads},...void 0===t?{}:{defaultModel:!t||"object"!=typeof t||Array.isArray(t)?t:{modelEntityId:t.modelEntityId,modelName:t.modelName}},...void 0===e.defaultReasoningEffort?{}:{defaultReasoningEffort:e.defaultReasoningEffort}}})();return{...void 0===t.modelVerbosity?{}:{modelVerbosity:t.modelVerbosity},...void 0===t.personality?{}:{personality:t.personality},...void 0===n?{}:{multiAgent:i}}}(r))),updatedAt:s.updatedAt});var r;if(o.instanceId!==e)throw Object.assign(new Error(`Private config identity mismatch for instance ${e}.`),{statusCode:409,code:"INSTANCE_PRIVATE_CONFIG_IDENTITY_MISMATCH"});return o}put(e){const n=Rl.parse(e);this.init();const i=this.filePath(n.instanceId);return p.sync(i,`${JSON.stringify(n,null,2)}\n`,{encoding:"utf8",mode:384}),t.chmodSync(i,384),n}materialize(e,t,n,i,s){if(!t)throw Object.assign(new Error(`Instance ${e} does not have a long-lived credential.`),{statusCode:409,code:"INSTANCE_PRIVATE_CONFIG_CREDENTIAL_MISSING"});return this.put({version:1,instanceId:e,instanceCredential:t,environment:n,...i?{modelCatalog:i}:{},...s?{codexSettings:s}:{},updatedAt:(new Date).toISOString()})}delete(e){t.rmSync(this.filePath(e),{force:!0})}}const kl=a.z.object({id:a.z.string().trim().min(1).max(120),status:a.z.literal("pending"),input:od,createdAt:a.z.string().datetime(),updatedAt:a.z.string().datetime(),expiresAt:a.z.string().datetime()}).strict();class Dl{repository;workspaceProvisioningTtlMs;workspaceProvisioningCleanupTimer;constructor(e,t={}){this.workspaceProvisioningTtlMs=t.workspaceProvisioningTtlMs??864e5,this.repository=t.repository||hd(gl(e)).git}init(){this.repository.deleteExpiredProvisioning((new Date).toISOString()),this.scheduleWorkspaceProvisioningCleanup()}putPayload(e){const t=Yc.parse(e),n=this.repository.getPayload(t.credential.id);if(n&&n.payload.credential.revision>t.credential.revision)throw i=t.credential.id,Object.assign(new Error(`Refusing stale payload revision for ${i}.`),{code:"GIT_CREDENTIAL_REVISION_STALE",statusCode:409});var i;if(n&&n.payload.credential.revision===t.credential.revision&&JSON.stringify(n.payload)!==JSON.stringify(t))throw function(e,t){return Object.assign(new Error(`Refusing conflicting payload revision for ${t}.`),{code:"GIT_CREDENTIAL_REVISION_CONFLICT",statusCode:409})}(0,t.credential.id);const s=(new Date).toISOString();return this.repository.putPayload({id:t.credential.id,payload:t,createdAt:n?.createdAt||s,updatedAt:s}).payload}getPayload(e){return this.repository.getPayload(e)?.payload}putAuthorizationSet(e){const t=Jc.parse(e),n=this.repository.getAuthorization(t.instanceId),i=(new Date).toISOString();return this.publicAuthorizationSet(this.repository.putAuthorizationCas({id:t.instanceId,...t,createdAt:n?.createdAt||i}))}getAuthorizationSet(e){const t=this.repository.getAuthorization(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=cd(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.repository.listAuthorizations().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.repository.deletePayload(e)}collectUnreferencedPayloads(){return this.repository.collectUnreferencedPayloads()}removeInstance(e){const t=this.repository.deleteAuthorization(e)?1:0;return this.repository.deleteProvisioning(e),this.scheduleWorkspaceProvisioningCleanup(),t}putWorkspaceProvisioning(e){const t=od.parse(e);if(!Pl(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.repository.getProvisioning(t.instanceId);if("consumed"===n?.status&&n.operationId===t.operationId)return t;const i=(new Date).toISOString(),s=kl.parse(this.repository.putProvisioning({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.repository.getProvisioning(e);if(t&&"pending"===t.status)return!Pl(t.input)||Date.parse(t.expiresAt)<=Date.now()?(this.repository.deleteProvisioning(e),void this.scheduleWorkspaceProvisioningCleanup()):t.input}removeWorkspaceProvisioning(e){const t=this.repository.deleteProvisioning(e);return this.scheduleWorkspaceProvisioningCleanup(),t}discardPendingWorkspaceProvisioning(e){const t=this.repository.getProvisioning(e);return!(!t||"pending"!==t.status)&&this.removeWorkspaceProvisioning(e)}completeWorkspaceProvisioning(e,t){const n=(new Date).toISOString(),i=this.repository.consumeProvisioning(e,t,n,new Date(Date.now()+6048e5).toISOString());return this.scheduleWorkspaceProvisioningCleanup(),i}workspaceProvisioningStatus(e){const t=this.repository.getProvisioning(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.repository.listProvisioning().map(e=>Date.parse(e.expiresAt)));Number.isFinite(e)&&(this.workspaceProvisioningCleanupTimer=setTimeout(()=>{this.workspaceProvisioningCleanupTimer=void 0;const e=Date.now();this.repository.deleteExpiredProvisioning(new Date(e).toISOString()),this.scheduleWorkspaceProvisioningCleanup()},Math.min(2147483647,Math.max(0,e-Date.now()))),this.workspaceProvisioningCleanupTimer.unref?.())}publicAuthorizationSet(e){const{id:t,createdAt:n,...i}=e;return Jc.parse(i)}}function Pl(e){return e.credentials.length>0&&e.credentials.every(e=>"operation-only"===e.retention)}const Ll=function(e,t=process.env,n=e){let i;return()=>{const s=t.TASK_HANDOFF_VERSION?.trim();return s||(i||=R(e,t,n),i)}}("@task-handoff/node-agent",process.env,"@task-handoff/control-plane");function Ml(){return Ll()}function jl(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 Ul(e){const t=Ml();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:jl(t,e)}}function Fl(e,t,n=!0){if(!n){const n=Ml(),i=e.runtimeVersion;return"matched"===i?.phase&&i.desiredVersion===n&&i.actualVersion===t?i:Ul(t)}const i=Ml(),s=e.runtimeVersion;if(!s||s.desiredVersion!==i)return Ul(t);const o="INSTANCE_RUNTIME_VERSION_MISMATCH"!==s.error?.code?s.error:t===i?void 0:jl(i,t);return Wi.parse({...s,desiredVersion:i,...t?{actualVersion:t}:{actualVersion:void 0},..."pending"===s.phase?{error:o||(t!==i?jl(i,t):void 0)}:{}})}const $l="runtime_local_host",Hl="task-handoff.node-agent.builtin";function ql(e){const t={...e};return delete t[Hl],t}function Vl(e){return"local-folder"===e.type?cs.parse({mode:"local-bind",path:"/workspace",readOnly:!1}):cs.parse({mode:"git-clone",path:"/workspace",readOnly:!1})}function Bl(e){const t=as.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 ps.parse({id:n,name:"string"==typeof e.sourceSnapshot.name?e.sourceSnapshot.name:e.name,source:t,defaultImageSelection:e.imageSelection,defaultNodeId:e.nodeId,workspacePolicy:Vl(t),labels:{},createdAt:e.createdAt,updatedAt:e.updatedAt})}function Kl(e,t){throw Object.assign(new Error(t),{statusCode:403,code:e})}function Gl(e,t){e!==Pn&&console.warn(JSON.stringify({message:"protocol version mismatch",peer:t,expectedProtocolVersion:Pn,actualProtocolVersion:e||"missing",errorCode:"PROTOCOL_VERSION_MISMATCH"}))}function Wl(e){return"none"!==e.capabilities.artifactKind}function Xl(e={}){return{...e,requiresImage:!1,supportsControlledInstanceApi:!0,supportsContainerLifecycle:!1,supportsAppSessions:!0,supportsHostSessions:!0,artifactKind:"none",isolation:"none"}}class Yl{onStored;records;constructor(e){this.records=e}init(){}setOnStored(e){this.onStored=e}put(e){const t=this.records.put(po.parse(e));return this.onStored?.(t),t}putObservation(e){const t=this.records.putObservation(po.parse(e));return this.onStored?.(t),t}get(e){return this.records.get(e)}list(){return this.records.list()}delete(e){return this.records.delete(e)}}class Jl{nodeId;paths;persistence;localFolders;nodeRuntimes;controlledInstances;environmentTemplates;instancePrivateConfigs;modelRegistry;gitCredentials;updateJobs;node;listenerPort;containerUrlOverride;platform;constructor(e,t,n,i,s,o,r){this.paths=e,this.nodeId=t;const a=r||hd(gl(e));this.persistence=a,a.topology.nodeIdentity.ensure(t,ae()),this.localFolders=a.topology.localFolders,this.nodeRuntimes=a.topology.runtimes,this.instancePrivateConfigs=new xl(e),this.controlledInstances=new Yl(a.topology.instances),this.environmentTemplates=new zl(e),this.gitCredentials=new Dl(e,{repository:a.git}),this.modelRegistry=new Al(e,t,{has:e=>Boolean(this.controlledInstances.get(e)),list:()=>this.listInstances(),require:e=>this.requireInstance(e),put:e=>this.controlledInstances.put(e)},a.model),this.updateJobs=new Ol(e),this.listenerPort=s,this.platform=o,this.containerUrlOverride=i;const c=ae();this.node=Gs.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:c,updatedAt:c})}init(){for(const e of this.localFolders.list())this.localFolders.put(e);if(this.instancePrivateConfigs.init(),this.controlledInstances.init(),this.environmentTemplates.init(),this.gitCredentials.init(),this.modelRegistry.init(),this.updateJobs.init(),this.updateJobs.reconcileServerUpdates(Ml(),{processStarted:!0}),!this.nodeRuntimes.get("runtime_local_docker")){const e=ae();this.nodeRuntimes.put(Ws.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($l),t=ae();this.nodeRuntimes.put(Ws.parse({id:$l,nodeId:this.nodeId,name:"Local Runtime",type:"local",status:e?.status||"unknown",accessStrategy:"node-proxy",capabilities:Xl(e?.capabilities),labels:{...e?.labels,[Hl]:"true"},createdAt:e?.createdAt||t,updatedAt:e?.updatedAt||t}))}for(const e of this.nodeRuntimes.list())e.nodeId!==this.nodeId&&this.nodeRuntimes.put(Ws.parse({...e,nodeId:this.nodeId,updatedAt:ae()}));for(const e of this.localFolders.list())e.nodeId!==this.nodeId&&this.localFolders.put(rs.parse({...e,nodeId:this.nodeId,updatedAt:ae()}));this.normalizeInstanceRuntimeVersions()}normalizeInstanceRuntimeVersions(){for(const e of this.controlledInstances.list()){const t=Ul(e.build?.packageVersion||e.instanceVersion),n=Wl(this.requireRuntime(e.runtimeId)),i=["created","stopped","failed"].includes(e.status),s=n&&e.runtimeVersion?.desiredVersion===t.desiredVersion?e.runtimeVersion:void 0,o=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(po.parse({...e,ready:!1,runtimeVersion:o,updatedAt:ae()}))}}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=ae()}runningInstanceCount(){const e=new Set(["created","stopped","failed"]);return this.listInstances().filter(t=>!e.has(t.status)).length}createLocalFolder(e){const t=ae(),i=pa(e.path),s=rs.parse({...e,name:e.name.trim()||n.basename(i),path:i,id:e.id||Ya("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(rs.parse({...i,name:t.name.trim()||n.basename(i.path),updatedAt:ae()}))}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=ae(),n=Ws.parse({...e,id:e.id||Ya("runtime"),nodeId:this.nodeId,accessStrategy:e.accessStrategy||(i=e.type,"docker"===i?"direct-port":"node-proxy"),capabilities:e.capabilities||{},labels:ql(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[Hl]){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=Ws.parse({...n,...t,id:n.id,nodeId:this.nodeId,accessStrategy:t.accessStrategy||n.accessStrategy,capabilities:t.capabilities||n.capabilities,labels:t.labels?ql(t.labels):n.labels,createdAt:n.createdAt,updatedAt:ae()});return this.nodeRuntimes.put(i)}deleteRuntime(e){if("true"===this.requireRuntime(e).labels[Hl]){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=Ws.parse({...n,...e,id:n.id,nodeId:this.nodeId,createdAt:n.createdAt,updatedAt:ae()});return this.nodeRuntimes.put(t)}):this.nodeRuntimes.put(Ws.parse({...n,status:"unknown",updatedAt:ae()}))}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=fo(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 ${Pn}: ${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 po.parse({...e,status:"starting",ready:!1,updatedAt:n});case"stop-requested":return po.parse({...e,status:"stopping",ready:!1,updatedAt:n});case"stop-failed":return"stopping"!==e.status?e:po.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 po.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 po.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 po.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 po.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=fo(e);return t.success?[t.data]:[]})}resolvedAssignedModelEnvironment(e){return this.modelRegistry.resolvedEnvironment(e)}createInstance(e){const t=this.requireRuntime(e.runtimeId),i=ae(),s=e.id||Ya("inst"),o=function(e){const t=as.parse(e);return"local-folder"===t.type?t:as.parse({...t,auth:{type:"none"}})}(e.source),r=e.environmentSource||(e.imageSelection?{type:"image",imageSelection:e.imageSelection}:void 0);if("template"===r?.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"===r?.type?this.environmentTemplates.get(r.environmentTemplateId):void 0;if("template"===r?.type&&(!a||"ready"!==a.status)){const e=new Error(`Environment template ${r.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)&&(!r||"image"===r.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"!==o.type){const e=new Error("Localhost runtime currently supports local folder sources only.");throw Object.assign(e,{statusCode:400,code:"LOCAL_RUNTIME_REQUIRES_LOCAL_FOLDER"}),e}if("local"===t.type&&this.listInstances().some(e=>"local"===this.requireRuntime(e.runtimeId).type)){const e=new Error("A localhost instance already exists on this node.");throw Object.assign(e,{statusCode:409,code:"LOCAL_RUNTIME_INSTANCE_EXISTS"}),e}const c=a?Ms.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?Ms.parse(e.image):void 0,d="local"===t.type&&"local-folder"===o.type?n.resolve(o.path):void 0,l=po.parse({id:s,name:e.name||`instance-${s.replace(/^inst_?/,"").slice(0,6)}`,source:o,sourceSnapshot:e.sourceSnapshot||{},modelSelection:e.modelSelection,projectId:e.projectId,nodeId:this.nodeId,runtimeId:t.id,imageSelection:"image"===r?.type?r.imageSelection:void 0,environmentSource:r,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"!==r?.type?{phase:"checking-image",requestedReference:c.requestedReference,generation:0,startedAt:i,updatedAt:i}:void 0,status:c&&"docker"===t.type&&"template"!==r?.type?"provisioning":"created",health:"unknown",connectionStatus:"unknown",agentStatus:"unknown",targetStatus:"unknown",uiAccessStatus:"unknown",controlMode:"controlled",ready:!1,runtimeVersion:Ul(),capabilities:{},config:{autoImportAgentConfigs:e.config?.autoImportAgentConfigs??!0,codexConfigEnabled:e.config?.codexConfigEnabled??!0,codexHomeMode:e.config?.codexHomeMode??("local"===t.type?"taskhandoff":"default"),defaultCodexPermissionMode:e.config?.defaultCodexPermissionMode??("docker"===t.type?"full-access":"ask"),...e.config?.codexSettings?{codexSettings:e.config.codexSettings}:{},aiSessionHistoryLimit:e.config?.aiSessionHistoryLimit??50,aiSessionAttachmentRetentionDays:e.config?.aiSessionAttachmentRetentionDays??30,aiSessionMaxFileAttachmentBytes:e.config?.aiSessionMaxFileAttachmentBytes??he},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:Ja(),createdAt:i,updatedAt:i}),u=this.persistence.transactionSync(()=>{let t=this.controlledInstances.put(l);const n=e.modelSelection;return n&&Object.values(n).some(e=>Array.isArray(e)?e.length>0:Boolean(e))&&(t=this.modelRegistry.assign(s,{modelSelection:n,modelEntityIds:n.modelEntityIds,codexModelHash:n.codexModelHash,claudeModelHash:n.claudeModelHash,opencodeModelHash:n.opencodeModelHash}).instance),e.gitWorkspaceProvisioning?.credentials.every(e=>"operation-only"===e.retention)&&this.gitCredentials.putWorkspaceProvisioning(e.gitWorkspaceProvisioning),t});return this.instancePrivateConfigs.materialize(u.id,u.registrationToken,this.resolvedAssignedModelEnvironment(u.id),this.modelRegistry.privateCatalog(u.id),u.config.codexSettings),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=cd(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=Eo.parse(t),s=ae(),o=this.controlledInstances.get(e);if(!o){const t=new Error(`Instance ${e} was not found on node ${this.nodeId}.`);throw Object.assign(t,{statusCode:404,code:"NODE_INSTANCE_NOT_FOUND"}),t}if(this.validateInstanceReport(o,i,n),i.processIncarnationId&&i.processIncarnationId===o.processIncarnationId)return o;Gl(i.protocolVersion,`Instance ${e}`);const r=i.build?.packageVersion||i.instanceVersion,a=Wl(this.requireRuntime(o.runtimeId)),c=Fl(o,r,a),d=po.parse({...o,status:"registered",health:r===Ml()?"ok":"degraded",ready:!a&&r===Ml(),connectionStatus:"online",agentStatus:"online",targetStatus:o.targetStatus,uiAccessStatus:o.uiAccessStatus,controlMode:i.controlMode,protocolVersion:i.protocolVersion,instanceVersion:i.instanceVersion,build:i.build,runtimeVersion:c,processIncarnationId:i.processIncarnationId||o.processIncarnationId,capabilities:i.capabilities,appInventory:i.appInventory,workspace:i.workspace,target:o.target,registrationToken:o.registrationToken||i.registrationToken,lastHeartbeatAt:s,updatedAt:s});return this.controlledInstances.putObservation(d)}heartbeatInstance(e,t,n){const i=this.requireInstance(e);this.validateInstanceToken(i,n);const s=To.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.`),Gl(s.protocolVersion,`Instance ${e}`);const o=ae(),r=i.target,a=i.targetStatus,c=Fl(i,s.build?.packageVersion||i.build?.packageVersion||i.instanceVersion,Wl(this.requireRuntime(i.runtimeId))),d=s.health||i.health,l="running"===(s.status||i.status)&&"failed"!==d,u=po.parse({...i,...s,target:r,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:o,updatedAt:o});return this.controlledInstances.putObservation(u)}validateInstanceReport(e,t,n){this.validateInstanceToken(e,n||t.registrationToken),t.instanceId&&t.instanceId!==e.id&&Kl("INSTANCE_ID_MISMATCH",`Instance ${t.instanceId} cannot register as ${e.id}.`),t.nodeId&&t.nodeId!==this.nodeId&&Kl("INSTANCE_NODE_MISMATCH",`Instance ${e.id} belongs to node ${this.nodeId}.`),t.runtimeId&&t.runtimeId!==e.runtimeId&&Kl("INSTANCE_RUNTIME_MISMATCH",`Instance ${e.id} belongs to runtime ${e.runtimeId}.`),t.imageSelection&&t.imageSelection.imageId!==e.imageSelection?.imageId&&Kl("INSTANCE_IMAGE_MISMATCH",`Instance ${e.id} belongs to image ${e.imageSelection?.imageId}.`)}validateInstanceToken(e,t){e.registrationToken&&t===e.registrationToken||Kl("INSTANCE_REGISTRATION_TOKEN_INVALID",`Invalid registration token for instance ${e.id}.`)}authenticateInstance(e,t){const n=this.requireInstance(e);return this.validateInstanceToken(n,t),n}context(e,t=this.resolvedAssignedModelEnvironment(e.id)){const n=t,i=e.imageSnapshot||Ms.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}),s=this.instancePrivateConfigs.materialize(e.id,e.registrationToken,n,this.modelRegistry.privateCatalog(e.id),e.config.codexSettings),o=this.gitWorkspaceProvisioningFor(e);return{project:Bl(e),image:i,node:this.node,runtime:this.requireRuntime(e.runtimeId),instance:e,nodeAgentUrl:this.containerUrl,modelEnv:n,privateConfigPath:this.instancePrivateConfigs.filePath(s.instanceId),...o?{gitWorkspaceProvisioning:o,completeGitWorkspaceProvisioning:()=>this.gitCredentials.completeWorkspaceProvisioning(e.id,o.operationId)}:{}}}}async function Ql(e,t){const n=function(e){const t=nu(e),n=[],i=t.pathname.split("/").filter(Boolean).at(-1)||"";return au(n,eu(t.toString(),/^v\d+$/.test(i)?"models":"v1/models")),au(n,new URL("/v1/models",t.origin).toString()),au(n,new URL("/models",t.origin).toString()),n}(t.endpoint),i=Date.now();let s;for(const o of n){const n=await iu(e,o,{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 ou("MODEL_DISCOVERY_FAILED",n.status);const r=await su(n,"MODEL_DISCOVERY_RESPONSE_INVALID"),a=Array.isArray(r.data)?r.data:void 0;if(!a)throw ru("MODEL_DISCOVERY_RESPONSE_INVALID","The model endpoint returned an invalid model list.",502);return{models:cu(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 ru("MODEL_DISCOVERY_UNSUPPORTED","No compatible model-list endpoint was found for this endpoint.",502,s)}async function Zl(e,t){const n=Date.now(),i=t.protocol||("claude"===t.app?"anthropic-messages":"opencode"===t.app?"openai-chat-completions":"openai-responses"),s="openai-responses"===i?await iu(e,tu(t.endpoint,"responses"),{method:"POST",headers:{accept:"application/json",authorization:`Bearer ${t.key}`,"content-type":"application/json"},body:JSON.stringify({model:t.model,input:"Reply with OK.",max_output_tokens:32,stream:!1})}):"openai-chat-completions"===i?await iu(e,tu(t.endpoint,"chat/completions"),{method:"POST",headers:{accept:"application/json",authorization:`Bearer ${t.key}`,"content-type":"application/json"},body:JSON.stringify({model:t.model,messages:[{role:"user",content:"Reply with OK."}],max_tokens:32,stream:!1})}):await iu(e,function(e){const t=nu(e);if(/\/messages\/?$/.test(t.pathname))return t.toString();const n=t.pathname.split("/").filter(Boolean).at(-1)||"";return eu(t.toString(),/^v\d+$/.test(n)?"messages":"v1/messages")}(t.endpoint),{method:"POST",headers:{accept:"application/json","anthropic-version":"2023-06-01","content-type":"application/json","x-api-key":t.key},body:JSON.stringify({model:t.model,max_tokens:8,messages:[{role:"user",content:"Reply with OK."}]})});if(!s.ok)throw ou("MODEL_TEST_FAILED",s.status);if((await su(s,"MODEL_TEST_RESPONSE_INVALID")).error)throw ru("MODEL_TEST_RESPONSE_INVALID","The model endpoint returned an error payload.",502);return{success:!0,latencyMs:Date.now()-n}}function eu(e,t){const n=nu(e);return n.pathname=`${n.pathname.replace(/\/+$/,"")}/${t.replace(/^\/+/,"")}`,n.search="",n.hash="",n.toString()}function tu(e,t){const n=nu(e);return n.pathname.replace(/\/+$/,"").endsWith(`/${t}`)?n.toString():eu(n.toString(),t)}function nu(e){let t;try{t=new URL(e.trim())}catch{throw ru("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 ru("MODEL_ENDPOINT_INVALID","The model endpoint must be an HTTP or HTTPS URL without embedded credentials.",400);return t}async function iu(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 ru(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 su(e,t){const n=await e.text();if(n.length>1e6)throw ru(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 ru(t,"The model endpoint returned invalid JSON.",502)}}function ou(e,t){return ru(e,401===t||403===t?"The model endpoint rejected the API key.":"The model endpoint rejected the request.",502,t)}function ru(e,t,n,i){return Object.assign(new Error(t),{code:e,statusCode:n,...i?{details:{upstreamStatus:i}}:{}})}function au(e,t){e.includes(t)||e.push(t)}function cu(e){const t=new Set;return e.filter(e=>!t.has(e.id)&&(t.add(e.id),!0))}const du=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(),lu=du.extend({model:a.z.string().trim().min(1).max(240),app:a.z.enum(["codex","claude","opencode"]).optional(),protocol:a.z.enum(["openai-responses","openai-chat-completions","anthropic-messages"]).optional()}).strict().refine(e=>Boolean(e.protocol||e.app),{message:"A model protocol is required.",path:["protocol"]});class uu{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:o}=this.store.resolve(e,i);if("unique"!==s.status||"ssh-key"!==o?.secret.kind)return{status:s.status};const r=`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 mu("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:o.secret.passphrase||""};await hu("ssh-add",["-"],o.secret.privateKey,s);const c=await mu("ssh-add",["-L"],s);t.rmSync(u,{force:!0});const d=Date.now();return this.invocations.set(r,{instanceId:e,remoteUrl:i,credentialId:o.credential.id,credentialRevision:o.credential.revision,socketPath:l,agentPid:p,directory:a,idleExpiresAt:d+this.idleTtlMs,absoluteExpiresAt:d+this.maxTtlMs}),this.scheduleCleanup(),{status:"ok",invocationId:r,publicIdentity:c,pinnedKnownHosts:o.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 pu("GIT_CREDENTIAL_SSH_INVOCATION_INVALID",404);const{match:s,payload:o}=this.store.resolve(e,i.remoteUrl);if("unique"!==s.status||"ssh-key"!==o?.secret.kind||o.credential.id!==i.credentialId||o.credential.revision!==i.credentialRevision)throw this.release(t,e),pu("GIT_CREDENTIAL_SSH_INVOCATION_REVOKED",403);const r=Buffer.from(n,"base64");if(r.length<5||r.length>1048576||r.readUInt32BE(0)!==r.length-4)throw pu("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 o=h.createConnection(e),r=[];let a=0,c=!1;const d=(e,t)=>{c||(c=!0,o.destroy(),e?s(e):i(t))};o.setTimeout(n),o.once("timeout",()=>d(new Error("Managed Git SSH agent exchange timed out."))),o.once("error",e=>d(e)),o.once("end",()=>d(new Error("Managed Git SSH agent closed before returning a complete frame."))),o.once("close",()=>d(new Error("Managed Git SSH agent closed before returning a complete frame."))),o.on("data",e=>{r.push(e);const t=Buffer.concat(r);!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))}),o.once("connect",()=>o.write(t,e=>{e&&d(e)}))})}(i.socketPath,r,a);return{frame:e.toString("base64")}}catch{throw this.release(t,e),pu("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 pu(e,t){return Object.assign(new Error("Managed Git broker request was rejected."),{code:e,statusCode:t})}function mu(e,t,n=process.env){return hu(e,t,void 0,n)}function hu(e,t,n,i){return new Promise((s,o)=>{const r=l.spawn(e,t,{shell:!1,env:i,stdio:[void 0===n?"ignore":"pipe","pipe","pipe"]}),a=[];r.stdout.on("data",e=>a.push(e)),r.once("error",()=>o(new Error(`Managed Git SSH broker could not start ${e}.`))),r.once("close",t=>0===t?s(Buffer.concat(a).toString("utf8")):o(new Error(`Managed Git SSH broker command ${e} failed.`))),void 0!==n&&r.stdin.end(n)})}const gu=a.z.object({credentialId:a.z.string().trim().min(1).max(120)}).strict(),fu=a.z.object({id:a.z.string().trim().min(1).max(120)}).strict(),yu=fu.extend({invocationId:a.z.string().trim().min(1).max(120)}).strict();function Iu(e){const t=e.authorization;return"string"==typeof t&&t.startsWith("Bearer ")?t.slice(7).trim():void 0}const Au=a.z.object({maxIdleAiSessions:a.z.number().int().min(1).max(50).default(5)}).strict(),_u=a.z.string().trim().min(1).max(1024).refine(e=>!e.startsWith("/")&&!e.includes("\\")&&e.split("/").every(e=>e.length>0&&"."!==e&&".."!==e),"Story paths must be normalized relative POSIX paths."),Eu=a.z.string().regex(/^[a-f0-9]{64}$/),Tu=a.z.object({title:a.z.string().trim().min(1).max(240),storyPath:_u,revision:Eu}).strict(),wu=a.z.object({agent:be.optional(),mode:tt.optional(),permissionMode:nt.optional(),modelSelection:ht.optional(),reasoningEffort:gt.optional(),cwdFolderId:a.z.string().trim().min(1).max(120).optional(),gitSelection:ft.optional()}).strict(),bu=a.z.object({id:a.z.string().trim().min(1).max(120),title:a.z.string().trim().min(1).max(120),promptTemplate:a.z.string().trim().min(1).max(32e3),targetInstanceId:a.z.string().trim().min(1).max(120).optional(),sessionPreset:wu.optional()}).strict(),Su=bu.omit({id:!0}).strict(),vu=Su.extend({id:bu.shape.id.optional()}).strict(),Nu=a.z.discriminatedUnion("scheduleKind",[a.z.object({scheduleKind:a.z.literal("interval"),intervalMs:a.z.number().int().min(6e4)}).strict(),a.z.object({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({scheduleKind:a.z.literal("weekly"),weekdays:a.z.array(a.z.number().int().min(0).max(6)).min(1).max(7).refine(e=>new Set(e).size===e.length,"Weekdays must be unique."),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({scheduleKind:a.z.literal("monthly"),dayOfMonth:a.z.number().int().min(-3).max(31).refine(e=>0!==e,"Day of month must not be zero."),timeOfDay:a.z.string().regex(/^([01]\d|2[0-3]):[0-5]\d$/),timezone:a.z.string().trim().min(1).max(120)}).strict()]),Ou=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(),zu=a.z.object({id:a.z.string().trim().min(1).max(120),storyId:ue,actionId:bu.shape.id,schedule:Nu,enabled:a.z.boolean().default(!0),policy:Ou.default({maxConcurrentRuns:1,whenBusy:"skip"}),createdAt:a.z.string().datetime(),updatedAt:a.z.string().datetime()}).strict(),Cu=zu.omit({id:!0,createdAt:!0,updatedAt:!0}).strict(),Ru=a.z.object({action:bu,automation:Cu.omit({storyId:!0,actionId:!0}).strict()}).strict(),xu=a.z.object({actionId:zu.shape.actionId.optional(),schedule:Nu.optional(),enabled:a.z.boolean().optional(),policy:Ou.optional()}).strict().refine(e=>Object.keys(e).length>0,"At least one Automation field is required."),ku=a.z.object({code:a.z.string().trim().min(1).max(120),message:a.z.string().trim().min(1).max(2e3)}).strict(),Du=a.z.enum(["queued","dispatching","running","completed","failed","skipped"]),Pu=a.z.object({id:a.z.string().trim().min(1).max(160),automationId:zu.shape.id,eventType:a.z.enum(["manual","schedule"]),status:Du,scheduledFor:a.z.string().datetime(),targetInstanceId:a.z.string().trim().min(1).max(120),aiSessionId:a.z.string().trim().min(1).max(120).optional(),error:ku.optional(),queuedAt:a.z.string().datetime(),startedAt:a.z.string().datetime().optional(),completedAt:a.z.string().datetime().optional()}).strict(),Lu=a.z.enum(["disabled","blocked","scheduled","running","error"]),Mu=a.z.object({automation:zu,effectiveStatus:Lu,blockedReason:ku.optional(),nextRunAt:a.z.string().datetime().optional(),currentRuns:a.z.array(Pu).max(20).default([]),lastRun:Pu.optional()}).strict(),ju=a.z.object({automations:a.z.array(Mu).default([])}).strict(),Uu=a.z.object({runs:a.z.array(Pu).max(120).default([])}).strict(),Fu=a.z.object({clientRequestId:a.z.string().trim().min(1).max(160)}).strict(),$u="story.automation.changed";a.z.object({storyId:ue,automationId:zu.shape.id,change:a.z.enum(["created","updated","deleted","status","run"]),status:Mu.optional(),run:Pu.optional()}).strict();const Hu=a.z.object({id:ue,ownerNodeId:a.z.string().trim().min(1).max(120),title:a.z.string().trim().min(1).max(240),description:a.z.string().trim().max(4e3).optional(),documents:a.z.array(Tu).max(500).default([]),actions:a.z.array(bu).max(50).default([]),createdAt:a.z.string().datetime(),updatedAt:a.z.string().datetime(),archivedAt:a.z.string().datetime().optional()}).strict();a.z.object({stories:a.z.array(Hu).default([])}).strict();const qu=a.z.object({title:Hu.shape.title,description:Hu.shape.description,actions:a.z.array(Su).max(50).optional(),maxIdleAiSessions:Au.shape.maxIdleAiSessions.optional()}).strict(),Vu=a.z.object({title:Hu.shape.title.optional(),description:Hu.shape.description.nullable().optional(),actions:a.z.array(vu).max(50).optional(),maxIdleAiSessions:Au.shape.maxIdleAiSessions.optional()}).strict().refine(e=>Object.keys(e).length>0,"At least one Story field is required."),Bu=a.z.object({title:Tu.shape.title.optional(),storyPath:_u.optional()}).strict().refine(e=>Object.keys(e).length>0,"At least one document field is required."),Ku=a.z.object({storyPaths:a.z.array(_u).max(500)}).strict();a.z.object({storyPath:_u,title:Tu.shape.title.optional(),expectedRevision:Eu.optional()}).strict();const Gu=a.z.object({documents:a.z.array(Tu).max(500)}).strict(),Wu=a.z.union([a.z.number(),a.z.string().regex(/^\d+$/).transform(Number)]),Xu=a.z.object({page:Wu.pipe(a.z.number().int().min(1).max(500)).default(1),pageSize:Wu.pipe(a.z.number().int().min(1).max(100)).default(20)}).strict(),Yu=a.z.object({title:Tu.shape.title,storyPath:_u}).strict(),Ju=a.z.object({page:a.z.number().int().min(1).max(500),pageSize:a.z.number().int().min(1).max(100),totalItems:a.z.number().int().nonnegative(),totalPages:a.z.number().int().nonnegative(),hasMore:a.z.boolean()}).strict(),Qu=a.z.object({storyCreatedAt:Hu.shape.createdAt,documents:a.z.array(Yu).max(100),pagination:Ju}).strict();a.z.object({storyCreatedAt:Hu.shape.createdAt,documents:a.z.array(Yu.strip()).max(100),pagination:Ju.strip()}).strip(),a.z.object({storyPath:_u,revision:Eu,content:a.z.string(),size:a.z.number().int().nonnegative()}).strict(),a.z.object({storyPaths:a.z.array(_u).min(1).max(20),destinationPath:a.z.string().trim().min(1).max(4096)}).strict(),a.z.object({storyPath:_u,title:Tu.shape.title.optional(),sourcePath:a.z.string().trim().min(1).max(4096),expectedRevision:Eu.optional()}).strict();const Zu=a.z.object({storyPath:_u,path:a.z.string().trim().min(1).max(4096).optional(),revision:Eu.optional(),error:a.z.object({code:a.z.string().trim().min(1).max(120),message:a.z.string().trim().min(1).max(2e3)}).strict().optional()}).strict();a.z.object({items:a.z.array(Zu).min(1).max(20)}).strict(),a.z.object({storyId:ue,nodeId:a.z.string().trim().min(1).max(120),change:a.z.enum(["created","updated","archived","restored","deleted","content.written","document.updated","document.reordered","document.deleted"]).optional(),storyPath:_u.optional()}).strict();const ep=a.z.object({storyId:ue}).strict(),tp=ep.extend({storyPath:a.z.string().min(1).max(2048)}).strict(),np=ep.extend({automationId:a.z.string().trim().min(1).max(120)}).strict(),ip=a.z.object({id:a.z.string().trim().min(1).max(120),sessionId:a.z.string().trim().min(1).max(120)}).strict(),sp=a.z.object({storyPath:_u}).strict(),op=sp.extend({title:a.z.string().trim().min(1).max(240).optional(),expectedRevision:a.z.string().regex(/^[a-f0-9]{64}$/).optional()}).strict();function rp(e){const t=e.authorization;return"string"==typeof t&&t.startsWith("Bearer ")?t.slice(7).trim():void 0}async function ap(e,t,n,i,s){const o=e.authenticateInstance(n,s).aiSessions.sessions.find(e=>e.id===i);if(!o)throw Object.assign(new Error("AI Session was not found in the authoritative instance snapshot."),{code:"AI_SESSION_NOT_FOUND",statusCode:404});if(!o.storyId)throw Object.assign(new Error("AI Session is not assigned to a Story."),{code:"STORY_CONTEXT_REQUIRED",statusCode:409});return await t.get(o.storyId)||(()=>{throw Object.assign(new Error("Story was not found."),{code:"STORY_NOT_FOUND",statusCode:404})})()}function cp(e,t,n,i){return e.header("content-type","application/octet-stream"),e.header("content-length",String(i)),e.header("x-story-revision",n),e.send(t)}class dp{tails=new Map;accepting=!0;async acquire(e){if(!this.accepting)throw Object.assign(new Error("Story storage is shutting down."),{code:"STORY_STORAGE_QUIESCING",statusCode:503});const t=this.tails.get(e)??Promise.resolve();let n;const i=new Promise(e=>{n=e}),s=t.catch(()=>{}).then(()=>i);this.tails.set(e,s),await t.catch(()=>{});let o=!1;return()=>{o||(o=!0,n(),s.finally(()=>{this.tails.get(e)===s&&this.tails.delete(e)}))}}async run(e,t){const n=await this.acquire(e);try{return await t()}finally{n()}}stopAccepting(){this.accepting=!1}async drain(){await Promise.all([...this.tails.values()])}pendingStoryIds(){return[...this.tails.keys()]}}class lp{coordinator;paths;ownerNodeId;repository;maxFileBytes;onChange;constructor(e,t,n,i=33554432,s){this.paths=e,this.ownerNodeId=t,this.repository=n,this.maxFileBytes=i,this.onChange=s,this.coordinator=new dp}async init(){t.mkdirSync(this.paths.storyMutationsDir,{recursive:!0,mode:448}),t.mkdirSync(this.paths.storyTrashDir,{recursive:!0,mode:448}),t.chmodSync(this.paths.storyMutationsDir,448),t.chmodSync(this.paths.storyTrashDir,448),await this.recoverFileMutations()}setOnChange(e){this.onChange=e}async list(){const e=await this.repository.stories.list();return Promise.all(e.map(e=>this.project(e)))}async get(e){const t=await this.repository.stories.get(e);return t?this.project(t):void 0}async require(e){const t=await this.repository.stories.get(e);if(!t)throw up("STORY_NOT_FOUND","Story was not found.",404);return t}async exists(e){return Boolean(await this.repository.stories.get(e))}async automationContext(e){const t=await this.repository.stories.get(e);if(!t)return;if(await this.repository.deletionIntents.get(e))throw up("STORY_DELETING","Story is being deleted.",409);const n=(await this.repository.actions.list(e)).map(({storyId:e,displayOrder:t,sessionPreset:n,...i})=>bu.parse({...i,sessionPreset:n||void 0}));return{id:t.id,archivedAt:t.archivedAt||void 0,actions:n}}async create(e){const t=qu.parse(e),n=(new Date).toISOString(),i=await this.repository.transaction(async e=>{const i=await e.stories.insert({id:Ya("story"),title:t.title,description:t.description,createdAt:n,updatedAt:n,maxIdleAiSessions:t.maxIdleAiSessions??5,nextDocumentSequence:1}),s=(t.actions||[]).map((e,t)=>({storyId:i.id,id:Ya("story_action"),title:e.title,promptTemplate:e.promptTemplate,targetInstanceId:e.targetInstanceId,sessionPreset:e.sessionPreset,displayOrder:t}));return await e.actions.replace(i.id,s),i}),s=await this.project(i);return this.onChange?.("created",s),s}async retentionSettings(e){return Au.parse({maxIdleAiSessions:(await this.require(e)).maxIdleAiSessions})}async update(e,t,n=!0){const i=Vu.parse(t),s=(new Date).toISOString(),o=await this.repository.transaction(async t=>{if(!await t.stories.get(e))throw up("STORY_NOT_FOUND","Story was not found.",404);if(await t.deletionIntents.get(e))throw up("STORY_DELETING","Story is being deleted.",409);if(void 0!==i.actions){const n=await t.actions.list(e),s=new Set(i.actions.flatMap(e=>e.id?[e.id]:[])),o=n.map(e=>e.id).filter(e=>!s.has(e)),r=await t.automations.referencingActions(e,o);if(r.length)throw up("STORY_ACTION_AUTOMATION_IN_USE","Story Action is referenced by an Automation.",409,{automationIds:r.map(e=>e.id)});await t.actions.replace(e,i.actions.map((t,n)=>({storyId:e,id:t.id||Ya("story_action"),title:t.title,promptTemplate:t.promptTemplate,targetInstanceId:t.targetInstanceId,sessionPreset:t.sessionPreset,displayOrder:n})))}return t.stories.update(e,{...void 0!==i.title?{title:i.title}:{},...void 0!==i.description?{description:i.description||null}:{},...void 0!==i.maxIdleAiSessions?{maxIdleAiSessions:i.maxIdleAiSessions}:{},updatedAt:s})}),r=await this.project(o);return n&&this.onChange?.("updated",r),r}async archive(e){return this.setArchived(e,!0)}async restore(e){return this.setArchived(e,!1)}async setArchived(e,t){await this.require(e);const n=(new Date).toISOString(),i=await this.repository.stories.update(e,{archivedAt:t?n:null,updatedAt:n}),s=await this.project(i);return this.onChange?.(t?"archived":"restored",s),s}async deleteRecord(e){const t=await this.get(e);if(!t)return!1;const n=await this.repository.stories.delete(e);return n&&this.onChange?.("deleted",t),n}notifyDeleted(e){this.onChange?.("deleted",e)}notifyUpdated(e){this.onChange?.("updated",e)}async listContent(e){const t=await this.require(e);return(await this.project(t)).documents}async pageContent(e,t,n){const i=await this.require(e),{items:s,totalItems:o}=await this.repository.documents.page(e,t,n),r=Math.ceil(o/n);return{storyCreatedAt:i.createdAt,documents:s,pagination:{page:t,pageSize:n,totalItems:o,totalPages:r,hasMore:t*n<o}}}async readContent(e,n){const i=await this.coordinator.acquire(e);try{await this.require(e);const s=_u.parse(n);if(!await this.repository.documents.get(e,s))throw up("STORY_CONTENT_NOT_INDEXED","Story content is not indexed.",404);const o=this.openRegularFileWithinRoot(e,s),r=t.createReadStream("",{fd:o.fd,autoClose:!0});let a=!1;const c=()=>{a||(a=!0,i())};return r.once("close",c),r.once("error",c),{stream:r,size:o.size,revision:o.revision}}catch(t){if(i(),"ENOENT"===t.code)throw await this.removeMissingDocument(e,n),up("STORY_CONTENT_NOT_FOUND","Story content file was not found.",404);throw t}}async writeContent(e,i){return this.coordinator.run(e,async()=>{if((await this.require(e)).archivedAt)throw up("STORY_ARCHIVED","Archived Story content is read-only.",409);const s=_u.parse(i.storyPath),o=await this.repository.documents.get(e,s);if(o){if(!i.expectedRevision)throw up("STORY_REVISION_REQUIRED","expectedRevision is required when replacing Story content.",409);const n=this.openRegularFileWithinRoot(e,s);if(t.closeSync(n.fd),n.revision!==i.expectedRevision)throw up("STORY_REVISION_CONFLICT","Story content changed since it was read.",409)}else if(!i.title?.trim())throw up("STORY_CONTENT_TITLE_REQUIRED","A title is required for new Story content.",400);this.ensureStoryParent(e,s);const r=Ya("story_file_mutation"),a=this.filePath(e,s),c=`${a}.${r}.tmp`,d=`${a}.${r}.bak`,l=(new Date).toISOString();if(!o&&t.existsSync(a))throw up("STORY_PATH_CONFLICT","Story path already exists on disk.",409);await this.repository.fileMutations.insert({id:r,storyId:e,operation:"write",storyPath:s,title:i.title?.trim(),temporaryName:c,backupName:d,phase:"receiving",createdAt:l,updatedAt:l});let u=0,p=!1;try{const l=new g.Transform({transform:(e,t,n)=>{u+=e.byteLength,n(u>this.maxFileBytes?up("STORY_FILE_TOO_LARGE","Story content exceeds the node limit.",413):null,e)}});await y.pipeline(i.stream,l,t.createWriteStream(c,{flags:"wx",mode:384})),this.fsyncFile(c),await this.repository.fileMutations.update(r,{phase:"prepared",updatedAt:(new Date).toISOString()}),o&&t.renameSync(a,d),t.renameSync(c,a),this.fsyncDirectory(n.dirname(a)),await this.repository.fileMutations.update(r,{phase:"files-staged",updatedAt:(new Date).toISOString()}),await this.repository.transaction(async t=>{const n=await t.stories.get(e);if(!n)throw up("STORY_NOT_FOUND","Story was not found.",404);if(o)await t.documents.update(e,s,{title:i.title?.trim()||o.title});else{const o=await t.documents.list(e);await t.documents.insert({storyId:e,storyPath:s,title:i.title.trim(),indexedSequence:n.nextDocumentSequence,displayOrder:o.length}),await t.stories.update(e,{nextDocumentSequence:n.nextDocumentSequence+1,updatedAt:(new Date).toISOString()})}o&&await t.stories.update(e,{updatedAt:(new Date).toISOString()}),await t.fileMutations.update(r,{phase:"database-committed",updatedAt:(new Date).toISOString()})}),p=!0,t.rmSync(d,{force:!0}),await this.repository.fileMutations.update(r,{phase:"cleanup",updatedAt:(new Date).toISOString()}),await this.repository.fileMutations.delete(r);const m=this.openRegularFileWithinRoot(e,s);t.closeSync(m.fd);const h=await this.get(e);return h&&this.onChange?.("content.written",h),{storyPath:s,revision:m.revision,size:u}}catch(e){throw p||await this.rollbackFileMutation(r,a,c,d,Boolean(o)),e}})}async updateDocument(e,i,s){return this.coordinator.run(e,async()=>{if((await this.require(e)).archivedAt)throw up("STORY_ARCHIVED","Archived Story content is read-only.",409);const o=_u.parse(i),r=await this.repository.documents.get(e,o);if(!r)throw up("STORY_CONTENT_NOT_INDEXED","Story content is not indexed.",404);const a=s.storyPath?_u.parse(s.storyPath):o;if(a!==o&&await this.repository.documents.get(e,a))throw up("STORY_PATH_CONFLICT","Story path is already indexed.",409);if(a===o)await this.repository.transaction(async t=>{await t.documents.update(e,o,{title:s.title?.trim()||r.title}),await t.stories.update(e,{updatedAt:(new Date).toISOString()})});else{this.openAndClose(e,o),this.ensureStoryParent(e,a);const i=this.filePath(e,o),c=this.filePath(e,a);if(t.existsSync(c))throw up("STORY_PATH_CONFLICT","Story path already exists on disk.",409);const d=Ya("story_file_mutation"),l=(new Date).toISOString();await this.repository.fileMutations.insert({id:d,storyId:e,operation:"rename",storyPath:o,nextStoryPath:a,title:s.title?.trim(),temporaryName:i,backupName:c,phase:"prepared",createdAt:l,updatedAt:l});let u=!1;try{t.renameSync(i,c),this.fsyncDirectory(n.dirname(i)),n.dirname(i)!==n.dirname(c)&&this.fsyncDirectory(n.dirname(c)),await this.repository.fileMutations.update(d,{phase:"files-staged",updatedAt:(new Date).toISOString()}),await this.repository.transaction(async t=>{await t.documents.replacePath(e,o,{...r,storyPath:a,title:s.title?.trim()||r.title}),await t.stories.update(e,{updatedAt:(new Date).toISOString()}),await t.fileMutations.update(d,{phase:"database-committed",updatedAt:(new Date).toISOString()})}),u=!0,await this.repository.fileMutations.update(d,{phase:"cleanup",updatedAt:(new Date).toISOString()}),await this.repository.fileMutations.delete(d)}catch(e){throw u||(t.existsSync(c)&&!t.existsSync(i)&&t.renameSync(c,i),await this.repository.fileMutations.delete(d)),e}}const c=await this.get(e);return this.onChange?.("document.updated",c),c})}async reorderDocuments(e,t){const{storyPaths:n}=Ku.parse(t),i=(await this.repository.documents.list(e)).map(e=>e.storyPath);if(n.length!==i.length||new Set(n).size!==n.length||i.some(e=>!n.includes(e)))throw up("STORY_DOCUMENT_ORDER_INVALID","Document order must contain every indexed storyPath exactly once.",400);await this.repository.transaction(async t=>{await t.documents.reorder(e,n),await t.stories.update(e,{updatedAt:(new Date).toISOString()})});const s=await this.get(e);return this.onChange?.("document.reordered",s),s}async deleteDocument(e,i){return this.coordinator.run(e,async()=>{if((await this.require(e)).archivedAt)throw up("STORY_ARCHIVED","Archived Story content is read-only.",409);const s=_u.parse(i);if(!await this.repository.documents.get(e,s))return!1;const o=this.filePath(e,s),r=`${o}.${Ya("story_file_mutation")}.deleted`,a=Ya("story_file_mutation"),c=(new Date).toISOString();await this.repository.fileMutations.insert({id:a,storyId:e,operation:"delete",storyPath:s,backupName:r,phase:"prepared",createdAt:c,updatedAt:c});let d=!1;try{this.openAndClose(e,s),t.renameSync(o,r),this.fsyncDirectory(n.dirname(o)),await this.repository.fileMutations.update(a,{phase:"files-staged",updatedAt:(new Date).toISOString()}),await this.repository.transaction(async t=>{await t.documents.delete(e,s),await t.stories.update(e,{updatedAt:(new Date).toISOString()}),await t.fileMutations.update(a,{phase:"database-committed",updatedAt:(new Date).toISOString()})}),d=!0,t.rmSync(r,{force:!0}),await this.repository.fileMutations.update(a,{phase:"cleanup",updatedAt:(new Date).toISOString()}),await this.repository.fileMutations.delete(a)}catch(e){throw d||(t.existsSync(r)&&!t.existsSync(o)&&t.renameSync(r,o),await this.repository.fileMutations.delete(a)),e}const l=await this.get(e);return l&&this.onChange?.("document.deleted",l),!0})}stopAccepting(){this.coordinator.stopAccepting()}drain(){return this.coordinator.drain()}async project(e){const n=(await this.repository.actions.list(e.id)).map(({storyId:e,displayOrder:t,sessionPreset:n,...i})=>bu.parse({...i,sessionPreset:n||void 0})),i=await this.repository.documents.list(e.id),s=[];for(const n of i)try{const i=this.openRegularFileWithinRoot(e.id,n.storyPath);t.closeSync(i.fd),s.push({title:n.title,storyPath:n.storyPath,revision:i.revision})}catch(t){if("ENOENT"!==t.code)throw t;await this.removeMissingDocument(e.id,n.storyPath)}return Hu.parse({id:e.id,ownerNodeId:this.ownerNodeId,title:e.title,description:e.description||void 0,actions:n,documents:s,createdAt:e.createdAt,updatedAt:e.updatedAt,archivedAt:e.archivedAt||void 0})}storyRoot(e){return n.resolve(this.paths.storyContentDir,Hu.shape.id.parse(e))}filePath(e,t){const i=this.storyRoot(e),s=n.resolve(i,..._u.parse(t).split("/"));if(s===i||!s.startsWith(`${i}${n.sep}`))throw up("STORY_PATH_OUTSIDE_ROOT","Story path is outside the Story directory.",400);return s}ensureStoryParent(e,i){const s=this.filePath(e,i);try{const e=t.lstatSync(this.paths.storyContentDir);if(e.isSymbolicLink()||!e.isDirectory())throw up("STORY_PATH_UNSAFE","Story content root must be a real directory.",409)}catch(e){if("ENOENT"!==e.code)throw e;t.mkdirSync(this.paths.storyContentDir,{recursive:!0,mode:448})}t.chmodSync(this.paths.storyContentDir,448);let o=this.paths.storyContentDir;for(const e of n.relative(this.paths.storyContentDir,n.dirname(s)).split(n.sep).filter(Boolean)){o=n.join(o,e);try{const e=t.lstatSync(o);if(e.isSymbolicLink()||!e.isDirectory())throw up("STORY_PATH_UNSAFE","Story path parent must be a real directory.",409)}catch(e){if("ENOENT"!==e.code)throw e;t.mkdirSync(o,{mode:448})}t.chmodSync(o,448)}}openRegularFileWithinRoot(e,i){const s=this.filePath(e,i);this.assertExistingParentsSafe(this.storyRoot(e),n.dirname(s));const o="number"==typeof t.constants.O_NOFOLLOW?t.constants.O_NOFOLLOW:0;if(!o)throw up("STORY_NOFOLLOW_UNAVAILABLE","Safe no-follow file access is unavailable on this platform.",500);const r=t.openSync(s,t.constants.O_RDONLY|o);try{const e=t.fstatSync(r);if(!e.isFile())throw up("STORY_CONTENT_NOT_FILE","Story content must be a regular file.",409);if(e.size>this.maxFileBytes)throw up("STORY_FILE_TOO_LARGE","Story content exceeds the node limit.",413);const n=d.createHash("sha256"),i=Buffer.allocUnsafe(65536);let s=0;for(;s<e.size;){const o=t.readSync(r,i,0,Math.min(i.length,e.size-s),s);if(!o)break;n.update(i.subarray(0,o)),s+=o}return{fd:r,size:e.size,revision:n.digest("hex")}}catch(e){throw t.closeSync(r),e}}assertExistingParentsSafe(e,i){const s=n.relative(this.paths.storyContentDir,i);let o=this.paths.storyContentDir;for(const e of s.split(n.sep).filter(Boolean)){o=n.join(o,e);const i=t.lstatSync(o);if(i.isSymbolicLink()||!i.isDirectory())throw up("STORY_PATH_UNSAFE","Story path parent must be a real directory.",409)}if(!i.startsWith(e))throw up("STORY_PATH_OUTSIDE_ROOT","Story path is outside the Story directory.",400)}openAndClose(e,n){const i=this.openRegularFileWithinRoot(e,n);t.closeSync(i.fd)}fsyncFile(e){const n=t.openSync(e,"r");try{t.fsyncSync(n)}finally{t.closeSync(n)}}fsyncDirectory(e){if("win32"===process.platform)return;const n=t.openSync(e,"r");try{t.fsyncSync(n)}finally{t.closeSync(n)}}async removeMissingDocument(e,t){if(!await this.repository.documents.get(e,t))return;await this.repository.transaction(async n=>{await n.documents.delete(e,t),await n.stories.update(e,{updatedAt:(new Date).toISOString()})});const n=await this.get(e);n&&this.onChange?.("document.deleted",n)}async rollbackFileMutation(e,n,i,s,o){t.rmSync(i,{force:!0}),o&&t.existsSync(s)?(t.rmSync(n,{force:!0}),t.renameSync(s,n)):o||t.rmSync(n,{force:!0}),await this.repository.fileMutations.delete(e)}async recoverFileMutations(){for(const e of await this.repository.fileMutations.list())await this.coordinator.run(e.storyId,async()=>{const n=this.filePath(e.storyId,e.nextStoryPath||e.storyPath);if("database-committed"===e.phase||"cleanup"===e.phase)"write"===e.operation?(e.temporaryName&&t.rmSync(e.temporaryName,{force:!0}),e.backupName&&t.rmSync(e.backupName,{force:!0})):"delete"===e.operation&&e.backupName&&t.rmSync(e.backupName,{force:!0});else if("write"===e.operation){const i=Boolean(e.temporaryName&&t.existsSync(e.temporaryName)),s=Boolean(await this.repository.documents.get(e.storyId,e.storyPath));e.backupName&&t.existsSync(e.backupName)?(t.rmSync(n,{force:!0}),t.renameSync(e.backupName,n)):s||"files-staged"!==e.phase&&("prepared"!==e.phase||i)||t.rmSync(n,{force:!0}),e.temporaryName&&t.rmSync(e.temporaryName,{force:!0})}else"rename"===e.operation&&e.temporaryName&&t.existsSync(n)&&!t.existsSync(e.temporaryName)?t.renameSync(n,e.temporaryName):"delete"===e.operation&&e.backupName&&t.existsSync(e.backupName)&&!t.existsSync(n)&&t.renameSync(e.backupName,n);await this.repository.fileMutations.delete(e.id)})}}function up(e,t,n,i){return Object.assign(new Error(t),{code:e,statusCode:n,...void 0===i?{}:{details:i}})}const pp=a.z.object({storyId:a.z.string().trim().min(1).max(120),actionId:a.z.string().trim().min(1).max(120),targetInstanceId:a.z.string().trim().min(1).max(120),prompt:a.z.string().trim().min(1).max(32e3),sessionPreset:wu.optional(),cwd:a.z.string().trim().min(1).max(4096)}).strict(),mp=Nu,hp=Ou,gp=ku,fp=Pu.extend({executionKey:a.z.string().trim().min(1).max(160),requestFingerprint:a.z.string().regex(/^[a-f0-9]{64}$/),executionInput:pp}).strict(),yp=new Set(["completed","failed","skipped"]),Ip={queued:["dispatching","skipped"],dispatching:["running","failed"],running:["completed","failed"],completed:[],failed:[],skipped:[]};class Ap{repository;now;constructor(e,t=()=>new Date){this.repository=e,this.now=t}async init(){}async list(e){return(await this.repository.automations.list(e)).map(_p)}async stored(e){const t=await this.repository.automations.get(e);return t?function(e){return{..._p(e),scheduleAnchorAt:e.scheduleAnchorAt}}(t):void 0}async get(e){const t=await this.repository.automations.get(e);return t?_p(t):void 0}async create(e){const t=Cu.parse(e),n=this.now().toISOString();return _p(await this.repository.automations.insert({id:Ya("story_automation"),storyId:t.storyId,actionId:t.actionId,schedule:mp.parse(t.schedule),enabled:t.enabled,policy:hp.parse(t.policy),scheduleAnchorAt:n,createdAt:n,updatedAt:n}))}async update(e,t){const n=xu.parse(t),i=await this.repository.automations.get(e);if(!i)return;const s=this.now().toISOString(),o=void 0!==n.schedule||!0===n.enabled&&!i.enabled,r=await this.repository.automations.update(e,{...n,...o?{scheduleAnchorAt:s}:{},updatedAt:s});return r?_p(r):void 0}referencingActions(e,t){return this.repository.automations.referencingActions(e,[...t])}async hasActiveRuns(e){return(await this.repository.runs.list(e)).some(e=>!yp.has(e.status))}activeRunsForStory(e){return this.repository.runs.activeForStory(e).then(e=>e.map(Ep))}async delete(e){if(!await this.repository.automations.get(e))return!1;if(await this.hasActiveRuns(e))throw wp("STORY_AUTOMATION_RUN_ACTIVE","Automation has a non-terminal run.",409);return this.repository.automations.delete(e)}async deleteForStory(e){if((await this.activeRunsForStory(e)).length)throw wp("STORY_AUTOMATION_RUN_ACTIVE","Story has a non-terminal Automation run.",409);await this.repository.automations.deleteForStory(e)}async createRun(e){const t=pp.parse(e.executionInput);return this.repository.transaction(async n=>{const i=await n.runs.byExecutionKey(e.executionKey);if(i)return Ep(i);const s=await n.runs.insert({...e,executionInput:t,id:Ya("story_automation_run"),status:"queued",targetInstanceId:t.targetInstanceId,queuedAt:this.now().toISOString()});return await n.runs.trimTerminal(e.automationId,100),Ep(s)})}async transition(e,t,n={}){return this.repository.transaction(async i=>{const s=await i.runs.get(e);if(!s)throw wp("STORY_AUTOMATION_RUN_NOT_FOUND","Automation run was not found.",404);const o=Ep(s);if(o.status===t)return o;if(!Ip[o.status].includes(t))throw wp("STORY_AUTOMATION_RUN_TRANSITION_INVALID",`Cannot transition run from ${o.status} to ${t}.`,409);const r=this.now().toISOString(),a=await i.runs.update(e,{...n,status:t,..."dispatching"===t?{startedAt:r}:{},...yp.has(t)?{completedAt:r}:{}});return await i.runs.trimTerminal(o.automationId,100),Ep(a)})}async runsFor(e){return(await this.repository.runs.list(e)).map(Tp)}async run(e){const t=await this.repository.runs.get(e);return t?Tp(t):void 0}async runByExecutionKey(e){const t=await this.repository.runs.byExecutionKey(e);return t?Ep(t):void 0}async pendingRuns(){return(await this.repository.runs.pending()).map(Ep)}}function _p(e){return zu.parse({id:e.id,storyId:e.storyId,actionId:e.actionId,schedule:mp.parse(e.schedule),enabled:e.enabled,policy:hp.parse(e.policy),createdAt:e.createdAt,updatedAt:e.updatedAt})}function Ep(e){return fp.parse({...e,aiSessionId:e.aiSessionId||void 0,startedAt:e.startedAt||void 0,completedAt:e.completedAt||void 0,error:e.error?gp.parse(e.error):void 0,executionInput:pp.parse(e.executionInput)})}function Tp(e){const{executionKey:t,requestFingerprint:n,executionInput:i,...s}=Ep(e);return Pu.parse(s)}function wp(e,t,n){return Object.assign(new Error(t),{code:e,statusCode:n})}class bp{state;stories;automations;scheduler;repository;constructor(e,t,n,i,s){this.state=e,this.stories=t,this.automations=n,this.scheduler=i,this.repository=s}async init(){t.mkdirSync(this.state.paths.storyTrashDir,{recursive:!0,mode:448});for(const e of await this.repository.deletionIntents.list()){const i=await this.repository.stories.get(e.storyId),s=this.storyRoot(e.storyId),o=e.trashName?n.join(this.state.paths.storyTrashDir,e.trashName):void 0;i?o&&t.existsSync(o)&&!t.existsSync(s)&&t.renameSync(o,s):o&&t.rmSync(o,{recursive:!0,force:!0}),await this.repository.deletionIntents.delete(e.storyId)}}async update(e,t){const n=Vu.parse(t),i=await this.stories.update(e,n);return await this.scheduler.refresh(),i}async createAutomationWithAction(e,t){const n=Ru.parse(t),i=await this.stories.automationContext(e);if(!i)throw Sp("STORY_NOT_FOUND","Story was not found.",404);if(i.archivedAt)throw Sp("STORY_ARCHIVED","Archived Story cannot create an Automation.",409);if(i.actions.some(e=>e.id===n.action.id))throw Sp("STORY_ACTION_ID_CONFLICT","Story Action id already exists.",409);const s={storyId:e,actionId:n.action.id,...n.automation};await this.scheduler.validateCreate(s,{...i,actions:[...i.actions,n.action]});let o="";await this.repository.transaction(async t=>{await t.actions.replace(e,[...i.actions,n.action].map((t,n)=>({storyId:e,id:t.id,title:t.title,promptTemplate:t.promptTemplate,targetInstanceId:t.targetInstanceId,sessionPreset:t.sessionPreset,displayOrder:n}))),await t.stories.update(e,{updatedAt:(new Date).toISOString()}),o=(await this.automations.create(s)).id});const r=await this.stories.get(e);return r&&this.stories.notifyUpdated(r),this.scheduler.activateCreated(o)}async archive(e){const t=await this.stories.archive(e);return await this.scheduler.refresh(),t}async restore(e){const t=await this.stories.restore(e);return await this.scheduler.refresh(),t}async delete(e){return this.stories.coordinator.run(e,async()=>{const t=await this.stories.get(e);return!!t&&(await this.assertStoryCanBeDeleted(e),this.deleteCoordinated(t))})}async assertStoryCanBeDeleted(e){const t=this.state.listInstances().flatMap(t=>t.aiSessions.sessions.filter(t=>t.storyId===e).map(e=>({instanceId:t.id,aiSessionId:e.id})));if(t.length)throw Sp("STORY_IN_USE","Story is still referenced by an AI Session.",409,{sessions:t});const n=await this.automations.activeRunsForStory(e);if(n.length)throw Sp("STORY_AUTOMATION_RUN_ACTIVE","Story has a non-terminal Automation run.",409,{runIds:n.map(e=>e.id)})}async deleteCoordinated(e){const i=e.id;await this.scheduler.clearStory(i);const s=this.storyRoot(i),o=`${i}-${Date.now()}-${Math.random().toString(16).slice(2)}`,r=n.join(this.state.paths.storyTrashDir,o),a=(new Date).toISOString();await this.repository.deletionIntents.put({storyId:i,phase:"prepared",trashName:null,createdAt:a,updatedAt:a});try{let c=!1;return t.existsSync(s)&&(t.renameSync(s,r),this.fsyncDirectory(n.dirname(s)),this.fsyncDirectory(n.dirname(r)),c=!0),await this.repository.deletionIntents.put({storyId:i,phase:"files-staged",trashName:c?o:null,createdAt:a,updatedAt:(new Date).toISOString()}),await this.repository.transaction(async e=>{const t=await e.runs.activeForStory(i);if(t.length)throw Sp("STORY_AUTOMATION_RUN_ACTIVE","Story has a non-terminal Automation run.",409,{runIds:t.map(e=>e.id)});await e.automations.deleteForStory(i),await e.stories.delete(i),await e.deletionIntents.put({storyId:i,phase:"database-committed",trashName:c?o:null,createdAt:a,updatedAt:(new Date).toISOString()})}),c&&t.rmSync(r,{recursive:!0,force:!0}),await this.repository.deletionIntents.put({storyId:i,phase:"cleanup",trashName:c?o:null,createdAt:a,updatedAt:(new Date).toISOString()}),await this.repository.deletionIntents.delete(i),this.stories.notifyDeleted(e),!0}catch(e){throw await this.repository.stories.get(i)&&(t.existsSync(r)&&!t.existsSync(s)&&t.renameSync(r,s),await this.repository.deletionIntents.delete(i)),e}}storyRoot(e){return n.join(this.state.paths.storyContentDir,ue.parse(e))}fsyncDirectory(e){if("win32"===process.platform)return;const n=t.openSync(e,"r");try{t.fsyncSync(n)}finally{t.closeSync(n)}}}function Sp(e,t,n,i){return Object.assign(new Error(t),{code:e,statusCode:n,details:i})}class vp{timers=new Map;running=new Map;queued=new Map;lastStartedAt=new Map;accepting=!0;adapter;maxQueuedPerJob;now;constructor(e,t=100,n=Date.now){this.adapter=e,this.maxQueuedPerJob=t,this.now=n}start(){this.accepting=!0}setTimer(e,t){const n=this.timers.get(e);n&&clearTimeout(n),this.timers.set(e,t)}clearTimer(e){const t=this.timers.get(e);t&&clearTimeout(t),this.timers.delete(e)}clearQueued(e,t="job-disabled"){const n=this.queued.get(e);if(n){for(const e of n)this.adapter.skipped(e.event,t);this.queued.delete(e)}}submit(e,t,n){if(!this.accepting)return this.adapter.skipped(t,"scheduler-stopped"),"skipped";const i=this.now(),s=this.lastStartedAt.get(e);if(n.cooldownMs&&void 0!==s&&i-s<n.cooldownMs)return this.adapter.skipped(t,"cooldown"),"skipped";if((this.running.get(e)??0)>=n.maxConcurrentRuns){if("skip"===n.whenBusy)return this.adapter.skipped(t,"busy"),"skipped";const i=this.queued.get(e)??[];return i.length>=this.maxQueuedPerJob?(this.adapter.skipped(t,"queue-full"),"skipped"):(i.push({event:t,policy:n}),this.queued.set(e,i),"queued")}return this.begin(e,t,n),"started"}stop(){this.accepting=!1;for(const e of this.timers.values())clearTimeout(e);this.timers.clear();for(const e of this.queued.values())for(const t of e)this.adapter.skipped(t.event,"scheduler-stopped");this.queued.clear()}begin(e,t,n){this.running.set(e,(this.running.get(e)??0)+1),this.lastStartedAt.set(e,this.now());const i=()=>{const t=(this.running.get(e)??1)-1;t>0?this.running.set(e,t):this.running.delete(e),this.drain(e)};this.adapter.execute(t).then(i,i)}drain(e){if(!this.accepting)return;const t=this.queued.get(e);if(!t?.length)return;const n=t[0];(this.running.get(e)??0)>=n.policy.maxConcurrentRuns||(t.shift(),t.length||this.queued.delete(e),this.begin(e,n.event,n.policy))}}function Np(e,t){return new Date(Date.UTC(e,t+1,0)).getUTCDate()}function Op(e,t,n,i,s,o){return S.CronExpressionParser.parse(`0 ${i} ${n} ${e} ${t} *`,{currentDate:o,strict:!0,tz:s}).next().toDate()}function zp(e,t,n){return`sch_${d.createHash("sha256").update(`${e}\0${t}\0${n}`).digest("hex").slice(0,32)}`}a.z.object({agent:be,cwd:mt,cwdFolderId:a.z.string().trim().min(1).max(120).optional(),gitSelection:ft.optional(),message:a.z.string().trim().min(1).max(32e3),permissionMode:nt.optional(),clientRequestId:a.z.string().trim().min(1).max(160),modelSelection:ht.optional(),reasoningEffort:gt.optional(),storyId:ue}).strict();const Cp=a.z.object({disposition:a.z.enum(["created","already-created"]),aiSessionId:a.z.string().trim().min(1).max(120)}).strict();class Rp{runtime;nextRunAt=new Map;completion=new Map;registeredAutomationIds=new Set;backgroundMutations=new Set;state;stories;automations;fetchImpl;resolveInstanceWeb;publish;now;constructor(e,t,n,i,s,o,r=()=>new Date){this.state=e,this.stories=t,this.automations=n,this.fetchImpl=i,this.resolveInstanceWeb=s,this.publish=o,this.now=r,this.runtime=new vp({execute:({runId:e})=>this.executeRun(e),skipped:({runId:e},t)=>this.trackMutation(this.skipRun(e,t))})}async start(){this.runtime.stop(),this.runtime.start(),this.nextRunAt.clear(),this.registeredAutomationIds.clear();for(const e of await this.automations.list())await this.register(e);for(const e of await this.automations.pendingRuns())await this.resume(e);await this.reconcileInstances()}async stop(){this.runtime.stop(),this.nextRunAt.clear(),await Promise.allSettled([...this.backgroundMutations])}async refresh(){for(const e of this.registeredAutomationIds)this.runtime.clearTimer(e);this.registeredAutomationIds.clear(),this.nextRunAt.clear();for(const e of await this.automations.list())e.enabled&&!await this.blockedReason(e)||this.runtime.clearQueued(e.id),await this.register(e)}async clearStory(e){for(const t of await this.automations.list(e))this.runtime.clearTimer(t.id),this.runtime.clearQueued(t.id),this.registeredAutomationIds.delete(t.id),this.nextRunAt.delete(t.id)}async status(e){const t=await this.requireAutomation(e),n=await this.automations.runsFor(e),i=n.filter(e=>!kp(e.status)),s=await this.blockedReason(t),o=n.find(e=>kp(e.status)),r=t.enabled?s?"blocked":i.length?"running":"failed"===o?.status?"error":"scheduled":"disabled";return Mu.parse({automation:t,effectiveStatus:r,blockedReason:s,nextRunAt:this.nextRunAt.get(e),currentRuns:i.slice(0,20),lastRun:o})}async list(e){return Promise.all((await this.automations.list(e)).map(e=>this.status(e.id)))}async create(e){const t=await this.validateInput(e),n=await this.automations.create(t);return await this.register(n),await this.publishStatus(n.id,"created"),this.status(n.id)}async validateCreate(e,t){const n=Cu.parse(e);return await this.validateReferences({...n,id:"validation",createdAt:this.now().toISOString(),updatedAt:this.now().toISOString()},t),n}async activateCreated(e){const t=await this.requireAutomation(e);return await this.register(t),await this.publishStatus(e,"created"),this.status(e)}async update(e,t){const n={...await this.requireAutomation(e),...t};if(await this.validateReferences(n),await this.automations.update(e,t))return await this.refresh(),await this.publishStatus(e,"updated"),this.status(e)}setEnabled(e,t){return this.update(e,{enabled:t})}async delete(e){const t=await this.requireAutomation(e),n=await this.automations.delete(e);return n&&(this.runtime.clearTimer(e),this.nextRunAt.delete(e),this.publish?.($u,{storyId:t.storyId,automationId:e,change:"deleted"},{nodeId:this.state.node.id})),n}async manualRun(e,t){const n=await this.requireAutomation(e),i=this.now().toISOString(),s=zp(e,"manual",t.clientRequestId),o=await this.automations.runByExecutionKey(s);if(o)return this.automations.run(o.id);const r=await this.prepareRun(n,"manual",i,s);return this.runtime.submit(e,{runId:r.id},n.policy),this.automations.run(r.id)}async runs(e){return await this.requireAutomation(e),this.automations.runsFor(e)}async reconcileInstances(e){for(const t of(await this.automations.pendingRuns()).filter(e=>"running"===e.status&&e.aiSessionId)){if(e&&t.targetInstanceId!==e)continue;const n=this.state.listInstances().find(e=>e.id===t.targetInstanceId),i=n?.aiSessions.sessions.find(e=>e.id===t.aiSessionId);if(!i&&e!==t.targetInstanceId)continue;if(i&&"idle"!==i.status&&"failed"!==i.status)continue;const s="failed"===i?.status?"failed":"completed",o="failed"===s?{code:"AI_SESSION_FAILED",message:"The automated AI Session failed."}:void 0,r=await this.automations.transition(t.id,s,o?{error:o}:{});this.resolveCompletion(t.id),await this.publishRun(r),await this.publishStatus(t.automationId,"status")}}async register(e){if(!e.enabled||await this.blockedReason(e))return;const t=await this.automations.stored(e.id);if(!t)return;const n=function(e){const t=e.schedule;if("interval"===t.scheduleKind)return{type:"interval",intervalMs:t.intervalMs};if("daily"===t.scheduleKind)return{type:"daily",timeOfDay:t.timeOfDay,timezone:t.timezone};if("weekly"===t.scheduleKind)return{type:"weekly",weekdays:t.weekdays,timeOfDay:t.timeOfDay,timezone:t.timezone};if("monthly"===t.scheduleKind)return{type:"monthly",dayOfMonth:t.dayOfMonth,timeOfDay:t.timeOfDay,timezone:t.timezone};throw new Error(`Unsupported Story automation schedule kind: ${t.schedule.scheduleKind}`)}(e),i=function(e,t,n=t){if("interval"===e.type){const i=Math.max(0,t.getTime()-n.getTime()),s=Math.floor(i/e.intervalMs)+1;return new Date(n.getTime()+s*e.intervalMs)}const[i,s]=e.timeOfDay.split(":").map(Number);if("monthly"===e.type&&e.dayOfMonth<0)return function(e,t,n,i,s){const o=function(e,t){const n=new Intl.DateTimeFormat("en-US",{timeZone:t,year:"numeric",month:"2-digit",day:"2-digit"}).formatToParts(e),i=e=>Number(n.find(t=>t.type===e)?.value);return{year:i("year"),month:i("month")-1,day:i("day")}}(s,i),r=[];for(let a=0;a<12;a+=1){const c=new Date(Date.UTC(o.year,o.month+a,1)),d=c.getUTCFullYear(),l=c.getUTCMonth(),u=Np(d,l)+e+1;r.push(Op(u,l+1,t,n,i,s))}return r.sort((e,t)=>e.getTime()-t.getTime()),r[0]}(e.dayOfMonth,i,s,e.timezone,t);const o="weekly"===e.type?[...new Set(e.weekdays)].sort((e,t)=>e-t).join(","):"*",r="monthly"===e.type?String(e.dayOfMonth):"*";return S.CronExpressionParser.parse(`0 ${s} ${i} ${r} * ${o}`,{currentDate:t,strict:!0,tz:e.timezone}).next().toDate()}(n,this.now(),new Date(t.scheduleAnchorAt));this.nextRunAt.set(e.id,i.toISOString()),this.registeredAutomationIds.add(e.id);const s=setTimeout(()=>{this.trackMutation(this.handleTimer(e.id,i))},Math.max(1,i.getTime()-this.now().getTime()));s.unref?.(),this.runtime.setTimer(e.id,s)}async handleTimer(e,t){const n=await this.automations.get(e);if(!n?.enabled||await this.blockedReason(n))return;const i=t.toISOString();try{const e=await this.prepareRun(n,"schedule",i,zp(n.id,"schedule",i));this.runtime.submit(n.id,{runId:e.id},n.policy)}catch{await this.publishStatus(n.id,"status")}await this.register(n),await this.publishStatus(n.id,"status")}async prepareRun(e,t,n,i){const s=await this.executionInput(e),o=xp(s,i);return this.automations.createRun({automationId:e.id,eventType:t,scheduledFor:n,executionKey:i,requestFingerprint:(r=o,d.createHash("sha256").update(JSON.stringify(r)).digest("hex")),executionInput:s});var r}async resume(e){const t=await this.automations.get(e.automationId);t&&(e.status,this.runtime.submit(t.id,{runId:e.id},t.policy))}async executeRun(e){let t=(await this.automations.pendingRuns()).find(t=>t.id===e);if(t){if("queued"===t.status&&(t=await this.automations.transition(t.id,"dispatching")),"dispatching"===t.status)try{const e=this.state.requireInstance(t.targetInstanceId);if(!e.registrationToken)throw Lp("STORY_AUTOMATION_INSTANCE_CREDENTIAL_MISSING","Target instance has no registration credential.",503);const n=`${await this.resolveInstanceWeb(e)}/api/internal/node-agent/story-automation/ai-sessions`;let i;try{i=await this.fetchImpl(n,{method:"POST",headers:{"content-type":"application/json",authorization:`Bearer ${e.registrationToken}`},body:JSON.stringify(xp(t.executionInput,t.executionKey))})}catch{return void await this.publishStatus(t.automationId,"status")}const s=await i.json().catch(()=>({}));if(!i.ok)throw Lp(s.error?.code||"STORY_AUTOMATION_DISPATCH_FAILED",s.error?.message||`Target instance returned HTTP ${i.status}.`,i.status);const o=Cp.parse(s.data);t=await this.automations.transition(t.id,"running",{aiSessionId:o.aiSessionId}),await this.publishRun(t)}catch(e){const n=await this.automations.transition(t.id,"failed",{error:Dp(e)});return await this.publishRun(n),void await this.publishStatus(t.automationId,"status")}await this.completionFor(t.id).promise}}async skipRun(e,t){const n=await this.automations.run(e);if(!n||"queued"!==n.status)return;const i=await this.automations.transition(e,"skipped",{error:{code:`STORY_AUTOMATION_${t.replaceAll("-","_").toUpperCase()}`,message:Pp(t)}});await this.publishRun(i)}async executionInput(e,t){const n=t?.id===e.storyId?t:await this.stories.automationContext(e.storyId);if(!n)throw Lp("STORY_NOT_FOUND","Story was not found.",404);if(n.archivedAt)throw Lp("STORY_ARCHIVED","Archived Story cannot run Automation.",409);const i=n.actions.find(t=>t.id===e.actionId);if(!i)throw Lp("STORY_ACTION_NOT_FOUND","Story Action was not found.",404);if(!i.targetInstanceId)throw Lp("STORY_ACTION_TARGET_REQUIRED","Automated Story Action requires a target instance.",409);const s=this.state.requireInstance(i.targetInstanceId);return{storyId:n.id,actionId:i.id,targetInstanceId:s.id,prompt:i.promptTemplate,sessionPreset:i.sessionPreset,cwd:this.runtimeCwd(s,i.sessionPreset?.cwdFolderId)}}runtimeCwd(e,t){if(!t)return e.runtime.workspacePath||e.workspace.path||"/workspace";const i=this.state.localFolders.get(t);if(!i)throw Lp("NODE_LOCAL_FOLDER_NOT_FOUND","Story Action working folder was not found.",404);if("local"===this.state.requireRuntime(e.runtimeId).type)return n.resolve(i.path);if("local-folder"!==e.source.type)throw Lp("AI_SESSION_CWD_UNAVAILABLE","Working folder is unavailable for this instance source.",409);const s=n.relative(n.resolve(e.source.path),n.resolve(i.path));if(".."===s||s.startsWith(`..${n.sep}`)||n.isAbsolute(s))throw Lp("AI_SESSION_CWD_OUTSIDE_WORKSPACE","Working folder is outside the instance workspace.",409);const o=e.runtime.workspacePath||e.workspace.path||"/workspace";return s?n.posix.join(o,...s.split(n.sep)):o}async validateInput(e){const t=Cu.parse(e);return await this.validateReferences({...t,id:"validation",createdAt:this.now().toISOString(),updatedAt:this.now().toISOString()}),t}async validateReferences(e,t){await this.executionInput(e,t)}async blockedReason(e){try{return void await this.executionInput(e)}catch(e){const t=Dp(e);return["STORY_ARCHIVED","STORY_DELETING","STORY_NOT_FOUND","STORY_ACTION_NOT_FOUND","STORY_ACTION_TARGET_REQUIRED","NODE_INSTANCE_NOT_FOUND","STORY_NODE_MISMATCH"].includes(t.code)?t:void 0}}async requireAutomation(e){const t=await this.automations.get(e);if(!t)throw Lp("STORY_AUTOMATION_NOT_FOUND","Story Automation was not found.",404);return t}completionFor(e){const t=this.completion.get(e);if(t)return t;let n;const i={promise:new Promise(e=>{n=e}),resolve:n};return this.completion.set(e,i),i}resolveCompletion(e){this.completion.get(e)?.resolve(),this.completion.delete(e)}trackMutation(e){return this.backgroundMutations.add(e),e.finally(()=>this.backgroundMutations.delete(e)),e}async publishRun(e){const t=await this.automations.run(e.id),n=await this.automations.get(e.automationId);t&&n&&this.publish?.($u,{storyId:n.storyId,automationId:n.id,change:"run",run:t},{nodeId:this.state.node.id,instanceId:e.targetInstanceId})}async publishStatus(e,t){const n=await this.status(e);this.publish?.($u,{storyId:n.automation.storyId,automationId:e,change:t,status:n},{nodeId:this.state.node.id})}}function xp(e,t){const n=e.sessionPreset;return{agent:n?.agent||"codex",cwd:{type:"runtime-path",path:e.cwd},cwdFolderId:n?.cwdFolderId,gitSelection:n?.gitSelection,message:e.prompt,permissionMode:n?.permissionMode||"ask",clientRequestId:t,modelSelection:n?.modelSelection,reasoningEffort:n?.reasoningEffort,storyId:e.storyId}}function kp(e){return"completed"===e||"failed"===e||"skipped"===e}function Dp(e){const t=e&&"object"==typeof e?e:void 0;return{code:"string"==typeof t?.code?t.code:"STORY_AUTOMATION_FAILED",message:"string"==typeof t?.message?t.message:String(e)}}function Pp(e){return{cooldown:"Skipped by cooldown policy.",busy:"Skipped because the concurrency limit was reached.","queue-full":"Skipped because the queue is full.","scheduler-stopped":"Skipped because the scheduler stopped.","job-disabled":"Skipped because the Automation was disabled or blocked."}[e]}function Lp(e,t,n){return Object.assign(new Error(t),{code:e,statusCode:n})}class Mp{closed=new Set;pending=new Set;reconciliation;state;stories;fetchImpl;resolveInstanceWeb;warn;constructor(e,t,n,i,s){this.state=e,this.stories=t,this.fetchImpl=n,this.resolveInstanceWeb=i,this.warn=s}reconcile(){if(this.reconciliation)return this.reconciliation;const e=this.reconcileOnce().finally(()=>{this.reconciliation===e&&(this.reconciliation=void 0)});return this.reconciliation=e,e}async reconcileOnce(){const e=new Map,t=new Set,n=[];for(const n of this.state.listInstances()){if(!n.registrationToken)continue;let i;try{i=await this.fetchImpl(`${await this.resolveInstanceWeb(n)}/api/internal/node-agent/ai-sessions/idle-retention`,{headers:{authorization:`Bearer ${n.registrationToken}`}})}catch(e){this.warn({instanceId:n.id,error:e instanceof Error?e.message:String(e)},"could not inspect Story idle sessions");continue}if(!i.ok)continue;const s=await i.json().catch(()=>({}));if(Array.isArray(s.data))for(const i of s.data){if(!i||"object"!=typeof i)continue;const s=i;if("string"!=typeof s.sessionId||"string"!=typeof s.storyId||"idle"!==s.status)continue;if(void 0===Up(s))continue;if(!await this.stories.exists(s.storyId))continue;const o=`${n.id}:${s.sessionId}`;if(t.add(o),this.closed.has(o))continue;const r=e.get(s.storyId)||[];r.push({instance:n,sessionId:s.sessionId,storyId:s.storyId,status:"idle",completedAt:s.completedAt,updatedAt:s.updatedAt}),e.set(s.storyId,r)}}for(const[t,i]of e){const e=(await this.stories.retentionSettings(t)).maxIdleAiSessions;for(;i.length>e;){i.sort((e,t)=>Up(e)-Up(t)||`${e.instance.id}:${e.sessionId}`.localeCompare(`${t.instance.id}:${t.sessionId}`));const e=i.shift(),s=`${e.instance.id}:${e.sessionId}`;this.pending.has(s)||(this.pending.add(s),n.push(this.close(e,s).catch(n=>{this.warn({storyId:t,instanceId:e.instance.id,sessionId:e.sessionId,error:n instanceof Error?n.message:String(n)},"Story idle Session retention close failed"),setTimeout(()=>{this.reconcile()},5e3).unref?.()})))}}await Promise.all(n);for(const e of this.closed)t.has(e)||this.closed.delete(e)}async close(e,t){try{if(!await this.isUnchangedCandidate(e))return;const n=await this.fetchImpl(`${await this.resolveInstanceWeb(e.instance)}/api/internal/node-agent/ai-sessions/${encodeURIComponent(e.sessionId)}/close`,{method:"POST",headers:{"content-type":"application/json",authorization:`Bearer ${e.instance.registrationToken}`},body:JSON.stringify({clientRequestId:d.randomUUID()})});if(204===n.status)return;if(!n.ok)throw new Error(`HTTP ${n.status}`);this.closed.add(t)}finally{this.pending.delete(t)}}async isUnchangedCandidate(e){const t=await this.fetchImpl(`${await this.resolveInstanceWeb(e.instance)}/api/internal/node-agent/ai-sessions/idle-retention`,{headers:{authorization:`Bearer ${e.instance.registrationToken}`}});if(!t.ok)throw new Error(`HTTP ${t.status}`);const n=await t.json().catch(()=>({}));if(!Array.isArray(n.data))return!1;const i=n.data.find(t=>{if(!t||"object"!=typeof t)return!1;const n=t;return n.sessionId===e.sessionId&&n.storyId===e.storyId&&"idle"===n.status});return void 0!==i&&Up(i)===Up(e)}}class jp{closed=new Set;pending=new Set;reconciliation;state;fetchImpl;resolveInstanceWeb;warn;constructor(e,t,n,i){this.state=e,this.fetchImpl=t,this.resolveInstanceWeb=n,this.warn=i}reconcile(){if(this.reconciliation)return this.reconciliation;const e=this.reconcileOnce().finally(()=>{this.reconciliation===e&&(this.reconciliation=void 0)});return this.reconciliation=e,e}async reconcileOnce(){const e=new Map,t=new Set,n=[];for(const n of this.state.listInstances()){if(!n.registrationToken)continue;let i;try{i=await this.fetchImpl(`${await this.resolveInstanceWeb(n)}/api/internal/node-agent/ai-sessions/instance-idle-retention`,{headers:{authorization:`Bearer ${n.registrationToken}`}})}catch(e){this.warn({instanceId:n.id,error:e instanceof Error?e.message:String(e)},"could not inspect instance idle sessions");continue}if(!i.ok)continue;const s=await i.json().catch(()=>({}));if(Array.isArray(s.data))for(const i of s.data){if(!i||"object"!=typeof i)continue;const s=i;if("string"!=typeof s.sessionId||"idle"!==s.status)continue;if(void 0===Up(s))continue;const o=`${n.id}:${s.sessionId}`;if(t.add(o),this.closed.has(o))continue;const r=e.get(n.id)||[];r.push({instance:n,sessionId:s.sessionId,status:"idle",completedAt:s.completedAt,updatedAt:s.updatedAt}),e.set(n.id,r)}}for(const[t,i]of e)for(;i.length>100;){i.sort((e,t)=>Up(e)-Up(t)||`${e.instance.id}:${e.sessionId}`.localeCompare(`${t.instance.id}:${t.sessionId}`));const e=i.shift(),s=`${e.instance.id}:${e.sessionId}`;this.pending.has(s)||(this.pending.add(s),n.push(this.close(e,s).catch(n=>{this.warn({instanceId:t,sessionId:e.sessionId,error:n instanceof Error?n.message:String(n)},"Instance idle Session retention close failed"),setTimeout(()=>{this.reconcile()},5e3).unref?.()})))}await Promise.all(n);for(const e of this.closed)t.has(e)||this.closed.delete(e)}async close(e,t){try{const n=await this.fetchImpl(`${await this.resolveInstanceWeb(e.instance)}/api/internal/node-agent/ai-sessions/${encodeURIComponent(e.sessionId)}/close`,{method:"POST",headers:{"content-type":"application/json",authorization:`Bearer ${e.instance.registrationToken}`},body:JSON.stringify({clientRequestId:d.randomUUID()})});if(204===n.status)return;if(!n.ok)throw new Error(`HTTP ${n.status}`);this.closed.add(t)}finally{this.pending.delete(t)}}}function Up(e){return Fp(e.completedAt)??Fp(e.updatedAt)}function Fp(e){const t=e?Date.parse(e):Number.NEGATIVE_INFINITY;return Number.isFinite(t)?t:void 0}const $p=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(),Hp=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:pi.optional(),labels:a.z.record(a.z.string(),a.z.string()).default({})}).strict(),qp=a.z.object({name:a.z.string().trim().max(160)}).strict(),Vp=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(),Bp=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:pi.optional(),environmentSource:mi.optional(),projectId:a.z.string().trim().min(1).max(120).optional(),image:Ms.optional(),source:as,sourceSnapshot:a.z.record(a.z.string(),a.z.unknown()).default({}),config:a.z.object({autoImportAgentConfigs:a.z.boolean().optional(),codexConfigEnabled:a.z.boolean().optional(),codexHomeMode:a.z.enum(["default","taskhandoff"]).optional(),defaultCodexPermissionMode:nt.optional(),codexSettings:Hn.optional(),aiSessionHistoryLimit:a.z.number().int().min(1).max(500).optional(),aiSessionAttachmentRetentionDays:a.z.number().int().min(0).max(365).optional(),aiSessionMaxFileAttachmentBytes:a.z.number().int().positive().max(ge).optional()}).strict().optional(),modelSelection:po.shape.modelSelection,gitWorkspaceProvisioning:od.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."})}),Kp=a.z.object({name:a.z.string().trim().min(1).max(160).optional(),config:a.z.object({autoImportAgentConfigs:a.z.boolean().optional(),codexConfigEnabled:a.z.boolean().optional(),codexHomeMode:a.z.enum(["default","taskhandoff"]).optional(),defaultCodexPermissionMode:nt.optional(),codexSettings:Hn.optional(),aiSessionHistoryLimit:a.z.number().int().min(1).max(500).optional(),aiSessionAttachmentRetentionDays:a.z.number().int().min(0).max(365).optional(),aiSessionMaxFileAttachmentBytes:a.z.number().int().positive().max(ge).optional()}).strict().optional(),modelSelection:po.shape.modelSelection.optional()}).strict(),Gp=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(),Wp=Gp.omit({id:!0}).partial().strict();function Xp(e){const t=e.authorization;return"string"==typeof t&&t.startsWith("Bearer ")?t.slice(7).trim():void 0}class Yp{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 Jp=a.z.object({gitWorkspaceProvisioning:od.optional()}).strict().default({});class Qp{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=ae();return this.state.controlledInstances.put(po.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 o=this.provisionGeneration(e,n,t).finally(()=>{this.inFlight.get(i)===o&&this.inFlight.delete(i)});return this.inFlight.set(i,o),o}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,o=0,r=!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||(r=!0,o=n.sequence,this.publishTerminalOutput(e,t,n))},this.abortController.signal);if(await a,s)throw s.error;if(this.stopped)return;r&&this.publishFinished(e,t,o+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(po.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:ae()},updatedAt:ae()}));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;r&&this.publishFinished(e,t,o+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(po.parse({...n,status:"failed",health:"failed",imageProvisioning:{...n.imageProvisioning,phase:"failed",error:i,updatedAt:ae()},updatedAt:ae()})),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(po.parse({...s,status:"starting"===s.status?"starting":"provisioning",imageProvisioning:{...s.imageProvisioning,phase:n,error:void 0,updatedAt:ae()},updatedAt:ae()})),this.options.sync())};await(this.options.runInstanceOperation?.(e,s)??s())}eventBase(e,t){return{instanceId:e.id,generation:t,requestedReference:e.imageProvisioning.requestedReference,observedAt:ae()}}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(Us,{...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(Fs,{...this.eventBase(e,t),sequence:1e3*n,outcome:i},e.id)}}const Zp=a.z.object({name:a.z.string().trim().min(1).max(160)}).strict();function em(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 tm{templateOperations=new Yp;store;docker;requireInstanceValue;requireRuntimeValue;runInstanceOperationValue;privateSecretValues;isImageReferencedValue;constructor(e,t,n,i,s,o,r=()=>!1){this.store=e,this.docker=t,this.requireInstanceValue=n,this.requireRuntimeValue=i,this.runInstanceOperationValue=s,this.privateSecretValues=o,this.isImageReferencedValue=r}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=Zp.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 o=ae(),r=Ya("envtpl"),a=`task-handoff/environment-template:${r.toLowerCase().replace(/[^a-z0-9_.-]/g,"-")}`;return this.store.put(zi.parse({id:r,name:n.name,sourceInstanceId:i.id,nodeId:i.nodeId,internalTag:a,status:"creating",createdAt:o,updatedAt:o})),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.privateSecretValues(n);await this.docker.inspectContainerConfigSecurity(n.runtime.containerName,s),e=await this.docker.commitEnvironmentTemplate(n.runtime.containerName,n.runtime.containerId,a),t=!0;const o=await this.docker.inspectEnvironmentTemplateImage(a);return await this.docker.inspectImageConfigSecurity(a,s),this.store.put(zi.parse({...this.require(r),...o,status:"ready",error:void 0,updatedAt:ae()}))}catch(n){return t&&(await this.docker.untagEnvironmentTemplate(a,e).catch(()=>!1),e&&await this.docker.garbageCollectEnvironmentTemplateImage(e).catch(()=>!1)),this.store.put(zi.parse({...this.require(r),status:"failed",error:em(n,"ENVIRONMENT_TEMPLATE_CREATE_FAILED","commit"),updatedAt:ae()}))}})}async delete(e){return this.runTemplateOperation(e,async()=>{const t=this.require(e);this.store.put(zi.parse({...t,status:"deleting",error:void 0,updatedAt:ae()}));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(zi.parse({...t,status:"failed",error:em(e,"ENVIRONMENT_TEMPLATE_DELETE_FAILED","delete"),updatedAt:ae()})),e}})}async releaseUnusedImage(e){return!this.store.list().some(t=>t.imageId===e)&&!this.isImageReferencedValue(e)&&this.docker.garbageCollectEnvironmentTemplateImage(e)}}const nm=new Set(["content-encoding","content-length","transfer-encoding"]),im=67108864;function sm(e){return Object.fromEntries([...e.entries()].filter(([e])=>!nm.has(e.toLowerCase())))}function om(e){return e.bodyBase64?Buffer.from(e.bodyBase64,"base64"):e.body}function rm(){const e=Number(process.env.TASK_HANDOFF_INSTANCE_PROXY_MAX_RESPONSE_BYTES);return Number.isSafeInteger(e)&&e>0?e:67108864}const am="x-task-handoff-trace-id";function cm(e){return e.startsWith("/")?e:`/${e}`}function dm(e,t){return e.code(502).send({error:{code:"INSTANCE_PROXY_RESPONSE_TOO_LARGE",message:`Instance response exceeds ${t} bytes.`}})}async function lm(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 um(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 pm(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 um(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 um(e,"endpoint must be an origin-only http://127.0.0.1:<port> URL");return i.origin}const mm=a.z.object({version:a.z.literal(1),externalListener:to}).strict();function hm(e){return"all-ipv4"===e?"0.0.0.0":"127.0.0.1"}function gm(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 fm(e){const t=hm(e.bindScope);return!await new Promise(t=>{const n=h.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=h.createServer();i.once("error",()=>n(!1)),i.listen({host:t,port:e.port,exclusive:!0},()=>i.close(()=>n(!0)))})}class ym{app;state;settings;sockets=new Set;config;source;status="error";error;onActiveListener;validateUpdate;synchronizeUpdate;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.validateUpdate=e.validateUpdate,this.synchronizeUpdate=e.synchronizeUpdate,this.app.server.on("connection",e=>{this.sockets.add(e),e.once("close",()=>this.sockets.delete(e))})}current(){return no.parse({...this.config,host:hm(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:hm(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 ${hm(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=io.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&&!this.synchronizeUpdate)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});await(this.validateUpdate?.(t))}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 ${hm(t.bindScope)}:${t.port}: ${e instanceof Error?e.message:String(e)}`),{statusCode:409,code:"NODE_AGENT_LISTENER_BIND_FAILED"})}this.state.setListenerPort(t.port);try{await(this.synchronizeUpdate?.(t))}catch(e){throw await this.stop(),await this.restore(n),await Promise.resolve(this.synchronizeUpdate?.(n.config)).catch(e=>{this.app.log.error({error:e instanceof Error?e.message:String(e)},"node agent listener instance endpoint rollback failed")}),Object.assign(new Error(`Failed to switch controlled instances to node agent port ${t.port}: ${e instanceof Error?e.message:String(e)}`),{statusCode:409,code:"NODE_AGENT_LISTENER_INSTANCE_SYNC_FAILED"})}try{this.settings.put({version:1,externalListener:t})}catch(e){throw await this.stop(),await this.restore(n),await Promise.resolve(this.synchronizeUpdate?.(n.config)).catch(e=>{this.app.log.error({error:e instanceof Error?e.message:String(e)},"node agent listener persistence rollback failed")}),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;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:hm(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 Im="TASK_HANDOFF_NODE_AGENT_V1",Am="/api/node-tunnel";function _m(e=""){return d.createHash("sha256").update(e).digest("hex")}function Em(e,t){return d.createHmac("sha256",e).update(function(e){return[Im,e.keyId,e.method.toUpperCase(),e.pathWithQuery,e.timestamp,e.nonce,e.bodySha256].join("\n")}(t)).digest("hex")}function Tm(e){const t=e.timestamp||(new Date).toISOString(),n=e.nonce||d.randomBytes(18).toString("base64url"),i=_m(e.body||""),s=Em(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 wm{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 o=Date.parse(t.timestamp);if(!Number.isFinite(o)||Math.abs(this.nowMs()-o)>6e4)throw Object.assign(new Error("Node agent HMAC timestamp is outside the allowed window."),{statusCode:401,code:"NODE_AGENT_HMAC_TIMESTAMP_INVALID"});if(!t.nonce)throw Object.assign(new Error("Node agent HMAC nonce is missing."),{statusCode:401,code:"NODE_AGENT_HMAC_NONCE_MISSING"});this.pruneNonces();const r=`${t.nodeId}:${t.keyId}:${t.nonce}`;if(this.usedNonces.has(r))throw Object.assign(new Error("Node agent HMAC nonce was already used."),{statusCode:401,code:"NODE_AGENT_HMAC_NONCE_REPLAY"});const a=_m(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,Em(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(r,o+6e4+1),t.keyId}pruneNonces(){const e=this.nowMs();for(const[t,n]of this.usedNonces)n<=e&&this.usedNonces.delete(t)}}function bm(e,t){console.warn(JSON.stringify({message:e,...t}))}class Sm{repository;logger;constructor(e,t,n={}){const i=t&&"readIdentity"in t?t:void 0,s=i?n:t||n;this.repository=i||hd(gl(e)).access,this.logger=s.logger||bm}read(){const e=this.repository.readIdentity();return e?Hd(e,this.logger):void 0}init(){}write(e){const t=Hd({...e,updatedAt:ae()},this.logger);return this.repository.writeIdentity(t)}}class vm{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 Nm{store;repository;pairingInvites=new vm;controlPlaneConnectionOperations=new Map;constructor(e,t){this.repository=t||hd(gl(e)).access,this.store=new Sm(e,this.repository),this.store.init(),this.recoverControlPlaneConnectionOperations()}async runControlPlaneConnectionOperation(e,t){const n=e.replace(/\/$/,""),i=this.controlPlaneConnectionOperations.get(n)||Promise.resolve();let s;const o=new Promise(e=>{s=e});this.controlPlaneConnectionOperations.set(n,o),await i;try{return await t()}finally{s(),this.controlPlaneConnectionOperations.get(n)===o&&this.controlPlaneConnectionOperations.delete(n)}}resolveNodeId(e){if(e?.trim())return this.writeNodeId(e.trim()),e.trim();const t=this.store.read();if(t?.nodeId)return t.nodeId;const n=Ya("node");return this.writeNodeId(n),n}createPairingInvite(e){const t=ae(),n=new Date(Date.now()+(e.expiresInMs||6e5)).toISOString(),i=Ja(),s={tokenHash:_m(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=_m(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=ae(),o={id:e.controlPlaneId||Ya("cp"),keyId:Ya("key"),...e.controlPlaneName||i.controlPlaneName?{name:e.controlPlaneName||i.controlPlaneName}:{},secret:Ja(),pairedAt:s,updatedAt:s};return this.store.write({...t,controlPlanePairings:[...(t.controlPlanePairings||[]).filter(e=>e.id!==o.id),o]}),o}stageControlPlaneConnection(e){const{pairing:t,connection:n}=this.createControlPlaneConnection(e),i=this.store.read()||this.newIdentity(),s=n.url.replace(/\/$/,""),o=(i.controlPlaneConnections||[]).filter(e=>e.id===n.id||e.url.replace(/\/$/,"")===s),r={operationId:Ya("connection_operation"),pairing:t,connection:n,replacedConnections:o},a=ae();return this.repository.transaction(()=>{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]}),this.repository.putOperation({id:r.operationId,kind:"create-connection",phase:"prepared",requested:r,pairingKeyId:t.keyId,connectionId:n.id,replacedConnections:o,createdAt:a,updatedAt:a})}),r}markControlPlaneConnectionRemoteAccepted(e){const t=this.repository.listOperations().find(t=>t.id===e.operationId);if(!t)throw Object.assign(new Error("Control-plane connection operation was not found."),{code:"NODE_AGENT_CONNECTION_OPERATION_NOT_FOUND",statusCode:409});this.repository.putOperation({...t,phase:"remote-accepted",updatedAt:ae()})}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}:{}},o=new Set((n.controlPlaneConnections||[]).map(e=>e.pairingKeyId)),r=new Set(e.replacedConnections.map(e=>e.pairingKeyId));return this.repository.transaction(()=>{this.store.write({...n,controlPlanePairings:[...(n.controlPlanePairings||[]).filter(e=>e.keyId!==i.keyId&&(!r.has(e.keyId)||o.has(e.keyId))),i],controlPlaneConnections:[...(n.controlPlaneConnections||[]).filter(e=>e.id!==s.id),s]});const t=this.repository.listOperations().find(t=>t.id===e.operationId);t&&this.repository.putOperation({...t,phase:"committed",updatedAt:ae()}),this.repository.deleteOperation(e.operationId)}),{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.repository.transaction(()=>{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]}),this.repository.deleteOperation(e.operationId)})}recoverControlPlaneConnectionOperations(){for(const e of this.repository.listOperations(["prepared","remote-accepted"])){const t=e.requested;t?.pairing?.keyId&&t?.connection?.id?"remote-accepted"===e.phase?(this.repository.putOperation({...e,phase:"committed",updatedAt:ae()}),this.repository.deleteOperation(e.id)):this.rollbackControlPlaneConnection(t):this.repository.putOperation({...e,phase:"failed",error:{code:"NODE_AGENT_CONNECTION_OPERATION_INVALID"},updatedAt:ae()})}}createControlPlaneConnection(e){const t=ae(),n={id:Ya("cp"),keyId:Ya("key"),...e.name?{name:e.name}:{},secret:Ja(),pairedAt:t,updatedAt:t};return{pairing:n,connection:{id:Ya("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=ae();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),o=n&&s.find(e=>e.keyId===n.pairingKeyId);if(o)return{keyId:o.keyId,secret:o.secret}}const o=[...s].sort((e,t)=>t.updatedAt.localeCompare(e.updatedAt))[0];return o?{keyId:o.keyId,secret:o.secret}:void 0}newIdentity(){return{nodeId:this.resolveNodeId(),createdAt:ae(),updatedAt:ae(),controlPlanePairings:[],controlPlaneConnections:[]}}writeNodeId(e){const t=this.store.read();this.store.write({...t||{createdAt:ae()},nodeId:e,updatedAt:ae(),controlPlanePairings:t?.controlPlanePairings||[],controlPlaneConnections:t?.controlPlaneConnections||[]})}}const Om=a.z.string().trim().min(1).max(160);const zm=es.strict();function Cm(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 Rm{preflights=new Map;options;applying=!1;constructor(e){this.options=e}async check(e){const t=Ji.parse(e),n=Cm(this.options.listInstances()),i=await vl(this.options.runCommand,this.options.moduleDir),s=this.options.currentRuntimeVersion(),o=this.options.managedUpdateSupport?.(i)||{supported:!0};if(!o.supported)return Qi.parse({source:"npm",channel:t.channel,currentVersion:i.currentVersion||s,availableVersion:i.currentVersion||s||"unavailable",impact:n,updateAvailable:!1,supported:!1,reason:o.reason||"Managed updates are unavailable on this node.",checkedAt:(new Date).toISOString()});const r="@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(bl(),["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 o=JSON.parse(s.stdout);if("string"!=typeof o)throw new Error(`npm did not resolve ${t}@${i} to one version.`);return o}(e.runCommand,t,e.channel);if(!n)return function(e){return Qi.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:ae()})}({channel:e.channel,currentVersion:e.currentVersion,impact:e.impact});const i=wl(e.currentVersion,n)||(e.relatedCurrentVersions||[]).some(e=>wl(e,n)),s=i?await async function(e,t,n){const i=await e(bl(),["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 Qi.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:ae()})}({channel:t.channel,currentVersion:i.currentVersion||s,runCommand:this.options.runCommand,packageName:i.packageName,relatedCurrentVersions:r,impact:n});if(!a.updateAvailable)return a;const c={...a,runtimeArtifacts:await this.options.resolveRuntimeArtifacts(a.availableVersion),preflightToken:Ja()};return this.preflights.set(c.preflightToken,{result:c,expiresAt:Date.now()+6e5}),c}async apply(e){const i=zm.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 o=this.options.jobs.create(this.options.nodeId,e),{worker:r,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")],o=s.find(i),r=n.resolve(e,"..","..","..","..","scripts","node-update-worker.cts");return o?{worker:o,packaged:!0,expectedWorker:s[0]}:i(r)?{worker:r,packaged:!1,expectedWorker:s[0]}:{worker:void 0,packaged:!1,expectedWorker:s[0]}}(this.options.moduleDir);if(!r)throw this.options.jobs.patch(o.id,{status:"failed",rollout:{...o.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-${o.id}`,"--collect","--property=Type=exec",...a?[r]:[process.execPath,r],"--job-file",this.options.jobs.records.filePath(o.id),"--target-version",o.toVersion,"--npm-command",bl(),"--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(o.id,{status:"failed",rollout:{...o.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(o)}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 vl(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(Cm(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 xm=new Set(["provisioning","starting","registering","registered","running"]);function km(e){return xm.has(e.status)&&!ja(e)}function Dm(e){return po.parse({...e,health:"unknown",connectionStatus:"offline",agentStatus:"offline",targetStatus:"unknown",uiAccessStatus:"unknown",target:{...e.target,status:"unknown"},updatedAt:ae()})}class Pm{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)&&!ja(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),o=this.options.crashStableWindowMs??3e4,r=s&&i-s.lastExitAt<o?s.attempt+1:1;this.unexpectedExitRetries.set(e,{attempt:r,lastExitAt:i});const a=this.options.retryBaseDelayMs??1e3,c=1===r?0:Math.min(this.options.retryMaxDelayMs??3e4,a*2**Math.min(r-2,10)),d=t instanceof Error?t.message:String(t);this.restoreErrors.set(e,{message:d,attempt:r,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(xm.has(t.status)||"failed"===t.status)&&(!e||e.nextAttemptAt<=(this.options.nowMs?.()??Date.now()))}return"docker"===n.type&&km(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),o=(s?.attempt??0)+1,r=this.options.retryBaseDelayMs??1e3,a=Math.min(this.options.retryMaxDelayMs??3e4,r*2**Math.min(o-1,10)),c=(this.options.nowMs?.()??Date.now())+a;this.restoreErrors.set(n.id,{message:i,attempt:o,nextAttemptAt:c}),s?.message===i&&s.attempt===o||this.options.warn({instanceId:n.id,action:"restore",runtimeId:n.runtimeId,error:i,attempt:o,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(xm.has(e.status)||"failed"===e.status)&&(!t||t.nextAttemptAt<=(this.options.nowMs?.()??Date.now()))}return"docker"===t.type&&km(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)&&!ja(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(Dm(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:xm.has(s.status)||"failed"===s.status?Math.min(e,i.nextAttemptAt):e},Number.POSITIVE_INFINITY),i=Math.min(this.options.intervalMs??1e4,Math.max(0,n-e));this.timer=setTimeout(()=>{this.timer=void 0,this.runAndContinue()},i),this.timer.unref?.()}requestCycle(e=0){if(this.started&&!this.stopped){if(this.activeCycle)return this.cycleRequested=!0,void(this.cycleRequestDelayMs=void 0===this.cycleRequestDelayMs?e:Math.min(this.cycleRequestDelayMs,e));this.timer&&clearTimeout(this.timer),this.timer=setTimeout(()=>{this.timer=void 0,this.runAndContinue()},e),this.timer.unref?.()}}}const Lm=new Set(["DELETE","GET","HEAD","PATCH","POST","PUT","OPTIONS"]);function Mm(e){return"string"==typeof e&&Lm.has(e.toUpperCase())?e.toUpperCase():"GET"}function jm(e,t){const n=new URL(t.tunnelUrl);n.searchParams.set("nodeId",t.nodeId);const i=t.secret?Tm({nodeId:t.nodeId,keyId:t.keyId,secret:t.secret,method:"GET",pathWithQuery:`${n.pathname}${n.search}`}):{},s=new m(n,{headers:i}),o=new Map,r=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 o=e.startsWith("/")?e:`/${e}`;return{...s,...t.secret&&t.keyId?Tm({nodeId:t.nodeId,keyId:t.keyId,secret:t.secret,method:n,pathWithQuery:`/api/node-agent${o}`,body:i}):t.token?{authorization:`Bearer ${t.token}`}:{}}},u=e=>t.secret?Tm({nodeId:t.nodeId,keyId:t.keyId,secret:t.secret,method:"GET",pathWithQuery:`${e.pathname}${e.search}`}):{},p=(e,t,n)=>{const i=o.get(e);o.delete(e),i?.upstream&&L(i.upstream,t,n),i?.tunnel&&L(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 o.keys())p(e,1001,"Reverse tunnel disconnected.");for(const[e,t]of r)r.delete(e),t.controller.abort(),L(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:"",o="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=Mm(a.method);let p;try{p=ni(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 m(y,{headers:u(y)});return r.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}`)})(o),{method:d,headers:l(o,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{r.delete(i)}}),I.on("close",()=>{f.abort(),r.delete(i)}),void I.on("error",()=>f.abort())}if("control-plane.http.cancel"===g.type){const e="string"==typeof g.streamId?g.streamId:"",t=r.get(e);if(!t)return;return r.delete(e),t.controller.abort(),void L(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 r=l(t,"GET",void 0),a=i?.length?new m(d(t),i,{headers:r}):new m(d(t),{headers:r}),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)});o.set(e,{upstream:a,tunnel:p,close:(e=1e3,t="")=>{L(a,e,t),L(p,e,t)}}),a.on("open",()=>{s.send(JSON.stringify({type:"node-agent.websocket.open",streamId:e,protocol:a.protocol}))}),j(p,a,{pendingFrameLimit:256,upstreamOpenTimeoutMs:1e4,onClientClose:()=>{o.delete(e)},onClientError:t=>{o.delete(e),s.send(JSON.stringify({type:"node-agent.websocket.error",streamId:e,message:t instanceof Error?t.message:String(t)}))},onUpstreamClose:(t,n)=>{o.delete(e);const i=P(t),r=D(n);s.send(JSON.stringify({type:"node-agent.websocket.close",streamId:e,...void 0===i?{}:{code:i},...r?{reason:r}:{}}))},onUpstreamError:t=>{o.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 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:{},o="string"==typeof g.route&&g.route.startsWith("/")?g.route:"/health",r=i.headers&&"object"==typeof i.headers?i.headers:{},c=Mm(i.method);let d;try{d=ni(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${o}`,headers:l(o,c,d,r),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,g.aiSessionHierarchy)})(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 Um(e,t){return Number.isFinite(e)&&Number(e)>0?Number(e):t}function Fm(e){if(!e.length)return;const t=[...e].sort((e,t)=>e-t);return t[Math.ceil(.95*t.length)-1]}function $m(e){return e.unref?.(),e}class Hm{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=Um(e.connectTimeoutMs,1e4),this.handshakeTimeoutMs=Um(e.handshakeTimeoutMs,1e4),this.heartbeatIntervalMs=Um(e.heartbeatIntervalMs,25e3),this.heartbeatTimeoutMs=Um(e.heartbeatTimeoutMs,15e3),this.heartbeatMissThreshold=Math.max(1,Math.floor(Um(e.heartbeatMissThreshold,2))),this.stableThresholdMs=Um(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=$m(this.setTimeoutFn(()=>this.timeout("connect"),this.connectTimeoutMs))}opened(){this.stopped||(this.clearTimer("connectTimer"),this.setPhase("handshaking"),this.handshakeTimer=$m(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=$m(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:Fm(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=$m(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 qm(e){const t=new URL(Am,e);return t.protocol="https:"===t.protocol?"wss:":"ws:",t.toString()}const Vm=new Set(["linux","darwin","win32","freebsd","openbsd","aix","sunos"]);function Bm(e){return Vm.has(e)?e:"unknown"}function Km(e){return!0===e.managedArtifacts}class Gm{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)}resolveNodeAgentUrl(e){return this.executor.resolveNodeAgentUrl(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;return!!n&&function(e,t){return e.packageName===t.packageName&&e.version===t.version&&e.platform===t.platform&&e.arch===t.arch&&e.formatVersion===t.formatVersion&&e.launcherAbi===t.launcherAbi&&e.entrypoint===t.entrypoint&&e.sha256===t.sha256}(await this.executor.inspectRuntimeVersion(n),t)}start(e){return this.executor.start(e)}stop(e){return this.executor.stop(e)}restart(e){return this.executor.restart(e,e.instance.runtime.containerId)}delete(e,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:Bm(this.platform),...t?{serverVersion:t}:{}}}}}catch(t){return{status:"offline",capabilities:{...e.capabilities,daemon:{status:"offline",hostPlatform:Bm(this.platform),error:t instanceof Error?t.message:String(t)}}}}}}class Wm{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(Km)}async stopAll(){await(this.local.stopAll?.())}}const Xm="task-handoff.local-process-nonce",Ym=1e3,Jm=1e4,Qm=2e3;function Zm(e,t){try{e?.(t)}catch{}}function eh(e){return e.runtime.port?`http://127.0.0.1:${e.runtime.port}`:void 0}async function th(e,t){try{const n=await fetch(`${e}/api/internal/node-agent/process-identity`,{headers:{authorization:`Bearer ${t}`},signal:AbortSignal.timeout(Ym)});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 nh(e,t){if($.processStartIdentity(e)!==t)return!1;try{process.kill(e,"SIGTERM")}catch{return!0}const n=Date.now()+Jm;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()+Qm;for(;Date.now()<i;){try{process.kill(e,0)}catch{return!0}await new Promise(e=>setTimeout(e,50))}return!1}function ih(e,t){return Object.assign(new Error(t),{statusCode:503,code:"LOCAL_INSTANCE_STOP_UNCONFIRMED",instanceId:e.id})}async function sh(e){return!await function(e){return new Promise(t=>{const n=h.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=h.createServer();n.once("error",()=>t(!1)),n.listen({host:"127.0.0.1",port:e,exclusive:!0},()=>n.close(()=>t(!0)))})}const oh=sh;function rh(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 ah(e,t=1e4,n=2e3,i){if(await rh(e,t))return;Zm(i,{stage:"graceful-timeout",pid:e.pid,timeoutMs:t});let s=!1;if(null===e.exitCode&&null===e.signalCode&&(e.kill("SIGKILL"),s=!0,Zm(i,{stage:"force-signal-sent",pid:e.pid,signal:"SIGKILL"})),!await rh(e,n))throw Zm(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&&Zm(i,{stage:"force-exit-confirmed",pid:e.pid,signal:"SIGKILL"})}class ch{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},o=e=>{try{this.onUnexpectedExitError?.(e,s)}catch{}};try{Promise.resolve(this.onUnexpectedExit?.(s)).catch(o)}catch(e){o(e)}}}),t.unref()}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"),Zm(n,{stage:"graceful-signal-sent",pid:t.pid,signal:"SIGTERM"})),this.children.delete(e.id),void await ah(t,Jm,Qm,n)}const i=await async function(e){const t=eh(e),n=e.runtime.labels?.[Xm];if(!t||!n||!e.registrationToken)return;const i=await th(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(Ym)})).ok?i:void 0}catch{return}}(e);if(i){const t=eh(e),n=Date.now()+Jm;for(;t&&Date.now()<n;){if(!await th(t,e.registrationToken))return;await new Promise(e=>setTimeout(e,50))}const s=t?await th(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 nh(s.pid,s.startIdentity))return;throw ih(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 G(e)}(this.lockPath),o=await async function(e){const t=eh(e);if(t)try{const[n,i]=await Promise.all([fetch(`${t}/api/instance/status`,{signal:AbortSignal.timeout(Ym)}),fetch(`${t}/api/diagnostics`,{signal:AbortSignal.timeout(Ym)})]);if(!n.ok||!i.ok)return;const s=await n.json(),o=await i.json(),r=o.data?.runtime?.pid;if(s.data?.id!==e.id||"controlled"!==s.data.controlMode||"number"!=typeof r||!Number.isInteger(r)||r<=0)return;const a=$.processStartIdentity(r);return a?{pid:r,startIdentity:a}:void 0}catch{return}}(e);if(o){if(await nh(o.pid,o.startIdentity))return;throw ih(e,`Legacy controlled instance ${e.id} did not exit after termination.`)}if(s?.instanceId===e.id&&Y(s))throw ih(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 o=Date.now()+s;for(;Date.now()<o;){if(null!==n.exitCode||null!==n.signalCode)return!1;const s=await th(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"),Zm(e,{stage:"graceful-signal-sent",pid:t.pid,signal:"SIGTERM"}))}this.children.clear(),await Promise.all(e.map(e=>ah(e,Jm,Qm,this.lifecycleReporters.get(e))))}}async function dh(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 lh{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,o,r){this.runCommand=e,this.paths=t,this.nodeAgentUrl=n,this.commandOverride=i,this.lockPath=s,this.processSupervisor=new ch(s,o,r)}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,o=!!s&&await sh(s),r="allocate"===process.env.TASK_HANDOFF_LOCAL_INSTANCE_PORT_CONFLICT;if(s&&!o&&!r)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&&o?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 oh(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"),m=(e.instance.config?.codexConfigEnabled??1)&&"taskhandoff"===(e.instance.config?.codexHomeMode??"taskhandoff")?n.join(u,"configs","codex"):void 0;t.mkdirSync(p,{recursive:!0,mode:448}),m&&t.mkdirSync(m,{recursive:!0,mode:448}),t.chmodSync(u,448),t.chmodSync(p,448),m&&t.chmodSync(m,448);const[h,...g]=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),f=[...g,"--host","127.0.0.1","--port",String(a)],y=d.randomUUID(),I=n.join(p,"controlled-instance.out.log"),A=n.join(p,"controlled-instance.err.log");Ea(I),Ea(A);const _=t.mkdtempSync(function(e,t=process.platform,i=c.tmpdir()){const s="darwin"===t?"/private/tmp":i,o=d.createHash("sha256").update(e).digest("hex").slice(0,12);return n.join(s,`th-git-${o}-`)}(e.instance.id));t.chmodSync(_,448);const E=t.openSync(I,"a",384),T=t.openSync(A,"a",384),w=l.spawn(h,f,{cwd:i,detached:!1,stdio:["ignore",E,T],env:{...process.env,TASK_HANDOFF_CONTROL_MODE:"controlled",TASK_HANDOFF_RUNTIME_KIND:"local",TASK_HANDOFF_CONTROLLED_INSTANCE_VERSION:Ml(),...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:y,TASK_HANDOFF_WORKSPACE:i,TASK_HANDOFF_WORKSPACE_MODE:"local-bind",TASK_HANDOFF_DATA_DIR:u,TASK_HANDOFF_INSTANCE_PRIVATE_CONFIG_PATH:e.privateConfigPath||"",TASK_HANDOFF_LOG_DIR:p,TASK_HANDOFF_APP_SESSION_PERSIST:"1",TASK_HANDOFF_CODEX_APP_SERVER:process.env.TASK_HANDOFF_CODEX_APP_SERVER||"1",TASK_HANDOFF_WEB_PORT:String(a),TASK_HANDOFF_WEB_HOST:"127.0.0.1",TASK_HANDOFF_GIT_CREDENTIAL_SOCKET:n.join(_,"broker.sock"),...e.modelEnv||{},CODEX_HOME:m}});t.closeSync(E),t.closeSync(T);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(_,{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=${h} cwd=${i} error=${s}\n`)}catch{}throw Object.assign(new Error(`Controlled instance process could not start with command ${h} in ${i}: ${s}`),{statusCode:500,code:"LOCAL_INSTANCE_PROCESS_SPAWN_FAILED"})}const b=n.join(p,"controlled-instance.lifecycle.log");this.processSupervisor.track(e.instance.id,w,e=>{t.appendFileSync(b,`[${(new Date).toISOString()}] shutdown stage=${e.stage} pid=${e.pid??""} signal=${e.signal??""} timeoutMs=${e.timeoutMs??""}\n`)}),w.on("error",e=>{try{t.appendFileSync(b,`[${(new Date).toISOString()}] process error pid=${w.pid??""} error=${e.message}\n`)}catch{}}),w.once("exit",(e,n)=>{t.rmSync(_,{recursive:!0,force:!0});try{t.appendFileSync(b,`[${(new Date).toISOString()}] exited pid=${w.pid??""} code=${e??""} signal=${n??""}\n`)}catch{}});const S=`http://127.0.0.1:${a}`,v=w.pid?$.processStartIdentity(w.pid):void 0;if(!(w.pid&&e.instance.registrationToken&&await this.processSupervisor.waitUntilHealthy(S,{instanceId:e.instance.id,pid:w.pid,processNonce:y,startIdentity:v},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 ah(w),Object.assign(new Error(`Controlled instance process did not become ready for instance ${e.instance.id} on ${S}.`),{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:S,api:`${S}/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",[Xm]:y}}}}async stop(e){return await this.processSupervisor.stop(e.instance),{status:"stopped",health:"unknown",connectionStatus:"offline",agentStatus:"offline",targetStatus:"unknown",uiAccessStatus:"unknown",target:{...e.instance.target,status:"unknown"},runtime:e.instance.runtime}}async restart(e){return this.start(e)}async delete(e,t){return await this.stop(e),Ti.parse({instanceId:e.instance.id,containerDeleted:!0,completed:!0,deletedVolumes:[],retainedVolumes:[],volumeResults:[]})}async check(e){const[t,n]=await Promise.all([dh(this.runCommand,"codex"),dh(this.runCommand,"claude")]);return{status:"online",capabilities:Xl({...e.capabilities,apps:{terminal:!0,codex:t,claude:n}})}}async stopAll(){await this.processSupervisor.stopAll()}}const uh=["codex","claude"],ph=5e3,mh=$.processStartIdentity(process.pid),hh=new WeakSet;function gh(e){const t=process.env[e]?.trim();return t||void 0}function fh(e){const t=e.authorization;return"string"==typeof t&&t.startsWith("Bearer ")?t.slice(7).trim():void 0}function yh(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 Ih(e){return!e.ip&&!e.socket.remoteAddress&&!e.socket.remoteFamily}function Ah(e){const t=e.split("?")[0];return/^\/api\/node-agent\/instances\/[^/]+\/(register|heartbeat)$/.test(t)||/^\/api\/node-agent\/instances\/[^/]+\/git-credentials\//.test(t)||/^\/api\/node-agent\/instances\/[^/]+\/ai-sessions\/[^/]+\/story-content(?:\/|$)/.test(t)}async function _h(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 Eh(e,t,n,i){const s=new AbortController,o=setTimeout(()=>s.abort(),i);try{return await e(t,{...n,signal:s.signal})}finally{clearTimeout(o)}}async function Th(e,t,n,i=async e=>pm(e)){if(!t.registrationToken)return"unavailable";const s=Wn.parse({nodeAgentUrl:n}),o=await Eh(e,`${await i(t)}/api/internal/node-agent-connection`,{method:"PUT",headers:{"content-type":"application/json",authorization:`Bearer ${t.registrationToken}`},body:JSON.stringify(s)},5e3);if(404===o.status)return"unsupported";if(!o.ok)throw Object.assign(new Error(`Controlled instance rejected the node-agent connection update (HTTP ${o.status}).`),{code:"NODE_AGENT_CONNECTION_UPDATE_FAILED",statusCode:o.status});return"applied"}async function wh(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 o=await s(t),r=Number(process.env.TASK_HANDOFF_CONFIG_AUTO_IMPORT_TIMEOUT_MS||ph);for(const s of uh)try{const a=await Eh(e,`${o}/api/config-sync/import/${encodeURIComponent(s)}`,{method:"POST"},Number.isFinite(r)&&r>0?r:ph);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 bh(e,t,n,i,s=async e=>pm(e)){const o=t.requireInstance(n),r=t.resolvedAssignedModelEnvironment(n),a=t.modelRegistry.privateCatalog(n);if(t.instancePrivateConfigs.materialize(o.id,o.registrationToken,r,a,o.config.codexSettings),"reachable"!==o.targetStatus)return!1;let c;try{c=await Eh(e,`${await s(o)}/api/internal/model-environment`,{method:"PUT",headers:{"content-type":"application/json",authorization:`Bearer ${o.registrationToken}`},body:JSON.stringify(r)},ph)}catch(e){return i?.({instanceId:n,targetWeb:o.target.web,error:e instanceof Error?e.message:String(e)},"node instance model environment live sync deferred"),!1}if(!c.ok)return i?.({instanceId:n,targetWeb:o.target.web,statusCode:c.status},"node instance model environment live sync deferred"),!1;if(!Xn(o.capabilities).features.privateModelCatalog)return!0;try{const t=await Eh(e,`${await s(o)}/api/internal/model-catalog`,{method:"PUT",headers:{"content-type":"application/json",authorization:`Bearer ${o.registrationToken}`},body:JSON.stringify(a)},ph);t.ok||404===t.status||i?.({instanceId:n,statusCode:t.status},"node instance model catalog live sync deferred")}catch(e){i?.({instanceId:n,error:e instanceof Error?e.message:String(e)},"node instance model catalog live sync deferred")}return!0}async function Sh(e,t,n,i,s,o,r="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:r,runtimeId:c.runtimeId,imageId:c.imageSelection?.imageId,imagePhase:c.imageProvisioning.phase},"node instance start queued until image provisioning completes"),e.controlledInstances.put(po.parse({...c,status:"starting",updatedAt:ae()}));s.diagnostic({instanceId:i,action:"start",reason:r,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=po.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:ae()}),m=u.target?.web?await _h(n,p,o):"unknown";if("docker"===e.requireRuntime(d.runtimeId).type&&"reachable"===m){const t=await(l.resolveNodeAgentUrl?.(e.context(p)))||e.containerUrl;Th(n,p,t,o).then(e=>{s.diagnostic({instanceId:i,action:"node-agent-connection.sync",reason:r,syncStatus:e,nodeAgentUrl:t},"node instance connection endpoint synchronized")}).catch(e=>{s.warn({instanceId:i,action:"node-agent-connection.sync",reason:r,error:e instanceof Error?e.message:String(e)},"node instance connection endpoint sync deferred")})}const h=e.applyInstanceLifecycle(i,{type:"runtime-lifecycle-completed",baseline:d,observation:{...u,target:u.target?{...u.target,status:m}:void 0,workspace:u.workspace?{error:void 0,...u.workspace}:void 0,targetStatus:m,uiAccessStatus:m}});return s.diagnostic({instanceId:i,action:"start",reason:r,status:h.status,connectionStatus:h.connectionStatus,targetStatus:h.targetStatus,targetWeb:h.target.web,containerName:h.runtime.containerName},"node instance start completed"),h}async function vh(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=Aa(e.dataDir),h=await async function(e){return gl(e)}(u);try{const y=hd(h),I=e.remoteSecret||process.env.TASK_HANDOFF_NODE_AGENT_REMOTE_SECRET,A=e.remoteKeyId||process.env.TASK_HANDOFF_NODE_AGENT_REMOTE_KEY_ID,_=new Nm(u,y.access),E=_.resolveNodeId(e.nodeId||process.env.TASK_HANDOFF_NODE_ID),T=e.connectionMode||("local-ipc"===process.env.TASK_HANDOFF_NODE_AGENT_CONNECTION_MODE?"local-ipc":"local-loopback"),w=e.ipcPath||process.env.TASK_HANDOFF_NODE_AGENT_IPC_PATH||wa(u.dataDir),b="local-ipc"===T?`ipc://${encodeURIComponent(w)}`:d,S=e.platform||process.platform,v=e.arch||process.arch,N=new Jl(u,E,d,l,c,S,y);N.node.connectionMode=T,N.node.controlEndpoint=b,N.node.endpoint=b,N.init();const z=new lp(u,E,y);await z.init();const C=new Ap(y);await C.init();const R=e.dockerCommandRunner||zo,k=new Ro(R,e.dockerTerminalCommandRunner),D=function(e,i=Do()){const s=t.readdirSync(i,{withFileTypes:!0}),o=new Map(s.flatMap(e=>{if(!e.isFile())return[];const s=n.join(i,e.name);return[[e.name,{source:s,mode:511&t.statSync(s).mode}]]})),r=[...ko].filter(e=>!o.has(e));if(r.length)throw new Error(`Node agent bootstrap assets are incomplete: missing ${r.sort().join(", ")} in ${i}.`);t.mkdirSync(e,{recursive:!0,mode:493}),t.chmodSync(e,493);for(const[i,s]of o){const o=n.join(e,i);p.sync(o,t.readFileSync(s.source),{mode:s.mode}),t.chmodSync(o,s.mode)}for(const i of t.readdirSync(e,{withFileTypes:!0}))o.has(i.name)||t.rmSync(n.join(e,i.name),{recursive:!0,force:!0});return n.resolve(e)}(u.dockerBootstrapDir),P=new Vo(R,{publishHost:"127.0.0.1",imageService:k,launcherAssetsDir:D,nodeAgentContainerIpcPath:e.containerIpcPath});let L;const M=new Wm(new Gm(P,R,S,v),new lh(e.dockerCommandRunner||zo,u,()=>N.localNodeAgentUrl,function(){const e=process.env.TASK_HANDOFF_LOCAL_CONTROLLED_COMMAND_ARGV?.trim();if(!e){const e=process.env.TASK_HANDOFF_LOCAL_CONTROLLED_COMMAND?.trim();return e?e.split(/\s+/):void 0}let t;try{t=JSON.parse(e)}catch{throw Object.assign(new Error("TASK_HANDOFF_LOCAL_CONTROLLED_COMMAND_ARGV must be valid JSON."),{code:"LOCAL_CONTROLLED_COMMAND_INVALID"})}if(!Array.isArray(t)||!t.length||t.some(e=>"string"!=typeof e||!e))throw Object.assign(new Error("TASK_HANDOFF_LOCAL_CONTROLLED_COMMAND_ARGV must be a non-empty string array."),{code:"LOCAL_CONTROLLED_COMMAND_INVALID"});return t}(),e.localControlledInstanceLockPath||process.env.TASK_HANDOFF_LOCAL_CONTROLLED_INSTANCE_LOCK_PATH,e=>L.handleUnexpectedLocalExit(e.instanceId,new Error(`Local controlled instance exited unexpectedly (pid=${e.pid??"unknown"}, code=${e.code??"none"}, signal=${e.signal??"none"}).`)),(e,t)=>se.log.error({error:e,instanceId:t.instanceId,pid:t.pid},"local controlled instance exit recovery failed"))),U=async e=>pm(e,await M.forRuntime(N.requireRuntime(e.runtimeId)).resolveInstanceWeb(N.context(e))),F=e.updateCommandRunner||e.dockerCommandRunner||zo,$=e.fetchImpl||fetch,H=new Mp(N,z,$,U,(e,t)=>se.log.warn(e,t)),q=new jp(N,$,U,(e,t)=>se.log.warn(e,t)),V=new Map,B=new Map,K=e=>{if("endpoint-unreachable"!==e.targetStatus||"online"!==e.connectionStatus||"online"!==e.agentStatus||!e.target.web||B.has(e.id))return;const t=e.processIncarnationId,n=(async()=>{if("reachable"!==await _h($,e,U))return;const n=N.requireInstance(e.id);n.processIncarnationId===t&&"online"===n.connectionStatus&&"online"===n.agentStatus&&(N.controlledInstances.put(po.parse({...n,target:{...n.target,status:"reachable"},targetStatus:"reachable",uiAccessStatus:"reachable",updatedAt:ae()})),he.syncNow())})().catch(t=>{se.log.debug({instanceId:e.id,error:t},"node instance endpoint reconciliation probe failed")}).finally(()=>{B.delete(e.id)});B.set(e.id,n)},G=async e=>{const t=N.requireInstance(e);if(!Xn(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(V.get(e)===s)return!0;let o;try{o=await Eh($,`${await U(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}:{}})},ph)}catch(t){return Te.warn({instanceId:e,error:t instanceof Error?t.message:String(t)},"node instance AI session persistence settings live sync deferred"),!1}return o.ok?(V.set(e,s),!0):(Te.warn({instanceId:e,statusCode:o.status},"node instance AI session persistence settings live sync deferred"),!1)},W=async e=>{const t=N.requireInstance(e);if(N.instancePrivateConfigs.materialize(t.id,t.registrationToken,N.resolvedAssignedModelEnvironment(e),N.modelRegistry.privateCatalog(e),t.config.codexSettings),!t.config.codexSettings)return!0;if(!Xn(t.capabilities).features.codexManagedSettings||"reachable"!==t.targetStatus||!t.registrationToken)return!1;try{const n=await Eh($,`${await U(t)}/api/internal/codex-settings`,{method:"PUT",headers:{"content-type":"application/json",authorization:`Bearer ${t.registrationToken}`},body:JSON.stringify(t.config.codexSettings||{})},ph);return!!n.ok||(Te.warn({instanceId:e,statusCode:n.status},"node instance Codex settings live sync deferred"),!1)}catch(t){return Te.warn({instanceId:e,error:t instanceof Error?t.message:String(t)},"node instance Codex settings live sync deferred"),!1}},X=new ka({cacheDir:n.join(u.dataDir,"runtime-artifacts"),fetchImpl:$}),Y=e.resolveRuntimeArtifactRelease||((e,t,n)=>Da(e,t,n,$)),J=async(t,n,i)=>{const s=await n.artifactTarget(i);if(e.resolveRuntimeArtifact)return e.resolveRuntimeArtifact(t,s.platform,s.arch);const o=await Y(t,s.platform,s.arch);if(o.identity.launcherAbi>s.launcherAbi)throw Object.assign(new Error(`Runtime requires launcher ABI ${o.identity.launcherAbi}, but ${s.platform}-${s.arch} provides ABI ${s.launcherAbi}.`),{code:"INSTANCE_BASE_RUNTIME_INCOMPATIBLE",retryable:!1});return X.resolve(o.identity,o.source)},Q=e=>M.forRuntime(N.requireRuntime(e.runtimeId)),Z=async e=>"docker"!==N.requireRuntime(e.runtimeId).type?N.localNodeAgentUrl:await(Q(e).resolveNodeAgentUrl?.(N.context(e)))||N.containerUrl,ee=e=>{const t=Q(e);return Km(t)?t:void 0},te=e=>{const t=ee(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})},ne=e=>Boolean(ee(e)),ie=(e,t)=>{const n=N.context(e);return J(t,te(e),n)},se=o({logger:e.logger??!0}),oe=new Ta(u,{logger:(e,t)=>se.log.warn(t,e)}),re=()=>N.listInstances().map(e=>e.id),ce=()=>{try{oe.run(re())}catch(e){se.log.warn({error:e},"node-agent persistence maintenance failed")}},de=()=>{try{oe.capNodeAgentLogs(),oe.capActiveInstanceLogs(re())}catch(e){se.log.warn({error:e},"node-agent open log maintenance failed")}};ce();const le=setInterval(()=>{ce()},216e5);le.unref();const pe=setInterval(()=>{de()},6e4);pe.unref();const me={requests:0,active:0,completed:0,aborted:0,limitRejected:0,responseBytes:0,totalDurationMs:0,maxResponseBytes:rm()};se.decorate("nodeAgentState",N),se.decorate("nodeAgentIdentityService",_),se.decorate("nodeAgentResolveInstanceNodeAgentUrl",Z),await se.register(r,{options:x});const he=new Gr(N,i,{logger:se.log,safetyIntervalMs:Number(process.env.TASK_HANDOFF_EVENT_CONNECTION_SAFETY_INTERVAL_MS)||void 0}),ge=new Pa(N.controlledInstances,Ml,{isInstalled:async(e,t)=>{const n=await ie(e,t);return await te(e).inspectRuntime(N.context(e),n.identity)},beginDrain:async e=>{try{const t=await async function(e,t,n=async e=>pm(e)){const i=await n(t);if(t.registrationToken&&(await Eh(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 Eh(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 o=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]:[]}),r=await Promise.all(o.map(async t=>{try{const n=await Eh(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:o.length,failures:r.filter(e=>Boolean(e))}}($,e,U);return t.failures.length?se.log.warn({instanceId:e.id,requested:t.requested,failures:t.failures},"runtime convergence could not stop every app session"):se.log.info({instanceId:e.id,requested:t.requested},"runtime convergence requested app session drain"),!0}catch(t){return se.log.warn({instanceId:e.id,error:t instanceof Error?t.message:String(t)},"runtime convergence could not request app session drain"),!1}},endDrain:async e=>{try{await async function(e,t,n=async e=>pm(e)){return!!t.registrationToken&&(await Eh(e,`${await n(t)}/api/internal/node-agent/resume`,{method:"POST",headers:{authorization:`Bearer ${t.registrationToken}`}},5e3)).ok}($,e,U)&&se.log.info({instanceId:e.id},"runtime convergence released app session drain")}catch(t){se.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=te(e);await n.installRuntime(N.context(e),await ie(e,t))},restart:async e=>{const t=Q(e),n=N.applyInstanceLifecycle(e.id,{type:"convergence-restart-requested"}),i=await t.restart(N.context(n)),s=po.parse({...n,...i,target:i.target?{...n.target,...i.target}:n.target,runtime:i.runtime?{...n.runtime,...i.runtime}:n.runtime,updatedAt:ae()}),o=await _h($,s,U);N.applyInstanceLifecycle(e.id,{type:"runtime-lifecycle-completed",baseline:n,observation:{...i,target:i.target?{...i.target,status:o}:void 0,targetStatus:o,uiAccessStatus:o}})},onForcedDrain:e=>se.log.warn({instanceId:e.id},"runtime convergence drain deadline reached; restarting instance")},{drainTimeoutMs:Number(process.env.TASK_HANDOFF_RUNTIME_DRAIN_TIMEOUT_MS)||void 0,verificationTimeoutMs:Number(process.env.TASK_HANDOFF_RUNTIME_VERIFY_TIMEOUT_MS)||void 0,maxAttempts:Number(process.env.TASK_HANDOFF_RUNTIME_MAX_ATTEMPTS)||void 0});N.controlledInstances.setOnStored(e=>{he.publishInstanceLifecycle(e)}),he.start(),se.decorate("nodeAgentEventForwarder",he);const fe=new Rp(N,z,C,$,U,(e,t,n)=>he.publish(e,t,n)),ye=new bp(N,z,C,fe,y);await ye.init(),await fe.start(),z.setOnChange((e,t)=>{he.publish("story.changed",{storyId:t.id,nodeId:t.ownerNodeId,change:e},{nodeId:t.ownerNodeId}),H.reconcile()});const Ie=new na(R,()=>N.listInstances().filter(e=>"docker"===N.requireRuntime(e.runtimeId).type),e=>he.publish("instance.metrics.snapshot",e,{instanceId:e.instanceId}));Ie.start(),se.decorate("nodeAgentRuntimeMetrics",Ie);const Ae=(f=process.env.TASK_HANDOFF_DIAGNOSTIC_LOGS,["1","true","yes","on"].includes(String(f||"").trim().toLowerCase())),_e=new wm(_,E,I,A),Ee=(e,t)=>{Ae&&se.log.info(e,t)},Te={diagnostic:Ee,warn:(e,t)=>se.log.warn(e,t)},we=new Yp,be=new tm(N.environmentTemplates,P,e=>N.requireInstance(e),e=>N.requireRuntime(e),(e,t)=>we.run(e,t),e=>[e.registrationToken,...N.modelRegistry.privateSecretValues(e.id)].filter(e=>Boolean(e)),e=>N.listInstances().some(t=>t.environmentTemplateOrigin?.imageId===e)),Se=(e,t,n)=>{const i=n&&"object"==typeof n&&!Array.isArray(n)?n.protocolVersion:void 0;if("string"!=typeof i||i===Pn)return n;const s=({field:n,action:s})=>se.log.warn({instanceId:e,report:t,protocolVersion:i,expectedProtocolVersion:Pn,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"}),{..._o(n,i),imageSelection:bi(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 _o(e,n)}(n,s)},ve=async(e,t,n=()=>!0,i)=>{try{if(!n())return N.requireInstance(e);let s=N.requireInstance(e);"failed"===s.runtimeVersion?.phase&&ne(s)&&(s=N.controlledInstances.put(po.parse({...s,ready:!1,runtimeVersion:Ul(La(s)),updatedAt:ae()})));const o=N.requireRuntime(s.runtimeId);await Sh(N,M,$,e,Te,U,t,i);const r=N.requireInstance(e);if("docker"===o.type&&r.imageProvisioning&&"ready"!==r.imageProvisioning.phase)return he.syncNow(),r;if(!n())return N.requireInstance(e);L.markRestored(e);let a=N.requireInstance(e);if(ne(a)){try{a=await ge.schedule(e,{startRequested:!0})}catch(n){a=N.requireInstance(e),Te.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&&Te.warn({instanceId:e,action:"runtime.converge",reason:t,error:a.runtimeVersion.error},"node instance started with pending runtime convergence")}if("docker"===o.type&&"reachable"===a.targetStatus){const n=await(M.forRuntime(o).resolveNodeAgentUrl?.(N.context(a)))||N.containerUrl;Th($,a,n,U).then(i=>{Te.diagnostic({instanceId:e,action:"node-agent-connection.sync",reason:t,syncStatus:i,nodeAgentUrl:n},"node instance connection endpoint synchronized after runtime convergence")}).catch(n=>{Te.warn({instanceId:e,action:"node-agent-connection.sync",reason:t,error:n instanceof Error?n.message:String(n)},"node instance connection endpoint sync after runtime convergence deferred")})}return n()?(await wh($,a,"start",Te,U),he.syncNow(),a):N.requireInstance(e)}catch(n){throw N.applyInstanceLifecycle(e,{type:"start-failed",error:n}),he.syncNow(),Te.warn({instanceId:e,action:"start",reason:t,error:n instanceof Error?n.message:String(n)},"node instance start failed"),n}},Ne=new Qp(N,k,{sync:()=>he.syncNow(),diagnostic:Te.diagnostic,warn:Te.warn,publish:(e,t,n)=>he.publish(e,t,{instanceId:n}),runInstanceOperation:(e,t)=>we.run(e,t)}),Oe=e=>{const t=we.intent(e.id);Ne.provision(e,async()=>{await ve(e.id,"image-ready",()=>we.isIntentCurrent(e.id,t),we.signal(e.id,t)).catch(()=>{})})};L=new Pm({state:N,runtimeAdapters:M,convergence:ge,restoreInstance:e=>Sh(N,M,$,e,Te,U,"restore"),autoImport:e=>wh($,e,"start",Te,U),provisionImage:Oe,stopImageProvisioning:()=>Ne.stop(),usesManagedArtifact:ne,warn:Te.warn,error:(e,t)=>se.log.error(e,t),runInstanceOperation:(e,t)=>we.run(e,t)});const ze=async e=>{const t=new Map;for(const e of M.managedAdapters()){const n=await e.artifactTarget();t.set(`${n.platform}-${n.arch}`,{adapter:e})}for(const e of N.listInstances()){const n=ee(e);if(!n)continue;const i=N.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})=>J(e,t,n)))).sort((e,t)=>`${e.identity.platform}/${e.identity.arch}`.localeCompare(`${t.identity.platform}/${t.identity.arch}`))},Ce=new Rm({nodeId:E,jobs:N.updateJobs,runCommand:F,currentRuntimeVersion:Ml,listInstances:()=>N.listInstances(),resolveRuntimeArtifacts:async e=>(await ze(e)).map(e=>e.identity),moduleDir:("undefined"==typeof document?require("url").pathToFileURL(__filename).href:O&&"SCRIPT"===O.tagName.toUpperCase()&&O.src||new URL("cli.js",document.baseURI).href)?n.dirname(s.fileURLToPath("undefined"==typeof document?require("url").pathToFileURL(__filename).href:O&&"SCRIPT"===O.tagName.toUpperCase()&&O.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 se.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);(Ae||i.statusCode>=500)&&(i.statusCode>=500?se.log.error.bind(se.log):se.log.warn.bind(se.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,...i.details?{details:i.details}:{},...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}:{}}})}),se.addHook("preHandler",async e=>{if(hh.has(e.raw)){if(Ah(e.url))return;const t=new Error("Container IPC only accepts instance-scoped node agent requests.");throw Object.assign(t,{statusCode:401,code:"NODE_AGENT_CONTAINER_IPC_ROUTE_FORBIDDEN"}),t}const t=_e.verify(e);if(t){if(_.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(Ih(e)){if(i&&fh(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]&&!Ah(e.url)){if(_e.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 yh(e.ip)||yh(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&&fh(e.headers)!==i){const e=new Error("Invalid node agent token.");throw Object.assign(e,{statusCode:401,code:"NODE_AGENT_UNAUTHORIZED"}),e}}}),se.addHook("onClose",async()=>{z.stopAccepting(),y.stopAccepting();const e=Number(process.env.TASK_HANDOFF_STORY_DRAIN_DIAGNOSTIC_MS)||3e4,t=setTimeout(()=>{se.log.warn({pendingStoryIds:z.coordinator.pendingStoryIds()},"Story storage drain deadline reached; waiting for accepted operations and preserving recovery intents")},e);t.unref();try{await fe.stop(),clearInterval(le),clearInterval(pe),Ie.stop(),he.stop(),await L.stop(),await z.drain(),await y.close()}finally{clearTimeout(t)}}),se.decorate("nodeAgentRestoreManagedInstances",()=>L.restoreManagedInstances()),se.decorate("nodeAgentRecoverManagedInstances",()=>L.recoverManagedInstances()),se.decorate("nodeAgentStartRecoverySupervisor",()=>L.start()),se.get("/api/node-agent/health",async()=>{return{data:{ok:!0,role:"node-agent",process:{pid:process.pid,...mh?{startIdentity:mh}:{}},listener:{host:"127.0.0.1",port:N.currentListenerPort},nodeId:E,platform:Bm(S),arch:process.arch,protocolVersion:Pn,capabilities:{modelEndpointProbe:!0,managedModels:{multiEntityAssignment:!0,privateModelCatalog:!0},aiSessionHistoryLimit:!0,aiSessionAttachmentRetention:!0,aiSessionFileAttachmentLimit:!0,codexManagedSettings:!0,folderPlaces:!0,localFolderNameUpdate:!0,managedGitCredentials:{registry:!0,runtimeBroker:!0,workspaceProvisioning:{docker:!0,kubernetes:!1,local:!1}},stories:{enabled:!0,agentTools:!0,sessionRetention:!0,maxFileBytes:33554432,maxBatchPaths:20}},build:(e="node-agent",{component:e,packageName:"@task-handoff/node-agent",packageVersion:Ml(),protocolVersion:Pn,buildId:gh("TASK_HANDOFF_BUILD_ID"),builtAt:gh("TASK_HANDOFF_BUILT_AT"),gitCommit:gh("TASK_HANDOFF_GIT_COMMIT"),imageRef:gh("TASK_HANDOFF_IMAGE_REF"),imageDigest:gh("TASK_HANDOFF_IMAGE_DIGEST")}),instanceProxy:{...me},eventTransport:he.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)}))}(se,e=>{if(!Ih(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(!se.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 se.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)}))}(se,Ce,N.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(Rd.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(xd.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=Om.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=Om.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,o)=>{const r=kd.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(/\/$/,"")}(r.controlPlaneUrl);return n.runControlPlaneConnectionOperation(a,async()=>{const e=n.stageControlPlaneConnection({url:a,...r.controlPlaneName?{name:r.controlPlaneName}:{},enabled:!1!==r.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:r.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}n.markControlPlaneConnectionRemoteAccepted(e);const d=n.commitControlPlaneConnection(e,{name:r.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 o.code(201).send({data:{pairing:n.listControlPlanePairings().find(e=>e.keyId===d.pairing.keyId),connection:d.connection,tunnel:{status:u,...l?{error:l}:{}}}})})})}(se,{identity:_,nodeId:E,nodeName:()=>N.node.name,fetchImpl:$,reverseTunnels:()=>se.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(Gp.parse(e.body))})),e.patch("/api/node-agent/runtimes/:id",async e=>({data:t.updateRuntime(e.params.id,Wp.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(Vp.parse(e.query))})),e.post("/api/node-agent/local-folders",async(e,n)=>n.code(201).send({data:t.createLocalFolder(Hp.parse(e.body))})),e.patch("/api/node-agent/local-folders/:id",async e=>({data:t.updateLocalFolder(e.params.id,qp.parse(e.body))})),e.delete("/api/node-agent/local-folders/:id",async e=>({data:{deleted:t.deleteLocalFolder(e.params.id)}}))}(se,{listRuntimes:()=>N.nodeRuntimes.list(),createRuntime:e=>N.createRuntime(e),updateRuntime:(e,t)=>N.updateRuntime(e,t),deleteRuntime:e=>N.deleteRuntime(e),checkRuntime:async e=>{const t=N.requireRuntime(e);return N.checkRuntime(e,M.forRuntime(t))},listLocalFolders:()=>N.localFolders.list(),listFolderPlaces:ga,listFolderTree:ya,createLocalFolder:e=>N.createLocalFolder(e),updateLocalFolder:(e,t)=>N.updateLocalFolder(e,t),deleteLocalFolder:e=>N.localFolders.delete(e)}),function(e,t,n,i){e.get("/api/node-agent/models",async()=>({data:t.list()})),e.post("/api/node-agent/models",async(e,n)=>n.code(201).send({data:t.create(Es.parse(e.body))})),e.post("/api/node-agent/models/discover",async e=>{const n=du.parse(e.body);return{data:await Ql(i,{...n,key:t.resolveProbeKey(n.existingModelId,n.key)})}}),e.post("/api/node-agent/models/test",async e=>{const n=lu.parse(e.body);return{data:await Zl(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=ws.parse(e.body);if(i.id!==n)throw Object.assign(new Error(`Model payload id ${i.id} does not match route id ${n}.`),{statusCode:400,code:"NODE_MODEL_ID_MISMATCH"});return{data:t.deploy(i)}}),e.patch("/api/node-agent/models/:id",async e=>({data:t.update(e.params.id,Ts.parse(e.body))})),e.delete("/api/node-agent/models/:id",async e=>({data:{deleted:t.delete(e.params.id)}})),e.put("/api/node-agent/instances/:id/model-assignment",async e=>{const i=e.params.id,s=e.body&&"object"==typeof e.body&&!Array.isArray(e.body)&&Object.prototype.hasOwnProperty.call(e.body,"modelEntityIds"),o=t.assign(i,bs.parse(e.body));if(await n(i),s)return{data:o};const{modelEntityIds:r,...a}=o.assignment;return{data:{...o,assignment:a}}})}(se,N.modelRegistry,e=>bh($,N,e,Te.warn,U),$),function(e,t){const n=new uu(t.gitCredentials);e.addHook("onClose",async()=>n.close()),e.put("/api/node-agent/git-credentials/:credentialId",async e=>{const n=gu.parse(e.params),i=Yc.parse(e.body);if(i.credential.id!==n.credentialId)throw Object.assign(new Error("Credential payload identity mismatch."),{code:"GIT_CREDENTIAL_IDENTITY_MISMATCH",statusCode:409});return{data:t.gitCredentials.putPayload(i).credential}}),e.delete("/api/node-agent/git-credentials/:credentialId",async e=>({data:{deleted:t.gitCredentials.removePayload(gu.parse(e.params).credentialId)}})),e.get("/api/node-agent/instances/:id/git-credential-authorizations",async e=>{const{id:n}=fu.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}=fu.parse(e.params);t.requireInstance(n);const i=Jc.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}=fu.parse(e.params);t.authenticateInstance(i,Iu(e.headers));const s=Qc.parse(e.body);return{data:Zc.parse(n.resolveHttps(i,s.remoteUrl))}}),e.post("/api/node-agent/instances/:id/git-credentials/ssh/prepare",async e=>{const{id:i}=fu.parse(e.params);t.authenticateInstance(i,Iu(e.headers));const s=ed.parse(e.body);return{data:td.parse(await n.prepareSsh(i,s.remoteUrl))}}),e.post("/api/node-agent/instances/:id/git-credentials/ssh/agent",async e=>{const{id:i}=fu.parse(e.params);t.authenticateInstance(i,Iu(e.headers));const s=nd.parse(e.body);return{data:id.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}=yu.parse(e.params);return t.authenticateInstance(i,Iu(e.headers)),{data:{deleted:n.release(s,i)}}})}(se,N),function(e,t,n,i={}){if(e.hasContentTypeParser("application/octet-stream")||e.addContentTypeParser("application/octet-stream",(e,t,n)=>n(null,t)),e.get("/api/node-agent/stories",async()=>({data:{stories:await n.list()}})),e.post("/api/node-agent/stories",async(e,t)=>{const s=await n.create(qu.parse(e.body));return i.onRetentionSettingsChanged?.(),t.code(201).send({data:s})}),e.get("/api/node-agent/stories/:storyId",async e=>{const{storyId:t}=ep.parse(e.params);return{data:await n.get(t)||(()=>{throw Object.assign(new Error("Story was not found."),{code:"STORY_NOT_FOUND",statusCode:404})})()}}),e.patch("/api/node-agent/stories/:storyId",async e=>{const{storyId:t}=ep.parse(e.params),s=Vu.parse(e.body),o=i.commands?await i.commands.update(t,s):await n.update(t,s);return void 0!==s.maxIdleAiSessions&&i.onRetentionSettingsChanged?.(),{data:o}}),e.get("/api/node-agent/stories/:storyId/settings",async e=>{const{storyId:t}=ep.parse(e.params);return{data:await n.retentionSettings(t)}}),e.post("/api/node-agent/stories/:storyId/archive",async e=>({data:i.commands?await i.commands.archive(ep.parse(e.params).storyId):await n.archive(ep.parse(e.params).storyId)})),e.post("/api/node-agent/stories/:storyId/restore",async e=>({data:i.commands?await i.commands.restore(ep.parse(e.params).storyId):await n.restore(ep.parse(e.params).storyId)})),e.delete("/api/node-agent/stories/:storyId",async e=>{const{storyId:t}=ep.parse(e.params);if(!i.commands)throw Object.assign(new Error("Story command service is unavailable."),{code:"STORY_COMMAND_UNAVAILABLE",statusCode:503});return{data:{deleted:await i.commands.delete(t)}}}),i.scheduler){const t=i.scheduler,s=async(e,n)=>{const i=await t.status(n);if(i.automation.storyId!==e)throw Object.assign(new Error("Story Automation belongs to another Story."),{code:"STORY_AUTOMATION_STORY_MISMATCH",statusCode:409});return i};e.get("/api/node-agent/stories/:storyId/automations",async e=>{const{storyId:i}=ep.parse(e.params);return await n.require(i),{data:ju.parse({automations:await t.list(i)})}}),e.post("/api/node-agent/stories/:storyId/automations",async(e,n)=>{const{storyId:i}=ep.parse(e.params),s=Cu.parse(e.body);if(s.storyId!==i)throw Object.assign(new Error("Automation storyId does not match the route."),{code:"STORY_AUTOMATION_STORY_MISMATCH",statusCode:409});return n.code(201).send({data:Mu.parse(await t.create(s))})}),e.post("/api/node-agent/stories/:storyId/automations/with-action",async(e,t)=>{const{storyId:n}=ep.parse(e.params);if(!i.commands)throw Object.assign(new Error("Story command service is unavailable."),{code:"STORY_COMMAND_UNAVAILABLE",statusCode:503});const s=Ru.parse(e.body);return t.code(201).send({data:Mu.parse(await i.commands.createAutomationWithAction(n,s))})}),e.get("/api/node-agent/stories/:storyId/automations/:automationId",async e=>{const{storyId:t,automationId:n}=np.parse(e.params);return{data:Mu.parse(await s(t,n))}}),e.patch("/api/node-agent/stories/:storyId/automations/:automationId",async e=>{const{storyId:n,automationId:i}=np.parse(e.params);return await s(n,i),{data:Mu.parse(await t.update(i,xu.parse(e.body)))}}),e.delete("/api/node-agent/stories/:storyId/automations/:automationId",async e=>{const{storyId:n,automationId:i}=np.parse(e.params);return await s(n,i),{data:{deleted:await t.delete(i)}}});for(const n of["enable","disable"])e.post(`/api/node-agent/stories/:storyId/automations/:automationId/${n}`,async e=>{const{storyId:i,automationId:o}=np.parse(e.params);return await s(i,o),{data:Mu.parse(await t.setEnabled(o,"enable"===n))}});e.post("/api/node-agent/stories/:storyId/automations/:automationId/run",async e=>{const{storyId:n,automationId:i}=np.parse(e.params);return await s(n,i),{data:await t.manualRun(i,Fu.parse(e.body))}}),e.get("/api/node-agent/stories/:storyId/automations/:automationId/runs",async e=>{const{storyId:n,automationId:i}=np.parse(e.params);return await s(n,i),{data:Uu.parse({runs:await t.runs(i)})}})}e.get("/api/node-agent/stories/:storyId/content",async e=>{const{storyId:t}=ep.parse(e.params);return{data:Gu.parse({documents:await n.listContent(t)})}}),e.get("/api/node-agent/stories/:storyId/content/file",async(e,t)=>{const{storyId:i}=ep.parse(e.params),{storyPath:s}=sp.parse(e.query),o=await n.readContent(i,s);return cp(t,o.stream,o.revision,o.size)}),e.put("/api/node-agent/stories/:storyId/content/file",{bodyLimit:33555456},async e=>{const{storyId:t}=ep.parse(e.params),i=op.parse(e.query);return{data:await n.writeContent(t,{...i,stream:e.body})}}),e.patch("/api/node-agent/stories/:storyId/documents/:storyPath",async e=>{const t=tp.parse(e.params),i=_u.parse(decodeURIComponent(t.storyPath));return{data:await n.updateDocument(t.storyId,i,Bu.parse(e.body))}}),e.delete("/api/node-agent/stories/:storyId/documents/:storyPath",async e=>{const t=tp.parse(e.params);return{data:{deleted:await n.deleteDocument(t.storyId,_u.parse(decodeURIComponent(t.storyPath)))}}}),e.post("/api/node-agent/stories/:storyId/documents/order",async e=>{const{storyId:t}=ep.parse(e.params);return{data:await n.reorderDocuments(t,e.body)}}),e.get("/api/node-agent/instances/:id/ai-sessions/:sessionId/story-content",async e=>{const{id:i,sessionId:s}=ip.parse(e.params),o=await ap(t,n,i,s,rp(e.headers)),{page:r,pageSize:a}=Xu.parse(e.query||{});return{data:Qu.parse(await n.pageContent(o.id,r,a))}}),e.get("/api/node-agent/instances/:id/ai-sessions/:sessionId/story-content/file",async(e,i)=>{const{id:s,sessionId:o}=ip.parse(e.params),r=await ap(t,n,s,o,rp(e.headers)),{storyPath:a}=sp.parse(e.query),c=await n.readContent(r.id,a);return cp(i,c.stream,c.revision,c.size)}),e.put("/api/node-agent/instances/:id/ai-sessions/:sessionId/story-content/file",{bodyLimit:33555456},async e=>{const{id:i,sessionId:s}=ip.parse(e.params),o=await ap(t,n,i,s,rp(e.headers)),r=op.parse(e.query);return{data:await n.writeContent(o.id,{...r,stream:e.body})}}),e.put("/api/node-agent/instances/:id/ai-sessions/:sessionId/story",async e=>{const{id:s,sessionId:o}=ip.parse(e.params),r=t.requireInstance(s),c=a.z.object({storyId:ue.nullable()}).strict().parse(e.body||{});if(c.storyId){const e=await n.get(c.storyId);if(!e)throw Object.assign(new Error("Story belongs to another node or was not found."),{code:"STORY_NODE_MISMATCH",statusCode:409});if(e.archivedAt)throw Object.assign(new Error("Archived Story cannot receive new Session associations."),{code:"STORY_ARCHIVED",statusCode:409})}if(!i.fetchImpl||!i.resolveInstanceWeb||!r.registrationToken)throw Object.assign(new Error("Managed instance Session association is unavailable."),{code:"STORY_SESSION_ASSOCIATION_UNAVAILABLE",statusCode:503});const d=await i.resolveInstanceWeb(r),l=await i.fetchImpl(`${d}/api/ai-sessions/${encodeURIComponent(o)}/story`,{method:"PUT",headers:{"content-type":"application/json",authorization:`Bearer ${r.registrationToken}`},body:JSON.stringify(c)}),u=await l.json().catch(()=>({}));if(!l.ok)throw Object.assign(new Error(u.error?.message||"Controlled instance rejected Story association."),{code:u.error?.code||"STORY_SESSION_ASSOCIATION_FAILED",statusCode:l.status});return u})}(se,N,z,{fetchImpl:$,resolveInstanceWeb:U,onRetentionSettingsChanged:()=>H.reconcile(),commands:ye,scheduler:fe}),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:zi.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)}))}(se,be),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(Bp.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,Kp.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),o=t.register(i,Eo.parse(s),Xp(e.headers));return t.afterReport(o,"register"),n.header("x-task-handoff-node-agent-protocol-version",Pn).code(201).send({data:o})}),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,To.parse(i),Xp(e.headers));return t.afterReport(s,"heartbeat"),{data:s}})}(se,{list:()=>N.listInstances(),create:e=>"template"===e.environmentSource?.type?be.runTemplateOperation(e.environmentSource.environmentTemplateId,()=>N.createInstance(e)):N.createInstance(e),retryImageProvisioning:e=>Ne.retry(e),update:(e,t)=>{const n=N.requireInstance(e),i=t.config?.codexSettings?.multiAgent.defaultModel;if(i){const t=N.modelRegistry.privateCatalog(e).entities.find(e=>e.id===i.modelEntityId&&e.protocols.includes("openai-responses"));if(!t?.modelNames.some(e=>e.name===i.modelName))throw Object.assign(new Error("The Codex subagent model must be assigned to this instance."),{statusCode:400,code:"CODEX_SUBAGENT_MODEL_UNAVAILABLE"})}return N.controlledInstances.put(po.parse({...n,...t,...t.config?{config:{...n.config,...t.config}}:{},updatedAt:ae()}))},register:(e,t,n)=>N.registerInstance(e,t,n),heartbeat:(e,t,n)=>N.heartbeatInstance(e,t,n),sanitizeReport:Se,afterCreate:e=>{he.syncNow(),e.imageProvisioning&&Oe(e)},afterImageRetry:e=>{he.syncNow(),Oe(e)},afterUpdate:async e=>{he.syncNow(),await Promise.all([G(e.id),W(e.id)])},afterReport:(e,t)=>{he.syncNow(),fe.reconcileInstances("heartbeat"===t?e.id:void 0).catch(t=>se.log.warn({error:t,instanceId:e.id},"Story scheduler reconciliation failed")),K(e),G(e.id),W(e.id),H.reconcile(),q.reconcile(),"register"===t?Ee({instanceId:e.id,action:t,protocolVersion:e.protocolVersion,build:e.build,targetStatus:e.targetStatus,targetStrategy:e.target.strategy},"node instance registered"):Ee({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"),!ne(e)||e.ready&&"matched"===e.runtimeVersion?.phase||ge.schedule(e.id).catch(n=>se.log.error({instanceId:e.id,error:n},`runtime convergence after ${t} failed`))}}),se.get("/api/node-agent/events",{websocket:!0},(e,t)=>{const n=e;n.send(JSON.stringify({type:"node-agent.events.connected",nodeId:E,serverTime:(new Date).toISOString()}));const i=t.query,s=he.addOutput(n,{expectsTransientSubscription:"1"===i.aiSessionTransient});n.on("message",e=>{try{const t=JSON.parse(String(e));"subscribe"===t.type&&void 0!==t.aiSessionTransient&&he.setOutputSubscription(n,t.aiSessionTransient,t.eventEnvelopeVersion,t.aiSessionHierarchy)}catch{}}),n.on("close",s),n.on("error",s)}),se.get("/api/node-agent/docker/images",async()=>({data:await nr(e.dockerCommandRunner)})),se.get("/api/node-agent/instances/:id/metrics",async e=>{const t=e.params.id,n=N.requireInstance(t);if("docker"!==N.requireRuntime(n.runtimeId).type){const e=new Error(`Runtime type ${N.requireRuntime(n.runtimeId).type} does not provide resource metrics.`);throw Object.assign(e,{statusCode:409,code:"INSTANCE_METRICS_UNSUPPORTED"}),e}return{data:await Ie.snapshot(t)}}),function(e,t,n,i,s,o=new Yp){const r=e=>o.intent(e),a=e=>Promise.resolve(i.cancel(e)).then(()=>({ok:!0}),e=>({ok:!1,error:e})),c=(e,t)=>{if(!o.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=o.signal;return"function"==typeof n?n.call(o,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=Jp.parse(e.body),n=e.params.id,i=r(n);return o.run(n,async()=>(c(n,i),l(n,t.gitWorkspaceProvisioning),s.allowRecovery(n),{data:u(await s.start(n,()=>o.isIntentCurrent(n,i),d(n,i)),t.gitWorkspaceProvisioning)}))}),e.post("/api/node-agent/instances/:id/runtime/reconcile",async e=>{const n=e.params.id;Jp.parse(e.body);const a=r(n);return o.run(n,async()=>{c(n,a);const e=t.requireInstance(n);t.putInstance(po.parse({...e,ready:!1,runtimeVersion:Ul(La(e)),updatedAt:ae()})),c(n,a);const o=await i.schedule(n,{startRequested:!["created","stopped"].includes(e.status),resumeCancelled:!0});return c(n,a),s.sync(),{data:o}})}),e.post("/api/node-agent/instances/:id/stop",async e=>{const i=e.params.id;t.requireInstance(i),t.discardGitWorkspaceProvisioning(i),o.invalidate(i);const r=a(i);return o.run(i,async()=>{const e=t.requireInstance(i);t.applyLifecycle(i,{type:"stop-requested"});try{await s.suppressRecovery(i);const e=await r;if("error"in e)throw e.error;const o=t.requireInstance(i);s.diagnostic({instanceId:i,action:"stop",runtimeId:o.runtimeId,containerName:o.runtime.containerName},"node instance stop requested"),await n.forRuntime(t.requireRuntime(o.runtimeId)).stop(t.context(o))}catch(n){try{t.applyLifecycle(i,{type:"stop-failed",baseline:e}),s.sync()}finally{s.allowRecovery(i)}throw n}const o=t.applyLifecycle(i,{type:"stop-completed"});return s.completeSuppressedRecovery(i),s.sync(),s.diagnostic({instanceId:i,action:"stop",status:o.status,connectionStatus:o.connectionStatus,containerName:o.runtime.containerName},"node instance stop completed"),{data:o}})}),e.post("/api/node-agent/instances/:id/restart",async e=>{const a=e.params.id,d=Jp.parse(e.body),p=r(a);return o.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(po.parse({...e,runtimeVersion:Ul(La(e)),updatedAt:ae()}))),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 o=await n.forRuntime(t.requireRuntime(e.runtimeId)).restart(t.context(e));let r=t.applyLifecycle(a,{type:"runtime-lifecycle-completed",baseline:e,observation:{...o,target:o.target?{...e.target,...o.target}:void 0}});s.markRestarted(a),c(a,p);const m=po.parse({...r,updatedAt:ae()}),h=await s.probe(m);return c(a,p),r=t.applyLifecycle(a,{type:"runtime-lifecycle-completed",baseline:r,observation:{target:{...r.target,status:h},targetStatus:h,uiAccessStatus:h}}),await s.autoImport(r),s.sync(),s.diagnostic({instanceId:a,action:"restart",status:r.status,connectionStatus:r.connectionStatus,targetStatus:r.targetStatus,targetWeb:r.target.web,containerName:r.runtime.containerName},"node instance restart completed"),{data:u(r,d.gitWorkspaceProvisioning)}})}),e.post("/api/node-agent/instances/:id/delete",async e=>{const i=e.params.id,r=_i.parse(e.body);t.requireInstance(i),o.invalidate(i);const c=a(i);return o.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(po.parse({...a,status:"deleting",ready:!1,updatedAt:ae()})),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,{}),r);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),o.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(po.parse({...e,updatedAt:ae()})),s.sync()}finally{s.allowRecovery(i)}throw n}})})}(se,{requireInstance:e=>N.requireInstance(e),requireRuntime:e=>N.requireRuntime(e),putInstance:e=>N.controlledInstances.put(e),deleteInstance:e=>N.controlledInstances.delete(e),applyLifecycle:(e,t)=>N.applyInstanceLifecycle(e,t),context:(e,t)=>N.context(e,t),setGitWorkspaceProvisioning:e=>N.setGitWorkspaceProvisioning(e),discardGitWorkspaceProvisioning:e=>N.discardGitWorkspaceProvisioning(e),gitWorkspaceProvisioningStatus:e=>N.gitWorkspaceProvisioningStatus(e)},M,ge,{start:(e,t,n)=>ve(e,"request",t,n),sync:()=>he.syncNow(),isManaged:ne,probe:e=>_h($,e,U),autoImport:e=>wh($,e,"restart",Te,U),markRestarted:e=>L.markRestored(e),allowRecovery:e=>L.allowRecovery(e),suppressRecovery:e=>L.suppressRecovery(e),forgetRecovery:e=>L.forgetInstance(e),completeSuppressedRecovery:e=>L.completeSuppressedOperation(e),deleteMetadata:e=>{V.delete(e),N.modelRegistry.deleteInstanceMetadata(e),N.gitCredentials.removeInstance(e),N.gitCredentials.collectUnreferencedPayloads(),N.discardGitWorkspaceProvisioning(e),N.instancePrivateConfigs.delete(e)},retireInstanceData:e=>{oe.retire(e)},releaseEnvironmentImage:e=>be.releaseUnusedImage(e),diagnostic:Ee},we),function(e,t){const{fetchImpl:n,metrics:i,diagnostic:s}=t;e.post("/api/node-agent/instances/:id/proxy",async(e,i)=>{const o=performance.now(),r=e.params.id,a=$p.parse(e.body),c=await t.instanceBase(r),d=cm(a.path);"POST"===a.method&&"/api/apps/sessions"===d&&await t.syncModelEnvironment(r),s({instanceId:r,action:"proxy",method:a.method,path:d,instanceBase:c},"node instance proxy requested");const l=await lm(n,`${c}${d}`,{method:a.method,headers:{...a.headers},body:om(a)},{instanceId:r,method:a.method,path:d,diagnostic:s}),u=l.headers.get("content-type")||"application/octet-stream",p=await l.text(),m=performance.now()-o,h=l.headers.get(am)||a.headers[am],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(am,h),s({instanceId:r,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:im},async(e,o)=>{const r=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()-r,i.responseBytes+=c,i[e]+=1)},p=()=>{a.abort(),d&&u("aborted")};e.raw.once("aborted",p),o.raw.once("close",p);try{const r=e.params.id,l=$p.parse(e.body),p=await t.instanceBase(r),m=cm(l.path);s({instanceId:r,action:"proxy.stream",method:l.method,path:m,instanceBase:p},"node instance streaming proxy requested");const h=await lm(n,`${p}${m}`,{method:l.method,headers:{...l.headers},body:om(l),signal:a.signal},{instanceId:r,method:l.method,path:m,diagnostic:s}),f=Number(h.headers.get("content-length"));if(Number.isFinite(f)&&f>i.maxResponseBytes)return i.limitRejected+=1,a.abort(),dm(o,i.maxResponseBytes);o.code(h.status);for(const[e,t]of Object.entries(sm(h.headers)))o.header(e,t);if(!h.body||"HEAD"===l.method)return u("completed"),o.send();const y=new g.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")),o.send(g.Readable.fromWeb(h.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:im},async(e,o)=>{const r=e.params.id,a=$p.parse(e.body),c=await t.instanceBase(r),d=cm(a.path);s({instanceId:r,action:"proxy.raw",method:a.method,path:d,instanceBase:c},"node instance raw proxy requested");const l=await lm(n,`${c}${d}`,{method:a.method,headers:{...a.headers},body:om(a)},{instanceId:r,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(()=>{})),dm(o,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:o}=await s.read();if(e)break;if(i+=o.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(o))}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,dm(o,i.maxResponseBytes)}return s({instanceId:r,action:"proxy.raw",method:a.method,path:d,statusCode:l.status,byteLength:p.length},"node instance raw proxy completed"),{data:{status:l.status,headers:sm(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,o=n.params["*"]||"",r=n.url.indexOf("?"),a=r>=0?n.url.slice(r):"";let c;try{const r=await t.instanceBase(i),d=new URL(`/${o}${a}`,`${r}/`);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:`/${o}${a}`,upstreamUrl:d.toString(),protocols:l||[]},"node instance websocket proxy opening"),c=l?new m(d,l,{perMessageDeflate:!1}):new m(d,{perMessageDeflate:!1}),c.on("open",()=>{s({instanceId:i,action:"proxy.ws",path:`/${o}${a}`},"node instance websocket proxy opened")}),c.on("close",()=>{s({instanceId:i,action:"proxy.ws",path:`/${o}${a}`},"node instance websocket proxy closed")}),c.on("error",e=>{s({instanceId:i,action:"proxy.ws",path:`/${o}${a}`,error:e instanceof Error?e.message:String(e)},"node instance websocket proxy failed")}),j(e,c,{upstreamOpenTimeoutMs:1e4})}catch(t){s({instanceId:i,action:"proxy.ws",path:`/${o}${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.")}})}(se,{fetchImpl:$,metrics:me,instanceBase:e=>U(N.requireInstance(e)),syncModelEnvironment:e=>bh($,N,e,Te.warn,U),diagnostic:Ee}),se}catch(e){throw await h.close(),e}var f}async function Nh(e){const s=Aa(e.dataDir),o=function(e,i={}){return function(e,i={}){t.mkdirSync(n.dirname(e),{recursive:!0});const s=$.processStartIdentity(process.pid),o={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(V(e),`${JSON.stringify({token:o.token,pid:o.pid,startIdentity:o.startIdentity,startedAt:(new Date).toISOString()})}\n`,{encoding:"utf8",mode:384,flag:"wx"}),J(e,o),{lockPath:e,owner:o,updateDetails:t=>Q(e,o,t),release(){const n=W(e);n?.token===o.token&&t.rmSync(e,{recursive:!0,force:!0})}}}catch(s){if("EEXIST"!==s.code)throw s;const o=W(e);if(Y(o))throw new H(e,o,i.error);if(!o&&(ee(e)||ie(e)<(i.incompleteLockStaleMs??2e3))){if(n+1<5){ne();continue}throw new H(e,void 0,i.error)}const r=d.randomUUID();if(!se(e,r)){if(n+1<5){ne();continue}throw new H(e,W(e),i.error)}const a=W(e);if(Y(a))throw te(B(e)),new H(e,a,i.error);if(o?.token&&a?.token!==o.token){te(B(e));continue}if(!re(e,r))continue;t.rmSync(e,{recursive:!0,force:!0})}const r=W(e);throw new H(e,r,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=(a=e.host,l=e.port,to.parse({bindScope:"0.0.0.0"===a.trim()?"all-ipv4":"loopback",port:l})),d=t.existsSync(s.settingsPath),u=function(e,t){return new Za(e.settingsPath,()=>({version:1,externalListener:t}),{schema:mm,sanitize:gm})}(s,c);let p=u.get().externalListener;"allocate"===process.env.TASK_HANDOFF_NODE_AGENT_PORT_CONFLICT&&(p=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 fm(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"})}(p));const m=e=>{if(!o.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.")},h=e.ipcPath||process.env.TASK_HANDOFF_NODE_AGENT_IPC_PATH||wa(s.dataDir),g="linux"===(e.platform||process.platform)?e.containerIpcPath||process.env.TASK_HANDOFF_NODE_AGENT_CONTAINER_IPC_PATH||(r=s.dataDir,n.join(n.resolve(r),"container-ipc","node-agent.sock")):void 0,f={...e,port:p.port,ipcPath:h,containerIpcPath:g},y=await vh(f),I=y.nodeAgentState;if(!I)throw new Error("Node agent state was not initialized.");const A=y.nodeAgentIdentityService;if(!A)throw new Error("Node agent identity service was not initialized.");const _=y.nodeAgentResolveInstanceNodeAgentUrl;if(!_)throw new Error("Node agent runtime transport resolver was not initialized.");const E=A.resolveNodeId(e.nodeId||process.env.TASK_HANDOFF_NODE_ID),T=function(e,t,n,i,s){const o=t.token||process.env.TASK_HANDOFF_NODE_AGENT_TOKEN,r=s||new Nm(n),a=new Map;let c=!1;const d=(t,n)=>{if(c||n.retry.pending||a.get(t)!==n)return;const s=n.retry.schedule(()=>{c||a.get(t)!==n||n.socket||l(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"))},l=(n,s)=>{let r;s.status=s.lastDisconnectedAt?"reconnecting":"connecting",s.error=void 0,s.failureReason=void 0,s.nextRetryAt=void 0;try{r=jm(e,{...s.config,nodeId:i,port:()=>e.nodeAgentState.currentListenerPort,token:o})}catch(e){return s.status="failed",s.lastDisconnectedAt=(new Date).toISOString(),s.error=e instanceof Error?e.message:String(e),void d(n,s)}s.socket=r;const l=new Hm({connectTimeoutMs:t.connectTimeoutMs,handshakeTimeoutMs:t.handshakeTimeoutMs,heartbeatIntervalMs:t.heartbeatIntervalMs,heartbeatTimeoutMs:t.heartbeatTimeoutMs,heartbeatMissThreshold:t.heartbeatMissThreshold,stableThresholdMs:t.stableThresholdMs,ping:()=>r.ping(),onTimeout:e=>{a.get(n)===s&&s.socket===r&&(s.status="failed",s.failureReason=`Reverse tunnel ${e} timeout.`,s.error=s.failureReason,r.terminate())},onStable:()=>s.retry.reset()});return s.supervisor=l,l.start(),r.on("open",()=>{a.get(n)===s&&s.socket===r&&(s.status="connecting",l.opened())}),r.on("message",t=>{if(a.get(n)!==s||s.socket!==r)return;if(l.activity(),"connected"===s.status)return;let o;try{o=JSON.parse(String(t))}catch{return}const c=o&&"object"==typeof o?o.type:void 0;"control-plane.hello"!==c&&"control-plane.identified"!==c||(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"))}),r.on("pong",()=>l.pong()),r.on("close",(t,o)=>{if(a.get(n)!==s||s.socket!==r)return;l.close(),s.socket=void 0,s.lastDisconnectedAt=(new Date).toISOString();const u=`WebSocket closed${t?` (${t})`:""}${o?`: ${Buffer.isBuffer(o)?o.toString("utf8"):String(o)}`:""}`;s.error=s.failureReason||u,c||(e.log.warn({nodeId:i,tunnelUrl:new URL(s.config.tunnelUrl).origin,code:t,reason:Buffer.isBuffer(o)?o.toString("utf8"):String(o||""),error:s.error,closeOrigin:s.failureReason?"supervisor":"transport"},"node agent reverse tunnel disconnected"),d(n,s))}),r.on("error",e=>{a.get(n)===s&&s.socket===r&&(s.status="failed",s.failureReason=e instanceof Error?e.message:String(e),s.error=s.failureReason,r.terminate())}),r},u=(e,t)=>{const n=a.get(e);n?.retry.cancel(),n?.supervisor?.close();const i={config:t,retry:new qr,status:"connecting"};return a.set(e,i),n?.socket?.close(1e3,"Reverse tunnel reconnecting."),l(e,i)},p=(e,t)=>e.tunnelUrl===t.tunnelUrl&&e.keyId===t.keyId&&e.secret===t.secret;return{connectConfigured:()=>{c=!1;const n=new Map,s=r.resolvedControlPlaneAccess(),o=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=qm(t.url);n.set(t.id,{tunnelUrl:s,keyId:r.keyId,secret:r.secret}),o.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&&!o.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}),o.add(d)}const l=s.hasPersistedAccess?void 0:function(){const e=process.env.TASK_HANDOFF_CONTROL_PLANE_URL;if(!e)return;const t=new URL(Am,e);return t.protocol="https:"===t.protocol?"wss:":"ws:",t.toString()}();if(l&&!o.has(l)){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:${l}`,{tunnelUrl:l,keyId:e?.keyId,secret:e?.secret})}(e=>{for(const[t,n]of a)e.has(t)||(n.retry.cancel(),n.supervisor?.close(),a.delete(t),n.socket?.close(1e3,"Reverse tunnel configuration removed."));for(const[t,n]of e){const e=a.get(t);e&&p(e.config,n)||u(t,n)}})(n)},state:e=>{const t=a.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:()=>{c=!0;for(const e of a.values())e.retry.cancel(),e.supervisor?.close(),e.socket?.close(1001,"Node agent shutting down.");a.clear()}}}({log:y.log,inject:e=>y.inject(e),nodeAgentEventForwarder:y.nodeAgentEventForwarder,nodeAgentState:I},f,s,E,A);y.decorate("nodeAgentReverseTunnels",T);const w=new ym({app:y,state:I,settings:u,config:p,source:d?"persisted":"bootstrap",onActiveListener:m,validateUpdate:()=>{const e=I.listInstances().filter(e=>!["created","stopped","failed"].includes(e.status)).filter(e=>"reachable"!==e.targetStatus||!Xn(e.capabilities).features.nodeAgentConnectionUpdate);if(e.length)throw Object.assign(new Error(`Cannot change the node agent port while ${e.length} controlled instance(s) cannot switch endpoints live.`),{statusCode:409,code:"NODE_AGENT_LISTENER_LIVE_UPDATE_UNSUPPORTED",details:{instanceIds:e.map(e=>e.id)}})},synchronizeUpdate:async()=>{const t=I.listInstances().filter(e=>!["created","stopped","failed"].includes(e.status));await Promise.all(t.map(async t=>{const n=await _(t);return Th(e.fetchImpl||fetch,t,n).then(e=>{if("applied"!==e)throw new Error(`Controlled instance ${t.id} did not apply the node-agent endpoint update (${e}).`)})}))}});let b,S;y.decorate("nodeAgentListenerManager",w),function(e){let t=!1;const n=async n=>{if(!t){t=!0,T.closeAll(),b?.close(),S?.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)})}(y),y.addHook("onClose",async()=>{b?.close(),S?.close(),o.release()});try{await y.ready(),b=await async function(e,t){ba(t);const n=i.createServer((t,n)=>{e.server.emit("request",t,n)});return n.on("upgrade",(t,n,i)=>{e.server.emit("upgrade",t,n,i)}),await new Promise((e,i)=>{n.once("error",i),n.listen(t,()=>{n.off("error",i),e()})}),n}(y,h),g&&(S=await async function(e,t){ba(t);const n=i.createServer((t,n)=>{hh.add(t),e.server.emit("request",t,n)});return await new Promise((e,i)=>{n.once("error",i),n.listen(t,()=>{n.off("error",i),e()})}),n}(y,g)),await w.start(),T.connectConfigured(),y.nodeAgentStartRecoverySupervisor?.()}catch(e){throw await y.close(),e}}catch(e){throw o.release(),e}var r,a,l}const Oh="task-handoff-node-agent.service",zh=`/etc/systemd/system/${Oh}`,Ch="/etc/task-handoff/node-agent.env",Rh=["@task-handoff/node-agent","@task-handoff/controlled-instance"];function xh(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 kh(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 Dh={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(!N.stdin.isTTY||!N.stdout.isTTY)return!1;const t=v.createInterface({input:N.stdin,output:N.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 Ph(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 Lh(e){if("local-ipc"!==e&&"local-loopback"!==e)throw new Error("Connection mode must be local-ipc or local-loopback.");return e}function Mh(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(R("@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",Ph,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",Lh).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 Nh({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",Mh).option("--json","Print raw JSON output").action(async e=>{const n=t.opts(),i=e.ipcPath||n.ipcPath||process.env.TASK_HANDOFF_NODE_AGENT_IPC_PATH,s=e.dataDir||n.dataDir||process.env.TASK_HANDOFF_NODE_AGENT_DATA_DIR,o=e.endpoint?void 0:i||wa(s||Ia()),r=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 Sa(e.ipcPath,"/pairing/invites",{method:"POST",headers:t,body:n}),s=await i.json().catch(()=>({}));if(!i.ok)throw new Error(s.error?.message||`Node agent pairing invite failed with HTTP ${i.status}`);const o="string"==typeof s.data?.joinToken?s.data.joinToken:"";if(!o)throw new Error("Node agent pairing invite response did not include a join token.");return{nodeId:"string"==typeof s.data?.nodeId?s.data.nodeId:"",joinToken:o,expiresAt:"string"==typeof s.data?.expiresAt?s.data.expiresAt:""}}({endpoint:e.endpoint,ipcPath:o,token:e.token,expiresInMs:e.expiresInMs});e.json?console.log(JSON.stringify(r,null,2)):(r.nodeId&&console.log(`Node: ${r.nodeId}`),console.log(`Join token: ${r.joinToken}`),r.expiresAt&&console.log(`Expires: ${r.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,o=e.endpoint?void 0:i||wa(s||Ia()),r=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 Sa(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:o,token:e.token});e.json?console.log(JSON.stringify(r,null,2)):(console.log(`Control Plane: ${String(r?.connection?.url||e.controlPlane)}`),console.log(`Connection: ${String(r?.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=Dh){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(Ch)?t.readText(Ch):"",s=function(e,t){if(e.dataDir?.trim())return n.resolve(e.dataDir.trim());if(t.exists(Ch)){const e=kh(t.readText(Ch),"TASK_HANDOFF_NODE_AGENT_DATA_DIR");if(e)return n.resolve(e)}return n.resolve(Ia())}(e,{exists:e=>e===Ch&&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 o=kh(i,"TASK_HANDOFF_NPM_COMMAND")||process.env.TASK_HANDOFF_NPM_COMMAND||"npm";if(t.exists(zh)){const e=t.readText(zh);if(!/^ExecStart=\S*task-handoff-node-agent(?:\s|$)/m.test(e))throw new Error(`Refusing to remove ${Oh} because it is not owned by a standalone Node Agent installation.`);xh(t,"systemctl",["disable","--now",Oh]),t.remove(zh,{force:!0}),xh(t,"systemctl",["daemon-reload"])}xh(t,o,["uninstall","--global",...Rh]),t.remove(Ch,{force:!0}),t.log("TaskHandoff Node Agent service and packages were removed.");const r=!!e.deleteData||!e.keepData&&await t.confirmDeleteData(s);return r?(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:r}}(e)}),await t.parseAsync(process.argv)})().catch(e=>{console.error(e instanceof Error?e.message:String(e)),process.exitCode=1});