@task-handoff/node-agent 0.0.16 → 0.0.17
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 +1 -1
- package/docker/entrypoint.sh +42 -0
- package/package.json +1 -1
- package/runtime-artifacts/{controlled-instance-runtime-0.0.16-linux-universal.manifest.json → controlled-instance-runtime-0.0.17-linux-universal.manifest.json} +2 -2
- package/runtime-artifacts/controlled-instance-runtime-0.0.17-linux-universal.tar.gz +0 -0
- package/runtime-artifacts/controlled-instance-runtime-0.0.17-linux-universal.tar.gz.sha256 +1 -0
- package/runtime-artifacts/controlled-instance-runtime-0.0.16-linux-universal.tar.gz +0 -0
- package/runtime-artifacts/controlled-instance-runtime-0.0.16-linux-universal.tar.gz.sha256 +0 -1
package/dist/cli.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var e=require("commander"),t=require("node:fs"),n=require("node:path"),i=require("node:http"),r=require("node:url"),s=require("fastify"),o=require("@fastify/websocket"),a=require("zod"),c=require("node:crypto"),d=require("node:child_process"),l=require("node-pty"),u=require("ws"),p=require("node:os"),m=require("node:net"),g=require("node:stream"),h=require("node:fs/promises"),f=require("node:stream/promises"),y=require("tar"),I=require("write-file-atomic"),A=require("semver"),b="undefined"!=typeof document?document.currentScript:null;function w(e,n){try{const i=JSON.parse(t.readFileSync(e,"utf8"));if(n&&i.name!==n)return;return"string"==typeof i.version&&i.version.trim()?i.version.trim():void 0}catch{return}}function v(e){if(e)try{return n.dirname(t.realpathSync(e))}catch{return}}function E(e,t=process.env,i=e){const r=t.TASK_HANDOFF_VERSION?.trim();if(r)return r;const s=i.split("/").at(-1),o=process.argv[1]?n.resolve(process.argv[1]):void 0,a=o?n.dirname(o):void 0,c=[v(o),a,process.cwd()].filter(e=>Boolean(e));for(const t of new Set(c)){let i=t;for(;;){const t=w(n.join(i,"package.json"),e);if(t)return t;const r=n.dirname(i);if(r===i)break;i=r}}let d;for(const e of new Set(c)){let t=e;for(;;){if(s){const e=w(n.join(t,"packages",s,"package.json"),i);if(e)return e}d||=w(n.join(t,"package.json"));const e=n.dirname(t);if(e===t)break;t=e}}return d||"unknown"}const N=41943040,z="ai.sessions",S=a.z.string().trim().min(1).max(80),_=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 T=a.z.enum(["thinking","tool","editing","approval","responding","unknown"]),k=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(),C=a.z.enum(["pending-init","running","interrupted","completed","errored","shutdown","not-found"]),x=a.z.enum(["started","interacted","interrupted"]),O=a.z.object({threadId:a.z.string().trim().min(1).max(240),path:a.z.string().trim().max(4096).optional(),status:C,activity:x.optional(),message:a.z.string().trim().max(1e3).optional(),updatedAt:a.z.string().datetime()}).strict(),R=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}),D=a.z.object({send:a.z.boolean().optional(),interrupt:a.z.boolean().optional(),approval:a.z.boolean().optional()}).strict(),P=a.z.enum(["image","file"]),j=a.z.object({id:a.z.string().trim().min(1).max(120),kind:P,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)}),M=a.z.union([j.extend({source:a.z.object({type:a.z.literal("inline"),encoding:a.z.literal("base64"),data:a.z.string().min(1).max(31457280)}).strict()}).strict().superRefine((e,t)=>{const n="image"===e.kind?20971520:512e3;(e.size<=0||("file"===e.kind?e.size>=n:e.size>n))&&t.addIssue({code:a.z.ZodIssueCode.custom,path:["size"],message:`Inline ${e.kind} must be between 1 byte and ${n} bytes.`})}),j.extend({source:a.z.object({type:a.z.literal("runtime-path"),path:a.z.string().trim().min(1).max(4096)}).strict()}).strict()]),L=j.extend({sourceType:a.z.enum(["inline","runtime-path"])}).strict(),$=a.z.union([a.z.object({id:a.z.string().trim().min(1).max(120),kind:P.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:P,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()]),F=a.z.enum(["auto","queue","steer","immediate"]),U=a.z.enum(["ask","auto-review","full-access"]),V=a.z.enum(["review","rename","goal","compact"]);a.z.object({command:V,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:V,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 q=a.z.object({name:a.z.string().trim().min(1).max(240),path:a.z.string().trim().min(1).max(4096)}),H=a.z.discriminatedUnion("kind",[q.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(),q.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(),q.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()]),B=a.z.array(H).max(20).default([]),K=a.z.enum(["plugin","skill","file","directory","app"]),G=a.z.object({kind:K,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."})}),J=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(G).max(1e3).default([]),diagnostics:a.z.array(J).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(G.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 W=a.z.object({message:a.z.string().trim().min(1).max(2e4),mode:F.optional(),permissionMode:U.optional()});W.extend({attachments:a.z.array(M).max(6).default([]),references:B}).strict().superRefine((e,t)=>{e.attachments.reduce((e,t)=>e+("inline"===t.source.type?t.size:0),0)>N&&t.addIssue({code:a.z.ZodIssueCode.custom,path:["attachments"],message:"Inline attachments must be 41943040 bytes or less in total."})}),W.extend({attachments:a.z.array($).max(6).default([]),references:B}).strict(),a.z.object({decision:a.z.enum(["allow","deny","skip"])}).strict(),a.z.object({queueIds:a.z.array(a.z.string().trim().min(1).max(120)).max(100)}).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 Y=a.z.object({id:a.z.string().trim().min(1).max(120),message:a.z.string().trim().min(1).max(2e4),attachments:a.z.array(L).max(6).default([]),references:B,permissionMode:U.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(),X=a.z.object({pendingCount:a.z.number().int().min(0).default(0),items:a.z.array(Y).max(100).default([])}).strict().default({pendingCount:0,items:[]}),Q=a.z.enum(["control","realtime","adapter-snapshot","transcript-tail","transcript-scan","process-scan","app-session"]),Z=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(),ee=a.z.object({id:a.z.string().trim().min(1).max(240),providerTurnId:a.z.string().trim().max(240).optional(),source:Q.optional(),userPrompt:a.z.string().trim().optional(),status:a.z.enum(["queued","running","waiting","completed","failed"]).default("running"),phase:T.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(Z).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(),te=ee.pick({id:!0,providerTurnId:!0,userPrompt:!0,status:!0,phase:!0,summary:!0,lastMessage:!0,contextCompactions:!0,startedAt:!0,updatedAt:!0,completedAt:!0}).strict(),ne=a.z.object({id:a.z.string().trim().min(1).max(120),agent:S,appSessionId:a.z.string().trim().max(120).optional(),appId:a.z.string().trim().max(120).optional(),providerSessionId:a.z.string().trim().max(240).optional(),providerMeta:a.z.record(a.z.string(),a.z.unknown()).optional(),appBindingKeys:a.z.array(a.z.string().trim().min(1).max(240)).max(20).optional(),actions:D.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(),userPrompt:a.z.string().trim().optional(),turns:a.z.array(ee).max(50).optional(),status:_.default("running"),phase:T.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:k.optional(),toolCallsSinceLastMessage:a.z.number().int().min(0).default(0),subAgents:a.z.array(O).max(50).default([]),transcriptPath:a.z.string().trim().max(4096).optional(),transcriptSize:a.z.number().int().min(0).optional(),startedAt:a.z.string().datetime(),updatedAt:a.z.string().datetime(),completedAt:a.z.string().datetime().optional(),error:a.z.string().trim().max(4e3).optional(),counters:R,queue:X}).strict();a.z.object({session:ne,provider:a.z.string().trim().min(1).max(80),action:a.z.enum(["send","queue","steer","interrupt","approval"]),decision:a.z.enum(["allow","deny","skip"]).optional(),turnId:a.z.string().trim().min(1).max(240).optional(),providerTurnId:a.z.string().trim().min(1).max(240).optional(),queueId:a.z.string().trim().min(1).max(120).optional()}).strict();const ie=a.z.object({id:a.z.string().trim().min(1).max(120),agent:a.z.enum(["codex","claude"]),providerSessionId:a.z.string().trim().min(1).max(240),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),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(ie).max(50).default([])}).strict(),a.z.object({items:a.z.array(ie).max(50).default([])}).strict(),a.z.object({item:ie,turns:a.z.array(te).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)}).strict();const re=ne.pick({id:!0,agent:!0,appSessionId:!0,appId:!0,providerSessionId:!0,providerMeta:!0,appBindingKeys:!0,actions:!0,activeTurnId:!0,title:!0,cwd:!0,userPrompt:!0,turns:!0,status:!0,phase:!0,summary:!0,lastMessage:!0,lastMessageItemId:!0,currentTool:!0,toolCallsSinceLastMessage:!0,subAgents:!0,queue:!0,startedAt:!0,updatedAt:!0,error:!0}),se=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(re).default([]),updatedAt:a.z.string().datetime()}).strict();a.z.object({streamId:a.z.string().trim().min(1).max(240),revision:a.z.number().int().min(0),lastEventAt:a.z.string().datetime(),snapshot:se}).strict(),se.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 oe=a.z.enum(["provider-event","app-session-created","app-session-updated","app-session-deleted","discovery-scan","control-action","heartbeat-sync","startup"]),ae=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:oe}).strict(),ce=a.z.object({meta:ae,snapshot:se}).strict(),de=a.z.object({meta:ae,upserted:a.z.array(re).default([]),removed:a.z.array(a.z.string().trim().min(1).max(120)).default([])}).strict(),le=a.z.object({meta:ae,sessionIds:a.z.array(a.z.string().trim().min(1).max(120)).default([]),expiresAt:a.z.string().datetime()}).strict();a.z.object({instanceId:a.z.string().trim().min(1).max(160),nodeId:a.z.string().trim().min(1).max(160).optional(),sessionId:a.z.string().trim().min(1).max(120),providerSessionId:a.z.string().trim().min(1).max(240),turnId:a.z.string().trim().min(1).max(240),itemId:a.z.string().trim().min(1).max(240),delta:a.z.string().min(1),generatedAt:a.z.string().datetime()}).strict(),a.z.object({streamId:a.z.string().trim().min(1).max(240),instanceId:a.z.string().trim().min(1).max(160),sinceRevision:a.z.number().int().min(0),latestRevision:a.z.number().int().min(0),earliestRetainedRevision:a.z.number().int().min(0),syncRequired:a.z.boolean().default(!1),events:a.z.array(a.z.discriminatedUnion("type",[a.z.object({type:a.z.literal("ai-session.snapshot"),payload:ce}).strict(),a.z.object({type:a.z.literal("ai-session.patch"),payload:de}).strict(),a.z.object({type:a.z.literal("ai-session.removed"),payload:le}).strict()])).default([])}).strict();const ue=a.z.object({source:Q,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(),pe=ue.extend({type:a.z.literal("snapshot"),agent:a.z.string().trim().min(1).max(80),appSessionId:a.z.string().trim().max(120).optional(),appId:a.z.string().trim().max(120).optional(),providerSessionId:a.z.string().trim().max(240).optional(),providerMeta:a.z.record(a.z.string(),a.z.unknown()).optional(),appBindingKeys:a.z.array(a.z.string().trim().min(1).max(240)).max(20).optional(),actions:D.optional(),title:a.z.string().trim().max(240).optional(),cwd:a.z.string().trim().max(4096).optional(),activeTurnId:a.z.string().trim().max(240).optional(),userPrompt:a.z.string().trim().optional(),turns:a.z.array(ee).max(50).optional(),status:_.optional(),phase:T.optional(),summary:a.z.string().trim().max(1e3).optional(),lastMessage:a.z.string().trim().optional(),lastMessageItemId:a.z.string().trim().max(240).optional(),currentTool:k.optional(),toolCallsSinceLastMessage:a.z.number().int().min(0).optional(),subAgents:a.z.array(O).max(50).optional(),transcriptPath:a.z.string().trim().max(4096).optional(),transcriptSize:a.z.number().int().min(0).optional(),replaceActivity:a.z.boolean().optional()}).strict(),me=ue.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","tool-activity","sub-agent-activity","context-compaction"]),activeTurnId:a.z.string().trim().max(240).optional(),providerTurnId:a.z.string().trim().max(240).optional(),userPrompt:a.z.string().trim().optional(),text:a.z.string().optional(),itemId:a.z.string().trim().max(240).optional(),status:_.optional(),phase:T.optional(),summary:a.z.string().trim().max(1e3).optional(),error:a.z.string().trim().max(4e3).optional(),currentTool:k.nullable().optional(),toolCallsSinceLastMessage:a.z.number().int().min(0).optional(),subAgents:a.z.array(O).max(50).optional(),contextCompaction:Z.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("context-compaction"===e.kind?e.contextCompaction||t.addIssue({code:"custom",path:["contextCompaction"],message:"context-compaction events require contextCompaction"}):void 0!==e.contextCompaction&&t.addIssue({code:"custom",path:["contextCompaction"],message:"contextCompaction is only valid for context-compaction events"}),"sub-agent-activity"===e.kind?e.subAgents||t.addIssue({code:"custom",path:["subAgents"],message:"sub-agent-activity events require subAgents"}):void 0!==e.subAgents&&t.addIssue({code:"custom",path:["subAgents"],message:"subAgents is only valid for sub-agent-activity events"}),"tool-activity"!==e.kind)return void 0!==e.currentTool&&t.addIssue({code:"custom",path:["currentTool"],message:"currentTool is only valid for tool-activity events"}),void(void 0!==e.toolCallsSinceLastMessage&&t.addIssue({code:"custom",path:["toolCallsSinceLastMessage"],message:"toolCallsSinceLastMessage is only valid for tool-activity events"}));"currentTool"in e||t.addIssue({code:"custom",path:["currentTool"],message:"tool-activity events require currentTool"}),void 0===e.toolCallsSinceLastMessage&&t.addIssue({code:"custom",path:["toolCallsSinceLastMessage"],message:"tool-activity events require toolCallsSinceLastMessage"})});a.z.discriminatedUnion("type",[pe,me]);const ge=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()]),he=a.z.union([ge,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()]),fe=a.z.object({promptTemplate:a.z.string().trim().min(1).max(2e4)}).strict(),ye=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(),Ie=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:he,action:fe,policy:ye.default({maxConcurrentRuns:1,whenBusy:"skip"}),createdAt:a.z.string().datetime(),updatedAt:a.z.string().datetime()}).strict(),Ae=a.z.object({type:a.z.literal("ai-session"),aiSessionId:a.z.string().trim().min(1).max(160)}).strict(),be=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:Ae,localName:a.z.string().trim().min(1).max(160).optional(),createdAt:a.z.string().datetime(),updatedAt:a.z.string().datetime()}).strict(),we=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(),ve=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:Ae,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(Ie).default([]),deployments:a.z.array(be).default([]),runtime:a.z.array(we).default([]),recentRuns:a.z.array(ve).default([])}).strict();const Ee=a.z.string().regex(/^\d{4}-\d{2}-\d{2}$/,"Proxy protocol version must use YYYY-MM-DD format."),Ne=a.z.string().trim().min(1).max(160).regex(/^[a-zA-Z0-9][a-zA-Z0-9_.:-]*$/),ze=a.z.string().datetime(),Se=a.z.string().trim().min(32).max(4096),_e=a.z.string().trim().max(2048).transform((e,t)=>{try{return function(e){const t=new URL(e.trim());if("https:"!==t.protocol||t.username||t.password||"/"!==t.pathname||t.search||t.hash)throw new Error("Proxy origin must be an HTTPS origin without credentials, path, query, or fragment.");return t.origin}(e)}catch(e){return t.addIssue({code:"custom",message:e instanceof Error?e.message:String(e)}),a.z.NEVER}});a.z.string().trim().min(1).max(4096).transform((e,t)=>{try{return function(e){const t=e.trim();if(!t.startsWith("/")||t.startsWith("//")||t.includes("\\")||/%25/i.test(t))throw new Error("Proxy route must be a single-encoded node-agent relative route.");const n=t.split("?",1)[0];let i,r;try{i=n.split("/").map(e=>decodeURIComponent(e))}catch{throw new Error("Proxy route contains invalid percent encoding.")}if(i.some(e=>".."===e||"."===e))throw new Error("Proxy route cannot traverse outside the node-agent API.");try{r=new URL(t,"https://node-agent.invalid")}catch{throw new Error("Proxy route is invalid.")}if("https://node-agent.invalid"!==r.origin||r.username||r.password)throw new Error("Proxy route cannot select an absolute upstream URL.");return`${r.pathname}${r.search}`}(e)}catch(e){return t.addIssue({code:"custom",message:e instanceof Error?e.message:String(e)}),a.z.NEVER}});const Te=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"})),ke=a.z.object({code:Te,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(),Ce=a.z.enum(["active","consumed","revoked","expired"]),xe=a.z.object({id:Ne,targetNodeId:Ne,tokenHash:a.z.string().trim().min(32).max(256),status:Ce,createdBy:Ne,expiresAt:ze,consumedByClaimId:Ne.optional(),consumedAt:ze.optional(),revokedAt:ze.optional(),createdAt:ze,updatedAt:ze}).strict().omit({tokenHash:!0});a.z.object({targetNodeId:Ne,expiresInSeconds:a.z.number().int().min(60).max(3600).default(600)}).strict(),a.z.object({invite:xe,token:a.z.string().trim().min(24).max(512),proxyOrigin:_e,protocolVersion:Ee}).strict();const Oe=a.z.enum(["active","revoked"]),Re=a.z.object({id:Ne,claimId:Ne,sourceControlPlaneId:Ne,targetNodeId:Ne,bindingKeyId:Ne,credentialHash:a.z.string().trim().min(32).max(256),status:Oe,revision:a.z.number().int().positive(),lastError:ke.optional(),revokedAt:ze.optional(),createdAt:ze,updatedAt:ze}).strict().omit({credentialHash:!0});a.z.object({protocolVersion:Ee,inviteToken:a.z.string().trim().min(24).max(512).optional(),claimId:Ne,sourceControlPlaneId:Ne,targetNodeId:Ne.optional(),bindingKeyId:Ne,credential:Se}).strict(),a.z.object({sourceControlPlaneId:Ne,bindingKeyId:Ne,credential:Se}).strict();const De=a.z.object({id:Ne,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:ze.optional(),capabilities:a.z.record(a.z.string(),a.z.unknown()).default({})}).strict(),Pe=a.z.object({protocolVersion:Ee,binding:Re,streamId:Ne,revision:a.z.number().int().nonnegative(),observedAt:ze,target:De}).strict(),je=a.z.object({type:a.z.literal("control-plane-proxy.event"),protocolVersion:Ee,streamId:Ne,bindingId:Ne,sourceControlPlaneId:Ne,targetNodeId:Ne,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:De,event:a.z.object({type:a.z.string().trim().min(1).max(240),topic:a.z.string().trim().min(1).max(240),createdAt:ze}).strict()}).strict(),Me=a.z.object({type:a.z.literal("control-plane-proxy.events.ready"),protocolVersion:Ee,streamId:Ne,bindingId:Ne,sourceControlPlaneId:Ne,targetNodeId:Ne,latestRevision:a.z.number().int().nonnegative(),earliestRetainedRevision:a.z.number().int().nonnegative()}).strict(),Le=a.z.object({type:a.z.literal("control-plane-proxy.snapshot-required"),protocolVersion:Ee,streamId:Ne,bindingId:Ne,sourceControlPlaneId:Ne,targetNodeId:Ne,sinceRevision:a.z.number().int().nonnegative(),latestRevision:a.z.number().int().nonnegative(),earliestRetainedRevision:a.z.number().int().nonnegative(),error:ke}).strict();a.z.discriminatedUnion("type",[je,Me,Le]),a.z.object({protocolVersion:Ee,binding:Re,target:Pe.shape.target}).strict(),a.z.object({id:Ne,claimId:Ne,proxyOrigin:_e,requestedName:a.z.string().trim().min(1).max(160).optional(),sourceControlPlaneId:Ne,targetNodeId:Ne.optional(),bindingKeyId:Ne,credential:Se,status:a.z.enum(["pending","compensation-required"]),createdAt:ze,updatedAt:ze,expiresAt:ze}).strict().omit({credential:!0}),a.z.object({id:Ne,nodeId:Ne,proxyOrigin:_e,proxyBindingId:Ne,targetNodeId:Ne,sourceControlPlaneId:Ne,bindingKeyId:Ne,credential:Se,createdAt:ze,updatedAt:ze}).strict();const $e="2026-08-01",Fe=a.z.string(),Ue=a.z.string().trim().min(1).max(120).regex(/^[a-zA-Z0-9][a-zA-Z0-9_.:-]*$/),Ve=a.z.string().datetime(),qe=a.z.record(a.z.string(),a.z.string()).default({}),He=a.z.record(a.z.string(),a.z.string()).default({}),Be=a.z.string().regex(/^\d{4}-\d{2}-\d{2}$/,"Protocol version must use YYYY-MM-DD format."),Ke=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 Ge(e){if(null==e)return;const t=Ke.parse(e);return"utf8"===t.encoding?t.data:Buffer.from(t.data,"base64")}const Je=/^[A-Za-z0-9_][A-Za-z0-9_.-]{0,127}$/,We=/^sha256:([a-fA-F0-9]{64})$/,Ye=/^(?:localhost|[a-z0-9](?:[a-z0-9.-]*[a-z0-9])?)(?::[1-9][0-9]{0,4})?$/,Xe=/^[a-z0-9]+(?:(?:[._]|__|-+)[a-z0-9]+)*$/;function Qe(e){const t=e.trim();if(!t||t.length>512||t.includes("://")||/\s/.test(t))throw new Error("Docker image reference must not contain a URL scheme or whitespace.");const n=t.indexOf("@");if(-1!==n&&n!==t.lastIndexOf("@"))throw new Error("Docker image reference contains more than one digest separator.");const i=-1===n?void 0:t.slice(n+1),r=-1===n?t:t.slice(0,n),s=i?We.exec(i):void 0;if(i&&!s)throw new Error("Docker image digest must use sha256 followed by 64 hexadecimal characters.");const o=r.lastIndexOf("/"),a=r.lastIndexOf(":"),c=a>o,d=c?r.slice(a+1):void 0,l=c?r.slice(0,a):r;if(d&&!Je.test(d))throw new Error("Docker image tag is invalid.");if(!d&&!s)throw new Error("Docker image reference must include an explicit tag or sha256 digest.");const u=l.split("/");if(!u.length||u.some(e=>!e))throw new Error("Docker image repository path is invalid.");const p=u.length>1&&(u[0].includes(".")||u[0].includes(":")||"localhost"===u[0]),m=p?u.slice(1):u;if(p&&!Ye.test(u[0].toLowerCase()))throw new Error("Docker image registry host or port is invalid.");if(!m.length||m.some(e=>!Xe.test(e)))throw new Error("Docker image repository names must be lowercase and use valid separators.");const g=u.map((e,t)=>p&&0===t?e.toLowerCase():e).join("/"),h=s?`sha256:${s[1].toLowerCase()}`:void 0;return`${g}${d?`:${d}`:""}${h?`@${h}`:""}`}function Ze(e){const t=Qe(e),n=t.indexOf("@"),i=-1===n?void 0:t.slice(n+1),r=-1===n?t:t.slice(0,n),s=r.lastIndexOf("/"),o=r.lastIndexOf(":"),a=o>s;return{reference:t,repository:a?r.slice(0,o):r,tag:a?r.slice(o+1):void 0,digest:i}}const et=a.z.string().trim().min(1).max(512).transform((e,t)=>{try{return Qe(e)}catch(e){return t.addIssue({code:"custom",message:e instanceof Error?e.message:String(e)}),a.z.NEVER}}),tt=a.z.string().trim().transform((e,t)=>{const n=We.exec(e);return n?`sha256:${n[1].toLowerCase()}`:(t.addIssue({code:"custom",message:"Docker image digest must use sha256 followed by 64 hexadecimal characters."}),a.z.NEVER)}),nt=a.z.object({codexModelHash:Ue.nullable().optional(),claudeModelHash:Ue.nullable().optional()}).strict().default({}),it=a.z.object({imageId:Ue,tag:a.z.string().trim().min(1).max(128).regex(Je).optional()}).strict(),rt={img_default:"market_taskhandoff_browser",img_codex:"market_taskhandoff_codex",img_ai:"market_taskhandoff_ai"};function st(e,t){if(e&&"object"==typeof e&&!Array.isArray(e)){const t=e;return{imageId:"string"==typeof t.imageId&&rt[t.imageId]||t.imageId,..."string"==typeof t.tag?{tag:t.tag}:{}}}if("string"==typeof t)return{imageId:rt[t]||t}}function ot(e){if(!e||"object"!=typeof e||Array.isArray(e))return e;const t=e,{defaultImageId:n,...i}=t;return{...i,defaultImageSelection:st(t.defaultImageSelection,n)}}const at=a.z.object({id:Ue,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(),ct=a.z.object({code:a.z.enum(["APP_CATALOG_INVALID"]),message:a.z.string().trim().min(1).max(500)}).strict(),dt=a.z.object({items:a.z.array(at).max(256),observedAt:Ve,issues:a.z.array(ct).max(32).default([])}).strict(),lt=a.z.enum(["linux","darwin","win32","freebsd","openbsd","aix","sunos","unknown"]),ut=a.z.enum(["x64","arm64","arm","ia32","ppc64","s390x","riscv64","unknown"]),pt=a.z.enum(["apt","dnf","brew","npm"]),mt=a.z.enum(["user","passwordless-sudo","root"]),gt=a.z.object({platform:lt,arch:ut,installers:a.z.array(pt).max(8),privilege:mt,installerAccess:a.z.object({npmGlobalWritable:a.z.boolean().optional()}).strict().optional()}).strict(),ht=a.z.enum(["installed","not-installed","broken","unsupported"]),ft=a.z.enum(["recipe","bundled","external","none"]),yt=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(),It=a.z.object({id:Ue,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:ht,managementSource:ft,version:a.z.string().trim().max(120).optional(),canInstall:a.z.boolean(),canUninstall:a.z.boolean(),installReason:yt.optional(),uninstallReason:yt.optional(),activeJobId:Ue.optional()}).strict(),At=a.z.enum(["install","uninstall"]),bt=a.z.enum(["queued","running","succeeded","failed","cancelled","interrupted"]),wt=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"]}),vt=a.z.object({executable:a.z.string().trim().min(1).max(4096),args:a.z.array(a.z.string().max(4096)).max(128)}).strict(),Et=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(Ue).max(64).optional()}).strict(),Nt=a.z.object({id:Ue,requestId:Ue.optional(),appId:Ue,operation:At,state:bt,phase:a.z.string().trim().min(1).max(120).optional(),progress:wt.optional(),command:vt.optional(),logTail:a.z.string().max(32768).optional(),logTruncated:a.z.boolean().optional(),error:Et.optional(),requestedAt:Ve,startedAt:Ve.optional(),finishedAt:Ve.optional(),updatedAt:Ve}).strict(),zt=a.z.object({streamId:Ue,sequence:a.z.number().int().nonnegative(),capabilities:gt,apps:a.z.array(It).max(256),activeJobs:a.z.array(Nt).max(256),recentJobs:a.z.array(Nt).max(256),observedAt:Ve}).strict();a.z.object({requestId:Ue.optional()}).strict(),a.z.object({job:Nt}).strict(),a.z.object({type:a.z.literal("app-management"),streamId:Ue,sequence:a.z.number().int().nonnegative(),observedAt:Ve,job:Nt.optional(),snapshot:zt.optional()}).strict().refine(e=>void 0!==e.job||void 0!==e.snapshot,{message:"An app management event requires a job or snapshot."});const St=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:Fe.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(),_t=a.z.enum(["stable","beta","alpha"]),Tt=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(),kt=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(),Ct=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:Ve.optional(),matchedAt:Ve.optional(),error:kt.optional()}).strict(),xt=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(Ue).max(1024).default([]),stoppedInstanceIds:a.z.array(Ue).max(1024).default([]),activeInstanceIds:a.z.array(Ue).max(1024).default([])}).strict(),Ot=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(Ue).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(),Rt=a.z.object({channel:_t.default("stable")}).strict(),Dt=a.z.object({source:a.z.literal("npm"),channel:_t,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(Tt).default([]),impact:xt,updateAvailable:a.z.boolean(),supported:a.z.boolean().default(!0),reason:a.z.string().trim().max(2048).optional(),checkedAt:Ve,preflightToken:a.z.string().trim().min(16).max(240).optional()}).strict(),Pt=a.z.object({id:Ue,nodeId:Ue,source:a.z.literal("npm"),channel:_t,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(Tt).default([]),impact:xt,rollout:Ot,status:a.z.enum(["queued","updating-node","restarting-node","converging-instances","succeeded","degraded","failed"]),error:kt.optional(),startedAt:Ve.optional(),completedAt:Ve.optional(),createdAt:Ve,updatedAt:Ve}).strict(),jt=a.z.object({channel:_t,targetVersion:a.z.string().trim().min(1).max(240),preflightToken:a.z.string().trim().min(16).max(240)}).strict(),Mt=a.z.object({type:a.z.enum(["branch","tag","commit"]),name:a.z.string().trim().min(1).max(240).optional(),commit:a.z.string().trim().max(80).optional()}).strict(),Lt=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(),$t=a.z.object({depth:a.z.number().int().positive().max(1e5).optional(),submodules:a.z.boolean().default(!1),lfs:a.z.boolean().default(!1),subdirectory:a.z.string().trim().max(240).default("")}).strict();a.z.object({id:Ue,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:Mt.default({type:"branch",name:"main"}),auth:Lt.default({type:"none"}),clone:$t.default({submodules:!1,lfs:!1,subdirectory:""}),defaultImageSelection:it.optional(),labels:qe,createdAt:Ve,updatedAt:Ve}).strict();const Ft=a.z.object({id:Ue,nodeId:Ue,name:a.z.string().trim().min(1).max(160),path:a.z.string().trim().min(1).max(4096),defaultImageSelection:it.optional(),labels:qe,createdAt:Ve,updatedAt:Ve}).strict(),Ut=a.z.discriminatedUnion("type",[a.z.object({type:a.z.literal("git-repository"),repositoryId:Ue.optional(),url:a.z.string().trim().min(1).max(2048),provider:a.z.string().trim().max(80).optional(),ref:Mt.default({type:"branch",name:"main"}),auth:Lt.default({type:"none"}),clone:$t.default({submodules:!1,lfs:!1,subdirectory:""})}).strict(),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:Mt.default({type:"branch",name:"main"}),auth:Lt.default({type:"none"}),clone:$t.default({submodules:!1,lfs:!1,subdirectory:""})}).strict(),a.z.object({type:a.z.literal("local-folder"),localFolderId:Ue.optional(),path:a.z.string().trim().min(1).max(4096),ownerNodeId:Ue.optional()}).strict()]),Vt=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(),qt=a.z.enum(["codex","claude"]),Ht=a.z.object({id:Ue,name:a.z.string().trim().min(1).max(160),source:Ut,defaultImageSelection:it.optional(),defaultNodeId:Ue.optional(),defaultRuntimeId:Ue.optional(),workspacePolicy:Vt,labels:qe,createdAt:Ve,updatedAt:Ve}).strict(),Bt=a.z.object({id:Ue,name:a.z.string().trim().min(1).max(160),endpoint:a.z.string().trim().min(1).max(2048),key:a.z.string().trim().min(1).max(4096),model:a.z.string().trim().min(1).max(240),app:qt,enabled:a.z.boolean().default(!0),order:a.z.number().int().min(0).max(1e6).default(0),labels:qe,createdAt:Ve,updatedAt:Ve}).strict(),Kt=Bt,Gt=Bt.omit({key:!0}).extend({keyPreview:a.z.string().trim().min(1).max(160),keySet:a.z.boolean()}).strict(),Jt=Gt.extend({referenceCount:a.z.number().int().min(0)}).strict(),Wt=a.z.object({instanceId:Ue,codexModelHash:Ue.optional(),claudeModelHash:Ue.optional(),updatedAt:Ve}).strict(),Yt=a.z.discriminatedUnion("type",[a.z.object({type:a.z.literal("control-plane"),name:Bt.shape.name,enabled:Bt.shape.enabled,order:Bt.shape.order}).strict(),a.z.object({type:a.z.literal("node"),nodeId:Ue,name:Bt.shape.name,enabled:Bt.shape.enabled,order:Bt.shape.order,referenceCount:a.z.number().int().min(0)}).strict()]),Xt=a.z.object({id:Ue,model:Gt,locations:a.z.array(Yt).min(1),referenceCount:a.z.number().int().min(0).default(0)}).strict(),Qt=a.z.object({nodeId:Ue,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(Xt),nodeDiagnostics:a.z.array(Qt).default([]),updatedAt:Ve}).strict();const Zt=Bt.omit({id:!0,createdAt:!0,updatedAt:!0}).strict(),en=Zt.partial().strict(),tn=Bt,nn=a.z.object({modelSelection:nt,codexModelHash:Ue.optional(),claudeModelHash:Ue.optional()}).strict();function rn(e){const t={app:qt.parse(e.app),endpoint:Bt.shape.endpoint.parse(e.endpoint),key:Bt.shape.key.parse(e.key),model:Bt.shape.model.parse(e.model)};return`mdl_${c.createHash("sha256").update(JSON.stringify(t)).digest("hex")}`}const sn=a.z.enum(["market","custom"]),on=a.z.enum(["active","deprecated","yanked"]),an=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:tt.optional()}).strict()]),cn=a.z.array(a.z.string().trim().min(1).max(80)).default([]),dn=a.z.array(a.z.string().trim().min(1).max(120)).default([]),ln=a.z.record(a.z.string().trim().min(2).max(35),a.z.string().trim().min(1).max(4096)),un=a.z.object({os:a.z.string().trim().min(1).max(40),architecture:a.z.string().trim().min(1).max(40),digest:tt.optional(),downloadSizeBytes:a.z.number().int().positive().optional(),unpackedSizeBytes:a.z.number().int().positive().optional()}).strict(),pn=a.z.object({name:a.z.string().trim().min(1).max(128).regex(Je),version:a.z.string().trim().min(1).max(160).optional(),reference:et,manifestDigest:tt.optional(),publishedAt:Ve.optional(),platforms:a.z.array(un).default([]),status:on.default("active")}).strict(),mn=a.z.object({id:Ue,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:ln.optional(),cover:an.optional(),repository:a.z.string().trim().min(1).max(512),defaultTag:a.z.string().trim().min(1).max(128).regex(Je),tags:a.z.array(pn).min(1),capabilities:cn,optionalApps:dn,defaultEnv:He,labels:qe,status:on.default("active")}).strict().superRefine((e,t)=>{e.tags.some(t=>t.name===e.defaultTag)||t.addIssue({code:"custom",path:["defaultTag"],message:"Market defaultTag must identify one of the image tags."})});a.z.object({protocolVersion:Be,catalogId:Ue,revision:a.z.string().trim().min(1).max(240),source:a.z.enum(["embedded","remote","cache"]),generatedAt:Ve,expiresAt:Ve.optional(),items:a.z.array(mn)}).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:Ve,error:a.z.string().trim().max(4096).optional()}).strict(),a.z.object({id:Ue,origin:a.z.literal("custom"),name:a.z.string().trim().min(1).max(160),description:a.z.string().trim().max(4096).optional(),localizedDescriptions:ln.optional(),cover:an.optional(),reference:et,repository:a.z.string().trim().min(1).max(512),tag:a.z.string().trim().min(1).max(128).regex(Je).optional(),pullPolicy:a.z.literal("if-not-present").default("if-not-present"),capabilities:cn,optionalApps:dn,defaultEnv:He,labels:qe,createdAt:Ve,updatedAt:Ve}).strict();const gn=a.z.object({name:a.z.string().trim().min(1).max(128).regex(Je),version:a.z.string().trim().min(1).max(160).optional(),reference:et,manifestDigest:tt.optional(),status:on}).strict(),hn=a.z.object({id:Ue,origin:sn,name:a.z.string().trim().min(1).max(160),description:a.z.string().trim().max(4096).optional(),localizedDescriptions:ln.optional(),cover:an,repository:a.z.string().trim().min(1).max(512),tag:a.z.string().trim().min(1).max(128).regex(Je).optional(),availableTags:a.z.array(gn),reference:et,digest:tt.optional(),downloadSizeBytes:a.z.number().int().positive().optional(),unpackedSizeBytes:a.z.number().int().positive().optional(),capabilities:cn,optionalApps:dn,defaultEnv:He,labels:qe,readOnly:a.z.boolean(),lifecycleStatus:on.optional(),market:a.z.object({catalogId:Ue,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(),fn=a.z.object({id:Ue,origin:sn,name:a.z.string().trim().min(1).max(160),description:a.z.string().trim().max(4096).optional(),localizedDescriptions:ln.optional(),cover:an.optional(),repository:a.z.string().trim().min(1).max(512),tag:a.z.string().trim().min(1).max(128).regex(Je).optional(),requestedReference:et,resolvedDigest:tt.optional(),resolvedReference:et.optional(),downloadSizeBytes:a.z.number().int().positive().optional(),pullPolicy:a.z.literal("if-not-present").default("if-not-present"),capabilities:cn,optionalApps:dn,defaultEnv:He,labels:qe,market:a.z.object({catalogId:Ue,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:Ve,updatedAt:Ve}).strict(),yn=a.z.object({phase:a.z.enum(["checking-image","pulling-image","resolving-image","ready","failed"]),requestedReference:et,generation:a.z.number().int().nonnegative().default(0),error:a.z.string().trim().max(4096).optional(),startedAt:Ve,updatedAt:Ve}).strict(),In="image.pull.terminal.output",An="image.pull.terminal.finished",bn=a.z.object({instanceId:Ue,generation:a.z.number().int().nonnegative(),requestedReference:et,sequence:a.z.number().int().nonnegative(),observedAt:Ve}).strict(),wn=bn.extend({data:a.z.string().min(1).max(65536),replay:a.z.boolean().optional()}).strict(),vn=bn.extend({outcome:a.z.enum(["succeeded","failed"])}).strict();bn.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 En=a.z.discriminatedUnion("kind",[a.z.object({kind:a.z.literal("direct")}).strict(),a.z.object({kind:a.z.literal("control-plane-proxy"),proxyId:Ue,proxyBindingId:Ue,targetNodeId:Ue}).strict()]),Nn=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:Ve.optional(),target:De.optional(),lastError:ke.optional(),updatedAt:Ve}).strict(),zn=a.z.object({id:Ue,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:En.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:Ue.optional(),secret:a.z.string().trim().max(4096).optional(),pairedAt:Ve.optional(),pairing:a.z.object({status:a.z.enum(["pending","paired","expired"]).default("pending"),joinToken:a.z.string().trim().max(4096).optional(),expiresAt:Ve.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:Nn.optional(),appInventory:dt.optional(),labels:qe,lastSeenAt:Ve.optional(),createdAt:Ve,updatedAt:Ve}).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."})}),Sn=a.z.object({id:Ue,nodeId:Ue,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:qe,createdAt:Ve,updatedAt:Ve}).strict(),_n=a.z.object({instanceId:Ue,runtimeKind:a.z.literal("docker"),state:a.z.enum(["pending","available","stopped","unavailable"]),sampledAt:Ve,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();a.z.object({ok:a.z.boolean().optional(),role:a.z.string().optional(),nodeId:Ue.optional(),platform:lt.optional()}).passthrough();const Tn=a.z.object({bindScope:a.z.enum(["loopback","all-ipv4"]),port:a.z.number().int().min(1).max(65535)}).strict(),kn=Tn.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(),Cn=Tn;a.z.object({nodeId:Ue,joinToken:a.z.string().trim().min(1),expiresAt:Ve}).passthrough(),a.z.object({nodeId:Ue,keyId:Ue,secret:a.z.string().regex(/^[A-Za-z0-9_-]{32,128}$/),pairedAt:Ve}).strict();const xn=a.z.object({id:Ue,keyId:Ue,name:a.z.string().trim().min(1).max(160).optional(),pairedAt:Ve,updatedAt:Ve,current:a.z.boolean()}).passthrough();a.z.object({keyId:Ue,revoked:a.z.literal(!0),revokedAt:Ve}).strict(),a.z.object({id:Ue,pairingKeyId:Ue,url:a.z.string().trim().min(1).max(2048),name:a.z.string().trim().min(1).max(160).optional(),enabled:a.z.boolean(),createdAt:Ve,updatedAt:Ve,status:a.z.enum(["disabled","connecting","connected","reconnecting","failed"]),lastConnectedAt:Ve.optional(),lastDisconnectedAt:Ve.optional(),error:a.z.string().optional()}).passthrough(),a.z.object({pairing:xn,connection:a.z.object({id:Ue,pairingKeyId:Ue,url:a.z.string().trim().min(1).max(2048),name:a.z.string().trim().min(1).max(160).optional(),enabled:a.z.boolean(),createdAt:Ve,updatedAt:Ve}).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 On=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:hn,status:a.z.enum(["available","pull-required","unknown"]),localImage:On.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 Rn=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(Rn)}).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 Dn=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(),Pn=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"}),jn=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(),Mn=a.z.object({id:Ue,name:a.z.string().trim().min(1).max(160),projectId:Ue.optional(),source:Ut,sourceSnapshot:a.z.record(a.z.string(),a.z.unknown()).default({}),modelSelection:nt,nodeId:Ue,runtimeId:Ue,imageSelection:it.optional(),imageSnapshot:fn.optional(),imageProvisioning:yn.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","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:Fe.optional(),instanceVersion:a.z.string().trim().max(80).optional(),build:St.optional(),runtimeVersion:Ct.optional(),ready:a.z.boolean().default(!1),capabilities:a.z.record(a.z.string(),a.z.unknown()).default({}),appInventory:dt.optional(),config:a.z.object({autoImportAgentConfigs:a.z.boolean().default(!0),defaultCodexPermissionMode:U.default("ask")}).strict().default({autoImportAgentConfigs:!0,defaultCodexPermissionMode:"ask"}),workspace:jn.default({status:"unknown"}),target:Dn.default({strategy:"direct-port",status:"unknown"}),access:Pn,apps:a.z.object({runningCount:a.z.number().int().min(0).default(0),problemCount:a.z.number().int().min(0).default(0),updatedAt:Ve.optional(),revision:a.z.number().int().min(0).optional()}).strict().default({runningCount:0,problemCount:0}),aiSessions:se.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:Ie,deployments:a.z.array(be).default([]),runtime:a.z.array(we).default([])}).strict()).default([]),recentRuns:a.z.array(ve).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:Ve.optional(),createdAt:Ve,updatedAt:Ve}).strict(),Ln="instance.lifecycle.snapshot",$n=a.z.object({instanceId:Mn.shape.id,revision:a.z.number().int().min(0),updatedAt:Ve,status:Mn.shape.status.unwrap(),health:Mn.shape.health.unwrap(),connectionStatus:Mn.shape.connectionStatus.unwrap(),accessStatus:a.z.enum(["reachable","endpoint-unreachable"]),imageProvisioning:yn.optional(),workspace:jn,runtime:Mn.shape.runtime.unwrap(),runtimeVersion:Ct.optional(),ready:a.z.boolean(),lastHeartbeatAt:Ve.optional()}).strict();function Fn(e,t){return Mn.safeParse(Un(e,t))}function Un(e,t){if(!e||"object"!=typeof e||Array.isArray(e))return e;const n=e,i=new Set(Object.keys(Mn.shape)),r={};for(const[e,s]of Object.entries(n))i.has(e)?r[e]=s:t?.({instanceId:"string"==typeof n.id?n.id:void 0,field:e});if(n.capabilities&&"object"==typeof n.capabilities&&!Array.isArray(n.capabilities)){const e={...n.capabilities};Object.prototype.hasOwnProperty.call(e,"apps")&&(t?.({instanceId:"string"==typeof n.id?n.id:void 0,field:"capabilities.apps"}),delete e.apps),r.capabilities=e}else r.capabilities={};r.appInventory=function(e,t,n){if(!e||"object"!=typeof e||Array.isArray(e))return;const i=e;Object.keys(i).some(e=>!["observedAt","items","issues"].includes(e))&&t?.({instanceId:n,field:"appInventory"});const r={observedAt:i.observedAt,items:Array.isArray(i.items)?i.items.map(e=>{e&&"object"==typeof e&&!Array.isArray(e)&&Object.keys(e).some(e=>!["id","name","kind","source","availability","capabilities","diagnosticCode"].includes(e))&&t?.({instanceId:n,field:"appInventory.items"});const i=Hn(e,["id","name","kind","source","availability","diagnosticCode"]);return!i||"object"!=typeof i||Array.isArray(i)?i:{...i,capabilities:Hn(e.capabilities,["automation","supportsCwdSelection"])}}):i.items,issues:Array.isArray(i.issues)?i.issues.map(e=>Hn(e,["code","message"])):i.issues},s=dt.safeParse(r);return s.success?s.data:void 0}(n.appInventory,t,"string"==typeof n.id?n.id:void 0),r.source=function(e,t,n){if(!e||"object"!=typeof e||Array.isArray(e))return e;const i=e,r=i.type,s=Ut.options.find(e=>e.shape.type.value===r);if(!s)return e;const o="local-folder"===r?["type","localFolderId","path","ownerNodeId"]:"git-template"===r?["type","url","templateId","ref","auth","clone"]:["type","repositoryId","url","provider","ref","auth","clone"],a=Hn(i,o);if("local-folder"!==r){const e=Vn(Mt,Hn(i.ref,["type","name","commit"]),"source.ref",t,n),r=Vn(Lt,Hn(i.auth,["type","secretId"]),"source.auth",t,n),s=Vn($t,Hn(i.clone,["depth","submodules","lfs","subdirectory"]),"source.clone",t,n);e?a.ref=e:delete a.ref,r?a.auth=r:delete a.auth,s?a.clone=s:delete a.clone}const c=Vn(s,a,"source",t,n);return c?(Object.keys(i).some(e=>!o.includes(e))&&t?.({instanceId:n,field:"source"}),c):a}(n.source,t,"string"==typeof n.id?n.id:void 0),r.sourceSnapshot=n.sourceSnapshot&&"object"==typeof n.sourceSnapshot&&!Array.isArray(n.sourceSnapshot)?n.sourceSnapshot:{},r.build=Vn(St,n.build,"build",t,"string"==typeof n.id?n.id:void 0),r.aiSessions=function(e,t,n){if(!e||"object"!=typeof e||Array.isArray(e))return;const i=e,r=Array.isArray(i.sessions)?i.sessions.flatMap((e,i)=>{const r=Vn(re,e,`aiSessions.sessions.${i}`,t,n);return r?[r]:[]}):[],s={runningCount:"number"==typeof i.runningCount&&Number.isInteger(i.runningCount)&&i.runningCount>=0?i.runningCount:0,waitingCount:"number"==typeof i.waitingCount&&Number.isInteger(i.waitingCount)&&i.waitingCount>=0?i.waitingCount:0,staleCount:"number"==typeof i.staleCount&&Number.isInteger(i.staleCount)&&i.staleCount>=0?i.staleCount:0,sessions:r,updatedAt:Ve.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"}),se.parse(s)}(n.aiSessions,t,"string"==typeof n.id?n.id:void 0),r.triggers=function(e,t,n){if(!e||"object"!=typeof e||Array.isArray(e))return;const i=e;Object.keys(i).some(e=>!["enabledCount","runningCount","errorCount","configs","recentRuns"].includes(e))&&t?.({instanceId:n,field:"triggers"});const r=(e,i,r)=>Array.isArray(e)?e.flatMap((e,s)=>{const o=Vn(i,e,`${r}.${s}`,t,n);return o?[o]:[]}):[],s=Array.isArray(i.configs)?i.configs.flatMap((e,i)=>{if(!e||"object"!=typeof e||Array.isArray(e))return[];const s=e;Object.keys(s).some(e=>!["configHash","config","deployments","runtime"].includes(e))&&t?.({instanceId:n,field:`triggers.configs.${i}`});const o=function(e,t,n,i){if(!e||"object"!=typeof e||Array.isArray(e))return;const r=e,s=Hn(r,["configHash","name","description","createdAt","updatedAt"]);if(r.source&&"object"==typeof r.source&&!Array.isArray(r.source)){const e=r.source,t="schedule"===e.type?"interval"===e.scheduleKind?["type","scheduleKind","intervalMs"]:"daily"===e.scheduleKind?["type","scheduleKind","timeOfDay","timezone"]:["type","scheduleKind","weekdays","timeOfDay","timezone"]:"file-change"===e.type?["type","roots","globs","ignore","debounceMs"]:["type","agent","statuses","phases"];s.source=Hn(e,t)}return s.action=Hn(r.action,["promptTemplate"]),s.policy=Hn(r.policy,["cooldownMs","maxConcurrentRuns","whenBusy"]),Vn(Ie,s,t,n,i)}(s.config,`triggers.configs.${i}.config`,t,n);return"string"==typeof s.configHash&&o?[{configHash:s.configHash,config:o,deployments:r(s.deployments,be,`triggers.configs.${i}.deployments`),runtime:r(s.runtime,we,`triggers.configs.${i}.runtime`)}]:[]}):[];return{enabledCount:"number"==typeof i.enabledCount&&Number.isInteger(i.enabledCount)&&i.enabledCount>=0?i.enabledCount:0,runningCount:"number"==typeof i.runningCount&&Number.isInteger(i.runningCount)&&i.runningCount>=0?i.runningCount:0,errorCount:"number"==typeof i.errorCount&&Number.isInteger(i.errorCount)&&i.errorCount>=0?i.errorCount:0,configs:s,recentRuns:r(i.recentRuns,ve,"triggers.recentRuns")}}(n.triggers,t,"string"==typeof n.id?n.id:void 0),r.apps=Vn(Mn.shape.apps.unwrap(),Hn(n.apps,["runningCount","problemCount","updatedAt","revision"]),"apps",t,"string"==typeof n.id?n.id:void 0)||{runningCount:0,problemCount:0},r.config=Vn(Mn.shape.config.unwrap(),Hn(n.config,["autoImportAgentConfigs","defaultCodexPermissionMode"]),"config",t,"string"==typeof n.id?n.id:void 0)||{autoImportAgentConfigs:!0,defaultCodexPermissionMode:"ask"},r.modelSelection=Vn(nt.unwrap(),Hn(n.modelSelection,["codexModelHash","claudeModelHash"]),"modelSelection",t,"string"==typeof n.id?n.id:void 0)||{},r.imageSnapshot=function(e,t,n,i){if(!e||"object"!=typeof e||Array.isArray(e))return e;const r=e,s=function(e){if(!e||"object"!=typeof e||Array.isArray(e))return e;const t=e,n=new Set(["id","origin","name","description","localizedDescriptions","cover","reference","repository","tag","image","registry","pullPolicy","capabilities","optionalApps","defaultEnv","labels","createdAt","updatedAt"]);for(const e of Object.keys(t))n.has(e);"string"==typeof t.id&&t.id;const i="string"==typeof t.image?t.image:void 0;Object.prototype.hasOwnProperty.call(t,"registry");let r,s="string"==typeof t.reference?t.reference:i;if(s)try{s=Qe(s)}catch{if(!s.includes("@")&&s.lastIndexOf(":")<=s.lastIndexOf("/"))try{s=Qe(`${s}:latest`)}catch{}}try{r=s?Ze(s):void 0}catch{}return{id:t.id,origin:"custom",name:t.name,description:t.description,localizedDescriptions:t.localizedDescriptions,cover:Hn(t.cover,["kind","key","url","mediaType","digest"]),reference:r?.reference??s,repository:r?.repository??t.repository,tag:r?.tag??t.tag,pullPolicy:t.pullPolicy??"if-not-present",capabilities:t.capabilities,optionalApps:t.optionalApps,defaultEnv:t.defaultEnv,labels:t.labels,createdAt:t.createdAt,updatedAt:t.updatedAt}}(r),{reference:o,...a}=s,c=r.requestedReference??o;let d;try{d="string"==typeof c?Ze(c):void 0}catch{}const l={img_default:"market_taskhandoff_browser",img_codex:"market_taskhandoff_codex",img_ai:"market_taskhandoff_ai"},u="string"==typeof r.id?r.id:"string"==typeof t?t:void 0,p="market"===r.origin||u&&l[u]?"market":"custom";return void 0===r.image&&void 0===r.reference||n?.({instanceId:i,field:"imageSnapshot.reference"}),{...a,id:u&&l[u]?l[u]:u,origin:p,repository:d?.repository??r.repository,tag:d?.tag??r.tag,requestedReference:d?.reference??c,resolvedDigest:r.resolvedDigest,resolvedReference:r.resolvedReference,downloadSizeBytes:r.downloadSizeBytes,market:"market"===p?Hn(r.market,["catalogId","catalogRevision","publisher","version"])??{catalogId:"task_handoff_embedded",catalogRevision:"legacy",publisher:"task-handoff"}:void 0}}(n.imageSnapshot,n.imageId,t,"string"==typeof n.id?n.id:void 0);const s="string"==typeof n.imageId?{img_default:"market_taskhandoff_browser",img_codex:"market_taskhandoff_codex",img_ai:"market_taskhandoff_ai"}[n.imageId]||n.imageId:void 0,o=Hn(n.imageSelection,["imageId","tag"]);r.imageSelection=o||(s?{imageId:s,tag:r.imageSnapshot?.tag}:void 0),r.imageProvisioning=Vn(yn,Hn(n.imageProvisioning,["phase","requestedReference","generation","error","startedAt","updatedAt"]),"imageProvisioning",t,"string"==typeof n.id?n.id:void 0),r.runtimeVersion=function(e,t,n){if(!e||"object"!=typeof e||Array.isArray(e))return;const i=e,r=e=>{if("string"!=typeof e)return;const t=e.trim();return t&&t.length<=80?t:void 0},s=r(i.desiredVersion);if(!s)return void t?.({instanceId:n,field:"runtimeVersion.desiredVersion"});const o=new Set(Ct.shape.phase.options),a="string"==typeof i.phase?i.phase:"pending",c=o.has(a)?a:{idle:"pending",queued:"pending",checking:"pending",downloading:"installing",updating:"installing",completed:"matched",succeeded:"matched",ready:"matched",error:"failed"}[a]||"pending";let d;if(c!==a&&t?.({instanceId:n,field:"runtimeVersion.phase"}),i.error&&"object"==typeof i.error&&!Array.isArray(i.error)){const e=i.error,s="string"==typeof e.message?e.message.trim().slice(0,4096):"";if(s){const i=new Set(kt.shape.code.options),o="string"==typeof e.code&&i.has(e.code)?e.code:"INSTANCE_RUNTIME_INSTALL_FAILED";o!==e.code&&t?.({instanceId:n,field:"runtimeVersion.error.code"});const a=r(e.expectedVersion),c=r(e.actualVersion);d={code:o,message:s,...a?{expectedVersion:a}:{},...c?{actualVersion:c}:{},retryable:!0===e.retryable}}else t?.({instanceId:n,field:"runtimeVersion.error"})}"string"==typeof i.error&&i.error.trim()&&(d={code:"INSTANCE_RUNTIME_INSTALL_FAILED",message:i.error.trim().slice(0,4096),expectedVersion:s,...r(i.actualVersion)?{actualVersion:r(i.actualVersion)}:{},retryable:!1});const l=r(i.actualVersion),u=Ve.safeParse(i.lastAttemptAt),p=Ve.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:s,...l?{actualVersion:l}:{},phase:c,attempt:"number"==typeof i.attempt&&Number.isInteger(i.attempt)&&i.attempt>=0?i.attempt:0,...u.success?{lastAttemptAt:u.data}:{},...p.success?{matchedAt:p.data}:{},...d?{error:d}:{}}}(n.runtimeVersion,t,"string"==typeof n.id?n.id:void 0),r.workspace=Vn(jn,n.workspace,"workspace",t,"string"==typeof n.id?n.id:void 0)||{status:"unknown"},r.runtime=Vn(Mn.shape.runtime.unwrap(),Hn(n.runtime,["kind","containerName","containerId","workspacePath","pid","port","labels"]),"runtime",t,"string"==typeof n.id?n.id:void 0)||{labels:{}},r.target=Vn(Dn,Hn(n.target??n.endpoints,["strategy","web","api","vnc","tty","logs","status"]),"target",t,"string"==typeof n.id?n.id:void 0)||{strategy:"direct-port",status:"unknown"},r.access=Vn(Pn,Hn(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(Mn.shape))Object.prototype.hasOwnProperty.call(r,e)&&!i.safeParse(r[e]).success&&i.safeParse(void 0).success&&(delete r[e],t?.({instanceId:"string"==typeof n.id?n.id:void 0,field:e}));return r}function Vn(e,t,n,i,r){if(!t||"object"!=typeof t||Array.isArray(t))return;let s=structuredClone(t),o=!1;for(let t=0;t<20;t+=1){const t=e.safeParse(s);if(t.success)return o&&i?.({instanceId:r,field:n}),t.data;let a=!1;for(const e of t.error.issues){if("unrecognized_keys"!==e.code)continue;const t=qn(s,e.path);if(t&&"object"==typeof t&&!Array.isArray(t))for(const n of e.keys)Object.prototype.hasOwnProperty.call(t,n)&&(delete t[n],a=!0,o=!0)}if(!a){const o=structuredClone(s);let a=!1;for(const e of t.error.issues){if(!e.path.length||"string"!=typeof e.path.at(-1))continue;const t=qn(o,e.path.slice(0,-1)),n=e.path.at(-1);t&&"object"==typeof t&&!Array.isArray(t)&&Object.prototype.hasOwnProperty.call(t,n)&&(delete t[n],a=!0)}if(a){const t=e.safeParse(o);if(t.success)return i?.({instanceId:r,field:n}),t.data}break}}i?.({instanceId:r,field:n})}function qn(e,t){let n=e;for(const e of t){if(!n||"object"!=typeof n)return;n=n[e]}return n}function Hn(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 Bn=a.z.object({instanceId:Ue.optional(),projectId:Ue.optional(),source:Ut.optional(),nodeId:Ue.optional(),runtimeId:Ue.optional(),imageSelection:it.optional(),instanceVersion:a.z.string().trim().max(80).optional(),protocolVersion:Fe,build:St.optional(),controlMode:a.z.enum(["standalone","controlled"]).default("controlled"),capabilities:a.z.record(a.z.string(),a.z.unknown()).default({}),appInventory:dt.optional(),target:Dn.default({strategy:"direct-port",status:"unknown"}),workspace:jn.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)=>{e.protocolVersion!==$e||e.appInventory||t.addIssue({code:"custom",path:["appInventory"],message:"Current protocol register payload requires appInventory."})}),Kn=a.z.object({status:Mn.shape.status.optional(),health:Mn.shape.health.optional(),protocolVersion:Fe,build:St.optional(),capabilities:Mn.shape.capabilities.optional(),appInventory:dt.optional(),apps:Mn.shape.apps.optional(),aiSessions:Mn.shape.aiSessions.optional(),triggers:Mn.shape.triggers.optional(),workspace:jn.optional(),target:Dn.partial().optional(),processIncarnationId:a.z.string().trim().min(1).max(120).optional()}).strict().superRefine((e,t)=>{e.protocolVersion!==$e||e.appInventory||t.addIssue({code:"custom",path:["appInventory"],message:"Current protocol heartbeat payload requires appInventory."})}),Gn=a.z.enum(["web","telegram","wechat","dingding"]);function Jn(e,t,n={}){return new Promise((i,r)=>{if(n.signal?.aborted)return void r(Object.assign(new Error(`${e} was aborted.`),{code:"RUNTIME_COMMAND_ABORTED"}));const s=d.spawn(e,t,{stdio:["ignore","pipe","pipe"]}),o=[],a=[];let c=!1;const l=n.timeoutMs?setTimeout(()=>{c=!0,s.kill("SIGKILL")},n.timeoutMs):void 0;let u=!1;const p=()=>{u=!0,s.kill("SIGKILL")},m=()=>{l&&clearTimeout(l),n.signal?.removeEventListener("abort",p)};n.signal?.addEventListener("abort",p,{once:!0}),l?.unref?.(),s.stdout.on("data",e=>o.push(Buffer.from(e))),s.stderr.on("data",e=>a.push(Buffer.from(e))),s.on("error",e=>{m(),r(e)}),s.on("close",t=>{m();const s={stdout:Buffer.concat(o).toString("utf8").trim(),stderr:Buffer.concat(a).toString("utf8").trim()};if(c){const t=new Error(`${e} timed out after ${n.timeoutMs}ms`);return Object.assign(t,{statusCode:504,code:"RUNTIME_COMMAND_TIMEOUT",details:s}),void r(t)}if(u)return void r(Object.assign(new Error(`${e} was aborted.`),{code:"RUNTIME_COMMAND_ABORTED",details:s}));if(0===t)return void i(s);const d=new Error(s.stderr||`${e} exited with code ${t}`);Object.assign(d,{statusCode:502,code:"RUNTIME_EXECUTOR_FAILED",details:s}),r(d)})})}a.z.object({id:Ue,channel:Gn,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:Ve,updatedAt:Ve}).strict(),a.z.object({id:Ue,channel:Gn,bridgeId:Ue.optional(),chatSessionId:a.z.string().trim().min(1).max(240),userId:a.z.string().trim().max(240).optional(),activeProjectId:Ue.optional(),activeInstanceId:Ue.optional(),activeAiSessionId:a.z.string().trim().min(1).max(120).optional(),lastUsedAt:Ve,createdAt:Ve,updatedAt:Ve}).strict(),a.z.object({source:a.z.object({type:a.z.literal("chat-gateway").default("chat-gateway"),channel:Gn,bridgeId:Ue.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(M).max(6).default([])}).strict().superRefine((e,t)=>{e.attachments.reduce((e,t)=>e+("inline"===t.source.type?t.size:0),0)>N&&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:Ue,aiSessionId:a.z.string().trim().min(1).max(120)}).strict().optional()}).strict(),a.z.object({id:Ue,instanceId:Ue,projectId:Ue.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:Ve}).strict();const Wn=(e,t,n={})=>new Promise((i,r)=>{if(n.signal?.aborted)return void r(Object.assign(new Error(`${e} was aborted.`),{code:"RUNTIME_COMMAND_ABORTED"}));const s=[];let o,a=!1,c=!1;try{o=l.spawn(e,t,{name:"xterm-256color",cols:n.cols||120,rows:n.rows||40,cwd:process.cwd(),env:process.env})}catch(e){return void r(e)}const d=n.timeoutMs?setTimeout(()=>{a=!0,o.kill("SIGKILL")},n.timeoutMs):void 0,u=()=>{c=!0;try{o.kill("SIGKILL")}catch{}};n.signal?.addEventListener("abort",u,{once:!0}),d?.unref?.(),o.onData(e=>{s.push(e),n.onData?.(e)}),o.onExit(({exitCode:t})=>{d&&clearTimeout(d),n.signal?.removeEventListener("abort",u);const o={stdout:s.join(""),stderr:""};a?r(Object.assign(new Error(`${e} timed out after ${n.timeoutMs}ms`),{statusCode:504,code:"RUNTIME_COMMAND_TIMEOUT",details:o})):c?r(Object.assign(new Error(`${e} was aborted.`),{code:"RUNTIME_COMMAND_ABORTED",details:o})):0!==t?r(Object.assign(new Error(o.stdout.replace(/\u001b\[[0-?]*[ -/]*[@-~]/g,"").split(/\r?\n/).map(e=>e.trim()).filter(Boolean).at(-1)||`${e} exited with code ${t}`),{statusCode:502,code:"RUNTIME_EXECUTOR_FAILED",details:o})):i(o)})});class Yn{inFlight=new Map;runCommand;runTerminalCommand;constructor(e=Jn,t){this.runCommand=e,this.runTerminalCommand=t||function(e){return e===Jn?Wn:async(t,n,i={})=>{const r=await e(t,n,{timeoutMs:i.timeoutMs,signal:i.signal});return r.stdout&&i.onData?.(r.stdout),r.stderr&&i.onData?.(r.stderr),r}}(e)}ensure(e,t,n,i){const r=Qe(e),s=this.inFlight.get(r);if(s)return t&&(s.phaseListeners.add(t),s.phase&&t(s.phase)),n&&(s.terminalListeners.add(n),s.terminalTail&&n({sequence:s.terminalSequence,data:s.terminalTail,replay:!0})),this.bindAbort(s,i),s.promise;const o=new Set,a=new Set;t&&o.add(t),n&&a.add(n);const c={promise:Promise.resolve(void 0),controller:new AbortController,abortDisposers:new Set,phaseListeners:o,terminalListeners:a,terminalSequence:0,terminalTail:""};return this.bindAbort(c,i),c.promise=this.ensureOnce(r,e=>{c.phase=e,o.forEach(t=>t(e))},e=>{c.terminalSequence+=1,c.terminalTail=`${c.terminalTail}${e}`.slice(-262144);const t={sequence:c.terminalSequence,data:e};a.forEach(e=>e(t))},c.controller.signal).finally(()=>{this.inFlight.delete(r);for(const e of c.abortDisposers)e();c.abortDisposers.clear()}),this.inFlight.set(r,c),c.promise}bindAbort(e,t){if(!t)return;if(t.aborted)return void e.controller.abort();const n=()=>e.controller.abort();t.addEventListener("abort",n,{once:!0}),e.abortDisposers.add(()=>t.removeEventListener("abort",n))}async ensureOnce(e,t,n,i){t("checking-image");let r=await this.inspect(e,i).catch(e=>{if(i.aborted)throw e}),s=!1;r||(t("pulling-image"),await this.runTerminalCommand("docker",["pull",e],{cols:120,rows:40,signal:i,onData:n}),s=!0,r=await this.inspect(e,i)),t("resolving-image");const o=(a=r,Array.isArray(a.RepoDigests)?a.RepoDigests.filter(e=>"string"==typeof e):[]).find(e=>/@sha256:[a-fA-F0-9]{64}$/.test(e));var a;const c=o?.split("@").at(-1)?.toLowerCase();return{requestedReference:e,...c?{resolvedDigest:c}:{},resolvedReference:o||e,pulled:s}}async inspect(e,t){const n=await this.runCommand("docker",["image","inspect",e,"--format","{{json .}}"],{signal:t});return JSON.parse(n.stdout.trim()||"{}")}}function Xn(e){if(!e)return;const t=/^([0-9]+(?:\.[0-9]+)?)\s*(B|kB|MB|GB|TB)$/i.exec(e.trim());if(!t)return;const n=Number(t[1])*{b:1,kb:1e3,mb:1e6,gb:1e9,tb:1e12}[t[2].toLowerCase()];return Number.isSafeInteger(Math.round(n))?Math.round(n):void 0}class Qn{runCommand;publishHost;images;launcherAssetsDir;portResolutionRetryDelaysMs;constructor(e=Jn,i={}){this.runCommand=e,this.images=i.imageService||new Yn(e),this.publishHost=i.publishHost||"127.0.0.1",this.launcherAssetsDir=i.launcherAssetsDir||function(){const e=("undefined"==typeof document?require("url").pathToFileURL(__filename).href:b&&"SCRIPT"===b.tagName.toUpperCase()&&b.src||new URL("cli.js",document.baseURI).href)?n.dirname(r.fileURLToPath("undefined"==typeof document?require("url").pathToFileURL(__filename).href:b&&"SCRIPT"===b.tagName.toUpperCase()&&b.src||new URL("cli.js",document.baseURI).href)):__dirname,i=[n.resolve(e,"../../../../../docker"),n.resolve(e,"../docker"),n.resolve(e,"../../docker")];return i.find(e=>t.existsSync(n.join(e,"runtime-installer.mjs")))||i[0]}(),this.portResolutionRetryDelaysMs=i.portResolutionRetryDelaysMs?.length?i.portResolutionRetryDelaysMs:[0,100,250,500,1e3]}async start(e){di(e);const t=e.instance.runtime.containerName||ai(e.instance.id),n=await this.inspectContainerForStart(t);if(n){si(t,n.id,e.instance.runtime.containerId,"before start","RUNTIME_EXECUTOR_FAILED");const i=n.labels["task-handoff.instance-id"];if(i!==e.instance.id)throw ni("RUNTIME_EXECUTOR_FAILED",`Docker container ${t} belongs to ${i||"an unknown instance"}, not ${e.instance.id}.`);try{await this.runCommand("docker",["start",t])}catch(e){throw ni("RUNTIME_EXECUTOR_FAILED",`Could not start Docker container ${t}.`,e)}return this.runningResult(e,t,n.id)}let i;await this.images.ensure(e.image.resolvedReference||e.image.requestedReference);try{i=await this.runCommand("docker",function(e,t,n={}){const i=n.publishHost||"127.0.0.1",r=e.node?.id||"node_unset",s=e.runtime?.id||"runtime_local_docker",o=["run","-d","--name",t,"--label",`task-handoff.instance-id=${e.instance.id}`,"--label",`task-handoff.project-id=${e.project.id}`,"--label",`task-handoff.node-id=${r}`,"--label",`task-handoff.runtime-id=${s}`,"--label",`task-handoff.image-id=${e.image.id}`,"--shm-size","1gb","--security-opt","seccomp=unconfined","--network","bridge","--add-host","host.docker.internal:host-gateway","--tmpfs","/tmp:rw,mode=1777","-v",`${t}-data:/data`,"-v",`${t}-agent-home:/home/agent`,"-p",`${i}::8080`],a={TASK_HANDOFF_CONTROL_MODE:"controlled",TASK_HANDOFF_NODE_AGENT_URL:e.nodeAgentUrl||e.node?.endpoint||"",TASK_HANDOFF_INSTANCE_ID:e.instance.id,TASK_HANDOFF_INSTANCE_NAME:e.instance.name,TASK_HANDOFF_REGISTRATION_TOKEN:e.instance.registrationToken||"",TASK_HANDOFF_PROJECT_ID:e.project.id,TASK_HANDOFF_NODE_ID:r,TASK_HANDOFF_RUNTIME_ID:s,TASK_HANDOFF_IMAGE_ID:e.image.id,...e.image.tag?{TASK_HANDOFF_IMAGE_TAG:e.image.tag}:{},TASK_HANDOFF_CHAT_BRIDGES:"none",TASK_HANDOFF_WORKSPACE:e.project.workspacePolicy.path||"/workspace",TASK_HANDOFF_WORKSPACE_MODE:e.project.workspacePolicy.mode};for(const[e,t]of Object.entries(a))ci(o,e,t);"local-folder"===e.project.source.type?o.push("-v",`${e.project.source.path}:${e.project.workspacePolicy.path||"/workspace"}:${e.project.workspacePolicy.readOnly?"ro":"rw"}`):(ci(o,"TASK_HANDOFF_PROJECT_SOURCE",JSON.stringify(e.project.source)),ci(o,"TASK_HANDOFF_WORKSPACE_POLICY",JSON.stringify(e.project.workspacePolicy)),ci(o,"TASK_HANDOFF_GIT_URL",e.project.source.url),e.project.source.ref?.commit?ci(o,"TASK_HANDOFF_GIT_COMMIT",e.project.source.ref.commit):e.project.source.ref?.name&&ci(o,"TASK_HANDOFF_GIT_REF",e.project.source.ref.name),e.project.source.clone?.depth&&ci(o,"TASK_HANDOFF_GIT_DEPTH",String(e.project.source.clone.depth)),ci(o,"TASK_HANDOFF_GIT_SUBMODULES",e.project.source.clone?.submodules?"true":"false"),ci(o,"TASK_HANDOFF_GIT_LFS",e.project.source.clone?.lfs?"true":"false"),e.project.source.clone?.subdirectory&&ci(o,"TASK_HANDOFF_WORKSPACE_SUBDIRECTORY",e.project.source.clone.subdirectory));for(const[t,n]of Object.entries(e.image.defaultEnv))ci(o,t,n);for(const[t,n]of Object.entries(e.modelEnv||{}))ci(o,t,n);return o.push(e.image.resolvedReference||e.image.requestedReference),o}(e,t,{publishHost:this.publishHost}))}catch(e){throw ni("RUNTIME_EXECUTOR_FAILED",`Could not create Docker container ${t}.`,e)}return this.runningResult(e,t,i.stdout||void 0)}async runningResult(e,t,n){const i=await this.containerPort(t,"8080/tcp"),r=i?`http://127.0.0.1:${i}`:void 0,s=e.node?.id||"node_unset",o=e.runtime?.id||"runtime_local_docker";return{status:"registering",health:"unknown",connectionStatus:r?"online":"unknown",agentStatus:"unknown",targetStatus:"unknown",uiAccessStatus:"unknown",target:{strategy:"direct-port",status:r?"reachable":"unknown",...r?{web:r,api:`${r}/api`}:{}},workspace:{mode:e.project.workspacePolicy.mode,status:"pending",path:e.project.workspacePolicy.path},runtime:{...e.instance.runtime,kind:"docker",containerName:t,...n?{containerId:n}:{},labels:{...e.instance.runtime.labels,"task-handoff.instance-id":e.instance.id,"task-handoff.project-id":e.project.id,"task-handoff.node-id":s,"task-handoff.runtime-id":o,"task-handoff.image-id":e.image.id}}}}async stop(e){const t=e.instance.runtime.containerName||ai(e.instance.id);try{await this.runCommand("docker",["stop",t])}catch(e){if(!ri(e))throw ni("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){di(e);const n=e.instance.runtime.containerName||ai(e.instance.id),i=await this.inspectContainerId(n);if(!i)throw ni("INSTANCE_RUNTIME_RESTART_FAILED",`Docker container ${n} does not exist.`);si(n,i,t,"before restart","INSTANCE_RUNTIME_RESTART_FAILED"),await this.runCommand("docker",["restart",n]);const r=await this.inspectContainerId(n);if(!r||r!==i)throw ni("INSTANCE_RUNTIME_RESTART_FAILED",`Docker container identity changed while restarting ${n}.`);return si(n,r,t,"after restart","INSTANCE_RUNTIME_RESTART_FAILED"),this.runningResult(e,n,r)}async delete(e){const t=e.instance.runtime.containerName||ai(e.instance.id);try{await this.runCommand("docker",["rm","-f",t])}catch(e){if(!ri(e))throw ni("RUNTIME_EXECUTOR_FAILED",`Could not delete Docker container ${t}.`,e)}return{status:"stopped",health:"unknown",connectionStatus:"offline",target:{...e.instance.target,status:"unknown"},runtime:e.instance.runtime}}async installRuntime(e){const t=await this.installRuntimeRelease(e);si(e.containerName,t,e.expectedContainerId,"before runtime restart","INSTANCE_RUNTIME_RESTART_FAILED");try{await this.runCommand("docker",["restart",e.containerName])}catch(t){throw ni("INSTANCE_RUNTIME_RESTART_FAILED",`Could not restart Docker container ${e.containerName}.`,t)}const n=await this.inspectContainerId(e.containerName);if(!n||n!==t)throw ni("INSTANCE_RUNTIME_RESTART_FAILED",`Docker container identity changed while updating ${e.containerName}.`);return si(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 ni("INSTANCE_RUNTIME_INSTALL_FAILED",`Docker container ${e.containerName} does not exist.`);si(e.containerName,t,e.expectedContainerId,"before runtime install","INSTANCE_RUNTIME_INSTALL_FAILED");const n=`/opt/task-handoff/instance-runtime/incoming/task-handoff-runtime-${i=e.identity.version,i.replace(/[^0-9A-Za-z.+_-]/g,"-")}-${e.identity.sha256.slice(0,12)}.tar.gz`;var i;await this.runCommand("docker",["exec","--user","0",e.containerName,"install","-d","-o","root","-g","root","-m","0755","/opt/task-handoff/instance-runtime/incoming"]),await this.runCommand("docker",["cp",e.artifactPath,`${e.containerName}:${n}`]);try{await this.runCommand("docker",["exec","--user","0",e.containerName,"task-handoff-runtime","install","--artifact",n,"--version",e.identity.version,"--sha256",e.identity.sha256,"--platform",e.identity.platform,"--arch",e.identity.arch,"--launcher-abi",String(e.identity.launcherAbi)])}catch(t){throw ni("INSTANCE_RUNTIME_INSTALL_FAILED",`Could not install controlled-instance ${e.identity.version} in ${e.containerName}.`,t)}finally{await this.runCommand("docker",["exec","--user","0",e.containerName,"rm","-f",n]).catch(()=>({stdout:"",stderr:""}))}const r=await this.inspectContainerId(e.containerName);if(!r||r!==t)throw ni("INSTANCE_RUNTIME_INSTALL_FAILED",`Docker container identity changed while installing ${e.containerName}.`);return si(e.containerName,r,e.expectedContainerId,"after runtime install","INSTANCE_RUNTIME_INSTALL_FAILED"),t}async inspectRuntimeVersion(e){const t=await this.inspectContainerId(e);if(!t)return{};const n=await this.runCommand("docker",["exec","--user","agent",e,"task-handoff-runtime","verify-active"]).catch(()=>{});if(!n?.stdout)return{containerId:t};try{const e=Tt.safeParse(JSON.parse(n.stdout));return e.success?{containerId:t,...e.data}:{containerId:t}}catch{return{containerId:t}}}async inspectRuntimeTarget(e){let t,n;if(e){const i=await this.runCommand("docker",["inspect","--format","{{json .}}",e]).then(e=>JSON.parse(e.stdout.trim()||"{}")).catch(()=>{});if(t=i?.Platform,"string"==typeof i?.Image&&i.Image){const e=await this.runCommand("docker",["image","inspect","--format","{{json .}}",i.Image]).then(e=>JSON.parse(e.stdout.trim()||"{}")).catch(()=>{});t=e?.Os||t,n=e?.Architecture}}if(!t||!n){const e=await this.runCommand("docker",["info","--format","{{json .}}"]).then(e=>JSON.parse(e.stdout.trim()||"{}")).catch(e=>{throw ni("INSTANCE_BASE_RUNTIME_INCOMPATIBLE","Could not inspect the Docker runtime target.",e)});t||=e.OSType,n||=e.Architecture}const i="linux"===(r=t)||"darwin"===r?r:"windows"===r||"win32"===r?"win32":void 0;var r;const s=function(e){return"amd64"===e||"x86_64"===e||"x64"===e?"x64":"arm64"===e||"aarch64"===e?"arm64":void 0}(n);if(!i||!s)throw ni("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Docker reported an unsupported runtime target ${String(t||"unknown")}/${String(n||"unknown")}.`);return{platform:i,arch:s,launcherAbi:1}}async installRuntimeLauncher(e){const t=await this.inspectContainerId(e);if(!t)throw ni("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Docker container ${e} does not exist.`);const i=[[n.join(this.launcherAssetsDir,"entrypoint.sh"),"/root/.task-handoff-entrypoint.bootstrap"],[n.join(this.launcherAssetsDir,"instance-launcher.sh"),"/root/.task-handoff-instance-launcher.bootstrap"],[n.join(this.launcherAssetsDir,"runtime-installer.mjs"),"/root/.task-handoff-runtime-installer.bootstrap"]];for(const[t,n]of i)await this.runCommand("docker",["cp",t,`${e}:${n}`]);try{await this.runCommand("docker",["exec","--user","0",e,"bash","-ceu","install -d -o root -g root -m 0755 /opt/task-handoff/instance-runtime /opt/task-handoff/instance-runtime/releases /opt/task-handoff/instance-runtime/staging /opt/task-handoff/instance-runtime/incoming; chown -R root:root /opt/task-handoff/instance-runtime; chmod -R go-w /opt/task-handoff/instance-runtime; install -m 0755 /root/.task-handoff-entrypoint.bootstrap /usr/local/bin/task-handoff-entrypoint; install -m 0755 /root/.task-handoff-instance-launcher.bootstrap /usr/local/bin/task-handoff-instance-launcher; install -d /usr/local/lib/task-handoff; install -m 0755 /root/.task-handoff-runtime-installer.bootstrap /usr/local/lib/task-handoff/runtime-installer.mjs; ln -sfn /usr/local/lib/task-handoff/runtime-installer.mjs /usr/local/bin/task-handoff-runtime; rm -f /root/.task-handoff-entrypoint.bootstrap /root/.task-handoff-instance-launcher.bootstrap /root/.task-handoff-runtime-installer.bootstrap"])}catch(t){throw ni("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Could not install the runtime launcher in ${e}.`,t)}if(await this.inspectContainerId(e)!==t)throw ni("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Docker container identity changed while installing the runtime launcher in ${e}.`)}async inspectContainerId(e){try{return(await this.runCommand("docker",["inspect","--format","{{.Id}}",e])).stdout.trim()||void 0}catch(t){if(ri(t))return;throw ni("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(ri(t))return;throw ni("RUNTIME_EXECUTOR_FAILED",`Could not inspect Docker container ${e}.`,t)}try{const e=JSON.parse(t.stdout||"{}");if("string"!=typeof e.Id||!e.Id)throw new Error("Docker inspect did not return a container id.");const n=e.Config?.Labels&&"object"==typeof e.Config.Labels&&!Array.isArray(e.Config.Labels)?Object.fromEntries(Object.entries(e.Config.Labels).filter(e=>"string"==typeof e[1])):{};return{id:e.Id,labels:n}}catch(t){throw ni("RUNTIME_EXECUTOR_FAILED",`Docker returned invalid inspection data for ${e}.`,t)}}async containerPort(e,t){let n,i=!1;for(const r of this.portResolutionRetryDelaysMs){r>0&&await ti(r);try{const n=Zn((await this.runCommand("docker",["port",e,t])).stdout);if(n)return n}catch(e){n=e}try{const n=ei((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 ni("RUNTIME_EXECUTOR_FAILED",`Docker container ${e} does not publish ${t}.`);throw ni("RUNTIME_EXECUTOR_FAILED",`Could not resolve the published port for Docker container ${e}.`,n)}}function Zn(e){const t=e.split(/\r?\n/).find(Boolean);return t?.match(/:(\d+)$/)?.[1]}function ei(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 ti(e){return new Promise(t=>setTimeout(t,e))}function ni(e,t,n){const i=ii(n),r=new Error(i?`${t} Cause: ${i}`:t,void 0===n?void 0:{cause:n});return Object.assign(r,{statusCode:502,code:e}),r}function ii(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 ri(e){const t=ii(e)?.toLowerCase()||"";return t.includes("no such container")||t.includes("no such object")}function si(e,t,n,i,r){if(n&&t!==n)throw ni(r,`Docker container ${e} identity mismatch ${i}: expected ${n}, got ${t}.`)}async function oi(e=Jn){return async function(e=Jn){return(await e("docker",["images","--digests","--format","{{json .}}"])).stdout.split(/\r?\n/).map(e=>e.trim()).filter(Boolean).map(e=>{const t=JSON.parse(e),n=t.Repository||"<none>",i=t.Tag||"<none>",r=t.ID||t.IDShort||"",s="<none>"!==n&&"<none>"!==i?`${n}:${i}`:r,o="<none>"!==n&&t.Digest&&"<none>"!==t.Digest?[`${n}@${t.Digest}`]:[];return{repository:n,tag:i,id:r,createdSince:t.CreatedSince,size:t.Size,sizeBytes:Xn(t.Size),reference:s,repoDigests:o}}).filter(e=>Boolean(e.reference))}(e)}function ai(e){return`task-handoff-${e.replace(/[^a-zA-Z0-9_.-]/g,"-")}`}function ci(e,t,n){e.push("-e",`${t}=${n}`)}function di(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 li=a.z.enum(["created","starting","running","stopping","stopped","exited","failed","closed","terminated","unknown"]),ui=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(),pi=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:li.default("unknown"),bindings:a.z.array(ui).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()})),mi=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(pi).default([]),updatedAt:a.z.string().datetime()}).strict();a.z.object({streamId:a.z.string().trim().min(1).max(240),revision:a.z.number().int().min(0),lastEventAt:a.z.string().datetime(),snapshot:mi}).strict(),mi.pick({runningCount:!0,problemCount:!0,updatedAt:!0}).extend({revision:a.z.number().int().min(0).optional()});const gi=a.z.enum(["app-session-created","app-session-updated","app-session-deleted","app-session-recovered","control-action","heartbeat-sync","startup"]),hi=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:gi}).strict(),fi=a.z.object({meta:hi,snapshot:mi}).strict(),yi=a.z.object({meta:hi,session:pi}).strict(),Ii=a.z.object({meta:hi,sessionId:a.z.string().trim().min(1).max(160),tombstone:pi.optional(),expiresAt:a.z.string().datetime().optional()}).strict();function Ai(e){return e.startsWith("ai-session.")||e.startsWith("ai.session.")?"ai.sessions":e.startsWith("app-session.")?"app.sessions":e.startsWith("app.management")?"apps":e.startsWith("trigger.")?"triggers":e.startsWith("instance.")?"instances":e.startsWith("node.")?"nodes":e.startsWith("project.")?"projects":e.startsWith("model.")?"models":e.startsWith("image.")?"images":e.startsWith("market.")?"market":"system"}a.z.object({streamId:a.z.string().trim().min(1).max(240),instanceId:a.z.string().trim().min(1).max(160),sinceRevision:a.z.number().int().min(0),latestRevision:a.z.number().int().min(0),earliestRetainedRevision:a.z.number().int().min(0),syncRequired:a.z.boolean().default(!1),events:a.z.array(a.z.discriminatedUnion("type",[a.z.object({type:a.z.literal("app-session.snapshot"),payload:fi}).strict(),a.z.object({type:a.z.literal("app-session.patch"),payload:yi}).strict(),a.z.object({type:a.z.literal("app-session.removed"),payload:Ii}).strict()])).default([])}).strict();const bi=a.z.enum(["ai.sessions","app.sessions"]),wi=a.z.object({topic:bi,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(),vi=a.z.object({protocolVersion:a.z.literal(1),streams:a.z.array(wi)}).strict();class Ei{attempt=0;timer;get pending(){return Boolean(this.timer)}get attempts(){return this.attempt}schedule(e,t={}){if(this.timer)return;const n=function(e,t=Math.random){const n=Math.min(3e4,1e3*2**Math.max(0,e));return Math.min(3e4,Math.round(n*(.75+.5*t())))}(this.attempt,t.random);this.attempt+=1;const i=t.setTimeoutFn||setTimeout;return this.timer=i(()=>{this.timer=void 0,e()},n),{attempt:this.attempt,delay:n}}reset(e=clearTimeout){this.timer&&e(this.timer),this.timer=void 0,this.attempt=0}cancel(e=clearTimeout){this.timer&&e(this.timer),this.timer=void 0}}function Ni(e,t=6e4){const n=[];for(let i=0;i<e.length;i+=t)n.push(e.slice(i,i+t));return n}class zi{sockets=new Map;socketUrls=new Map;retries=new Map;outputs=new Set;imagePullTerminalByInstance=new Map;state;token;logger;safetyIntervalMs;lastAiSessionEventByInstance=new Map;lastAppSessionEventByInstance=new Map;timer;reconnectAttempts=0;safetyReconciliations=0;localSequence=0;createSocket;setIntervalFn;clearIntervalFn;constructor(e,t,n={}){var i;this.state=e,this.token=t,this.logger=n.logger,this.safetyIntervalMs=(i=n.safetyIntervalMs,Math.min(6e4,Math.max(3e4,i??45e3))),this.createSocket=n.createSocket||((e,t)=>new u(e,t)),this.setIntervalFn=n.setIntervalFn||setInterval,this.clearIntervalFn=n.clearIntervalFn||clearInterval}start(){this.sync(),this.timer=this.setIntervalFn(()=>{this.safetyReconciliations+=1,this.sync()},this.safetyIntervalMs)}stop(){this.timer&&(this.clearIntervalFn(this.timer),this.timer=void 0);for(const e of this.sockets.values())e.close();this.sockets.clear(),this.socketUrls.clear();for(const e of this.retries.values())e.timer.cancel();this.retries.clear(),this.outputs.clear()}addOutput(e){this.outputs.add(e),e.on("close",()=>this.outputs.delete(e)),e.on("error",()=>this.outputs.delete(e));for(const t of this.state.listInstances()){const n=Si(t);n?this.sendForwarded(e,this.createEvent(Ln,n,{instanceId:t.id})):this.logger?.warn?.({instanceId:t.id},"instance.lifecycle.snapshot.invalid")}for(const[t,n]of this.imagePullTerminalByInstance)Ni(n.tail).forEach((i,r)=>this.sendForwarded(e,this.createEvent(In,{...n.output,sequence:n.output.sequence+r,data:i,...0===r?{replay:!0}:{}},{instanceId:t}))),n.finished&&this.sendForwarded(e,this.createEvent(An,n.finished,{instanceId:t}));return this.syncNow(),()=>{this.outputs.delete(e)}}publish(e,t,n={}){this.rememberImagePullTerminal(e,t);const i=this.createEvent(e,t,n);for(const e of this.outputs)this.sendForwarded(e,i)}rememberImagePullTerminal(e,t){if(e===In){const e=wn.safeParse(t);if(!e.success)return;const n=e.data,i=this.imagePullTerminalByInstance.get(n.instanceId);if(i&&n.generation<i.output.generation)return;const r=i?.output.generation===n.generation,s=n.replay||!r?n.data:`${i.tail}${n.data}`.slice(-262144);return void this.imagePullTerminalByInstance.set(n.instanceId,{output:n,tail:s})}if(e===An){const e=vn.safeParse(t);if(!e.success)return;const n=e.data,i=this.imagePullTerminalByInstance.get(n.instanceId);i?.output.generation===n.generation&&(i.finished=n)}}publishInstanceLifecycle(e){this.publish(Ln,function(e){return $n.parse(_i(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:Ai(e),createdAt:(new Date).toISOString(),payload:t,scope:n}}sendForwarded(e,t){const n=JSON.stringify({type:"node-agent.event.forwarded",event:t});e.readyState===u.OPEN&&e.send(n)}syncNow(){this.sync()}diagnostics(){return{reconnectAttempts:this.reconnectAttempts,safetyReconciliations:this.safetyReconciliations,activeConnections:this.sockets.size,pendingRetries:[...this.retries.values()].filter(e=>e.timer.pending).length,safetyIntervalMs:this.safetyIntervalMs}}sync(){const e=new Set(this.state.listInstances().map(e=>e.id));for(const t of this.imagePullTerminalByInstance.keys())e.has(t)||this.imagePullTerminalByInstance.delete(t);if(!this.outputs.size){for(const e of this.sockets.values())e.close();this.sockets.clear(),this.socketUrls.clear();for(const e of this.retries.values())e.timer.cancel();return void this.retries.clear()}const t=new Set;for(const e of this.state.listInstances()){const n=ki(e);if(!n)continue;t.add(e.id);const i=this.retries.get(e.id);i?.timer.pending&&i.url!==n&&(i.timer.cancel(),this.retries.delete(e.id)),this.socketUrls.get(e.id)!==n&&this.sockets.has(e.id)&&(this.sockets.get(e.id)?.close(),this.sockets.delete(e.id)),this.sockets.has(e.id)||this.retries.get(e.id)?.timer.pending||this.connect(e.id,n)}for(const[e,n]of this.sockets)if(!t.has(e)){n.close(),this.sockets.delete(e),this.socketUrls.delete(e);const t=this.retries.get(e);t?.timer.cancel(),this.retries.delete(e)}for(const[e,n]of this.retries)t.has(e)||(n.timer.cancel(),this.retries.delete(e),this.socketUrls.delete(e))}connect(e,t){const n=this.token?{authorization:`Bearer ${this.token}`}:void 0,i=this.createSocket(t,{headers:n});this.sockets.set(e,i),this.socketUrls.set(e,t),i.on("open",()=>{const n=this.retries.get(e);n?.timer.reset(),this.retries.set(e,{timer:n?.timer||new Ei,url:t}),i.readyState===u.OPEN&&(i.send(JSON.stringify({v:1,type:"subscribe",topics:[z,"app.sessions","apps","instances"]})),this.logger?.info?.({instanceId:e,url:t},"ai-session.event.forward.connect"),this.logger?.info?.({instanceId:e,url:t},"app-session.event.forward.connect"))}),i.on("message",t=>{const n=function(e,t){try{const n=JSON.parse(String(e));if(!n||"object"!=typeof n||Array.isArray(n))return;const i=n,r="string"==typeof i.type?i.type:"";if(!r||"events.connected"===r)return;const s=i.scope&&"object"==typeof i.scope&&!Array.isArray(i.scope)?i.scope:{};return{v:1,id:"string"==typeof i.id?i.id:`evt_${Date.now().toString(36)}`,seq:Number(i.seq)||0,type:r,topic:"string"==typeof i.topic?i.topic:Ai(r),createdAt:"string"==typeof i.createdAt?i.createdAt:(new Date).toISOString(),payload:"payload"in i?i.payload:{},scope:{...s,instanceId:t}}}catch{return}}(t,e);if(!n)return;if("streams.hello"===n.type){const t=vi.safeParse(n.payload);if(!t.success)return this.logger?.warn?.({instanceId:e,issues:t.error.issues},"session-stream.handshake.invalid"),void i.close(1002,"Incompatible session stream handshake.");const r=JSON.stringify({type:"node-agent.streams.hello",instanceId:e,payload:t.data});for(const e of this.outputs)e.readyState===u.OPEN&&e.send(r);return}this.recordAiSessionEvent(e,n),this.recordAppSessionEvent(e,n);const r=JSON.stringify({type:"node-agent.event.forwarded",event:n});for(const e of this.outputs)e.readyState===u.OPEN&&e.send(r)}),i.on("close",()=>{this.sockets.get(e)===i&&(this.sockets.delete(e),this.socketUrls.delete(e),this.scheduleReconnect(e))}),i.on("error",()=>{this.logger?.warn?.({instanceId:e,url:t},"ai-session.event.forward.error"),this.logger?.warn?.({instanceId:e,url:t},"app-session.event.forward.error"),i.close()})}scheduleReconnect(e){const t=this.state.listInstances().find(t=>t.id===e),n=t&&ki(t);if(!n||!this.outputs.size)return;const i=this.retries.get(e)??{timer:new Ei};if(i.timer.pending)return;i.url=n;const r=i.timer.schedule(()=>{this.sockets.has(e)||this.connect(e,n)});r&&(this.reconnectAttempts+=1,this.logger?.info?.({instanceId:e,url:n,attempt:r.attempt,delay:r.delay,reconnectAttempts:this.reconnectAttempts},"session-stream.connection.reconnect-scheduled")),this.retries.set(e,i)}recordAiSessionEvent(e,t){if(t.topic!==z)return;if("ai-session.message-delta"===t.type)return;const n=Ti(t.payload),i=this.lastAiSessionEventByInstance.get(e);i?.streamId===n.streamId&&void 0!==i.revision&&void 0!==n.revision&&n.revision>i.revision+1&&this.logger?.warn?.({instanceId:e,traceId:n.traceId,streamId:n.streamId,previousRevision:i.revision,revision:n.revision},"ai-session.event.forward.gap"),this.lastAiSessionEventByInstance.set(e,{streamId:n.streamId??i?.streamId,revision:n.revision??i?.revision}),this.logger?.info?.({instanceId:e,traceId:n.traceId,eventType:t.type,streamId:n.streamId,revision:n.revision},"ai-session.event.forward.message")}recordAppSessionEvent(e,t){if("app.sessions"!==t.topic)return;const n=Ti(t.payload),i=this.lastAppSessionEventByInstance.get(e);i?.streamId===n.streamId&&void 0!==i.revision&&void 0!==n.revision&&n.revision>i.revision+1&&this.logger?.warn?.({instanceId:e,traceId:n.traceId,streamId:n.streamId,previousRevision:i.revision,revision:n.revision},"app-session.event.forward.gap"),this.lastAppSessionEventByInstance.set(e,{streamId:n.streamId??i?.streamId,revision:n.revision??i?.revision}),this.logger?.info?.({instanceId:e,traceId:n.traceId,eventType:t.type,streamId:n.streamId,revision:n.revision},"app-session.event.forward.message")}}function Si(e){const t=$n.safeParse(_i(e));return t.success?t.data:void 0}function _i(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 Ti(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 ki(e){if(!function(e){return!1!==e.ready&&(!e.runtimeVersion||["matched","failed"].includes(e.runtimeVersion.phase))}(e))return;const t=e.target?.api||e.target?.web;if(t)try{const e=new URL("/api/events",t);return e.protocol="https:"===e.protocol?"wss:":"ws:",e.toString()}catch{return}}const Ci=new Set(["provisioning","starting","registering","registered","running","unhealthy"]),xi=JSON.stringify({id:"{{.ID}}",name:"{{.Name}}",cpu:"{{.CPUPerc}}",memory:"{{.MemUsage}}",memoryPercent:"{{.MemPerc}}",network:"{{.NetIO}}",blockIo:"{{.BlockIO}}",pids:"{{.PIDs}}"});class Oi{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(!Ci.has(t.status))return Li(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=Ri(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,Ri(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=>Ci.has(e.status)&&(e.runtime.containerId||e.runtime.containerName));for(const t of e.filter(e=>Ci.has(e.status)&&!e.runtime.containerId&&!e.runtime.containerName))this.update($i(t.id));for(const t of e.filter(e=>!Ci.has(e.status)))this.update(Li(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",xi,...n],{timeoutMs:5e3});this.applyDockerOutput(t,e.stdout,i)}catch(e){if(1===t.length)return void this.update(Fi(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",xi,t],{timeoutMs:5e3});this.applyDockerOutput([e],n.stdout,i)}catch(t){this.update(Fi(e.id,i,t instanceof Error?t.message:String(t)))}}))}}applyDockerOutput(e,t,n){const i=function(e,t=(new Date).toISOString()){const n=new Map;for(const i of e.split(/\r?\n/).filter(Boolean)){let e;try{e=JSON.parse(i)}catch{continue}const r=Mi(e.id),s=Mi(e.name),o=r||s;if(!o)continue;const a=Di(Mi(e.memory)),c=Di(Mi(e.network)),d=Di(Mi(e.blockIo)),l=_n.parse({instanceId:o,runtimeKind:"docker",state:"available",sampledAt:t,cpu:Pi(e.cpu,"usagePercent"),memory:a?{usageBytes:a[0],...void 0!==a[1]?{limitBytes:a[1]}:{},...Pi(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:ji(e.pids)});r&&n.set(r,l),s&&n.set(s,l)}return n}(t,n);for(const t of e){const e=[t.runtime.containerId,t.runtime.containerName].filter(Boolean),r=[...i.entries()].find(([t])=>e.some(e=>e===t||e.startsWith(t)||t.startsWith(e)))?.[1];this.update(r?{...r,instanceId:t.id}:Fi(t.id,n,"Container metrics were not returned by Docker."))}}update(e){const t=_n.parse(e);this.snapshots.set(t.instanceId,t),this.publish?.(t)}}function Ri(e){return[e.status,e.runtime.containerId||"",e.runtime.containerName||""].join("\0")}function Di(e){if(!e)return;const[t,n]=e.split("/").map(e=>function(e){const t=e.trim().match(/^([0-9]+(?:\.[0-9]+)?)\s*([kmgtpe]?i?b)$/i);if(!t)return;const n=Number(t[1]),i=t[2].toLowerCase(),r=i.includes("i"),s="b"===i[0]?"":i[0],o=s?"kmgtpe".indexOf(s)+1:0;return Math.round(n*(r?1024:1e3)**o)}(e||""));return void 0===t?void 0:[t,n]}function Pi(e,t){const n=Number(Mi(e).replace(/%$/,""));return Number.isFinite(n)&&n>=0?{[t]:n}:void 0}function ji(e){const t=Number(Mi(e));return Number.isFinite(t)&&t>=0?t:void 0}function Mi(e){return"string"==typeof e||"number"==typeof e?String(e).trim():""}function Li(e){return{instanceId:e,runtimeKind:"docker",state:"stopped",sampledAt:(new Date).toISOString()}}function $i(e){return{instanceId:e,runtimeKind:"docker",state:"pending",sampledAt:(new Date).toISOString()}}function Fi(e,t,n){return{instanceId:e,runtimeKind:"docker",state:"unavailable",sampledAt:t,error:n.slice(0,2048)}}function Ui(e){try{return t.statSync(e).isDirectory()}catch{return!1}}function Vi(e,i){let r;try{r=t.statSync(e)}catch{return}if(!r.isDirectory())return;const s=n.resolve(e),o=n.basename(s)||s;let a=[];try{a=i>0?t.readdirSync(s,{withFileTypes:!0}):[]}catch{a=[]}const c=i>0?a.filter(e=>e.isDirectory()||e.isSymbolicLink()&&Ui(n.join(s,e.name))).sort((e,t)=>e.name.localeCompare(t.name)).slice(0,80).flatMap(e=>{const t=Vi(n.join(s,e.name),i-1);return t?[t]:[]}):[];return{name:o,path:s,children:c}}function qi(e){return(e.path?[e.path]:function(){if("win32"!==process.platform)return[n.parse(n.resolve(process.cwd())).root];const e=n.parse(n.resolve(process.cwd())).root,t=Array.from({length:26},(e,t)=>`${String.fromCharCode(65+t)}:\\`);return[...new Set([e,...t])].filter(Ui)}()).flatMap(t=>{const n=Vi(t,e.depth);return n?[n]:[]})}function Hi(){return process.env.TASK_HANDOFF_NODE_AGENT_DATA_DIR||n.join(p.homedir(),".config","task-handoff","node-agent")}function Bi(e=Hi()){const t=n.resolve(e);return{dataDir:t,identityPath:n.join(t,"identity.json"),settingsPath:n.join(t,"runtime-settings.json"),localFoldersDir:n.join(t,"local-folders"),nodeRuntimesDir:n.join(t,"node-runtimes"),controlledInstancesDir:n.join(t,"controlled-instances"),nodeModelsDir:n.join(t,"models"),modelAssignmentsDir:n.join(t,"model-assignments"),modelEnvironmentsDir:n.join(t,"model-environments"),updatesDir:n.join(t,"updates"),logsDir:n.join(t,"logs")}}class Ki 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 Gi(e){return n.join(e,"owner.json")}function Ji(e){return n.join(e,"initializing.json")}function Wi(e){return n.join(e,"recovering.json")}function Yi(e){return Number.isInteger(e)&&Number(e)>0}function Xi(e,n=process.platform){if(Yi(e)){if("linux"===n)try{const n=t.readFileSync(`/proc/${e}/stat`,"utf8"),i=n.lastIndexOf(")");if(i<0)return;const r=n.slice(i+2).trim().split(/\s+/)[19];return r?`linux:${r}`:void 0}catch{return}if(["darwin","freebsd","openbsd","aix","sunos"].includes(n)){const t=d.spawnSync("ps",["-o","lstart=","-p",String(e)],{encoding:"utf8",timeout:1e3}),i=0===t.status?t.stdout.trim().replace(/\s+/g," "):"";return i?`${n}:${i}`:void 0}if("win32"===n){const t=`(Get-Process -Id ${e} -ErrorAction Stop).StartTime.ToUniversalTime().Ticks`,n=d.spawnSync("powershell.exe",["-NoProfile","-NonInteractive","-Command",t],{encoding:"utf8",timeout:2e3}),i=0===n.status?n.stdout.trim():"";return/^\d+$/.test(i)?`win32:${i}`:void 0}}}function Qi(e){try{const n=JSON.parse(t.readFileSync(Gi(e),"utf8"));if(Yi(n.pid)&&"string"==typeof n.startTime){const e=n;return{pid:e.pid,hostname:"string"==typeof e.hostname&&e.hostname?e.hostname:p.hostname(),component:e.component||"server-update",command:"string"==typeof e.command?e.command:"",acquiredAt:"string"==typeof e.createdAt&&Number.isFinite(Date.parse(e.createdAt))?e.createdAt:new Date(0).toISOString(),token:"string"==typeof e.token&&e.token?e.token:`legacy:${e.pid}:${e.startTime}`,startIdentity:e.startTime.startsWith("linux:")?e.startTime:`linux:${e.startTime}`}}if(!(Yi(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 Zi=Qi;function er(e){if(!Yi(e))return!1;try{return process.kill(Number(e),0),!0}catch(e){return"EPERM"===e.code}}function tr(e){if(!e||!er(e.pid))return!1;if(!e.startIdentity)return!0;const t=Xi(e.pid);return void 0===t||t===e.startIdentity}function nr(e,i){const r=n.join(e,`.owner-${i.token}.tmp`);t.writeFileSync(r,`${JSON.stringify(i,null,2)}\n`,{encoding:"utf8",mode:384,flag:"wx"});const s=ir(e);if(s?.token!==i.token)throw sr(r),new Error(`Process lock initialization was superseded: ${e}`);t.renameSync(r,Gi(e)),sr(Ji(e))}function ir(e){try{return JSON.parse(t.readFileSync(Ji(e),"utf8"))}catch{return}}function rr(e){const t=ir(e);return Yi(t?.pid)&&tr({pid:t.pid,startIdentity:t.startIdentity})}function sr(e){try{t.unlinkSync(e)}catch(e){if("ENOENT"!==e.code)throw e}}function or(){Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,20)}function ar(e){try{const n=ir(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 cr(e,i){try{return t.writeFileSync(Wi(e),`${JSON.stringify({token:i,pid:process.pid,startedAt:(new Date).toISOString()})}\n`,{encoding:"utf8",mode:384,flag:"wx"}),!0}catch(r){if("EEXIST"===r.code)return!!function(e){const i=Wi(e),r=dr(i),s=Date.parse(r?.startedAt||"");if(er(r?.pid)||Number.isFinite(s)&&Date.now()-s<2e3)return!1;const o=n.join(e,`.recovering-${c.randomUUID()}.stale`);try{t.renameSync(i,o)}catch(e){if(["ENOENT","EEXIST"].includes(e.code||""))return!1;throw e}const a=dr(o);if(a?.token===r?.token)return sr(o),!0;try{t.linkSync(o,i)}catch(e){if("EEXIST"!==e.code)throw e}finally{sr(o)}return!1}(e)&&cr(e,i);if("ENOENT"===r.code)return!1;throw r}}function dr(e){try{return JSON.parse(t.readFileSync(e,"utf8"))}catch{return}}function lr(e,t){return dr(Wi(e))?.token===t}function ur(e,t=process.platform){const i=n.resolve(e),r=c.createHash("sha256").update(i).digest("hex").slice(0,16);return"win32"===t?`\\\\.\\pipe\\task-handoff-node-agent-${r}`:n.join("/tmp",`task-handoff-node-agent-${process.getuid?.()??"user"}`,`${r}.sock`)}const pr="runtime-manifest.json";class mr 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 gr(e,t=""){const i=[],r=await h.readdir(n.join(e,t),{withFileTypes:!0});for(const s of r){const r=t?n.posix.join(t,s.name):s.name;if(!t&&r===pr)continue;const o=n.join(e,...r.split("/"));if(s.isDirectory()){i.push(...await gr(e,r));continue}if(s.isSymbolicLink()){const t=await h.readlink(o);if(n.isAbsolute(t))throw new mr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload symlink is absolute: ${r}`);const s=n.resolve(n.dirname(o),t),a=n.relative(n.resolve(e),s);if(!a||".."===a||a.startsWith(`..${n.sep}`)||n.isAbsolute(a))throw new mr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload symlink escapes the artifact: ${r}`);if(!await h.lstat(s).catch(()=>{}))throw new mr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload symlink is broken: ${r}`);i.push({absolutePath:o,relativePath:r,kind:"symlink",target:t,size:Buffer.byteLength(t)});continue}if(!s.isFile())throw new mr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload contains unsupported entry: ${r}`);const a=await h.lstat(o);i.push({absolutePath:o,relativePath:r,kind:"file",size:a.size})}return i}async function hr(e){const n=(await gr(e)).sort((e,t)=>function(e,t){return Buffer.compare(Buffer.from(e,"utf8"),Buffer.from(t,"utf8"))}(e.relativePath,t.relativePath)),i=c.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 fr(e){for(const[t,n]of[["version",e.version],["platform",e.platform],["arch",e.arch]])if(!/^[0-9A-Za-z._-]+$/.test(n))throw new mr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Invalid runtime artifact ${t}: ${n}`);return`${e.version}-${e.platform}-${e.arch}`}function yr(e,t){return`${fr(e)}-${e.sha256}-${t}`}async function Ir(e){const n=c.createHash("sha256");for await(const i of t.createReadStream(e))n.update(i);return n.digest("hex")}class Ar{#e;#t;#n=new Map;constructor(e){this.#e=e.cacheDir,this.#t=e.fetchImpl??fetch}resolve(e,t){const n=Tt.parse(e);if(!/^[a-f0-9]{64}$/.test(t.archiveSha256))throw new mr("INSTANCE_RUNTIME_ARTIFACT_INVALID","Runtime archive SHA-256 is invalid.");if((t.archiveUrl?1:0)+(t.archivePath?1:0)!=1)throw new mr("INSTANCE_RUNTIME_ARTIFACT_INVALID","Runtime artifact source must specify exactly one archive location.");const i=yr(n,t.archiveSha256),r=this.#n.get(i);if(r)return r;const s=this.#i(n,t).finally(()=>this.#n.delete(i));return this.#n.set(i,s),s}async#i(e,i){if(!/^[a-f0-9]{64}$/.test(i.archiveSha256))throw new mr("INSTANCE_RUNTIME_ARTIFACT_INVALID","Runtime archive SHA-256 is invalid.");const r=yr(e,i.archiveSha256),s=n.join(this.#e,"archives"),o=n.join(s,`${r}.tar.gz`);if(await h.mkdir(s,{recursive:!0}),await this.#r(o,e,i.archiveSha256))return{identity:e,archivePath:o,cacheHit:!0};await h.rm(o,{force:!0});const a=n.join(s,`.${r}.${c.randomUUID()}.part`);try{const n=await h.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 mr("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 Ir(a)!==i.archiveSha256)throw new mr("INSTANCE_RUNTIME_ARTIFACT_INVALID","Downloaded runtime archive SHA-256 does not match release metadata.");return await this.#s(a,e),await h.rename(a,o),{identity:e,archivePath:o,cacheHit:!1}}catch(e){if(e instanceof mr)throw e;throw new mr("INSTANCE_RUNTIME_ARTIFACT_UNAVAILABLE","Could not download runtime artifact.",{cause:e,retryable:!0})}finally{await h.rm(a,{force:!0})}}async#r(e,t,n){try{return await Ir(e)===n&&(await this.#s(e,t),!0)}catch{return!1}}async#s(e,t){const i=n.join(this.#e,"validation",`${fr(t)}-${c.randomUUID()}`);try{await async function(e,t){await h.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 mr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime archive entry escapes the artifact root: ${e}`);const r=t.type;if("File"!==r&&"OldFile"!==r&&"Directory"!==r&&"SymbolicLink"!==r)throw new mr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime archive contains unsupported entry type ${r??"unknown"}: ${e}`);return!0}})}catch(e){throw new mr("INSTANCE_RUNTIME_ARTIFACT_INVALID","Could not extract runtime artifact safely.",{cause:e})}}(e,i),await async function(e,t,i){const r=await async function(e){let t;try{t=JSON.parse(await h.readFile(n.join(e,pr),"utf8"))}catch(e){throw new mr("INSTANCE_RUNTIME_ARTIFACT_INVALID","Runtime artifact manifest is missing or invalid JSON.",{cause:e})}const i=Tt.safeParse(t);if(!i.success)throw new mr("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 mr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime artifact ${"sha256"===n?"SHA-256":n} mismatch: expected ${t[n]}, got ${e[n]}.`)}(r,t),1!==r.formatVersion)throw new mr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Unsupported runtime artifact format ${r.formatVersion}.`);if(i?.platform&&"universal"!==r.platform&&r.platform!==i.platform)throw new mr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime artifact platform ${r.platform} does not match ${i.platform}.`);if(i?.arch&&"universal"!==r.arch&&r.arch!==i.arch)throw new mr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime artifact architecture ${r.arch} does not match ${i.arch}.`);if(void 0!==i?.launcherAbi&&r.launcherAbi>i.launcherAbi)throw new mr("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Runtime requires launcher ABI ${r.launcherAbi}, but the base runtime provides ${i.launcherAbi}.`);const s=function(e,t){if(!e||e.includes("\\")||n.posix.isAbsolute(e))throw new mr("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 mr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`${t} escapes the runtime root.`);return i}(r.entrypoint,"Runtime entrypoint"),o=await h.lstat(n.join(e,...s.split("/"))).catch(()=>{});if(!o?.isFile())throw new mr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime entrypoint is missing: ${s}`);const a=await hr(e);if(a!==r.sha256)throw new mr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload SHA-256 mismatch: expected ${r.sha256}, got ${a}.`);return r}(i,t,{platform:t.platform,arch:t.arch})}finally{await h.rm(i,{recursive:!0,force:!0})}}}async function br(e,t,i,r=fetch){if("linux"!==t||!["x64","arm64"].includes(i))throw new mr("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Managed controlled-instance updates require a Linux x64 or arm64 target, received ${t}/${i}.`);const s=await async function(e){const t=`controlled-instance-runtime-${e}-linux-universal`,i=function(){const e=process.env.TASK_HANDOFF_BUNDLED_RUNTIME_DIR?.trim();return n.resolve(e||n.join(n.dirname(process.argv[1]||process.cwd()),"..","runtime-artifacts"))}();try{const[r,s]=await Promise.all([h.readFile(n.join(i,`${t}.manifest.json`),"utf8"),h.readFile(n.join(i,`${t}.tar.gz.sha256`),"utf8")]),o=Tt.safeParse(JSON.parse(r));if(!o.success||o.data.version!==e||"linux"!==o.data.platform||"universal"!==o.data.arch)throw new mr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Bundled controlled-instance ${e} has an invalid Linux manifest.`);const a=s.trim().split(/\s+/)[0]?.toLowerCase();if(!a||!/^[a-f0-9]{64}$/.test(a))throw new mr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Bundled controlled-instance ${e} has an invalid archive checksum.`);return{identity:o.data,source:{archivePath:n.join(i,`${t}.tar.gz`),archiveSha256:a}}}catch(t){if("ENOENT"===t.code)return;if(t instanceof mr)throw t;throw new mr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Could not read bundled controlled-instance ${e}.`,{cause:t})}}(e);if(s)return s;const o=`controlled-instance-runtime-${e}-linux-universal`,a=function(e){const t=process.env.TASK_HANDOFF_RUNTIME_RELEASE_BASE_URL?.trim();return t?t.replaceAll("{version}",e).replace(/\/$/,""):`https://github.com/edgestorage/task-handoff/releases/download/v${e}`}(e),c=`${a}/${o}.manifest.json`,d=`${a}/${o}.tar.gz`,l=`${a}/${o}.tar.gz.sha256`,[u,p]=await Promise.all([r(c),r(l)]).catch(t=>{throw new mr("INSTANCE_RUNTIME_ARTIFACT_UNAVAILABLE",`Could not read release metadata for controlled-instance ${e}.`,{cause:t,retryable:!0})});if(!u.ok||!p.ok)throw new mr("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 mr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Release manifest for controlled-instance ${e} is not valid JSON.`,{cause:t})}const g=Tt.safeParse(m);if(!g.success)throw new mr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Release manifest for controlled-instance ${e} is invalid: ${g.error.message}`);if(g.data.version!==e||"linux"!==g.data.platform||"universal"!==g.data.arch)throw new mr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Release identity mismatch: requested ${e}-linux-universal, received ${g.data.version}-${g.data.platform}-${g.data.arch}.`);const f=(await p.text()).trim().split(/\s+/)[0]?.toLowerCase();if(!f||!/^[a-f0-9]{64}$/.test(f))throw new mr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Release checksum for controlled-instance ${e} is invalid.`);return{identity:g.data,source:{archiveUrl:d,archiveSha256:f}}}class wr{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=kr(i.retryBaseDelayMs??1e3,"retryBaseDelayMs"),this.retryMaxDelayMs=kr(i.retryMaxDelayMs??3e4,"retryMaxDelayMs")}schedule(e,t={}){const n=this.requests.get(e)||{startRequested:!1,resumeCancelled:!1};n.startRequested||=!0===t.startRequested,n.resumeCancelled||=!0===t.resumeCancelled||!0===t.startRequested,n.resumeCancelled&&this.cancelled.delete(e),this.requests.set(e,n);const i=this.inFlight.get(e);if(i)return i;const r=Promise.resolve().then(()=>this.reconcile(e,n)).finally(()=>{this.inFlight.delete(e),this.requests.delete(e)});return this.inFlight.set(e,r),r}isRunning(e){return this.inFlight.has(e)}cancel(e){return this.cancelled.add(e),this.inFlight.get(e)}async reconcile(e,t){let n=this.requireInstance(e);const i=this.desiredVersion();if(this.cancelled.has(e)&&!t.resumeCancelled)return this.storePhase(n,"pending");const r=vr(n),s=r===i&&(await(this.hooks.isInstalled?.(n,i))??!0);if(this.cancelled.has(e))return this.storePhase(this.requireInstance(e),"pending");if(r===i&&s)return this.storeState(n,{desiredVersion:i,actualVersion:r,phase:"matched",attempt:n.runtimeVersion?.attempt||0,matchedAt:this.timestamp()},!Nr(n)&&"failed"!==n.health);const o=n.runtimeVersion?.desiredVersion===i;if(o&&"failed"===n.runtimeVersion?.phase)return n;if(o&&(n.runtimeVersion?.attempt||0)>=this.maxAttempts)return"failed"===n.runtimeVersion?.phase&&n.runtimeVersion.error?n:this.storeBatchFailure(n,i,Tr(i,r,this.maxAttempts,n.runtimeVersion?.error));if(n=this.storeState(n,function(e,t,n,i=!1){const r=e.runtimeVersion,s=r?.desiredVersion===t&&"matched"!==r.phase;return{desiredVersion:t,...n?{actualVersion:n}:{},phase:"pending",attempt:s?r.attempt:0,error:(s?r.error:void 0)||(n!==t||i?zr(t,n):Sr("INSTANCE_RUNTIME_VERIFICATION_FAILED",`Controlled-instance ${t} is running, but the active runtime artifact does not match the desired release identity.`,t,n,!0))}}(n,i,r,s)),Nr(n)&&!t.startRequested)return n;let a=!1;try{for(;(n.runtimeVersion?.attempt||0)<this.maxAttempts;){if(this.cancelled.has(e))return this.storePhase(this.requireInstance(e),"pending");let r;try{if(n=this.storePhase(n,"draining"),await(this.hooks.beginDrain?.(n)),a=!0,n=this.requireInstance(e),Er(n)){const t=await this.waitUntil(e,this.drainTimeoutMs,e=>!Er(e));if(n=this.requireInstance(e),!t){if(this.cancelled.has(e))return this.storePhase(n,"pending");await(this.hooks.onForcedDrain?.(n))}}if(n=this.storePhase(this.requireInstance(e),"installing",!0),await this.hooks.install(n,i),this.cancelled.has(e)||Nr(this.requireInstance(e))&&!t.startRequested)return this.storePhase(this.requireInstance(e),"pending");if(n=this.storePhase(this.requireInstance(e),"restarting"),await this.hooks.restart(n),this.cancelled.has(e))return this.storePhase(this.requireInstance(e),"pending");n=this.storePhase(this.requireInstance(e),"verifying");const r=await this.waitUntil(e,this.verificationTimeoutMs,e=>vr(e)===i);if(this.cancelled.has(e))return this.storePhase(this.requireInstance(e),"pending");if(!r)throw Sr("INSTANCE_RUNTIME_VERIFICATION_FAILED",`Instance ${e} did not register controlled-instance ${i} after restart.`,i,vr(this.requireInstance(e)),!0);const s=this.requireInstance(e);if(this.hooks.isInstalled&&!await this.hooks.isInstalled(s,i))throw Sr("INSTANCE_RUNTIME_VERIFICATION_FAILED",`Instance ${e} reported controlled-instance ${i}, but its active runtime release is missing.`,i,vr(s),!0);return this.storeState(s,{desiredVersion:i,actualVersion:i,phase:"matched",attempt:s.runtimeVersion?.attempt||1,matchedAt:this.timestamp()},!Nr(s)&&"failed"!==s.health)}catch(t){if(this.cancelled.has(e))return this.storePhase(this.requireInstance(e),"pending");r=_r(t,i,vr(this.store.get(e)))}n=this.requireInstance(e);const s=n.runtimeVersion?.attempt||1;if(!r.retryable||s>=this.maxAttempts)return this.storeBatchFailure(n,i,s>=this.maxAttempts&&r.retryable?Tr(i,vr(n),this.maxAttempts,r):r);n=this.storeState(n,{desiredVersion:i,...vr(n)?{actualVersion:vr(n)}:{},phase:"pending",attempt:s,lastAttemptAt:this.timestamp(),error:r}),await this.delay(this.retryDelayMs(s))}return this.storeBatchFailure(n,i,Tr(i,vr(n),this.maxAttempts,n.runtimeVersion?.error))}finally{a&&await(this.hooks.endDrain?.(this.requireInstance(e)))}}storeBatchFailure(e,t,n){const i=vr(e);return this.storeState(e,{desiredVersion:t,...i?{actualVersion:i}:{},phase:"failed",attempt:e.runtimeVersion?.attempt||0,lastAttemptAt:this.timestamp(),error:n})}retryDelayMs(e){return Math.min(this.retryMaxDelayMs,this.retryBaseDelayMs*2**Math.max(0,e-1))}storePhase(e,t,n=!1){const i=this.desiredVersion(),r=vr(e),s=e.runtimeVersion?.desiredVersion===i?e.runtimeVersion.error:void 0;return this.storeState(e,{desiredVersion:i,...r?{actualVersion:r}:{},phase:t,attempt:(e.runtimeVersion?.attempt||0)+(n?1:0),lastAttemptAt:this.timestamp(),...s?{error:s}:"pending"===t?{error:zr(i,r)}:{}},"restarting"!==t&&void 0)}storeState(e,t,n){const i=this.store.get(e.id)||e;return this.store.put(Mn.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 vr(e){return e?.build?.packageVersion||e?.instanceVersion}function Er(e){return e.apps.runningCount>0||e.aiSessions.runningCount>0}function Nr(e){return["created","stopped","failed"].includes(e.status)}function zr(e,t){return Sr("INSTANCE_RUNTIME_VERSION_MISMATCH",`Expected controlled-instance ${e}, received ${t||"an unknown version"}.`,e,t,!0)}function Sr(e,t,n,i,r){return{code:e,message:t,expectedVersion:n,...i?{actualVersion:i}:{},retryable:r}}function _r(e,t,n){if(e&&"object"==typeof e&&"code"in e&&"message"in e){const i=e,r=kt.shape.code.safeParse(i.code);if(r.success&&"string"==typeof i.message)return Sr(r.data,i.message,t,n,"boolean"!=typeof i.retryable||i.retryable)}return Sr("INSTANCE_RUNTIME_INSTALL_FAILED",e instanceof Error?e.message:String(e),t,n,!0)}function Tr(e,t,n,i){const r=i?.message?` Last error: ${i.message}`:"";return Sr(i?.code||"INSTANCE_RUNTIME_INSTALL_FAILED",`Runtime convergence stopped after ${n} attempts for this instance run.${r}`,e,t,!0)}function kr(e,t){if(!Number.isFinite(e)||e<0)throw new TypeError(`${t} must be a nonnegative finite number.`);return e}function Cr(e,n=448){t.mkdirSync(e,{recursive:!0,mode:n}),t.chmodSync(e,n)}function xr(e,i,r={}){const s=r.directoryMode??448,o=r.fileMode??384;Cr(n.dirname(e),s),I.sync(e,`${JSON.stringify(i,null,2)}\n`,{encoding:"utf8",mode:o}),t.chmodSync(e,o)}function Or(e,t){console.warn(JSON.stringify({message:e,...t}))}function Rr(e){return e&&"object"==typeof e&&"issues"in e?{issues:e.issues}:{error:e instanceof Error?e.message:String(e)}}function Dr(e,n){const i=n.logger||Or;let r;try{r=JSON.parse(t.readFileSync(e,"utf8"))}catch(t){return void i("stored JSON could not be read",{filePath:e,...Rr(t)})}if(!n.schema)return r;const s=n.sanitize?n.sanitize(r):r,o=n.schema.safeParse(s);if(o.success)return o.data;const a="strip"in n.schema&&"function"==typeof n.schema.strip?n.schema.strip().safeParse(s):void 0;if(a?.success)return i("unknown stored fields were ignored",{filePath:e,issues:o.error.issues}),a.data;i("stored record failed validation and was isolated",{filePath:e,issues:o.error.issues})}function Pr(e){return`${e}_${c.randomUUID().replace(/-/g,"").slice(0,20)}`}function jr(){return c.randomBytes(24).toString("base64url")}class Mr{directory;options;permissionsInitialized=!1;constructor(e,t={}){this.directory=e,this.options=t}init(){if(this.permissionsInitialized&&t.existsSync(this.directory))return;Cr(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=Dr(n.join(this.directory,e),this.options);return t?[t]:[]})}get(e){this.init();const n=this.filePath(e);return t.existsSync(n)?Dr(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 xr(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 Lr{filePathValue;defaults;options;constructor(e,t,n={}){this.filePathValue=e,this.defaults=t,this.options=n}init(){Cr(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)?Dr(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 xr(this.filePathValue,n,this.options),n}}const $r=a.z.record(a.z.string(),a.z.string()),Fr=new Set(["OPENAI_API_KEY","OPENAI_BASE_URL","CODEX_MODEL","TASK_HANDOFF_CODEX_BASE_URL","TASK_HANDOFF_CODEX_MODEL","TASK_HANDOFF_CODEX_MODEL_ID","ANTHROPIC_API_KEY","ANTHROPIC_BASE_URL","CLAUDE_MODEL","TASK_HANDOFF_CLAUDE_MODEL","TASK_HANDOFF_CLAUDE_MODEL_ID"]);class Ur{directory;constructor(e){this.directory=e}get(e){try{return $r.parse(JSON.parse(t.readFileSync(this.filePath(e),"utf8")))}catch(t){if(t&&"object"==typeof t&&"code"in t&&"ENOENT"===t.code)return{};throw new Error(`Stored model environment for instance ${e} is invalid: ${t instanceof Error?t.message:String(t)}`)}}has(e){return t.existsSync(this.filePath(e))}listInstanceIds(){return t.existsSync(this.directory)?t.readdirSync(this.directory).filter(e=>e.endsWith(".json")).map(e=>e.slice(0,-5)).sort():[]}put(e,n){const i=$r.parse(n);t.mkdirSync(this.directory,{recursive:!0,mode:448});const r=this.filePath(e);return I.sync(r,`${JSON.stringify(i,null,2)}\n`,{encoding:"utf8",mode:384}),t.chmodSync(r,384),i}delete(e){t.rmSync(this.filePath(e),{force:!0})}filePath(e){return n.join(this.directory,`${e}.json`)}}class Vr{directory;nodeId;constructor(e,t){this.directory=e,this.nodeId=t}init(){t.mkdirSync(this.directory,{recursive:!0,mode:448}),t.chmodSync(this.directory,448)}list(){return this.init(),t.readdirSync(this.directory).filter(e=>e.endsWith(".json")).sort().flatMap(e=>{const t=this.read(n.join(this.directory,e));return t?[t]:[]})}get(e){const n=this.filePath(e);return t.existsSync(n)?this.read(n):void 0}put(e){const n=Kt.parse(e);this.init();const i=this.filePath(n.id);return I.sync(i,`${JSON.stringify(n,null,2)}\n`,{encoding:"utf8",mode:384}),t.chmodSync(i,384),n}delete(e){const n=this.filePath(e);return!!t.existsSync(n)&&(t.unlinkSync(n),!0)}read(e){try{const i=JSON.parse(t.readFileSync(e,"utf8")),r=n.basename(e,".json"),s=Kt.safeParse(i);if(s.success&&s.data.id===r&&rn(s.data)===s.data.id)return s.data;const o=Kt.strip().safeParse(i);return o.success&&o.data.id===r&&rn(o.data)===o.data.id?(console.warn(JSON.stringify({message:"unknown stored node model fields were ignored",nodeId:this.nodeId,filePath:e})),o.data):void console.warn(JSON.stringify({message:"stored node model failed validation and was isolated",nodeId:this.nodeId,filePath:e}))}catch(t){return void console.warn(JSON.stringify({message:"stored node model could not be read",nodeId:this.nodeId,filePath:e,error:t instanceof Error?t.message:String(t)}))}}filePath(e){return n.join(this.directory,`${e}.json`)}}class qr{directory;constructor(e){this.directory=e}init(){t.mkdirSync(this.directory,{recursive:!0,mode:448}),t.chmodSync(this.directory,448)}get(e){const n=this.filePath(e);if(t.existsSync(n))try{const i=JSON.parse(t.readFileSync(n,"utf8")),r=Wt.safeParse(i);if(r.success)return r.data;const s=Wt.strip().safeParse(i);if(s.success)return console.warn(JSON.stringify({message:"unknown stored model assignment fields were ignored",instanceId:e,filePath:n})),s.data;throw r.error}catch(t){throw Object.assign(new Error(`Stored model assignment for instance ${e} is invalid.`),{statusCode:409,code:"NODE_MODEL_ASSIGNMENT_INVALID",cause:t})}}put(e){const n=Wt.parse(e);this.init();const i=this.filePath(n.instanceId);return I.sync(i,`${JSON.stringify(n,null,2)}\n`,{encoding:"utf8",mode:384}),t.chmodSync(i,384),n}delete(e){t.rmSync(this.filePath(e),{force:!0})}filePath(e){return n.join(this.directory,`${e}.json`)}}function Hr(){return(new Date).toISOString()}class Br{models;assignments;legacyEnvironments;nodeId;instances;constructor(e,t,n){this.nodeId=t,this.instances=n,this.models=new Vr(e.nodeModelsDir,t),this.assignments=new qr(e.modelAssignmentsDir),this.legacyEnvironments=new Ur(e.modelEnvironmentsDir)}init(){this.models.init(),this.assignments.init(),this.migrateLegacyEnvironments()}list(){const e=new Map;for(const t of this.instances.list()){const n=this.assignments.get(t.id);for(const t of[n?.codexModelHash,n?.claudeModelHash])t&&e.set(t,(e.get(t)||0)+1)}return this.models.list().map(t=>this.toPublic(t,e.get(t.id)||0))}create(e){const t=Hr(),n=rn(e),i=this.models.get(n),r=Kt.parse({...e,id:n,enabled:e.enabled??!0,order:e.order??this.nextOrder(),labels:e.labels||{},createdAt:i?.createdAt||t,updatedAt:t});return this.toPublic(this.models.put(r),this.referenceIds(n).length)}deploy(e){const t=rn(e);if(e.id!==t)throw Object.assign(new Error(`Model content hash ${t} does not match ${e.id}.`),{statusCode:400,code:"NODE_MODEL_HASH_MISMATCH"});const n=this.models.get(e.id)||this.models.put(Kt.parse(e));return this.toPublic(n,this.referenceIds(n.id).length)}update(e,t){const n=this.requireModel(e),i=Kt.parse({...n,...t,key:t.key?.trim()?t.key:n.key,createdAt:n.createdAt,updatedAt:Hr()}),r=rn(i),s=this.models.put(Kt.parse({...i,id:r}));return this.toPublic(s,this.referenceIds(r).length)}delete(e){this.requireModel(e);const t=this.referenceIds(e);if(t.length)throw Object.assign(new Error(`Model ${e} is assigned to ${t.length} instance${1===t.length?"":"s"}.`),{statusCode:409,code:"NODE_MODEL_IN_USE",instanceIds:t});return this.models.delete(e)}assign(e,t){const n=this.instances.require(e);if(this.validateRef("codex",t.codexModelHash),this.validateRef("claude",t.claudeModelHash),void 0!==t.modelSelection.codexModelHash&&(t.modelSelection.codexModelHash??void 0)!==t.codexModelHash)throw Object.assign(new Error("Codex model selection does not match its node assignment."),{statusCode:400,code:"NODE_MODEL_SELECTION_MISMATCH"});if(void 0!==t.modelSelection.claudeModelHash&&(t.modelSelection.claudeModelHash??void 0)!==t.claudeModelHash)throw Object.assign(new Error("Claude model selection does not match its node assignment."),{statusCode:400,code:"NODE_MODEL_SELECTION_MISMATCH"});const i=this.assignments.get(e),r=Wt.parse({instanceId:e,codexModelHash:t.codexModelHash,claudeModelHash:t.claudeModelHash,updatedAt:Hr()});this.assignments.put(r);try{return{assignment:r,instance:this.instances.put(Mn.parse({...n,modelSelection:t.modelSelection,updatedAt:Hr()}))}}catch(t){throw i?this.assignments.put(i):this.assignments.delete(e),t}}resolvedEnvironment(e){const t=this.assignments.get(e);if(!t){if(this.legacyEnvironments.has(e))throw Object.assign(new Error(`Legacy model environment for instance ${e} requires manual migration.`),{statusCode:409,code:"NODE_MODEL_MIGRATION_REQUIRED"});return{}}return{...this.environmentForRef("codex",t.codexModelHash),...this.environmentForRef("claude",t.claudeModelHash)}}deleteInstanceMetadata(e){this.assignments.delete(e),this.legacyEnvironments.delete(e)}validateRef(e,t){if(!t)return;const n=this.requireModel(t);if(n.app!==e)throw Object.assign(new Error(`Model ${n.id} belongs to ${n.app}, not ${e}.`),{statusCode:400,code:"NODE_MODEL_APP_MISMATCH"});if(!n.enabled)throw Object.assign(new Error(`Model ${n.id} is disabled.`),{statusCode:409,code:"NODE_MODEL_DISABLED"})}environmentForRef(e,t){if(!t)return{};this.validateRef(e,t);const n=this.requireModel(t);return"codex"===e?{OPENAI_API_KEY:n.key,OPENAI_BASE_URL:n.endpoint,TASK_HANDOFF_CODEX_BASE_URL:n.endpoint,TASK_HANDOFF_CODEX_MODEL:n.model}:{ANTHROPIC_API_KEY:n.key,ANTHROPIC_BASE_URL:n.endpoint,TASK_HANDOFF_CLAUDE_MODEL:n.model}}requireModel(e){const t=this.models.get(e);if(!t)throw Object.assign(new Error(`Model ${e} was not found on node ${this.nodeId}.`),{statusCode:404,code:"NODE_MODEL_NOT_FOUND"});if(rn(t)!==t.id)throw Object.assign(new Error(`Stored model ${e} does not match its content hash.`),{statusCode:409,code:"NODE_MODEL_HASH_INVALID"});return t}referenceIds(e){return this.instances.list().filter(t=>{const n=this.assignments.get(t.id);return n?.codexModelHash===e||n?.claudeModelHash===e}).map(e=>e.id)}toPublic(e,t){const{key:n,...i}=e;return Jt.parse({...i,keyPreview:n.length<=8?"set":`${n.slice(0,4)}...${n.slice(-4)}`,keySet:!0,referenceCount:t})}nextOrder(){return this.models.list().reduce((e,t)=>Math.max(e,t.order),0)+100}migrateLegacyEnvironments(){for(const e of this.legacyEnvironments.listInstanceIds()){if(!this.instances.has(e)){this.warnMigration(e,"instance-not-found");continue}if(this.assignments.get(e)){try{this.resolvedEnvironment(e),this.legacyEnvironments.delete(e)}catch{this.warnMigration(e,"existing-assignment-invalid")}continue}let t;try{t=this.legacyEnvironments.get(e)}catch{this.warnMigration(e,"sidecar-invalid");continue}if(!Object.keys(t).length){this.legacyEnvironments.delete(e);continue}if(Object.keys(t).some(e=>!Fr.has(e))){this.warnMigration(e,"unknown-fields");continue}const n=[];try{const i=this.migrateApp(t,"codex",n),r=this.migrateApp(t,"claude",n);if(!i&&!r)throw new Error("no complete model configuration");const s={...i?{codexModelHash:i}:{},...r?{claudeModelHash:r}:{}};this.assign(e,{modelSelection:s,codexModelHash:i,claudeModelHash:r}),this.resolvedEnvironment(e),this.legacyEnvironments.delete(e)}catch{this.assignments.delete(e);for(const e of n)this.models.delete(e);this.warnMigration(e,"mapping-failed")}}}migrateApp(e,t,n){const i=e["codex"===t?"OPENAI_API_KEY":"ANTHROPIC_API_KEY"],r="codex"===t?e.TASK_HANDOFF_CODEX_BASE_URL||e.OPENAI_BASE_URL:e.ANTHROPIC_BASE_URL,s="codex"===t?e.TASK_HANDOFF_CODEX_MODEL||e.CODEX_MODEL:e.TASK_HANDOFF_CLAUDE_MODEL||e.CLAUDE_MODEL;if(!i&&!r&&!s)return;if(!i||!r||!s)throw new Error("model configuration incomplete");const o=rn({app:t,endpoint:r,key:i,model:s}),a=this.models.get(o);if(a){if(a.app!==t||a.key!==i||a.endpoint!==r||a.model!==s||!a.enabled)throw new Error("existing model conflicts with legacy environment");return o}const c=Hr();return this.models.put(Kt.parse({id:o,name:`Migrated ${"codex"===t?"Codex":"Claude"} model`,endpoint:r,key:i,model:s,app:t,enabled:!0,order:this.nextOrder(),labels:{migratedFrom:"instance-model-environment"},createdAt:c,updatedAt:c})),n.push(o),o}warnMigration(e,t){console.warn(JSON.stringify({message:"legacy model environment was preserved because it could not be migrated",nodeId:this.nodeId,instanceId:e,reason:t}))}}function Kr(){return(new Date).toISOString()}function Gr(e,t){if(!e)return!0;const n=A.valid(e),i=A.valid(t);return n&&i?A.gt(i,n):e!==t}function Jr(){return process.env.TASK_HANDOFF_NPM_COMMAND||"npm"}function Wr(e,i){const r=n.join(e,...i.split("/"),"package.json");try{const e=JSON.parse(t.readFileSync(r,"utf8"));if(e.name!==i||"string"!=typeof e.version||!e.version.trim())throw new Error(`Installed package manifest is invalid: ${r}`);return{name:i,version:e.version.trim()}}catch(e){if("ENOENT"===e.code)return;throw e}}async function Yr(e){const t=(await e(Jr(),["root","--global"])).stdout.trim();if(!t)throw new Error("npm did not return its global module root.");const n=Wr(t,"@task-handoff/server"),i=Wr(t,"@task-handoff/node-agent");return n?{packageName:"@task-handoff/server",currentVersion:n.version,relatedCurrentVersions:i?[i.version]:[]}:{packageName:"@task-handoff/node-agent",currentVersion:i?.version,relatedCurrentVersions:[]}}function Xr(e){if(!e||"object"!=typeof e||Array.isArray(e))return e;const t=e,n="string"==typeof t.updatedAt?t.updatedAt:Kr(),i=t.target&&"object"==typeof t.target&&!Array.isArray(t.target)?t.target:void 0,r="controlled-instance"===i?.component,s={updating:"updating-node",downloading:"updating-node",installing:"updating-node",restarting:"restarting-node",completed:"succeeded",success:"succeeded",error:"failed"},o=new Set(["queued","updating-node","restarting-node","converging-instances","succeeded","degraded","failed"]),a="string"==typeof t.status?t.status:"queued",c=r?"failed":o.has(a)?a:s[a]||"failed",d="string"==typeof t.toVersion&&t.toVersion?t.toVersion:"unknown",l=xt.strip().safeParse(t.impact).success?xt.strip().parse(t.impact):{runningInstanceCount:0,stoppedInstanceCount:0,activeInstanceCount:0,restartInstanceCount:0,runningInstanceIds:[],stoppedInstanceIds:[],activeInstanceIds:[]},u=r?{code:"LEGACY_INSTANCE_UPDATE_RETIRED",message:"Independent controlled-instance update jobs were retired in favor of Node reconciliation.",retryable:!1}:"failed"!==c||t.error||o.has(a)||a in s?"string"==typeof t.error?{code:"NODE_UPDATE_FAILED",message:t.error,retryable:!1}:kt.strip().safeParse(t.error).success?kt.strip().parse(t.error):t.error&&"object"==typeof t.error?{code:"NODE_UPDATE_FAILED",message:"string"==typeof t.error.message?t.error.message:"Stored update job contained an unknown error.",retryable:!1}:void 0:{code:"NODE_UPDATE_FAILED",message:`Stored update job used an unknown status: ${a}.`,retryable:!1},{target:p,error:m,...g}=t,h={phase:"succeeded"===c?"succeeded":"failed"===c?"failed":c||"queued",desiredVersion:d,expectedInstanceIds:[],expectedInstanceCount:0,matchedInstanceCount:0,pendingInstanceCount:0,failedInstanceCount:r||"failed"===c?1:0,deferredInstanceCount:0},f=Ot.strip().safeParse(t.rollout);return{...g,source:"npm",status:c,impact:l,runtimeArtifacts:Array.isArray(t.runtimeArtifacts)?t.runtimeArtifacts.flatMap(e=>{const t=Tt.strip().safeParse(e);return t.success?[t.data]:[]}):[],rollout:f.success?f.data:h,...u?{error:u}:{},...r?{completedAt:t.completedAt||n}:{}}}class Qr{records;constructor(e){this.records=new Mr(e.updatesDir,{schema:Pt,sanitize:Xr})}init(){this.records.init()}list(){return this.records.list().sort((e,t)=>t.createdAt.localeCompare(e.createdAt))}create(e,t){const n=Kr();return this.records.put(Pt.parse({id:Pr("update"),nodeId:e,source:t.source,channel:t.channel,fromVersion:t.currentVersion,toVersion:t.availableVersion,artifactRef:t.artifactRef,runtimeArtifacts:t.runtimeArtifacts,impact:t.impact,status:"queued",rollout:{phase:"queued",desiredVersion:t.availableVersion,expectedInstanceIds:t.impact.runningInstanceIds,expectedInstanceCount:t.impact.runningInstanceCount,matchedInstanceCount:0,pendingInstanceCount:t.impact.runningInstanceCount,failedInstanceCount:0,deferredInstanceCount:t.impact.stoppedInstanceCount},createdAt:n,updatedAt:n}))}patch(e,t){const n=this.records.get(e);if(!n)throw Object.assign(new Error(`Update job ${e} was not found.`),{statusCode:404,code:"UPDATE_JOB_NOT_FOUND"});return this.records.put(Pt.parse({...n,...t,id:e,createdAt:n.createdAt,updatedAt:Kr()}))}reconcileRollouts(e,t,n={}){const i=new Map(e.map(e=>[e.id,e]));for(const e of this.list().filter(e=>["updating-node","restarting-node","converging-instances"].includes(e.status))){if(n.processStarted&&"restarting-node"===e.status&&t!==e.toVersion){this.patch(e.id,{status:"failed",rollout:{...e.rollout,phase:"failed",nodeVersion:t},error:{code:"NODE_UPDATE_FAILED",message:`Node agent restarted with version ${t}, expected ${e.toVersion}.`,retryable:!1},completedAt:Kr()});continue}const r="converging-instances"!==e.status&&t===e.toVersion?this.patch(e.id,{status:"converging-instances",rollout:{...e.rollout,phase:"converging-instances",nodeVersion:t}}):e;if("converging-instances"!==r.status)continue;const s=r.rollout.expectedInstanceIds,o=s.map(e=>i.get(e)),a=o.filter(e=>e?.ready&&"matched"===e.runtimeVersion?.phase&&e.runtimeVersion.actualVersion===r.toVersion).length,c=o.filter(e=>e&&["created","stopped","failed"].includes(e.status||"")&&"failed"!==e.runtimeVersion?.phase).length,d=o.filter(e=>!e||"failed"===e.runtimeVersion?.phase).length,l=Math.max(0,s.length-a-d-c),u=d>0?"degraded":0===l?"succeeded":"converging-instances";this.patch(r.id,{status:u,rollout:{...r.rollout,phase:u,nodeVersion:t,expectedInstanceCount:s.length,matchedInstanceCount:a,pendingInstanceCount:l,failedInstanceCount:d,deferredInstanceCount:r.impact.stoppedInstanceCount+c},..."succeeded"===u||"degraded"===u?{completedAt:Kr()}:{}})}}run(e,t){(async()=>{this.patch(e.id,{status:"updating-node",rollout:{...e.rollout,phase:"updating-node"},startedAt:Kr(),error:void 0});try{await t(e),this.patch(e.id,{status:"succeeded",completedAt:Kr()})}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:Kr()})}})()}}const Zr=function(e,t=process.env,n=e){let i;return()=>{const r=t.TASK_HANDOFF_VERSION?.trim();return r||(i||=E(e,t,n),i)}}("@task-handoff/node-agent",process.env,"@task-handoff/control-plane");function es(){return Zr()}function ts(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 ns(e){const t=es();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:ts(t,e)}}function is(e,t,n=!0){if(!n)return ns(t);const i=es(),r=e.runtimeVersion;if(!r||r.desiredVersion!==i)return ns(t);const s="INSTANCE_RUNTIME_VERSION_MISMATCH"!==r.error?.code?r.error:t===i?void 0:ts(i,t);return Ct.parse({...r,desiredVersion:i,...t?{actualVersion:t}:{actualVersion:void 0},..."pending"===r.phase?{error:s||(t!==i?ts(i,t):void 0)}:{}})}const rs="runtime_local_host",ss="task-handoff.node-agent.builtin";function os(){return(new Date).toISOString()}function as(e){const t={...e};return delete t[ss],t}function cs(e){return"local-folder"===e.type?Vt.parse({mode:"local-bind",path:"/workspace",readOnly:!1}):Vt.parse({mode:"git-clone",path:"/workspace",readOnly:!1})}function ds(e){const t=Ut.parse(e.source),n=e.projectId||("local-folder"===t.type?t.localFolderId:void 0)||("git-repository"===t.type?t.repositoryId:void 0)||("git-template"===t.type?t.templateId:void 0)||`project_${e.id}`;return Ht.parse({id:n,name:"string"==typeof e.sourceSnapshot.name?e.sourceSnapshot.name:e.name,source:t,defaultImageSelection:e.imageSelection,defaultNodeId:e.nodeId,defaultRuntimeId:e.runtimeId,workspacePolicy:cs(t),labels:{},createdAt:e.createdAt,updatedAt:e.updatedAt})}function ls(e,t){throw Object.assign(new Error(t),{statusCode:403,code:e})}function us(e,t){e!==$e&&console.warn(JSON.stringify({message:"protocol version mismatch",peer:t,expectedProtocolVersion:$e,actualProtocolVersion:e||"missing",errorCode:"PROTOCOL_VERSION_MISMATCH"}))}function ps(e){return"none"!==e.capabilities.artifactKind}function ms(e={}){return{...e,requiresImage:!1,supportsControlledInstanceApi:!0,supportsContainerLifecycle:!1,supportsAppSessions:!0,supportsHostSessions:!0,artifactKind:"none",isolation:"none"}}class gs extends Mr{onStored;setOnStored(e){this.onStored=e}put(e){const t=super.get(e.id)?.stateRevision||0,n=super.put(Mn.parse({...e,stateRevision:Math.max(e.stateRevision||0,t)+1}));return this.onStored?.(n),n}}class hs{nodeId;paths;localFolders;nodeRuntimes;controlledInstances;modelRegistry;updateJobs;node;listenerPort;containerUrlOverride;platform;constructor(e,t,n,i,r,s){this.paths=e,this.nodeId=t,this.localFolders=new Mr(e.localFoldersDir,{schema:Ft,sanitize:ot}),this.nodeRuntimes=new Mr(e.nodeRuntimesDir,{schema:Sn}),this.controlledInstances=new gs(e.controlledInstancesDir,{schema:Mn,sanitize:e=>Un(e,e=>{console.warn(JSON.stringify({message:"legacy controlled instance field was ignored",...e}))})}),this.modelRegistry=new Br(e,t,{has:e=>Boolean(this.controlledInstances.get(e)),list:()=>this.listInstances(),require:e=>this.requireInstance(e),put:e=>this.controlledInstances.put(e)}),this.updateJobs=new Qr(e),this.listenerPort=r,this.platform=s,this.containerUrlOverride=i;const o=os();this.node=zn.parse({id:t,name:t,connectionMode:"direct-http",endpoint:n,controlEndpoint:n,containerEndpoint:this.containerUrl,publicWebBase:n?n.replace(/:\d+$/,""):void 0,status:"online",health:"ok",capabilities:{},labels:{},createdAt:o,updatedAt:o})}init(){this.localFolders.init();for(const e of this.localFolders.list())this.localFolders.put(e);if(this.nodeRuntimes.init(),this.controlledInstances.init(),this.modelRegistry.init(),this.updateJobs.init(),this.updateJobs.reconcileRollouts(this.controlledInstances.list(),es(),{processStarted:!0}),!this.nodeRuntimes.get("runtime_local_docker")){const e=os();this.nodeRuntimes.put(Sn.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(rs),t=os();this.nodeRuntimes.put(Sn.parse({id:rs,nodeId:this.nodeId,name:"Local Runtime",type:"local",status:e?.status||"unknown",accessStrategy:"node-proxy",capabilities:ms(e?.capabilities),labels:{...e?.labels,[ss]:"true"},createdAt:e?.createdAt||t,updatedAt:e?.updatedAt||t}))}for(const e of this.nodeRuntimes.list())e.nodeId!==this.nodeId&&this.nodeRuntimes.put(Sn.parse({...e,nodeId:this.nodeId,updatedAt:os()}));for(const e of this.localFolders.list())e.nodeId!==this.nodeId&&this.localFolders.put(Ft.parse({...e,nodeId:this.nodeId,updatedAt:os()}));this.normalizeInstanceRuntimeVersions()}normalizeInstanceRuntimeVersions(){for(const e of this.controlledInstances.list()){const t=ns(e.build?.packageVersion||e.instanceVersion),n=ps(this.requireRuntime(e.runtimeId)),i=["created","stopped","failed"].includes(e.status),r=n&&e.runtimeVersion?.desiredVersion===t.desiredVersion?e.runtimeVersion:void 0,s=n?"matched"===t.phase?i?t:{...t,phase:"verifying",matchedAt:void 0}:"failed"===r?.phase?{...t,phase:"failed",attempt:r.attempt,lastAttemptAt:r.lastAttemptAt,error:r.error}:{...t,attempt:r?.attempt||0,lastAttemptAt:r?.lastAttemptAt}:t;this.controlledInstances.put(Mn.parse({...e,ready:!1,runtimeVersion:s,updatedAt:os()}))}}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=os()}runningInstanceCount(){const e=new Set(["created","stopped","failed"]);return this.listInstances().filter(t=>!e.has(t.status)).length}createLocalFolder(e){const t=os(),n=Ft.parse({...e,id:e.id||Pr("folder"),nodeId:this.nodeId,labels:e.labels||{},createdAt:t,updatedAt:t});return this.localFolders.put(n)}createRuntime(e){if("local"===e.type){const e="win32"===this.platform,t=new Error(e?"Local Runtime is not supported on Windows.":"Local Runtime is built in and cannot be added manually.");throw Object.assign(t,{statusCode:e?400:409,code:e?"LOCAL_RUNTIME_UNSUPPORTED":"LOCAL_RUNTIME_BUILTIN"}),t}const t=os(),n=Sn.parse({...e,id:e.id||Pr("runtime"),nodeId:this.nodeId,accessStrategy:e.accessStrategy||(i=e.type,"docker"===i?"direct-port":"node-proxy"),capabilities:e.capabilities||{},labels:as(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[ss]){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=Sn.parse({...n,...t,id:n.id,nodeId:this.nodeId,accessStrategy:t.accessStrategy||n.accessStrategy,capabilities:t.capabilities||n.capabilities,labels:t.labels?as(t.labels):n.labels,createdAt:n.createdAt,updatedAt:os()});return this.nodeRuntimes.put(i)}deleteRuntime(e){if("true"===this.requireRuntime(e).labels[ss]){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=Sn.parse({...n,...e,id:n.id,nodeId:this.nodeId,createdAt:n.createdAt,updatedAt:os()});return this.nodeRuntimes.put(t)}):this.nodeRuntimes.put(Sn.parse({...n,status:"unknown",updatedAt:os()}))}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=Fn(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 ${$e}: ${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 Mn.parse({...e,status:"starting",ready:!1,updatedAt:n});case"stop-requested":return Mn.parse({...e,status:"stopping",ready:!1,updatedAt:n});case"stop-failed":return"stopping"!==e.status?e:Mn.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 Mn.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"].includes(t.status))return t;const r=t.stateRevision>e.stateRevision&&t.lastHeartbeatAt!==e.lastHeartbeatAt&&"online"===t.agentStatus;return Mn.parse({...t,...n,...r?{status:t.status,health:t.health,connectionStatus:t.connectionStatus,agentStatus:t.agentStatus,targetStatus:t.targetStatus,uiAccessStatus:t.uiAccessStatus}:{},ready:!!r&&t.ready,target:n.target?r?{...n.target,...t.target}:{...t.target,...n.target}:t.target,workspace:n.workspace?r?{...n.workspace,...t.workspace}:{...t.workspace,...n.workspace}:t.workspace,runtime:n.runtime?{...t.runtime,...n.runtime}:t.runtime,updatedAt:i})}(t.baseline,e,t.observation,n);case"stop-completed":return Mn.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 Mn.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=Fn(e);return t.success?[t.data]:[]})}resolvedAssignedModelEnvironment(e){return this.modelRegistry.resolvedEnvironment(e)}createInstance(e){const t=this.requireRuntime(e.runtimeId),i=os(),r=e.id||Pr("inst"),s=Ut.parse(e.source);if(function(e){return"boolean"==typeof e.capabilities.requiresImage?e.capabilities.requiresImage:"local"!==e.type}(t)&&(!e.imageSelection||!e.image)){const e=new Error(`Runtime ${t.name} requires an image.`);throw Object.assign(e,{statusCode:400,code:"NODE_RUNTIME_IMAGE_REQUIRED"}),e}if("local"===t.type&&"local-folder"!==s.type){const e=new Error("Localhost runtime currently supports local folder sources only.");throw Object.assign(e,{statusCode:400,code:"LOCAL_RUNTIME_REQUIRES_LOCAL_FOLDER"}),e}if("local"===t.type&&this.listInstances().some(e=>"local"===this.requireRuntime(e.runtimeId).type)){const e=new Error("A localhost instance already exists on this node.");throw Object.assign(e,{statusCode:409,code:"LOCAL_RUNTIME_INSTANCE_EXISTS"}),e}const o=e.image?fn.parse(e.image):void 0,a="local"===t.type&&"local-folder"===s.type?n.resolve(s.path):void 0,c=Mn.parse({id:r,name:e.name||`instance-${r.replace(/^inst_?/,"").slice(0,6)}`,source:s,sourceSnapshot:e.sourceSnapshot||{},modelSelection:e.modelSelection,projectId:e.projectId,nodeId:this.nodeId,runtimeId:t.id,imageSelection:e.imageSelection,imageSnapshot:o,imageProvisioning:o&&"docker"===t.type?{phase:"checking-image",requestedReference:o.requestedReference,generation:0,startedAt:i,updatedAt:i}:void 0,status:o&&"docker"===t.type?"provisioning":"created",health:"unknown",connectionStatus:"unknown",agentStatus:"unknown",targetStatus:"unknown",uiAccessStatus:"unknown",controlMode:"controlled",ready:!1,runtimeVersion:ns(),capabilities:{},config:{autoImportAgentConfigs:e.config?.autoImportAgentConfigs??!0,defaultCodexPermissionMode:e.config?.defaultCodexPermissionMode??("docker"===t.type?"full-access":"ask")},workspace:"local"===t.type?{mode:"local-bind",status:"unknown",path:a}:{status:"unknown"},target:{strategy:"node-proxy",status:"unknown"},runtime:"local"===t.type?{kind:"local",workspacePath:a,labels:{"task-handoff.runtime-kind":"local"}}:{labels:{}},registrationToken:jr(),createdAt:i,updatedAt:i});return this.controlledInstances.put(c)}registerInstance(e,t,n){const i=Bn.parse(t),r=os(),s=this.controlledInstances.get(e);if(!s){const t=new Error(`Instance ${e} was not found on node ${this.nodeId}.`);throw Object.assign(t,{statusCode:404,code:"NODE_INSTANCE_NOT_FOUND"}),t}if(this.validateInstanceReport(s,i,n),i.processIncarnationId&&i.processIncarnationId===s.processIncarnationId)return s;us(i.protocolVersion,`Instance ${e}`);const o=i.build?.packageVersion||i.instanceVersion,a=ps(this.requireRuntime(s.runtimeId)),c=is(s,o,a),d=Mn.parse({...s,status:"registered",health:o===es()?"ok":"degraded",ready:!a&&o===es(),connectionStatus:"online",agentStatus:"online",targetStatus:"endpoint-unreachable"===i.target.status?"endpoint-unreachable":"reachable"===i.target.status?"reachable":s.targetStatus,uiAccessStatus:"endpoint-unreachable"===i.target.status?"endpoint-unreachable":s.uiAccessStatus,controlMode:i.controlMode,protocolVersion:i.protocolVersion,instanceVersion:i.instanceVersion,build:i.build,runtimeVersion:c,processIncarnationId:i.processIncarnationId||s.processIncarnationId,capabilities:i.capabilities,appInventory:i.appInventory,workspace:i.workspace,target:{...s.target,...i.target},registrationToken:s.registrationToken||i.registrationToken,lastHeartbeatAt:r,updatedAt:r});return this.controlledInstances.put(d)}heartbeatInstance(e,t,n){const i=this.requireInstance(e);this.validateInstanceToken(i,n);const r=Kn.parse(t);i.processIncarnationId&&r.processIncarnationId&&r.processIncarnationId!==i.processIncarnationId&&function(e,t){throw Object.assign(new Error(t),{statusCode:409,code:"INSTANCE_PROCESS_INCARNATION_MISMATCH"})}(0,`Instance ${e} report belongs to an obsolete controlled-instance process.`),us(r.protocolVersion,`Instance ${e}`);const s=os(),o=r.target?{...i.target,...r.target}:i.target,a={...o,status:"unknown"===o.status&&(o.web||o.api)?"reachable":o.status},c="endpoint-unreachable"===a.status?"endpoint-unreachable":"reachable"===a.status?"reachable":i.targetStatus,d=is(i,r.build?.packageVersion||i.build?.packageVersion||i.instanceVersion,ps(this.requireRuntime(i.runtimeId))),l=r.health||i.health,u="running"===(r.status||i.status)&&"failed"!==l,p=Mn.parse({...i,...r,target:a,ready:u,health:l,runtimeVersion:d,processIncarnationId:r.processIncarnationId||i.processIncarnationId,agentStatus:"online",targetStatus:c,uiAccessStatus:c,connectionStatus:"online",build:r.build||i.build,lastHeartbeatAt:s,updatedAt:s});return this.controlledInstances.put(p)}validateInstanceReport(e,t,n){this.validateInstanceToken(e,n||t.registrationToken),t.instanceId&&t.instanceId!==e.id&&ls("INSTANCE_ID_MISMATCH",`Instance ${t.instanceId} cannot register as ${e.id}.`),t.nodeId&&t.nodeId!==this.nodeId&&ls("INSTANCE_NODE_MISMATCH",`Instance ${e.id} belongs to node ${this.nodeId}.`),t.runtimeId&&t.runtimeId!==e.runtimeId&&ls("INSTANCE_RUNTIME_MISMATCH",`Instance ${e.id} belongs to runtime ${e.runtimeId}.`),t.imageSelection&&t.imageSelection.imageId!==e.imageSelection?.imageId&&ls("INSTANCE_IMAGE_MISMATCH",`Instance ${e.id} belongs to image ${e.imageSelection?.imageId}.`)}validateInstanceToken(e,t){e.registrationToken&&t===e.registrationToken||ls("INSTANCE_REGISTRATION_TOKEN_INVALID",`Invalid registration token for instance ${e.id}.`)}context(e,t=this.resolvedAssignedModelEnvironment(e.id)){const n=e.imageSnapshot||fn.parse({id:"img_localhost",origin:"custom",name:"Localhost",repository:"localhost",tag:"local",requestedReference:"localhost:local",pullPolicy:"if-not-present",capabilities:[],optionalApps:[],defaultEnv:{},labels:{},createdAt:e.createdAt,updatedAt:e.updatedAt});return{project:ds(e),image:n,node:this.node,runtime:this.requireRuntime(e.runtimeId),instance:e,nodeAgentUrl:this.containerUrl,modelEnv:t}}}const fs=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(),ys=a.z.object({id:a.z.string().trim().min(1).max(120).optional(),name:a.z.string().trim().min(1).max(160),path:a.z.string().trim().min(1).max(4096),defaultImageSelection:it.optional(),labels:a.z.record(a.z.string(),a.z.string()).default({})}).strict(),Is=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(),As=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:it.optional(),projectId:a.z.string().trim().min(1).max(120).optional(),image:fn.optional(),source:Ut,sourceSnapshot:a.z.record(a.z.string(),a.z.unknown()).default({}),config:a.z.object({autoImportAgentConfigs:a.z.boolean().optional(),defaultCodexPermissionMode:U.optional()}).strict().optional(),modelSelection:Mn.shape.modelSelection}).strict(),bs=a.z.object({name:a.z.string().trim().min(1).max(160).optional(),config:a.z.object({autoImportAgentConfigs:a.z.boolean().optional(),defaultCodexPermissionMode:U.optional()}).strict().optional(),modelSelection:Mn.shape.modelSelection.optional()}).strict(),ws=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(),vs=ws.omit({id:!0}).partial().strict();function Es(e){const t=e.authorization;return"string"==typeof t&&t.startsWith("Bearer ")?t.slice(7).trim():void 0}class Ns{operations=new Map;intents=new Map;intent(e){const t=this.intents.get(e);if(t)return t;const n={};return this.intents.set(e,n),n}invalidate(e){const t={};return this.intents.set(e,t),t}isIntentCurrent(e,t){return this.intents.get(e)===t}clearIntent(e){this.intents.delete(e)}async run(e,t){const n=this.operations.get(e)||Promise.resolve();let i;const r=new Promise(e=>{i=e});this.operations.set(e,r),await n;try{return await t()}finally{i(),this.operations.get(e)===r&&this.operations.delete(e)}}}const zs=a.z.object({}).strict().default({});function Ss(){return(new Date).toISOString()}function _s(){return(new Date).toISOString()}class Ts{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=_s();return this.state.controlledInstances.put(Mn.parse({...t,status:"provisioning",health:"unknown",imageProvisioning:{phase:"checking-image",requestedReference:t.imageSnapshot.requestedReference,generation:(t.imageProvisioning?.generation||0)+1,startedAt:n,updatedAt:n},updatedAt:n}))}provision(e,t){if(this.stopped)return Promise.resolve();const n=e.imageProvisioning?.generation;if(void 0===n)return Promise.resolve();const i=`${e.id}:${n}`,r=this.inFlight.get(i);if(r)return r;const s=this.provisionGeneration(e,n,t).finally(()=>{this.inFlight.get(i)===s&&this.inFlight.delete(i)});return this.inFlight.set(i,s),s}async stop(){this.stopped=!0,this.abortController.abort(),await Promise.allSettled([...this.inFlight.values()])}async provisionGeneration(e,t,n){const i=this.currentGeneration(e.id,t,!0,e.createdAt);if(!i)return;let r,s=0,o=!1,a=Promise.resolve();try{const c=await this.images.ensure(i.imageSnapshot.requestedReference,n=>{a=a.then(async()=>{if(!r)try{await this.updatePhase(e.id,t,n,e.createdAt)}catch(e){r={error:e}}})},n=>{this.stopped||(o=!0,s=n.sequence,this.publishTerminalOutput(e,t,n))},this.abortController.signal);if(await a,r)throw r.error;if(this.stopped)return;o&&this.publishFinished(e,t,s+1,"succeeded");const d=async()=>{if(this.stopped)return;const i=this.currentGeneration(e.id,t,!0,e.createdAt);if(!i)return;const r=this.state.controlledInstances.put(Mn.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:_s()},updatedAt:_s()}));this.options.sync(),this.options.diagnostic({instanceId:e.id,action:"image.provision",reference:c.requestedReference,digest:c.resolvedDigest,pulled:c.pulled},"node instance image provisioning completed"),"starting"===r.status&&await(n?.())};await(this.options.runInstanceOperation?.(e.id,d)??d())}catch(n){if(await a,r&&(n=r.error),this.stopped)return;o&&this.publishFinished(e,t,s+1,"failed");const i=n instanceof Error?n.message:String(n),c=async()=>{if(this.stopped)return;const n=this.currentGeneration(e.id,t,!1,e.createdAt);n?.imageProvisioning&&["provisioning","starting"].includes(n.status)&&(this.state.controlledInstances.put(Mn.parse({...n,status:"failed",health:"failed",imageProvisioning:{...n.imageProvisioning,phase:"failed",error:i,updatedAt:_s()},updatedAt:_s()})),this.options.sync(),this.options.warn({instanceId:e.id,action:"image.provision",reference:n.imageProvisioning.requestedReference,error:i},"node instance image provisioning failed"))};await(this.options.runInstanceOperation?.(e.id,c)??c())}}currentGeneration(e,t,n=!0,i){const r=this.state.controlledInstances.get(e);if(!(!r||i&&r.createdAt!==i||r.imageProvisioning?.generation!==t||n&&!r.imageSnapshot))return r}async updatePhase(e,t,n,i){if(this.stopped)return;const r=async()=>{if(this.stopped)return;const r=this.currentGeneration(e,t,!0,i);r&&["provisioning","starting"].includes(r.status)&&(this.state.controlledInstances.put(Mn.parse({...r,status:"starting"===r.status?"starting":"provisioning",imageProvisioning:{...r.imageProvisioning,phase:n,error:void 0,updatedAt:_s()},updatedAt:_s()})),this.options.sync())};await(this.options.runInstanceOperation?.(e,r)??r())}eventBase(e,t){return{instanceId:e.id,generation:t,requestedReference:e.imageProvisioning.requestedReference,observedAt:_s()}}publishTerminalOutput(e,t,n){for(const[i,r]of function(e,t=6e4){const n=[];for(let i=0;i<e.length;i+=t)n.push(e.slice(i,i+t));return n}(n.data).entries())this.options.publish(In,{...this.eventBase(e,t),sequence:1e3*n.sequence+i,data:r,...n.replay?{replay:!0}:{}},e.id)}publishFinished(e,t,n,i){this.options.publish(An,{...this.eventBase(e,t),sequence:1e3*n,outcome:i},e.id)}}const ks=new Set(["DELETE","GET","HEAD","PATCH","POST","PUT","OPTIONS"]);function Cs(e){return"string"==typeof e&&ks.has(e.toUpperCase())?e.toUpperCase():"GET"}const xs=new Set(["content-encoding","content-length","transfer-encoding"]),Os=67108864;function Rs(e){return Object.fromEntries([...e.entries()].filter(([e])=>!xs.has(e.toLowerCase())))}function Ds(e){return e.bodyBase64?Buffer.from(e.bodyBase64,"base64"):e.body}function Ps(){const e=Number(process.env.TASK_HANDOFF_INSTANCE_PROXY_MAX_RESPONSE_BYTES);return Number.isSafeInteger(e)&&e>0?e:67108864}function js(e){return e.startsWith("/")?e:`/${e}`}function Ms(e,t){return e.code(502).send({error:{code:"INSTANCE_PROXY_RESPONSE_TOO_LARGE",message:`Instance response exceeds ${t} bytes.`}})}const Ls=a.z.object({version:a.z.literal(1),externalListener:Tn}).strict();function $s(e){return"all-ipv4"===e?"0.0.0.0":"127.0.0.1"}function Fs(e){if(!e||"object"!=typeof e||Array.isArray(e))return e;const t=e,n=t.externalListener&&"object"==typeof t.externalListener&&!Array.isArray(t.externalListener)?t.externalListener:{},i=Object.keys(t).filter(e=>"version"!==e&&"externalListener"!==e),r=Object.keys(n).filter(e=>"bindScope"!==e&&"port"!==e);return(i.length||r.length)&&console.warn(JSON.stringify({message:"unknown stored node agent runtime setting fields were ignored",filePath:"runtime-settings.json",fields:[...i,...r.map(e=>`externalListener.${e}`)]})),{version:t.version,externalListener:{bindScope:n.bindScope,port:n.port}}}class Us{app;state;settings;sockets=new Set;config;source;status="error";error;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.app.server.on("connection",e=>{this.sockets.add(e),e.once("close",()=>this.sockets.delete(e))})}current(){return kn.parse({...this.config,host:$s(this.config.bindScope),status:this.status,source:this.source,...this.error?{error:this.error}:{}})}async start(){try{await this.listen(this.config),this.status="listening",this.error=void 0,this.state.setListenerPort(this.config.port)}catch(e){this.status="error",this.error=e instanceof Error?e.message:String(e),this.app.log.error({host:$s(this.config.bindScope),port:this.config.port,error:this.error},"node agent TCP listener failed to start; Unix IPC remains available")}return this.current()}update(e){const t=this.updateQueue.then(()=>this.updateOnce(e));return this.updateQueue=t.then(()=>{},()=>{}),t}async updateOnce(e){const t=Cn.parse(e);if(t.bindScope===this.config.bindScope&&t.port===this.config.port)return this.current();if(t.port!==this.config.port){const e=this.state.runningInstanceCount();if(e>0)throw Object.assign(new Error(`Cannot change the node agent port while ${e} controlled instance(s) are running.`),{statusCode:409,code:"NODE_AGENT_LISTENER_PORT_IN_USE_BY_INSTANCES",blockingInstanceCount:e})}const n=this.snapshot();await this.stop();try{await this.listen(t)}catch(e){throw await this.restore(n),Object.assign(new Error(`Failed to bind node agent TCP listener at ${$s(t.bindScope)}:${t.port}: ${e instanceof Error?e.message:String(e)}`),{statusCode:409,code:"NODE_AGENT_LISTENER_BIND_FAILED"})}try{this.settings.put({version:1,externalListener:t})}catch(e){throw await this.stop(),await this.restore(n),Object.assign(new Error(`Failed to persist node agent TCP listener: ${e instanceof Error?e.message:String(e)}`),{statusCode:500,code:"NODE_AGENT_LISTENER_PERSIST_FAILED"})}return this.config=t,this.source="persisted",this.status="listening",this.error=void 0,this.state.setListenerPort(t.port),this.current()}async shutdown(){await this.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)}async listen(e){await new Promise((t,n)=>{const i=e=>{this.app.server.off("listening",r),n(e)},r=()=>{this.app.server.off("error",i),t()};this.app.server.once("error",i),this.app.server.once("listening",r),this.app.server.listen({host:$s(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 Vs="TASK_HANDOFF_NODE_AGENT_V1",qs="/api/node-tunnel";function Hs(e=""){return c.createHash("sha256").update(e).digest("hex")}function Bs(e,t){return c.createHmac("sha256",e).update(function(e){return[Vs,e.keyId,e.method.toUpperCase(),e.pathWithQuery,e.timestamp,e.nonce,e.bodySha256].join("\n")}(t)).digest("hex")}function Ks(e){const t=e.timestamp||(new Date).toISOString(),n=e.nonce||c.randomBytes(18).toString("base64url"),i=Hs(e.body||""),r=Bs(e.secret,{keyId:e.keyId,method:e.method,pathWithQuery:e.pathWithQuery,timestamp:t,nonce:n,bodySha256:i});return{"x-taskhandoff-node-id":e.nodeId,"x-taskhandoff-key-id":e.keyId,"x-taskhandoff-timestamp":t,"x-taskhandoff-nonce":n,"x-taskhandoff-body-sha256":i,"x-taskhandoff-signature":r}}class Gs{usedNonces=new Map;identity;nodeId;overrideSecret;overrideKeyId;nowMs;constructor(e,t,n,i,r=Date.now){this.identity=e,this.nodeId=t,this.overrideSecret=n,this.overrideKeyId=i,this.nowMs=r}hasRemoteSecrets(){return this.identity.remoteSecrets(this.overrideSecret,this.overrideKeyId).length>0}verify(e){const t=function(e){const t=new Map;for(const[n,i]of Object.entries(e)){const e=Array.isArray(i)?i.join(","):"string"==typeof i?i:void 0===i?"":String(i);t.set(n.toLowerCase(),e)}return{nodeId:t.get("x-taskhandoff-node-id")||"",keyId:t.get("x-taskhandoff-key-id")||"",timestamp:t.get("x-taskhandoff-timestamp")||"",nonce:t.get("x-taskhandoff-nonce")||"",bodySha256:t.get("x-taskhandoff-body-sha256")||"",signature:t.get("x-taskhandoff-signature")||""}}(e.headers);if(!t.nodeId&&!t.signature)return!1;const n="DELETE"===e.method&&"/api/node-agent/pairing/current"===e.url.split("?")[0],i=this.identity.remoteSecrets(this.overrideSecret,this.overrideKeyId,n);if(!i.length)return!1;if(t.nodeId!==this.nodeId)throw Object.assign(new Error("Invalid node agent HMAC node id."),{statusCode:401,code:"NODE_AGENT_HMAC_NODE_MISMATCH"});if(!t.keyId)throw Object.assign(new Error("Node agent HMAC key id is missing."),{statusCode:401,code:"NODE_AGENT_HMAC_KEY_MISSING"});const r=i.filter(e=>t.keyId===e.keyId);if(!r.length)throw Object.assign(new Error("Invalid node agent HMAC key id."),{statusCode:401,code:"NODE_AGENT_HMAC_KEY_INVALID"});const s=Date.parse(t.timestamp);if(!Number.isFinite(s)||Math.abs(this.nowMs()-s)>6e4)throw Object.assign(new Error("Node agent HMAC timestamp is outside the allowed window."),{statusCode:401,code:"NODE_AGENT_HMAC_TIMESTAMP_INVALID"});if(!t.nonce)throw Object.assign(new Error("Node agent HMAC nonce is missing."),{statusCode:401,code:"NODE_AGENT_HMAC_NONCE_MISSING"});this.pruneNonces();const o=`${t.nodeId}:${t.keyId}:${t.nonce}`;if(this.usedNonces.has(o))throw Object.assign(new Error("Node agent HMAC nonce was already used."),{statusCode:401,code:"NODE_AGENT_HMAC_NONCE_REPLAY"});const a=Hs(null==(d=e.body)?"":"string"==typeof d||Buffer.isBuffer(d)?d:JSON.stringify(d));var d;if(t.bodySha256!==a)throw Object.assign(new Error("Node agent HMAC body hash mismatch."),{statusCode:401,code:"NODE_AGENT_HMAC_BODY_HASH_INVALID"});if(!r.some(n=>function(e,t){const n=Buffer.from(e,"hex"),i=Buffer.from(t,"hex");return n.length===i.length&&c.timingSafeEqual(n,i)}(t.signature,Bs(n.secret,{keyId:t.keyId,method:e.method,pathWithQuery:e.url,timestamp:t.timestamp,nonce:t.nonce,bodySha256:a}))))throw Object.assign(new Error("Invalid node agent HMAC signature."),{statusCode:401,code:"NODE_AGENT_HMAC_SIGNATURE_INVALID"});return this.usedNonces.set(o,s+6e4+1),t.keyId}pruneNonces(){const e=this.nowMs();for(const[t,n]of this.usedNonces)n<=e&&this.usedNonces.delete(t)}}const Js=a.z.string().trim().min(1).max(160),Ws=a.z.string().datetime(),Ys=a.z.string().min(1).max(4096),Xs=a.z.string().trim().url().max(2048),Qs=a.z.object({tokenHash:a.z.string().trim().min(1).max(256),expiresAt:Ws,createdAt:Ws,controlPlaneName:a.z.string().trim().min(1).max(160).optional()}).strip(),Zs=a.z.object({id:Js,keyId:Js,name:a.z.string().trim().min(1).max(160).optional(),secret:Ys,pairedAt:Ws,revokedAt:Ws.optional(),updatedAt:Ws}).strip(),eo=a.z.object({id:Js,pairingKeyId:Js,name:a.z.string().trim().min(1).max(160).optional(),url:Xs,enabled:a.z.boolean().default(!0),createdAt:Ws,updatedAt:Ws}).strip(),to=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(),no=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(),io=a.z.object({controlPlaneUrl:a.z.string().trim().url().max(2048),joinToken:a.z.string().trim().min(1).max(4096),controlPlaneName:a.z.string().trim().min(1).max(160).optional(),activate:a.z.boolean().optional()}).strict();function ro(){return(new Date).toISOString()}const so=new Set(["nodeId","createdAt","updatedAt","pairingInvites","controlPlanePairings","controlPlaneConnections","remoteControlPlanes"]),oo=new Set(["tokenHash","expiresAt","createdAt","controlPlaneName"]),ao=new Set(["id","keyId","name","secret","pairedAt","revokedAt","updatedAt"]),co=new Set(["id","pairingKeyId","name","url","enabled","createdAt","updatedAt"]),lo=new Set(["id","keyId","name","url","secret","pairedAt","updatedAt","active"]);function uo(e,t){console.warn(JSON.stringify({message:e,...t}))}function po(e,t){return Object.assign(new Error(e,void 0===t?void 0:{cause:t}),{code:"NODE_AGENT_IDENTITY_INVALID"})}function mo(e,t){return Object.keys(e).filter(e=>!t.has(e))}function go(e,t,n){const i=Ws.safeParse(e);return i.success?i.data:(n("invalid node agent identity timestamp was replaced",{field:t}),ro())}function ho(e,t){if(!e||"object"!=typeof e||Array.isArray(e))throw po("Node agent identity must be a JSON object.");const n=e,i=Js.safeParse(n.nodeId);if(!i.success)throw po("Node agent identity has an invalid nodeId.",i.error);const r=i.data,s=mo(n,so);s.length&&t("unknown node agent identity fields were ignored",{fields:s});const o=Array.isArray(n.remoteControlPlanes)?n.remoteControlPlanes.flatMap(e=>{if(!e||"object"!=typeof e||Array.isArray(e))return[];const n=e,i=mo(n,lo);i.length&&t("unknown legacy node agent remote control-plane fields were ignored",{fields:i});const r=Zs.safeParse(n);if(!r.success)return t("invalid legacy node agent control-plane pairing was ignored",{issues:r.error.issues}),[];const s=n.url?eo.safeParse({id:`connection_${r.data.keyId}`,pairingKeyId:r.data.keyId,name:n.name,url:n.url,enabled:!1!==n.active,createdAt:r.data.pairedAt,updatedAt:r.data.updatedAt}):void 0;return[{pairing:r.data,...s?.success?{connection:s.data}:{}}]}):[],a=(e,n,i,r)=>Array.isArray(e)?e.flatMap(e=>{if(!e||"object"!=typeof e||Array.isArray(e))return t(`invalid node agent ${r} was ignored`,{}),[];const s=mo(e,n);s.length&&t(`unknown node agent ${r} fields were ignored`,{fields:s});const o=i.safeParse(e);return o.success?[o.data]:(t(`invalid node agent ${r} was ignored`,{issues:o.error.issues}),[])}):[];return{nodeId:r,createdAt:go(n.createdAt,"createdAt",t),updatedAt:go(n.updatedAt,"updatedAt",t),pairingInvites:Array.isArray(n.pairingInvites)?n.pairingInvites.flatMap(e=>{if(!e||"object"!=typeof e||Array.isArray(e))return t("invalid node agent pairing invite was ignored",{}),[];const n=mo(e,oo);n.length&&t("unknown node agent pairing invite fields were ignored",{fields:n});const i=Qs.safeParse(e);return i.success?[i.data]:(t("invalid node agent pairing invite was ignored",{issues:i.error.issues}),[])}):[],controlPlanePairings:n.controlPlanePairings?a(n.controlPlanePairings,ao,Zs,"control-plane pairing"):o.map(e=>e.pairing),controlPlaneConnections:n.controlPlaneConnections?a(n.controlPlaneConnections,co,eo,"control-plane connection"):o.flatMap(e=>e.connection?[e.connection]:[])}}class fo{paths;logger;constructor(e,t={}){this.paths=e,this.logger=t.logger||uo}read(){let e,n;try{e=t.readFileSync(this.paths.identityPath,"utf8")}catch(e){if("ENOENT"===e.code)return;throw Object.assign(new Error(`Node agent identity could not be read: ${this.paths.identityPath}`,{cause:e}),{code:"NODE_AGENT_IDENTITY_READ_FAILED"})}try{n=JSON.parse(e)}catch(e){throw po(`Node agent identity contains invalid JSON: ${this.paths.identityPath}`,e)}return ho(n,this.logger)}write(e){t.mkdirSync(n.dirname(this.paths.identityPath),{recursive:!0});const i=ho({...e,updatedAt:ro()},this.logger);I.sync(this.paths.identityPath,`${JSON.stringify(i,null,2)}\n`,{encoding:"utf8",mode:384})}}function yo(){return(new Date).toISOString()}class Io{store;controlPlaneConnectionOperations=new Map;constructor(e){this.store=new fo(e)}async runControlPlaneConnectionOperation(e,t){const n=e.replace(/\/$/,""),i=this.controlPlaneConnectionOperations.get(n)||Promise.resolve();let r;const s=new Promise(e=>{r=e});this.controlPlaneConnectionOperations.set(n,s),await i;try{return await t()}finally{r(),this.controlPlaneConnectionOperations.get(n)===s&&this.controlPlaneConnectionOperations.delete(n)}}resolveNodeId(e){if(e?.trim())return this.writeNodeId(e.trim()),e.trim();const t=this.store.read();if(t?.nodeId)return t.nodeId;const n=Pr("node");return this.writeNodeId(n),n}createPairingInvite(e){const t=this.prunePairingInvites(this.store.read()||this.newIdentity()),n=yo(),i=new Date(Date.now()+(e.expiresInMs||6e5)).toISOString(),r=jr(),s={tokenHash:Hs(r),createdAt:n,expiresAt:i,...e.controlPlaneName?{controlPlaneName:e.controlPlaneName}:{}};return this.store.write({...t,pairingInvites:[...t.pairingInvites||[],s]}),{...s,token:r}}completePairingInvite(e){const t=this.prunePairingInvites(this.store.read()||this.newIdentity()),n=Hs(e.joinToken),i=(t.pairingInvites||[]).find(e=>e.tokenHash===n);if(!i){const e=new Error("Node agent pairing invite is invalid or expired.");throw Object.assign(e,{statusCode:401,code:"NODE_AGENT_PAIRING_INVITE_INVALID"}),e}const r=yo(),s={id:e.controlPlaneId||Pr("cp"),keyId:Pr("key"),...e.controlPlaneName||i.controlPlaneName?{name:e.controlPlaneName||i.controlPlaneName}:{},secret:jr(),pairedAt:r,updatedAt:r};return this.store.write({...t,pairingInvites:(t.pairingInvites||[]).filter(e=>e.tokenHash!==n),controlPlanePairings:[...(t.controlPlanePairings||[]).filter(e=>e.id!==s.id),s]}),s}stageControlPlaneConnection(e){const{pairing:t,connection:n}=this.createControlPlaneConnection(e),i=this.store.read()||this.newIdentity(),r=n.url.replace(/\/$/,""),s=(i.controlPlaneConnections||[]).filter(e=>e.id===n.id||e.url.replace(/\/$/,"")===r);return this.store.write({...i,controlPlanePairings:[...(i.controlPlanePairings||[]).filter(e=>e.keyId!==t.keyId),t],controlPlaneConnections:[...(i.controlPlaneConnections||[]).filter(e=>e.id!==n.id&&e.url.replace(/\/$/,"")!==r),n]}),{pairing:t,connection:n,replacedConnections:s}}commitControlPlaneConnection(e,t={}){const n=this.store.read()||this.newIdentity(),i={...e.pairing,...t.name?{name:t.name}:{}},r={...e.connection,...t.name?{name:t.name}:{}},s=new Set((n.controlPlaneConnections||[]).map(e=>e.pairingKeyId)),o=new Set(e.replacedConnections.map(e=>e.pairingKeyId));return this.store.write({...n,controlPlanePairings:[...(n.controlPlanePairings||[]).filter(e=>e.keyId!==i.keyId&&(!o.has(e.keyId)||s.has(e.keyId))),i],controlPlaneConnections:[...(n.controlPlaneConnections||[]).filter(e=>e.id!==r.id),r]}),{pairing:i,connection:r}}rollbackControlPlaneConnection(e){const t=this.store.read();if(!t)return;const n=new Set(e.replacedConnections.map(e=>e.id));this.store.write({...t,controlPlanePairings:(t.controlPlanePairings||[]).filter(t=>t.keyId!==e.pairing.keyId),controlPlaneConnections:[...(t.controlPlaneConnections||[]).filter(t=>t.id!==e.connection.id&&!n.has(t.id)),...e.replacedConnections]})}createControlPlaneConnection(e){const t=yo(),n={id:Pr("cp"),keyId:Pr("key"),...e.name?{name:e.name}:{},secret:jr(),pairedAt:t,updatedAt:t};return{pairing:n,connection:{id:Pr("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=yo();return this.store.write({...t,controlPlanePairings:t.controlPlanePairings.map(t=>t.keyId===e?{...t,revokedAt:i,updatedAt:i}:t)}),{keyId:e,revoked:!0,revokedAt:i}}deleteControlPlaneConnection(e){const t=this.store.read();if(!t)return!1;const n=(t.controlPlaneConnections||[]).filter(t=>t.id!==e);return n.length!==(t.controlPlaneConnections||[]).length&&(this.store.write({...t,controlPlaneConnections:n}),!0)}remoteSecrets(e,t,n=!1){return[...(this.store.read()?.controlPlanePairings||[]).filter(e=>n||!e.revokedAt).map(e=>({keyId:e.keyId,secret:e.secret})),...e&&t?[{keyId:t,secret:e}]:[]]}isRevokedPairing(e){return Boolean(this.store.read()?.controlPlanePairings?.some(t=>t.keyId===e&&t.revokedAt))}reverseTunnelSecret(e,t,n){if(t&&n)return{keyId:n,secret:t};const i=this.store.read(),r=(i?.controlPlanePairings||[]).filter(e=>!e.revokedAt);if(!r.length)return;if(e){const t=e.replace(/\/$/,""),n=(i?.controlPlaneConnections||[]).find(e=>e.url.replace(/\/$/,"")===t),s=n&&r.find(e=>e.keyId===n.pairingKeyId);if(s)return{keyId:s.keyId,secret:s.secret}}const s=[...r].sort((e,t)=>t.updatedAt.localeCompare(e.updatedAt))[0];return s?{keyId:s.keyId,secret:s.secret}:void 0}newIdentity(){return{nodeId:this.resolveNodeId(),createdAt:yo(),updatedAt:yo(),pairingInvites:[],controlPlanePairings:[],controlPlaneConnections:[]}}writeNodeId(e){const t=this.store.read();this.store.write({...t||{createdAt:yo()},nodeId:e,updatedAt:yo(),pairingInvites:t?.pairingInvites||[],controlPlanePairings:t?.controlPlanePairings||[],controlPlaneConnections:t?.controlPlaneConnections||[]})}prunePairingInvites(e){const t=Date.now();return{...e,pairingInvites:(e.pairingInvites||[]).filter(e=>Date.parse(e.expiresAt)>t)}}}const Ao=a.z.string().trim().min(1).max(160);const bo=jt.strict();function wo(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 vo{preflights=new Map;options;constructor(e){this.options=e}async check(e){const t=Rt.parse(e),n=wo(this.options.listInstances()),i=await Yr(this.options.runCommand),r=this.options.currentRuntimeVersion(),s="@task-handoff/server"===i.packageName?[...new Set([...i.relatedCurrentVersions,r])]:i.relatedCurrentVersions,o=await async function(e){const t=e.packageName||"@task-handoff/node-agent",n=await async function(e,t,n){const i=function(e){return"stable"===e?"latest":e}(n),r=await e(Jr(),["view",`${t}@${i}`,"version","--json"]).catch(e=>{if(!function(e){if(!e||"object"!=typeof e)return!1;const t=e,n=[t.message,t.details?.stdout,t.details?.stderr].filter(e=>"string"==typeof e).join("\n");return/\bE404\b/i.test(n)}(e))throw e});if(!r)return;const s=JSON.parse(r.stdout);if("string"!=typeof s)throw new Error(`npm did not resolve ${t}@${i} to one version.`);return s}(e.runCommand,t,e.channel);if(!n)return function(e){return Dt.parse({source:"npm",channel:e.channel,currentVersion:e.currentVersion,availableVersion:e.currentVersion||"unavailable",impact:e.impact||{runningInstanceCount:0,stoppedInstanceCount:0,activeInstanceCount:0,restartInstanceCount:0,runningInstanceIds:[],stoppedInstanceIds:[],activeInstanceIds:[]},updateAvailable:!1,reason:`No ${e.channel} release is currently published.`,checkedAt:Kr()})}({channel:e.channel,currentVersion:e.currentVersion,impact:e.impact});const i=Gr(e.currentVersion,n)||(e.relatedCurrentVersions||[]).some(e=>Gr(e,n)),r=i?await async function(e,t,n){const i=await e(Jr(),["view",`${t}@${n}`,"dist.integrity","--json"]),r=JSON.parse(i.stdout);if("string"!=typeof r||!/^sha(?:256|384|512)-[A-Za-z0-9+/=]+$/.test(r))throw Object.assign(new Error(`npm did not return immutable integrity metadata for ${t}@${n}.`),{statusCode:502,code:"NODE_UPDATE_PREFLIGHT_FAILED",retryable:!0});return r}(e.runCommand,t,n):void 0;return Dt.parse({source:"npm",channel:e.channel,currentVersion:e.currentVersion,availableVersion:n,...r?{artifactRef:`npm:${t}@${n}#${r}`}:{},runtimeArtifacts:e.runtimeArtifacts||[],impact:e.impact||{runningInstanceCount:0,stoppedInstanceCount:0,activeInstanceCount:0,restartInstanceCount:0,runningInstanceIds:[],stoppedInstanceIds:[],activeInstanceIds:[]},updateAvailable:i,checkedAt:Kr()})}({channel:t.channel,currentVersion:i.currentVersion||r,runCommand:this.options.runCommand,packageName:i.packageName,relatedCurrentVersions:s,impact:n});if(!o.updateAvailable)return o;const a={...o,runtimeArtifacts:await this.options.resolveRuntimeArtifacts(o.availableVersion),preflightToken:jr()};return this.preflights.set(a.preflightToken,{result:a,expiresAt:Date.now()+6e5}),a}async apply(e){const i=bo.parse(e),r=await this.consumePreflight(i);if(!r.supported)throw Object.assign(new Error(r.reason||"The requested update is not supported."),{statusCode:400,code:"UPDATE_UNSUPPORTED"});if(!r.updateAvailable)throw Object.assign(new Error(r.reason||"No update is available for the selected channel."),{statusCode:409,code:"UPDATE_NOT_AVAILABLE"});const s=this.options.jobs.create(this.options.nodeId,r),{worker:o,packaged:a,expectedWorker:c}=function(e,i=t.existsSync){const r=[n.resolve(e,"..","bin","task-handoff-node-update-worker"),n.resolve(e,"..","..","bin","task-handoff-node-update-worker")],s=r.find(i),o=n.resolve(e,"..","..","..","..","scripts","node-update-worker.cjs");return s?{worker:s,packaged:!0,expectedWorker:r[0]}:i(o)?{worker:o,packaged:!1,expectedWorker:r[0]}:{worker:void 0,packaged:!1,expectedWorker:r[0]}}(this.options.moduleDir);if(!o)throw this.options.jobs.patch(s.id,{status:"failed",rollout:{...s.rollout,phase:"failed"},error:{code:"NODE_UPDATE_FAILED",message:`Update worker was not found: ${c}`,retryable:!1},completedAt:(new Date).toISOString()}),Object.assign(new Error(`Node agent update worker was not found: ${c}`),{statusCode:500,code:"UPDATE_WORKER_NOT_FOUND"});const d=process.env.TASK_HANDOFF_CONTROL_PLANE_HEALTH_URL?.trim();try{await this.options.runCommand("systemd-run",["--unit",`task-handoff-update-${s.id}`,"--collect","--property=Type=exec",...a?[o]:[process.execPath,o],"--job-file",this.options.jobs.records.filePath(s.id),"--target-version",s.toVersion,"--npm-command",Jr(),...d?["--control-plane-health-url",d]:[]])}catch(e){const t=e instanceof Error?e.message:String(e);throw this.options.jobs.patch(s.id,{status:"failed",rollout:{...s.rollout,phase:"failed"},error:{code:"NODE_UPDATE_FAILED",message:`Failed to launch the node update worker: ${t}`,retryable:!0},completedAt:(new Date).toISOString()}),Object.assign(new Error(`Failed to launch the node update worker: ${t}`),{statusCode:500,code:"NODE_UPDATE_WORKER_LAUNCH_FAILED",cause:e})}return s}async consumePreflight(e){const t=this.preflights.get(e.preflightToken);if(this.preflights.delete(e.preflightToken),!t||t.expiresAt<=Date.now())throw Object.assign(new Error("The update preflight is missing or expired. Check for updates again."),{statusCode:409,code:"UPDATE_PREFLIGHT_EXPIRED"});const n=t.result,i=await Yr(this.options.runCommand);n.channel===e.channel&&n.availableVersion===e.targetVersion&&n.currentVersion===(i.currentVersion||this.options.currentRuntimeVersion())&&!0===n.artifactRef?.startsWith(`npm:${i.packageName}@`)&&JSON.stringify(n.impact)===JSON.stringify(wo(this.options.listInstances()))||this.throwStale();const r=await this.options.resolveRuntimeArtifacts(n.availableVersion);return JSON.stringify(n.runtimeArtifacts)!==JSON.stringify(r)&&this.throwStale(),n}throwStale(){throw Object.assign(new Error("The update target or affected instances changed after preflight. Check for updates again."),{statusCode:409,code:"UPDATE_PREFLIGHT_STALE"})}}const Eo=new Set(["provisioning","starting","registering","registered","running"]);function No(e){return Mn.parse({...e,health:"unknown",connectionStatus:"offline",agentStatus:"offline",targetStatus:"unknown",uiAccessStatus:"unknown",target:{...e.target,status:"unknown"},updatedAt:(new Date).toISOString()})}class zo{options;restoredInstances=new Set;restoreErrors=new Map;unexpectedExitRetries=new Map;suppressedInstances=new Set;pendingUnexpectedExits=new Map;activeRestores=new Map;timer;activeCycle;cycleRequested=!1;cycleRequestDelayMs;started=!1;stopped=!1;constructor(e){this.options=e}markRestored(e){const t=this.options.state.requireInstance(e).status;return!["failed","stopping","stopped"].includes(t)&&(this.restoredInstances.add(e),this.restoreErrors.delete(e),!0)}allowRecovery(e){this.suppressedInstances.delete(e);const t=this.pendingUnexpectedExits.get(e);void 0!==t&&(this.pendingUnexpectedExits.delete(e),this.applyUnexpectedLocalExit(e,t))}completeSuppressedOperation(e){this.pendingUnexpectedExits.delete(e),this.restoredInstances.delete(e),this.restoreErrors.delete(e),this.unexpectedExitRetries.delete(e)}forgetInstance(e){this.restoredInstances.delete(e),this.restoreErrors.delete(e),this.unexpectedExitRetries.delete(e),this.suppressedInstances.delete(e),this.activeRestores.delete(e),this.pendingUnexpectedExits.delete(e)}async suppressRecovery(e){this.suppressedInstances.add(e),await(this.activeRestores.get(e)?.catch(()=>{}))}handleUnexpectedLocalExit(e,t){this.stopped||(this.suppressedInstances.has(e)?this.pendingUnexpectedExits.set(e,t):this.applyUnexpectedLocalExit(e,t))}applyUnexpectedLocalExit(e,t){const n=this.options.state.requireInstance(e);if("local"!==this.options.state.requireRuntime(n.runtimeId).type)return;this.restoredInstances.delete(e);const i=this.options.nowMs?.()??Date.now(),r=this.unexpectedExitRetries.get(e),s=this.options.crashStableWindowMs??3e4,o=r&&i-r.lastExitAt<s?r.attempt+1:1;this.unexpectedExitRetries.set(e,{attempt:o,lastExitAt:i});const a=this.options.retryBaseDelayMs??1e3,c=1===o?0:Math.min(this.options.retryMaxDelayMs??3e4,a*2**Math.min(o-2,10)),d=t instanceof Error?t.message:String(t);this.restoreErrors.set(e,{message:d,attempt:o,nextAttemptAt:i+c}),this.options.state.applyInstanceLifecycle(e,{type:"runtime-exited",error:t}),this.requestCycle(c)}async restoreManagedInstances(){if(this.stopped)return;const{state:e}=this.options;for(const t of e.listInstances()){if(this.stopped)return;"docker"===e.requireRuntime(t.runtimeId).type&&["provisioning","starting"].includes(t.status)&&"ready"!==t.imageProvisioning?.phase&&this.options.provisionImage(t)}const t=e.listInstances().filter(t=>{if(this.restoredInstances.has(t.id))return!1;if(this.suppressedInstances.has(t.id))return!1;const n=e.requireRuntime(t.runtimeId);if("local"===n.type){const e=this.restoreErrors.get(t.id);return(Eo.has(t.status)||"failed"===t.status)&&(!e||e.nextAttemptAt<=(this.options.nowMs?.()??Date.now()))}return"docker"===n.type&&(Eo.has(t.status)||"provisioning"===t.status&&"ready"===t.imageProvisioning?.phase)});await Promise.all(t.map(async t=>{if(this.stopped)return;const n=async()=>{if(this.stopped)return;const n=e.listInstances().find(e=>e.id===t.id);if(!n)return;if(!this.isRestoreCandidate(n))return;const i=this.restoreErrors.get(n.id);try{const t=this.options.restoreInstance(n.id);this.activeRestores.set(n.id,t);try{await t}finally{this.activeRestores.get(n.id)===t&&this.activeRestores.delete(n.id)}if(this.stopped||this.suppressedInstances.has(n.id))return;if(await this.options.autoImport(e.requireInstance(n.id)),this.stopped||this.suppressedInstances.has(n.id))return;if(this.restoreErrors.get(n.id)!==i)return;if(!this.markRestored(n.id))throw new Error(`Restored instance ${n.id} did not reach a recoverable running state.`)}catch(t){if(this.stopped||this.suppressedInstances.has(n.id))return;"local"===e.requireRuntime(n.runtimeId).type&&e.applyInstanceLifecycle(n.id,{type:"start-failed",error:t});const i=t instanceof Error?t.message:String(t),r=this.restoreErrors.get(n.id),s=(r?.attempt??0)+1,o=this.options.retryBaseDelayMs??1e3,a=Math.min(this.options.retryMaxDelayMs??3e4,o*2**Math.min(s-1,10)),c=(this.options.nowMs?.()??Date.now())+a;this.restoreErrors.set(n.id,{message:i,attempt:s,nextAttemptAt:c}),r?.message===i&&r.attempt===s||this.options.warn({instanceId:n.id,action:"restore",runtimeId:n.runtimeId,error:i,attempt:s,nextAttemptAt:new Date(c).toISOString()},"node instance restore failed; recovery will retry")}};await(this.options.runInstanceOperation?.(t.id,n)??n())}))}isRestoreCandidate(e){if(this.restoredInstances.has(e.id)||this.suppressedInstances.has(e.id))return!1;const t=this.options.state.requireRuntime(e.runtimeId);if("local"===t.type){const t=this.restoreErrors.get(e.id);return(Eo.has(e.status)||"failed"===e.status)&&(!t||t.nextAttemptAt<=(this.options.nowMs?.()??Date.now()))}return"docker"===t.type&&(Eo.has(e.status)||"provisioning"===e.status&&"ready"===e.imageProvisioning?.phase)}async recoverManagedInstances(){if(this.stopped)return;const{state:e,convergence:t}=this.options,n=e.listInstances().filter(e=>this.options.usesManagedArtifact(e)&&!t.isRunning(e.id)&&(this.restoredInstances.has(e.id)||"unknown"!==e.target.status)&&(!e.ready||"matched"!==e.runtimeVersion?.phase)&&!["created","stopped","failed","provisioning","stopping"].includes(e.status));await Promise.all(n.map(async e=>{if(!this.stopped)try{await t.schedule(e.id)}catch(t){this.options.error({instanceId:e.id,error:t},"runtime convergence recovery failed")}}))}start(){this.started||this.stopped||(this.started=!0,this.runAndContinue())}async stop(){this.stopped=!0,this.timer&&clearTimeout(this.timer),this.timer=void 0;const e=this.options.stopImageProvisioning(),t=this.options.state.listInstances().map(e=>this.options.convergence.cancel(e.id));await Promise.all(t),await this.activeCycle,await e,await this.options.runtimeAdapters.stopAll();for(const e of this.options.state.listInstances())"local"===this.options.state.requireRuntime(e.runtimeId).type&&this.options.state.controlledInstances.put(No(e))}async runCycle(){await this.restoreManagedInstances(),this.stopped||await this.recoverManagedInstances()}runAndContinue(){if(this.stopped)return;const e=this.runCycle().catch(e=>this.options.error({error:e},"node agent startup recovery cycle failed"));this.activeCycle=e,e.finally(()=>{this.activeCycle===e&&(this.activeCycle=void 0),this.cycleRequested?(this.cycleRequested=!1,this.cycleRequestDelayMs=void 0,this.scheduleNext()):this.scheduleNext()})}scheduleNext(){if(this.stopped)return;const e=this.options.nowMs?.()??Date.now(),t=new Map(this.options.state.listInstances().map(e=>[e.id,e])),n=[...this.restoreErrors.entries()].reduce((e,[n,i])=>{const r=t.get(n);return!r||this.restoredInstances.has(n)||this.suppressedInstances.has(n)||"local"!==this.options.state.requireRuntime(r.runtimeId).type?e:Eo.has(r.status)||"failed"===r.status?Math.min(e,i.nextAttemptAt):e},Number.POSITIVE_INFINITY),i=Math.min(this.options.intervalMs??1e4,Math.max(0,n-e));this.timer=setTimeout(()=>{this.timer=void 0,this.runAndContinue()},i),this.timer.unref?.()}requestCycle(e=0){if(this.started&&!this.stopped){if(this.activeCycle)return this.cycleRequested=!0,void(this.cycleRequestDelayMs=void 0===this.cycleRequestDelayMs?e:Math.min(this.cycleRequestDelayMs,e));this.timer&&clearTimeout(this.timer),this.timer=setTimeout(()=>{this.timer=void 0,this.runAndContinue()},e),this.timer.unref?.()}}}function So(e){return e.readyState===(e.OPEN??1)}function _o(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 To(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 ko(e,t,n){e.close(To(t),_o(n)||void 0)}function Co(e,t,n,i){if(So(e))for(const e of t.splice(0))if(i(e),!n(e))return}function xo(e,t){const n=new URL(t.tunnelUrl);n.searchParams.set("nodeId",t.nodeId);const i=t.secret?Ks({nodeId:t.nodeId,keyId:t.keyId,secret:t.secret,method:"GET",pathWithQuery:`${n.pathname}${n.search}`}):{},r=new u(n,{headers:i}),s=new Map,o=new Map,a=new Map;let c;r.on("error",i=>{e.log.warn({nodeId:t.nodeId,tunnelUrl:`${n.origin}${n.pathname}`,error:i instanceof Error?i.message:String(i)},"node agent reverse tunnel connection failed")});const d=e=>{const n=e.startsWith("/")?e:`/${e}`,i="function"==typeof t.port?t.port():t.port,r=new URL(`/api/node-agent${n}`,`http://127.0.0.1:${i}`);return r.protocol="ws:",r},l=(e,n,i,r={})=>{const s=e.startsWith("/")?e:`/${e}`;return{...r,...t.secret&&t.keyId?Ks({nodeId:t.nodeId,keyId:t.keyId,secret:t.secret,method:n,pathWithQuery:`/api/node-agent${s}`,body:i}):t.token?{authorization:`Bearer ${t.token}`}:{}}},p=e=>t.secret?Ks({nodeId:t.nodeId,keyId:t.keyId,secret:t.secret,method:"GET",pathWithQuery:`${e.pathname}${e.search}`}):{},m=(e,t,n)=>{const i=s.get(e);s.delete(e),i?.upstream&&ko(i.upstream,t,n),i?.tunnel&&ko(i.tunnel,t,n)},g=(e,t,n=!1)=>new Promise((i,r)=>{e.send(t,{binary:n},e=>e?r(e):i())});r.on("open",()=>{r.send(JSON.stringify({type:"node-agent.identify",nodeId:t.nodeId,serverTime:(new Date).toISOString()})),c=e.nodeAgentEventForwarder?.addOutput(r)}),r.on("close",()=>{for(const e of s.keys())m(e,1001,"Reverse tunnel disconnected.");for(const[e,t]of o)o.delete(e),t.controller.abort(),ko(t.tunnel,1001,"Reverse tunnel disconnected.");for(const[e,t]of a)a.delete(e),t.abort();c?.(),c=void 0});return r.on("message",i=>{(async i=>{let c;try{c=JSON.parse(String(i))}catch{return void r.send(JSON.stringify({type:"node-agent.error",code:"INVALID_JSON"}))}const h=c&&"object"==typeof c?c:{};if("control-plane.http.open"===h.type){const i="string"==typeof h.streamId?h.streamId:"",s="string"==typeof h.route&&h.route.startsWith("/")?h.route:"/health",a=h.init&&"object"==typeof h.init?h.init:{},c=a.headers&&"object"==typeof a.headers?a.headers:{},d=Cs(a.method);let m;try{m=Ge(a.body)}catch(n){return e.log.warn({nodeId:t.nodeId,messageType:h.type,streamId:i,error:n instanceof Error?n.message:String(n)},"node agent reverse tunnel request body rejected"),void r.send(JSON.stringify({type:"node-agent.error",code:"NODE_TUNNEL_REQUEST_BODY_INVALID",streamId:i}))}const f=new AbortController,y=(e=>{const t=new URL(n);return t.pathname=`${t.pathname.replace(/\/$/,"")}/http-streams/${encodeURIComponent(e)}`,t})(i),I=new u(y,{headers:p(y)});return o.set(i,{tunnel:I,controller:f}),I.on("open",async()=>{try{const e=await fetch((e=>{const n=e.startsWith("/")?e:`/${e}`,i="function"==typeof t.port?t.port():t.port;return new URL(`/api/node-agent${n}`,`http://127.0.0.1:${i}`)})(s),{method:d,headers:l(s,d,m,c),body:Buffer.isBuffer(m)?new Uint8Array(m):m,signal:f.signal});if(await g(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 g(I,Buffer.from(n),!0)}}await g(I,JSON.stringify({type:"node-agent.http.end",streamId:i})),I.close(1e3,"HTTP stream completed.")}catch(e){I.readyState===u.OPEN&&(await g(I,JSON.stringify({type:"node-agent.http.error",streamId:i,message:e instanceof Error?e.message:String(e)})).catch(()=>{}),I.close(1011,"HTTP stream failed."))}finally{o.delete(i)}}),I.on("close",()=>{f.abort(),o.delete(i)}),void I.on("error",()=>f.abort())}if("control-plane.http.cancel"===h.type){const e="string"==typeof h.streamId?h.streamId:"",t=o.get(e);if(!t)return;return o.delete(e),t.controller.abort(),void ko(t.tunnel,1e3,"string"==typeof h.reason?h.reason:"HTTP stream canceled.")}if("control-plane.websocket.open"===h.type){const e="string"==typeof h.streamId?h.streamId:"",t="string"==typeof h.route?h.route:"",i=Array.isArray(h.protocols)?h.protocols.filter(e=>"string"==typeof e):void 0;try{const o=l(t,"GET",void 0),a=i?.length?new u(d(t),i,{headers:o}):new u(d(t),{headers:o}),c=(e=>{const t=new URL(n);return t.pathname=`${t.pathname.replace(/\/$/,"")}/streams/${encodeURIComponent(e)}`,t})(e),m=new u(c,{headers:p(c)});s.set(e,{upstream:a,tunnel:m,close:(e=1e3,t="")=>{ko(a,e,t),ko(m,e,t)}}),a.on("open",()=>{r.send(JSON.stringify({type:"node-agent.websocket.open",streamId:e,protocol:a.protocol}))}),function(e,t,n={}){const i=n.pendingFrameLimit??256,r=n.maxFrameBytes??8388608,s=n.maxTotalBytes??1073741824,o=n.maxBufferedBytes??16777216;let a=!1,c=So(t);const d=[],l=[];let u,p=0,m=0,g=0;const h=e=>Buffer.isBuffer(e)||e instanceof ArrayBuffer||ArrayBuffer.isView(e)?e.byteLength:Buffer.byteLength("string"==typeof e?e:String(e),"utf8"),f=(i,o)=>{const a=h(o);return g+=a,n.onFrame?.(i,a),!(a>r||g>s)||(ko(e,1009,"WebSocket bridge traffic limit exceeded."),ko(t,1009,"WebSocket bridge traffic limit exceeded."),!1)},y=()=>{u&&(clearTimeout(u),u=void 0)},I=(n,i)=>{const r=i.bytes;if((n.bufferedAmount??0)+r>o)return ko(e,1013,"WebSocket bridge consumer is too slow."),ko(t,1013,"WebSocket bridge consumer is too slow."),!1;try{return function(e,t){e.send(t.data,{binary:t.isBinary})}(n,i),!0}catch{return ko(e,1011,"WebSocket bridge send failed."),ko(t,1011,"WebSocket bridge send failed."),!1}},A=(n,r,s)=>{if(r.length>=i)return ko(e,1011,"WebSocket bridge pending frame limit exceeded."),void ko(t,1011,"WebSocket bridge pending frame limit exceeded.");const a="upstream"===n?p:m;if((("upstream"===n?t:e).bufferedAmount??0)+a+s.bytes>o)return ko(e,1013,"WebSocket bridge consumer is too slow."),void ko(t,1013,"WebSocket bridge consumer is too slow.");r.push(s),"upstream"===n?p+=s.bytes:m+=s.bytes};n.upstreamOpenTimeoutMs&&!c&&(u=setTimeout(()=>{c||a||(ko(e,1011,"Upstream websocket did not open."),ko(t))},n.upstreamOpenTimeoutMs)),e.on("open",()=>Co(e,l,t=>I(e,t),e=>{m-=e.bytes})),t.on("open",()=>{y(),c=!0,n.onUpstreamOpen?.(),Co(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:h(e)};So(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:h(t)};So(e)?I(e,i):A("client",l,i)}),t.on("close",(t,i)=>{y(),n.onUpstreamClose?.(t,i),(c||a||!n.onUpstreamCloseBeforeOpen?.())&&ko(e,t,i)}),t.on("error",t=>{n.onUpstreamError?.(t),(c||a||!n.onUpstreamErrorBeforeOpen?.(t))&&ko(e)}),e.on("close",(e,i)=>{y(),a=!0,n.onClientClose?.(e,i),ko(t,e,i)}),e.on("error",e=>{y(),a=!0,n.onClientError?.(e),ko(t,1011,"WebSocket bridge client failed.")})}(m,a,{pendingFrameLimit:256,upstreamOpenTimeoutMs:1e4,onClientClose:()=>{s.delete(e)},onClientError:t=>{s.delete(e),r.send(JSON.stringify({type:"node-agent.websocket.error",streamId:e,message:t instanceof Error?t.message:String(t)}))},onUpstreamClose:(t,n)=>{s.delete(e);const i=To(t),o=_o(n);r.send(JSON.stringify({type:"node-agent.websocket.close",streamId:e,...void 0===i?{}:{code:i},...o?{reason:o}:{}}))},onUpstreamError:t=>{s.delete(e),r.send(JSON.stringify({type:"node-agent.websocket.error",streamId:e,message:t instanceof Error?t.message:String(t)}))}})}catch(t){r.send(JSON.stringify({type:"node-agent.websocket.error",streamId:e,message:t instanceof Error?t.message:String(t)}))}return}if("control-plane.websocket.close"===h.type){const e="string"==typeof h.streamId?h.streamId:"";return void m(e,"number"==typeof h.code?h.code:1e3,"string"==typeof h.reason?h.reason:"")}if("control-plane.request.cancel"===h.type){const e="string"==typeof h.requestId?h.requestId:"";return a.get(e)?.abort(),void a.delete(e)}if("control-plane.request"===h.type){const n="string"==typeof h.requestId?h.requestId:"",i=h.init&&"object"==typeof h.init?h.init:{},s="string"==typeof h.route&&h.route.startsWith("/")?h.route:"/health",o=i.headers&&"object"==typeof i.headers?i.headers:{},c=Cs(i.method);let d;try{d=Ge(i.body)}catch(i){return e.log.warn({nodeId:t.nodeId,messageType:h.type,requestId:n,error:i instanceof Error?i.message:String(i)},"node agent reverse tunnel request body rejected"),void r.send(JSON.stringify({type:"node-agent.response",requestId:n,status:400,error:{code:"NODE_TUNNEL_REQUEST_BODY_INVALID",message:"Reverse tunnel request body does not match the negotiated protocol."}}))}const u=new AbortController;a.set(n,u);try{const t=await e.inject({method:c,url:`/api/node-agent${s}`,headers:l(s,c,d,o),payload:d,signal:u.signal});if(u.signal.aborted)return;r.send(JSON.stringify({type:"node-agent.response",requestId:n,status:t.statusCode,headers:t.headers,body:t.body}))}catch(e){if(u.signal.aborted)return;r.send(JSON.stringify({type:"node-agent.response",requestId:n,status:502,error:{code:"NODE_AGENT_REVERSE_INJECT_FAILED",message:e instanceof Error?e.message:String(e)}}))}finally{a.delete(n)}}})(i).catch(n=>{e.log.warn({nodeId:t.nodeId,error:n instanceof Error?n.message:String(n)},"node agent reverse tunnel message rejected");try{r.send(JSON.stringify({type:"node-agent.error",code:"INVALID_TUNNEL_MESSAGE"}))}catch{}})}),r}function Oo(e){const t=new URL(qs,e);return t.protocol="https:"===t.protocol?"wss:":"ws:",t.toString()}const Ro=new Set(["linux","darwin","win32","freebsd","openbsd","aix","sunos"]);function Do(e){return Ro.has(e)?e:"unknown"}function Po(e){return!0===e.managedArtifacts}class jo{managedArtifacts=!0;executor;runCommand;platform;arch;constructor(e,t,n,i){this.executor=e,this.runCommand=t,this.platform=n,this.arch=i}artifactTarget(e){return this.executor.inspectRuntimeTarget(e?.instance.runtime.containerName)}async installRuntime(e,t){const n=e.instance.runtime.containerName;if(!n)throw Object.assign(new Error(`Instance ${e.instance.id} does not have a Docker container.`),{code:"INSTANCE_RUNTIME_INSTALL_FAILED"});await this.executor.installRuntimeLauncher(n),await this.executor.installRuntimeRelease({containerName:n,expectedContainerId:e.instance.runtime.containerId,artifactPath:t.archivePath,identity:t.identity})}async inspectRuntime(e,t){const n=e.instance.runtime.containerName;return!!n&&function(e,t){return e.packageName===t.packageName&&e.version===t.version&&e.platform===t.platform&&e.arch===t.arch&&e.formatVersion===t.formatVersion&&e.launcherAbi===t.launcherAbi&&e.entrypoint===t.entrypoint&&e.sha256===t.sha256}(await this.executor.inspectRuntimeVersion(n),t)}start(e){return this.executor.start(e)}stop(e){return this.executor.stop(e)}restart(e){return this.executor.restart(e,e.instance.runtime.containerId)}delete(e){return this.executor.delete(e)}async check(e){try{const t=(await this.runCommand("docker",["version","--format","{{.Server.Version}}"],{timeoutMs:5e3})).stdout.trim();return{status:"online",capabilities:{...e.capabilities,daemon:{status:"online",hostPlatform:Do(this.platform),...t?{serverVersion:t}:{}}}}}catch(t){return{status:"offline",capabilities:{...e.capabilities,daemon:{status:"offline",hostPlatform:Do(this.platform),error:t instanceof Error?t.message:String(t)}}}}}}class Mo{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(Po)}async stopAll(){await(this.local.stopAll?.())}}const Lo="task-handoff.local-process-nonce",$o=1e3;function Fo(e){return e.runtime.port?`http://127.0.0.1:${e.runtime.port}`:e.target.web}async function Uo(e,t){try{const n=await fetch(`${e}/api/internal/node-agent/process-identity`,{headers:{authorization:`Bearer ${t}`},signal:AbortSignal.timeout($o)});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 Vo(e,t){if(Xi(e)!==t)return!1;try{process.kill(e,"SIGTERM")}catch{return!0}const n=Date.now()+3e3;for(;Date.now()<n;){try{process.kill(e,0)}catch{return!0}await new Promise(e=>setTimeout(e,50))}try{process.kill(e,"SIGKILL")}catch{}const i=Date.now()+1e3;for(;Date.now()<i;){try{process.kill(e,0)}catch{return!0}await new Promise(e=>setTimeout(e,50))}return!1}function qo(e,t){return Object.assign(new Error(t),{statusCode:503,code:"LOCAL_INSTANCE_STOP_UNCONFIRMED",instanceId:e.id})}function Ho(e){return new Promise(t=>{const n=m.createServer();n.once("error",()=>t(!1)),n.listen({host:"127.0.0.1",port:e},()=>n.close(()=>t(!0)))})}function Bo(e,t=3e3){return null!==e.exitCode||null!==e.signalCode?Promise.resolve():new Promise(n=>{const i=setTimeout(()=>{null===e.exitCode&&null===e.signalCode&&e.kill("SIGKILL"),n()},t);i.unref(),e.once("exit",()=>{clearTimeout(i),n()})})}class Ko{children=new Map;readyChildren=new WeakSet;expectedExits=new WeakSet;lockPath;onUnexpectedExit;onUnexpectedExitError;constructor(e,t,n){this.lockPath=e,this.onUnexpectedExit=t,this.onUnexpectedExitError=n}track(e,t){this.children.set(e,t),t.once("exit",(n,i)=>{if(this.release(e,t),this.readyChildren.has(t)&&!this.expectedExits.has(t)){const r={instanceId:e,pid:t.pid,code:n,signal:i},s=e=>{try{this.onUnexpectedExitError?.(e,r)}catch{}};try{Promise.resolve(this.onUnexpectedExit?.(r)).catch(s)}catch(e){s(e)}}})}markReady(e,t){return this.children.get(e)===t&&null===t.exitCode&&null===t.signalCode&&(this.readyChildren.add(t),!0)}release(e,t){this.children.get(e)===t&&this.children.delete(e)}async stop(e){const t=this.children.get(e.id);if(t)return this.expectedExits.add(t),t.killed||t.kill("SIGTERM"),this.children.delete(e.id),void await Bo(t);const i=await async function(e){const t=Fo(e),n=e.runtime.labels?.[Lo];if(!t||!n||!e.registrationToken)return;const i=await Uo(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($o)})).ok?i:void 0}catch{return}}(e);if(i){const t=Fo(e),n=Date.now()+3e3;for(;t&&Date.now()<n;){if(!await Uo(t,e.registrationToken))return;await new Promise(e=>setTimeout(e,50))}const r=t?await Uo(t,e.registrationToken):void 0;if(r&&r.instanceId===i.instanceId&&r.pid===i.pid&&r.processNonce===i.processNonce&&r.startIdentity===i.startIdentity&&r.startIdentity&&await Vo(r.pid,r.startIdentity))return;throw qo(e,`Controlled instance ${e.id} accepted shutdown but its exit could not be confirmed.`)}const r=function(e=function(){const e="win32"===process.platform?p.tmpdir():"/tmp";return n.join(e,`task-handoff-local-controlled-instance-${function(){const e=process.getuid?.();return void 0!==e?String(e):p.userInfo().username.replace(/[^a-zA-Z0-9_.-]/g,"_")}()}.lock`)}()){return Qi(e)}(this.lockPath),s=await async function(e){const t=Fo(e);if(t)try{const[n,i]=await Promise.all([fetch(`${t}/api/instance/status`,{signal:AbortSignal.timeout($o)}),fetch(`${t}/api/diagnostics`,{signal:AbortSignal.timeout($o)})]);if(!n.ok||!i.ok)return;const r=await n.json(),s=await i.json(),o=s.data?.runtime?.pid;if(r.data?.id!==e.id||"controlled"!==r.data.controlMode||"number"!=typeof o||!Number.isInteger(o)||o<=0)return;const a=Xi(o);return a?{pid:o,startIdentity:a}:void 0}catch{return}}(e);if(s){if(await Vo(s.pid,s.startIdentity))return;throw qo(e,`Legacy controlled instance ${e.id} did not exit after termination.`)}if(r?.instanceId===e.id&&tr(r))throw qo(e,`Local controlled instance ${e.id} is still owned by pid ${r.pid}, but its process identity could not be verified.`)}async waitUntilHealthy(e,t,n,i,r=3e3){const s=Date.now()+r;for(;Date.now()<s;){if(null!==n.exitCode||null!==n.signalCode)return!1;const r=await Uo(e,i);if(r&&r.instanceId===t.instanceId&&r.pid===t.pid&&r.processNonce===t.processNonce&&r.startIdentity===t.startIdentity)return!0;await new Promise(e=>setTimeout(e,100))}return!1}async stopAll(){const e=Array.from(this.children.values());for(const t of e)this.expectedExits.add(t),t.killed||t.kill("SIGTERM");this.children.clear(),await Promise.all(e.map(e=>Bo(e)))}}async function Go(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 Jo{runCommand;paths;nodeAgentUrl;processSupervisor;commandOverride;lockPath;constructor(e,t,n,i,r,s,o){this.runCommand=e,this.paths=t,this.nodeAgentUrl=n,this.commandOverride=i,this.lockPath=r,this.processSupervisor=new Ko(r,s,o)}async start(e){await this.processSupervisor.stop(e.instance);const i=function(e){if("local-folder"!==e.source.type){const e=new Error("Localhost runtime currently supports local folder sources only.");throw Object.assign(e,{statusCode:400,code:"LOCAL_RUNTIME_REQUIRES_LOCAL_FOLDER"}),e}return n.resolve(e.source.path)}(e.instance),r=e.instance.runtime.port||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 Ho(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"})}(),s=n.join(this.paths.dataDir,"local-instances",e.instance.id),o=n.join(s,"logs");t.mkdirSync(o,{recursive:!0});const[a,...l]=function(e){if(e)return e;const i=n.resolve(process.cwd(),"bin","task-handoff.js");if(t.existsSync(i))return[process.execPath,i,"web"];throw Object.assign(new Error("The bundled controlled-instance command is unavailable."),{statusCode:500,code:"LOCAL_CONTROLLED_COMMAND_MISSING"})}(this.commandOverride),u=[...l,"--host","127.0.0.1","--port",String(r)],p=c.randomUUID(),m=t.openSync(n.join(o,"controlled-instance.out.log"),"a"),g=t.openSync(n.join(o,"controlled-instance.err.log"),"a"),h=d.spawn(a,u,{cwd:i,detached:!1,stdio:["ignore",m,g],env:{...process.env,TASK_HANDOFF_CONTROL_MODE:"controlled",TASK_HANDOFF_RUNTIME_KIND:"local",TASK_HANDOFF_CONTROLLED_INSTANCE_VERSION:es(),...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:p,TASK_HANDOFF_WORKSPACE:i,TASK_HANDOFF_WORKSPACE_MODE:"local-bind",TASK_HANDOFF_DATA_DIR:s,TASK_HANDOFF_LOG_DIR:o,TASK_HANDOFF_APP_SESSION_PERSIST:"1",TASK_HANDOFF_CODEX_APP_SERVER:process.env.TASK_HANDOFF_CODEX_APP_SERVER||"1",TASK_HANDOFF_WEB_PORT:String(r),TASK_HANDOFF_WEB_HOST:"127.0.0.1",...e.modelEnv||{}}});t.closeSync(m),t.closeSync(g);try{await function(e){return new Promise((t,n)=>{const i=()=>{e.off("error",r),t()},r=t=>{e.off("spawn",i),n(t)};e.once("spawn",i),e.once("error",r)})}(h)}catch(e){const r=e instanceof Error?e.message:String(e);try{t.appendFileSync(n.join(o,"controlled-instance.lifecycle.log"),`[${(new Date).toISOString()}] spawn failed command=${a} cwd=${i} error=${r}\n`)}catch{}throw Object.assign(new Error(`Controlled instance process could not start with command ${a} in ${i}: ${r}`),{statusCode:500,code:"LOCAL_INSTANCE_PROCESS_SPAWN_FAILED"})}this.processSupervisor.track(e.instance.id,h),h.on("error",e=>{try{t.appendFileSync(n.join(o,"controlled-instance.lifecycle.log"),`[${(new Date).toISOString()}] process error pid=${h.pid??""} error=${e.message}\n`)}catch{}}),h.once("exit",(e,i)=>{try{t.appendFileSync(n.join(o,"controlled-instance.lifecycle.log"),`[${(new Date).toISOString()}] exited pid=${h.pid??""} code=${e??""} signal=${i??""}\n`)}catch{}});const f=`http://127.0.0.1:${r}`,y=h.pid?Xi(h.pid):void 0;if(!(h.pid&&e.instance.registrationToken&&await this.processSupervisor.waitUntilHealthy(f,{instanceId:e.instance.id,pid:h.pid,processNonce:p,startIdentity:y},h,e.instance.registrationToken)&&this.processSupervisor.markReady(e.instance.id,h)))throw this.processSupervisor.release(e.instance.id,h),null===h.exitCode&&null===h.signalCode&&h.kill("SIGTERM"),await Bo(h),Object.assign(new Error(`Controlled instance process did not become ready for instance ${e.instance.id} on ${f}.`),{statusCode:503,code:"LOCAL_INSTANCE_PROCESS_NOT_READY"});return{status:"registering",health:"unknown",connectionStatus:"online",agentStatus:"unknown",targetStatus:"unknown",uiAccessStatus:"unknown",target:{strategy:"direct-port",status:"unknown",web:f,api:`${f}/api`},workspace:{mode:"local-bind",status:"pending",path:i},runtime:{kind:"local",workspacePath:i,pid:h.pid,port:r,labels:{...e.instance.runtime.labels,"task-handoff.runtime-kind":"local",[Lo]:p}}}}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 await this.processSupervisor.stop(e.instance),this.start(e)}async delete(e){return this.stop(e)}async check(e){const[t,n]=await Promise.all([Go(this.runCommand,"codex"),Go(this.runCommand,"claude")]);return{status:"online",capabilities:ms({...e.capabilities,apps:{terminal:!0,codex:t,claude:n}})}}async stopAll(){await this.processSupervisor.stopAll()}}const Wo=["codex","claude"],Yo=5e3;function Xo(e){const t=process.env[e]?.trim();return t||void 0}function Qo(e){const t=e.authorization;return"string"==typeof t&&t.startsWith("Bearer ")?t.slice(7).trim():void 0}function Zo(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 ea(e){return!e.ip&&!e.socket.remoteAddress&&!e.socket.remoteFamily}function ta(){return(new Date).toISOString()}async function na(e,t){if(!t.target.web)return"unknown";const n=new AbortController,i=setTimeout(()=>n.abort(),2e3);try{return(await e(`${oa(t)}/api/health`,{signal:n.signal})).ok?"reachable":"endpoint-unreachable"}catch{return"endpoint-unreachable"}finally{clearTimeout(i)}}async function ia(e,t,n,i){const r=new AbortController,s=setTimeout(()=>r.abort(),i);try{return await e(t,{...n,signal:r.signal})}finally{clearTimeout(s)}}async function ra(e,t,n,i){if(!t.config.autoImportAgentConfigs)return void i.diagnostic({instanceId:t.id,action:n},"node instance config auto-import skipped");if("reachable"!==t.targetStatus)return;const r=oa(t),s=Number(process.env.TASK_HANDOFF_CONFIG_AUTO_IMPORT_TIMEOUT_MS||Yo);for(const o of Wo)try{const a=await ia(e,`${r}/api/config-sync/import/${encodeURIComponent(o)}`,{method:"POST"},Number.isFinite(s)&&s>0?s:Yo);if(!a.ok){i.warn({instanceId:t.id,action:n,preset:o,statusCode:a.status},"node instance config auto-import failed");continue}i.diagnostic({instanceId:t.id,action:n,preset:o},"node instance config auto-import completed")}catch(e){i.warn({instanceId:t.id,action:n,preset:o,error:e instanceof Error?e.message:String(e)},"node instance config auto-import failed")}}async function sa(e,t,n){const i=t.requireInstance(n);if("reachable"!==i.targetStatus||!i.target.web)return!1;const r=await ia(e,`${oa(i)}/api/internal/model-environment`,{method:"PUT",headers:{"content-type":"application/json",authorization:`Bearer ${i.registrationToken}`},body:JSON.stringify(t.resolvedAssignedModelEnvironment(n))},Yo);if(!r.ok)throw Object.assign(new Error(`Instance ${n} rejected its managed model environment with HTTP ${r.status}.`),{statusCode:502,code:"INSTANCE_MODEL_ENVIRONMENT_APPLY_FAILED"});return!0}function oa(e){const t=e.target.web;if(!t){const t=new Error(`Instance ${e.id} does not have a web endpoint.`);throw Object.assign(t,{statusCode:409,code:"NODE_INSTANCE_WEB_ENDPOINT_MISSING"}),t}if("direct-port"!==e.target.strategy)return t.replace(/\/$/,"");try{const e=new URL(t);return e.port?(e.hostname=process.env.TASK_HANDOFF_NODE_AGENT_PROXY_HOST||"127.0.0.1",e.toString().replace(/\/$/,"")):t.replace(/\/$/,"")}catch{return t.replace(/\/$/,"")}}async function aa(e,t,n,i,r,s="request"){const o=e.requireInstance(i);if(o.imageProvisioning&&"ready"!==o.imageProvisioning.phase&&"docker"===e.requireRuntime(o.runtimeId).type)return r.diagnostic({instanceId:i,action:"start",reason:s,runtimeId:o.runtimeId,imageId:o.imageSelection?.imageId,imagePhase:o.imageProvisioning.phase},"node instance start queued until image provisioning completes"),e.controlledInstances.put(Mn.parse({...o,status:"starting",updatedAt:ta()}));r.diagnostic({instanceId:i,action:"start",reason:s,runtimeId:o.runtimeId,imageId:o.imageSelection?.imageId},"node instance start requested");const a=e.applyInstanceLifecycle(i,{type:"start-requested"}),c=t.forRuntime(e.requireRuntime(a.runtimeId)),d=await c.start(e.context(a)),l=await na(n,Mn.parse({...a,...d,target:d.target?{...a.target,...d.target}:a.target,workspace:d.workspace?{...a.workspace,error:void 0,...d.workspace}:a.workspace,runtime:d.runtime?{...a.runtime,...d.runtime}:a.runtime,updatedAt:ta()})),u=e.applyInstanceLifecycle(i,{type:"runtime-lifecycle-completed",baseline:a,observation:{...d,target:d.target?{...d.target,status:l}:void 0,workspace:d.workspace?{error:void 0,...d.workspace}:void 0,targetStatus:l,uiAccessStatus:l}});return r.diagnostic({instanceId:i,action:"start",reason:s,status:u.status,connectionStatus:u.connectionStatus,targetStatus:u.targetStatus,targetWeb:u.target.web,containerName:u.runtime.containerName},"node instance start completed"),u}async function ca(e={}){const t=e.token||process.env.TASK_HANDOFF_NODE_AGENT_TOKEN,i=Number(e.port||process.env.TASK_HANDOFF_NODE_AGENT_PORT||"8091"),c=`http://127.0.0.1:${i}`,d=e.containerUrl||process.env.TASK_HANDOFF_NODE_AGENT_CONTAINER_URL,l=Bi(e.dataDir),p=e.remoteSecret||process.env.TASK_HANDOFF_NODE_AGENT_REMOTE_SECRET,m=e.remoteKeyId||process.env.TASK_HANDOFF_NODE_AGENT_REMOTE_KEY_ID,h=new Io(l),f=h.resolveNodeId(e.nodeId||process.env.TASK_HANDOFF_NODE_ID),y=e.connectionMode||("local-ipc"===process.env.TASK_HANDOFF_NODE_AGENT_CONNECTION_MODE?"local-ipc":"local-loopback"),I=e.ipcPath||process.env.TASK_HANDOFF_NODE_AGENT_IPC_PATH||ur(l.dataDir),A="local-ipc"===y?`ipc://${encodeURIComponent(I)}`:c,w=e.platform||process.platform,v=e.arch||process.arch,E=new hs(l,f,c,d,i,w);E.node.connectionMode=y,E.node.controlEndpoint=A,E.node.endpoint=A,E.init();const N=e.dockerCommandRunner||Jn,z=new Yn(N,e.dockerTerminalCommandRunner),S=new Qn(N,{publishHost:"127.0.0.1",imageService:z});let _;const T=new Mo(new jo(S,N,w,v),new Jo(e.dockerCommandRunner||Jn,l,()=>E.localNodeAgentUrl,function(){const e=process.env.TASK_HANDOFF_LOCAL_CONTROLLED_COMMAND_ARGV?.trim();if(!e){const e=process.env.TASK_HANDOFF_LOCAL_CONTROLLED_COMMAND?.trim();return e?e.split(/\s+/):void 0}let t;try{t=JSON.parse(e)}catch{throw Object.assign(new Error("TASK_HANDOFF_LOCAL_CONTROLLED_COMMAND_ARGV must be valid JSON."),{code:"LOCAL_CONTROLLED_COMMAND_INVALID"})}if(!Array.isArray(t)||!t.length||t.some(e=>"string"!=typeof e||!e))throw Object.assign(new Error("TASK_HANDOFF_LOCAL_CONTROLLED_COMMAND_ARGV must be a non-empty string array."),{code:"LOCAL_CONTROLLED_COMMAND_INVALID"});return t}(),e.localControlledInstanceLockPath,e=>_.handleUnexpectedLocalExit(e.instanceId,new Error(`Local controlled instance exited unexpectedly (pid=${e.pid??"unknown"}, code=${e.code??"none"}, signal=${e.signal??"none"}).`)),(e,t)=>$.log.error({error:e,instanceId:t.instanceId,pid:t.pid},"local controlled instance exit recovery failed"))),k=e.updateCommandRunner||e.dockerCommandRunner||Jn,C=e.fetchImpl||fetch,x=new Ar({cacheDir:n.join(l.dataDir,"runtime-artifacts"),fetchImpl:C}),O=e.resolveRuntimeArtifactRelease||((e,t,n)=>br(e,t,n,C)),R=async(t,n,i)=>{const r=await n.artifactTarget(i);if(e.resolveRuntimeArtifact)return e.resolveRuntimeArtifact(t,r.platform,r.arch);const s=await O(t,r.platform,r.arch);if(s.identity.launcherAbi>r.launcherAbi)throw Object.assign(new Error(`Runtime requires launcher ABI ${s.identity.launcherAbi}, but ${r.platform}-${r.arch} provides ABI ${r.launcherAbi}.`),{code:"INSTANCE_BASE_RUNTIME_INCOMPATIBLE",retryable:!1});return x.resolve(s.identity,s.source)},D=e=>T.forRuntime(E.requireRuntime(e.runtimeId)),P=e=>{const t=D(e);return Po(t)?t:void 0},j=e=>{const t=P(e);if(t)return t;throw Object.assign(new Error(`Runtime for instance ${e.id} does not use managed artifacts.`),{code:"INSTANCE_RUNTIME_ARTIFACT_UNMANAGED",retryable:!1})},M=e=>Boolean(P(e)),L=(e,t)=>{const n=E.context(e);return R(t,j(e),n)},$=s({logger:e.logger??!0}),F={requests:0,active:0,completed:0,aborted:0,limitRejected:0,responseBytes:0,totalDurationMs:0,maxResponseBytes:Ps()};$.decorate("nodeAgentState",E),await $.register(o);const U=new zi(E,t,{logger:$.log,safetyIntervalMs:Number(process.env.TASK_HANDOFF_EVENT_CONNECTION_SAFETY_INTERVAL_MS)||void 0}),V=new wr(E.controlledInstances,es,{isInstalled:async(e,t)=>{const n=await L(e,t);return j(e).inspectRuntime(E.context(e),n.identity)},beginDrain:async e=>{try{const t=await async function(e,t){const n=oa(t);if(t.registrationToken&&(await ia(e,`${n}/api/internal/node-agent/drain`,{method:"POST",headers:{authorization:`Bearer ${t.registrationToken}`}},1e4)).ok)return{requested:t.apps.runningCount,failures:[]};const i=await ia(e,`${n}/api/apps/sessions`,{method:"GET",headers:{"cache-control":"no-cache"}},5e3);if(!i.ok)throw new Error(`Could not list app sessions for runtime drain (HTTP ${i.status}).`);const r=function(e){if(!e||"object"!=typeof e||Array.isArray(e))return[];const t=e.data;if(Array.isArray(t))return t;if(!t||"object"!=typeof t||Array.isArray(t))return[];const n=t.snapshot,i=(n&&"object"==typeof n&&!Array.isArray(n)?n:t).sessions;return Array.isArray(i)?i:[]}(await i.json()).flatMap(e=>{if(!e||"object"!=typeof e||Array.isArray(e))return[];const t=e;return"running"===t.status&&"string"==typeof t.id&&t.id?[t.id]:[]}),s=await Promise.all(r.map(async t=>{try{const i=await ia(e,`${n}/api/apps/sessions/${encodeURIComponent(t)}/stop`,{method:"POST"},5e3);return i.ok?void 0:{sessionId:t,error:`HTTP ${i.status}`}}catch(e){return{sessionId:t,error:e instanceof Error?e.message:String(e)}}}));return{requested:r.length,failures:s.filter(e=>Boolean(e))}}(C,e);t.failures.length?$.log.warn({instanceId:e.id,requested:t.requested,failures:t.failures},"runtime convergence could not stop every app session"):$.log.info({instanceId:e.id,requested:t.requested},"runtime convergence requested app session drain")}catch(t){$.log.warn({instanceId:e.id,error:t instanceof Error?t.message:String(t)},"runtime convergence could not request app session drain")}},endDrain:async e=>{try{await async function(e,t){return!!t.registrationToken&&(await ia(e,`${oa(t)}/api/internal/node-agent/resume`,{method:"POST",headers:{authorization:`Bearer ${t.registrationToken}`}},5e3)).ok}(C,e)&&$.log.info({instanceId:e.id},"runtime convergence released app session drain")}catch(t){$.log.warn({instanceId:e.id,error:t instanceof Error?t.message:String(t)},"runtime convergence could not release app session drain")}},install:async(e,t)=>{const n=j(e);await n.installRuntime(E.context(e),await L(e,t))},restart:async e=>{const t=D(e),n=E.applyInstanceLifecycle(e.id,{type:"convergence-restart-requested"}),i=await t.restart(E.context(n));E.applyInstanceLifecycle(e.id,{type:"runtime-lifecycle-completed",baseline:n,observation:i})},onForcedDrain:e=>$.log.warn({instanceId:e.id},"runtime convergence drain deadline reached; restarting instance")},{drainTimeoutMs:Number(process.env.TASK_HANDOFF_RUNTIME_DRAIN_TIMEOUT_MS)||void 0,verificationTimeoutMs:Number(process.env.TASK_HANDOFF_RUNTIME_VERIFY_TIMEOUT_MS)||void 0,maxAttempts:Number(process.env.TASK_HANDOFF_RUNTIME_MAX_ATTEMPTS)||void 0});E.controlledInstances.setOnStored(e=>{U.publishInstanceLifecycle(e),E.updateJobs.reconcileRollouts(E.listInstances(),es())}),U.start(),$.decorate("nodeAgentEventForwarder",U);const q=new Oi(N,()=>E.listInstances().filter(e=>"docker"===E.requireRuntime(e.runtimeId).type),e=>U.publish("instance.metrics.snapshot",e,{instanceId:e.instanceId}));q.start(),$.decorate("nodeAgentRuntimeMetrics",q);const H=(Q=process.env.TASK_HANDOFF_DIAGNOSTIC_LOGS,["1","true","yes","on"].includes(String(Q||"").trim().toLowerCase())),B=new Gs(h,f,p,m),K=(e,t)=>{H&&$.log.info(e,t)},G={diagnostic:K,warn:(e,t)=>$.log.warn(e,t)},J=new Ns,W=async(e,t,n=()=>!0)=>{try{if(!n())return E.requireInstance(e);let i=E.requireInstance(e);"failed"===i.runtimeVersion?.phase&&M(i)&&(i=E.controlledInstances.put(Mn.parse({...i,ready:!1,runtimeVersion:ns(vr(i)),updatedAt:ta()})));const r=E.requireRuntime(i.runtimeId);await aa(E,T,C,e,G);const s=E.requireInstance(e);if("docker"===r.type&&"ready"!==s.imageProvisioning?.phase)return U.syncNow(),s;if(!n())return E.requireInstance(e);_.markRestored(e);let o=E.requireInstance(e);if(M(o)){try{o=await V.schedule(e,{startRequested:!0})}catch(n){o=E.requireInstance(e),G.warn({instanceId:e,action:"runtime.converge",reason:t,error:n instanceof Error?n.message:String(n)},"node instance runtime convergence failed after start")}"failed"===o.runtimeVersion?.phase&&G.warn({instanceId:e,action:"runtime.converge",reason:t,error:o.runtimeVersion.error},"node instance started with failed runtime convergence")}return n()?(await ra(C,o,"start",G),U.syncNow(),o):E.requireInstance(e)}catch(n){throw E.applyInstanceLifecycle(e,{type:"start-failed",error:n}),U.syncNow(),G.warn({instanceId:e,action:"start",reason:t,error:n instanceof Error?n.message:String(n)},"node instance start failed"),n}},Y=new Ts(E,z,{sync:()=>U.syncNow(),diagnostic:G.diagnostic,warn:G.warn,publish:(e,t,n)=>U.publish(e,t,{instanceId:n}),runInstanceOperation:(e,t)=>J.run(e,t)}),X=e=>{const t=J.intent(e.id);Y.provision(e,async()=>{await W(e.id,"image-ready",()=>J.isIntentCurrent(e.id,t)).catch(()=>{})})};var Q;_=new zo({state:E,runtimeAdapters:T,convergence:V,restoreInstance:e=>aa(E,T,C,e,G,"restore"),autoImport:e=>ra(C,e,"start",G),provisionImage:X,stopImageProvisioning:()=>Y.stop(),usesManagedArtifact:M,warn:G.warn,error:(e,t)=>$.log.error(e,t),runInstanceOperation:(e,t)=>J.run(e,t)});const Z=new vo({nodeId:f,jobs:E.updateJobs,runCommand:k,currentRuntimeVersion:es,listInstances:()=>E.listInstances(),resolveRuntimeArtifacts:async e=>(await(async e=>{const t=new Map;for(const e of T.managedAdapters()){const n=await e.artifactTarget();t.set(`${n.platform}-${n.arch}`,{adapter:e})}for(const e of E.listInstances()){const n=P(e);if(!n)continue;const i=E.context(e),r=await n.artifactTarget(i);t.set(`${r.platform}-${r.arch}`,{adapter:n,context:i})}return(await Promise.all([...t.values()].map(({adapter:t,context:n})=>R(e,t,n)))).sort((e,t)=>`${e.identity.platform}/${e.identity.arch}`.localeCompare(`${t.identity.platform}/${t.identity.arch}`))})(e)).map(e=>e.identity),moduleDir:("undefined"==typeof document?require("url").pathToFileURL(__filename).href:b&&"SCRIPT"===b.tagName.toUpperCase()&&b.src||new URL("cli.js",document.baseURI).href)?n.dirname(r.fileURLToPath("undefined"==typeof document?require("url").pathToFileURL(__filename).href:b&&"SCRIPT"===b.tagName.toUpperCase()&&b.src||new URL("cli.js",document.baseURI).href)):__dirname});return $.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);(H||i.statusCode>=500)&&(i.statusCode>=500?$.log.error.bind($.log):$.log.warn.bind($.log))({method:t.method,url:t.url,statusCode:i.statusCode,errorCode:i.code,error:i.message},"node agent request failed"),n.code(i.statusCode).send({error:{code:i.code,message:i.message,...e&&"object"==typeof e&&"string"==typeof e.expectedVersion?{expectedVersion:e.expectedVersion}:{},...e&&"object"==typeof e&&"string"==typeof e.actualVersion?{actualVersion:e.actualVersion}:{},...e&&"object"==typeof e&&"string"==typeof e.phase?{phase:e.phase}:{},...e&&"object"==typeof e&&"boolean"==typeof e.retryable?{retryable:e.retryable}:{},...e&&"object"==typeof e&&"number"==typeof e.blockingInstanceCount?{blockingInstanceCount:e.blockingInstanceCount}:{}}})}),$.addHook("preHandler",async e=>{const n=B.verify(e);if(n){if(h.isRevokedPairing(n)&&"/api/node-agent/pairing/current"!==e.url.split("?")[0]){const e=new Error("The node agent pairing used for this request has been revoked.");throw Object.assign(e,{statusCode:401,code:"NODE_AGENT_HMAC_KEY_REVOKED"}),e}e.nodeAgentAuthKeyId=n}else if(ea(e)){if(t&&Qo(e.headers)!==t){const e=new Error("Invalid node agent token.");throw Object.assign(e,{statusCode:401,code:"NODE_AGENT_UNAUTHORIZED"}),e}}else if("/api/node-agent/pairing/complete"!==e.url.split("?")[0]&&!function(e){const t=e.split("?")[0];return/^\/api\/node-agent\/instances\/[^/]+\/(register|heartbeat)$/.test(t)}(e.url)){if(B.hasRemoteSecrets()){const e=new Error("Node agent HMAC signature is required.");throw Object.assign(e,{statusCode:401,code:"NODE_AGENT_HMAC_SIGNATURE_REQUIRED"}),e}if(!function(e){return Zo(e.ip)||Zo(e.socket.remoteAddress)||!e.ip&&!e.socket.remoteAddress&&!e.socket.remoteFamily}(e)){const e=new Error("Local node agent access is only accepted from loopback or local IPC connections.");throw Object.assign(e,{statusCode:401,code:"NODE_AGENT_LOCAL_TOKEN_REQUIRES_LOOPBACK"}),e}if(t&&Qo(e.headers)!==t){const e=new Error("Invalid node agent token.");throw Object.assign(e,{statusCode:401,code:"NODE_AGENT_UNAUTHORIZED"}),e}}}),$.addHook("onClose",async()=>{q.stop(),U.stop(),await _.stop()}),$.decorate("nodeAgentRestoreManagedInstances",()=>_.restoreManagedInstances()),$.decorate("nodeAgentRecoverManagedInstances",()=>_.recoverManagedInstances()),$.decorate("nodeAgentStartRecoverySupervisor",()=>_.start()),$.get("/api/node-agent/health",async()=>{return{data:{ok:!0,role:"node-agent",nodeId:f,platform:Do(w),arch:process.arch,protocolVersion:$e,build:(e="node-agent",{component:e,packageName:"@task-handoff/node-agent",packageVersion:es(),protocolVersion:$e,buildId:Xo("TASK_HANDOFF_BUILD_ID"),builtAt:Xo("TASK_HANDOFF_BUILT_AT"),gitCommit:Xo("TASK_HANDOFF_GIT_COMMIT"),imageRef:Xo("TASK_HANDOFF_IMAGE_REF"),imageDigest:Xo("TASK_HANDOFF_IMAGE_DIGEST")}),instanceProxy:{...F},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)}))}($,e=>{if(!ea(e)){const e=new Error("Node agent TCP listener settings are available only over local Unix IPC.");throw Object.assign(e,{statusCode:403,code:"NODE_AGENT_LISTENER_LOCAL_IPC_ONLY"}),e}if(!$.nodeAgentListenerManager){const e=new Error("Node agent TCP listener manager is not initialized.");throw Object.assign(e,{statusCode:503,code:"NODE_AGENT_LISTENER_UNAVAILABLE"}),e}return $.nodeAgentListenerManager}),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)}))}($,Z,E.updateJobs),function(e,t){const{identity:n,nodeId:i,fetchImpl:r}=t;e.post("/api/node-agent/pairing/invites",async(e,t)=>{const r=n.createPairingInvite(to.parse(e.body||{}));return t.code(201).send({data:{nodeId:i,joinToken:r.token,expiresAt:r.expiresAt}})}),e.post("/api/node-agent/pairing/complete",async(e,t)=>{const r=n.completePairingInvite(no.parse(e.body));return t.code(201).send({data:{nodeId:i,keyId:r.keyId,secret:r.secret,pairedAt:r.pairedAt}})}),e.get("/api/node-agent/control-plane-pairings",async e=>({data:n.listControlPlanePairings(e.nodeAgentAuthKeyId)})),e.delete("/api/node-agent/control-plane-pairings/:keyId",async e=>{const t=Ao.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=Ao.parse(e.params.connectionId),r=n.deleteControlPlaneConnection(i);return r&&t.reverseTunnels()?.connectConfigured(),{data:{deleted:r}}}),e.post("/api/node-agent/control-plane-connections",async(e,s)=>{const o=io.parse(e.body),a=function(e){const t=new URL(e);if("http:"!==t.protocol&&"https:"!==t.protocol){const e=new Error("Control-plane URL must use http or https.");throw Object.assign(e,{statusCode:400,code:"NODE_AGENT_REMOTE_CONTROL_PLANE_URL_INVALID"}),e}return t.toString().replace(/\/$/,"")}(o.controlPlaneUrl);return n.runControlPlaneConnectionOperation(a,async()=>{const e=n.stageControlPlaneConnection({url:a,...o.controlPlaneName?{name:o.controlPlaneName}:{},enabled:!1!==o.activate});let c;try{c=await async function(e,t,n){const i=await e(new URL("/api/node-join/complete",t).toString(),{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(n)}),r=await i.json().catch(()=>({}));if(!i.ok){const e=new Error(r.error?.message||`Control-plane node join failed with HTTP ${i.status}.`);throw Object.assign(e,{statusCode:i.status,code:r.error?.code||"NODE_AGENT_REMOTE_JOIN_FAILED"}),e}return r.data||{}}(r,a,{joinToken:o.joinToken,nodeId:i,nodeName:t.nodeName(),keyId:e.pairing.keyId,secret:e.pairing.secret,pairedAt:e.pairing.pairedAt})}catch(t){throw n.rollbackControlPlaneConnection(e),t}const d=n.commitControlPlaneConnection(e,{name:o.controlPlaneName||("string"==typeof c.name&&c.name?c.name:void 0)});let l,u=d.connection.enabled?"saved":"disabled";const 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 s.code(201).send({data:{pairing:n.listControlPlanePairings().find(e=>e.keyId===d.pairing.keyId),connection:d.connection,tunnel:{status:u,...l?{error:l}:{}}}})})})}($,{identity:h,nodeId:f,nodeName:()=>E.node.name,fetchImpl:C,reverseTunnels:()=>$.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(ws.parse(e.body))})),e.patch("/api/node-agent/runtimes/:id",async e=>({data:t.updateRuntime(e.params.id,vs.parse(e.body))})),e.delete("/api/node-agent/runtimes/:id",async e=>({data:{deleted:t.deleteRuntime(e.params.id)}})),e.post("/api/node-agent/runtimes/:id/check",async e=>({data:await t.checkRuntime(e.params.id)})),e.get("/api/node-agent/local-folders",async()=>({data:t.listLocalFolders()})),e.get("/api/node-agent/folders/tree",async e=>({data:t.listFolderTree(Is.parse(e.query))})),e.post("/api/node-agent/local-folders",async(e,n)=>n.code(201).send({data:t.createLocalFolder(ys.parse(e.body))})),e.delete("/api/node-agent/local-folders/:id",async e=>({data:{deleted:t.deleteLocalFolder(e.params.id)}}))}($,{listRuntimes:()=>E.nodeRuntimes.list(),createRuntime:e=>E.createRuntime(e),updateRuntime:(e,t)=>E.updateRuntime(e,t),deleteRuntime:e=>E.deleteRuntime(e),checkRuntime:async e=>{const t=E.requireRuntime(e);return E.checkRuntime(e,T.forRuntime(t))},listLocalFolders:()=>E.localFolders.list(),listFolderTree:qi,createLocalFolder:e=>E.createLocalFolder(e),deleteLocalFolder:e=>E.localFolders.delete(e)}),function(e,t){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(Zt.parse(e.body))})),e.put("/api/node-agent/models/:id/deploy",async e=>{const n=e.params.id,i=tn.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,en.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 n=e.params.id,i=t.assign(n,nn.parse(e.body));return await(e=>sa(C,E,e))(n),{data:i}})}($,E.modelRegistry),function(e,t){e.get("/api/node-agent/instances",async()=>({data:t.list()})),e.post("/api/node-agent/instances",async(e,n)=>{const i=t.create(As.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,bs.parse(e.body));return t.afterUpdate(n),{data:n}}),e.post("/api/node-agent/instances/:id/register",async(e,n)=>{const i=e.params.id,r=t.sanitizeReport(i,"register",e.body),s=t.register(i,Bn.parse(r),Es(e.headers));return t.afterReport(s,"register"),n.code(201).send({data:s})}),e.post("/api/node-agent/instances/:id/heartbeat",async e=>{const n=e.params.id,i=t.sanitizeReport(n,"heartbeat",e.body),r=t.heartbeat(n,Kn.parse(i),Es(e.headers));return t.afterReport(r,"heartbeat"),{data:r}})}($,{list:()=>E.listInstances(),create:e=>E.createInstance(e),retryImageProvisioning:e=>Y.retry(e),update:(e,t)=>{const n=E.requireInstance(e);return E.controlledInstances.put(Mn.parse({...n,...t,...t.config?{config:{...n.config,...t.config}}:{},updatedAt:ta()}))},register:(e,t,n)=>E.registerInstance(e,t,n),heartbeat:(e,t,n)=>E.heartbeatInstance(e,t,n),sanitizeReport:(e,t,n)=>{const i=n&&"object"==typeof n&&!Array.isArray(n)?n.protocolVersion:void 0;if("string"!=typeof i||i===$e)return n;const r=({field:n,action:r})=>$.log.warn({instanceId:e,report:t,protocolVersion:i,expectedProtocolVersion:$e,field:n,action:r},"cross-version controlled instance report sanitized");return"register"===t?function(e,t){if(!e||"object"!=typeof e||Array.isArray(e))return e;const n=e,i=["instanceId","projectId","source","nodeId","runtimeId","imageSelection","instanceVersion","protocolVersion","build","controlMode","capabilities","appInventory","target","workspace","registrationToken","processIncarnationId"],r=new Set([...i,"imageId"]);for(const e of Object.keys(n))r.has(e)||t?.({field:e,action:"ignored"});return Object.prototype.hasOwnProperty.call(n,"imageId")&&t?.({field:"imageId",action:"migrated"}),{...Hn(n,i),imageSelection:st(n.imageSelection,n.imageId)}}(n,r):function(e,t){if(!e||"object"!=typeof e||Array.isArray(e))return e;const n=["status","health","protocolVersion","build","capabilities","appInventory","apps","aiSessions","triggers","workspace","target","processIncarnationId"],i=new Set(n);for(const n of Object.keys(e))i.has(n)||t?.({field:n,action:"ignored"});return Hn(e,n)}(n,r)},afterCreate:e=>{U.syncNow(),e.imageProvisioning&&X(e)},afterImageRetry:e=>{U.syncNow(),X(e)},afterUpdate:()=>U.syncNow(),afterReport:(e,t)=>{U.syncNow(),"register"===t?K({instanceId:e.id,action:t,protocolVersion:e.protocolVersion,build:e.build,targetStatus:e.targetStatus,targetStrategy:e.target.strategy},"node instance registered"):K({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"),!M(e)||e.ready&&"matched"===e.runtimeVersion?.phase||V.schedule(e.id).catch(n=>$.log.error({instanceId:e.id,error:n},`runtime convergence after ${t} failed`))}}),$.get("/api/node-agent/events",{websocket:!0},e=>{const t=e;t.send(JSON.stringify({type:"node-agent.events.connected",nodeId:f,serverTime:(new Date).toISOString()}));const n=U.addOutput(t);t.on("close",n),t.on("error",n)}),$.get("/api/node-agent/docker/images",async()=>({data:await oi(e.dockerCommandRunner)})),$.get("/api/node-agent/instances/:id/metrics",async e=>{const t=e.params.id,n=E.requireInstance(t);if("docker"!==E.requireRuntime(n.runtimeId).type){const e=new Error(`Runtime type ${E.requireRuntime(n.runtimeId).type} does not provide resource metrics.`);throw Object.assign(e,{statusCode:409,code:"INSTANCE_METRICS_UNSUPPORTED"}),e}return{data:await q.snapshot(t)}}),function(e,t,n,i,r,s=new Ns){const o=e=>s.intent(e),a=e=>Promise.resolve(i.cancel(e)).then(()=>({ok:!0}),e=>({ok:!1,error:e})),c=(e,t)=>{if(!s.isIntentCurrent(e,t))throw Object.assign(new Error(`Instance operation for ${e} was superseded by stop or delete.`),{statusCode:409,code:"INSTANCE_OPERATION_SUPERSEDED"})};e.post("/api/node-agent/instances/:id/start",async e=>{zs.parse(e.body);const t=e.params.id,n=o(t);return s.run(t,async()=>(c(t,n),r.allowRecovery(t),{data:await r.start(t,()=>s.isIntentCurrent(t,n))}))}),e.post("/api/node-agent/instances/:id/runtime/reconcile",async e=>{const n=e.params.id;zs.parse(e.body);const a=o(n);return s.run(n,async()=>{c(n,a);const e=t.requireInstance(n);t.putInstance(Mn.parse({...e,ready:!1,runtimeVersion:ns(vr(e)),updatedAt:Ss()})),c(n,a);const s=await i.schedule(n,{startRequested:!["created","stopped"].includes(e.status),resumeCancelled:!0});return c(n,a),r.sync(),{data:s}})}),e.post("/api/node-agent/instances/:id/stop",async e=>{const i=e.params.id;t.requireInstance(i),s.invalidate(i);const o=a(i);return s.run(i,async()=>{const e=t.requireInstance(i);t.applyLifecycle(i,{type:"stop-requested"});try{await r.suppressRecovery(i);const e=await o;if("error"in e)throw e.error;const s=t.requireInstance(i);r.diagnostic({instanceId:i,action:"stop",runtimeId:s.runtimeId,containerName:s.runtime.containerName},"node instance stop requested"),await n.forRuntime(t.requireRuntime(s.runtimeId)).stop(t.context(s))}catch(n){try{t.applyLifecycle(i,{type:"stop-failed",baseline:e}),r.sync()}finally{r.allowRecovery(i)}throw n}const s=t.applyLifecycle(i,{type:"stop-completed"});return r.completeSuppressedRecovery(i),r.sync(),r.diagnostic({instanceId:i,action:"stop",status:s.status,connectionStatus:s.connectionStatus,containerName:s.runtime.containerName},"node instance stop completed"),{data:s}})}),e.post("/api/node-agent/instances/:id/restart",async e=>{const a=e.params.id;zs.parse(e.body);const d=o(a);return s.run(a,async()=>{c(a,d),r.allowRecovery(a);let e=t.requireInstance(a);if(r.isManaged(e)&&(!e.ready||"matched"!==e.runtimeVersion?.phase)){"failed"===e.runtimeVersion?.phase&&(e=t.putInstance(Mn.parse({...e,runtimeVersion:ns(vr(e)),updatedAt:Ss()}))),c(a,d);const n=await i.schedule(a,{startRequested:!0});return c(a,d),r.sync(),{data:n}}r.diagnostic({instanceId:a,action:"restart",runtimeId:e.runtimeId,imageId:e.imageSelection?.imageId,containerName:e.runtime.containerName},"node instance restart requested");const s=await n.forRuntime(t.requireRuntime(e.runtimeId)).restart(t.context(e));let o=t.applyLifecycle(a,{type:"runtime-lifecycle-completed",baseline:e,observation:{...s,target:s.target?{...e.target,...s.target}:void 0}});r.markRestarted(a),c(a,d);const l=Mn.parse({...o,updatedAt:Ss()}),u=await r.probe(l);return c(a,d),o=t.applyLifecycle(a,{type:"runtime-lifecycle-completed",baseline:o,observation:{target:{...o.target,status:u},targetStatus:u,uiAccessStatus:u}}),await r.autoImport(o),r.sync(),r.diagnostic({instanceId:a,action:"restart",status:o.status,connectionStatus:o.connectionStatus,targetStatus:o.targetStatus,targetWeb:o.target.web,containerName:o.runtime.containerName},"node instance restart completed"),{data:o}})}),e.post("/api/node-agent/instances/:id/delete",async e=>{const i=e.params.id;t.requireInstance(i),s.invalidate(i);const o=a(i);return s.run(i,async()=>{const e=t.requireInstance(i);t.applyLifecycle(i,{type:"stop-requested"});try{await r.suppressRecovery(i);const e=await o;if("error"in e)throw e.error;const s=t.requireInstance(i);r.diagnostic({instanceId:i,action:"delete",runtimeId:s.runtimeId,containerName:s.runtime.containerName},"node instance delete requested"),await n.forRuntime(t.requireRuntime(s.runtimeId)).delete(t.context(s,{}))}catch(n){try{t.applyLifecycle(i,{type:"stop-failed",baseline:e}),r.sync()}finally{r.allowRecovery(i)}throw n}r.diagnostic({instanceId:i,action:"delete"},"node instance delete completed");const a=t.deleteInstance(i);return a&&(r.forgetRecovery(i),s.clearIntent(i)),r.deleteMetadata(i),r.sync(),{data:{deleted:a}}})})}($,{requireInstance:e=>E.requireInstance(e),requireRuntime:e=>E.requireRuntime(e),putInstance:e=>E.controlledInstances.put(e),deleteInstance:e=>E.controlledInstances.delete(e),applyLifecycle:(e,t)=>E.applyInstanceLifecycle(e,t),context:(e,t)=>E.context(e,t)},T,V,{start:(e,t)=>W(e,"request",t),sync:()=>U.syncNow(),isManaged:M,probe:e=>na(C,e),autoImport:e=>ra(C,e,"restart",G),markRestarted:e=>_.markRestored(e),allowRecovery:e=>_.allowRecovery(e),suppressRecovery:e=>_.suppressRecovery(e),forgetRecovery:e=>_.forgetInstance(e),completeSuppressedRecovery:e=>_.completeSuppressedOperation(e),deleteMetadata:e=>E.modelRegistry.deleteInstanceMetadata(e),diagnostic:K},J),function(e,t){const{fetchImpl:n,metrics:i,diagnostic:r}=t;e.post("/api/node-agent/instances/:id/proxy",async(e,i)=>{const s=e.params.id,o=fs.parse(e.body),a=t.instanceBase(s),c=js(o.path);"POST"===o.method&&"/api/apps/sessions"===c&&await t.syncModelEnvironment(s),r({instanceId:s,action:"proxy",method:o.method,path:c,instanceBase:a},"node instance proxy requested");const d=await n(`${a}${c}`,{method:o.method,headers:{...o.headers},body:Ds(o)}),l=d.headers.get("content-type")||"application/octet-stream",u=await d.text();r({instanceId:s,action:"proxy",method:o.method,path:c,statusCode:d.status,contentType:l},"node instance proxy completed"),i.code(d.status).type(l).send(u)}),e.post("/api/node-agent/instances/:id/proxy/stream",{bodyLimit:Os},async(e,s)=>{const o=Date.now();i.requests+=1,i.active+=1;const a=new AbortController;let c=0,d=!1,l=!1;const u=e=>{l||(l=!0,i.active-=1,i.totalDurationMs+=Date.now()-o,i.responseBytes+=c,i[e]+=1)},p=()=>{a.abort(),d&&u("aborted")};e.raw.once("aborted",p),s.raw.once("close",p);try{const o=e.params.id,l=fs.parse(e.body),p=t.instanceBase(o),m=js(l.path);r({instanceId:o,action:"proxy.stream",method:l.method,path:m,instanceBase:p},"node instance streaming proxy requested");const h=await n(`${p}${m}`,{method:l.method,headers:{...l.headers},body:Ds(l),signal:a.signal}),f=Number(h.headers.get("content-length"));if(Number.isFinite(f)&&f>i.maxResponseBytes)return i.limitRejected+=1,a.abort(),Ms(s,i.maxResponseBytes);s.code(h.status);for(const[e,t]of Object.entries(Rs(h.headers)))s.header(e,t);if(!h.body||"HEAD"===l.method)return u("completed"),s.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")),s.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:Os},async(e,s)=>{const o=e.params.id,a=fs.parse(e.body),c=t.instanceBase(o),d=js(a.path);r({instanceId:o,action:"proxy.raw",method:a.method,path:d,instanceBase:c},"node instance raw proxy requested");const l=await n(`${c}${d}`,{method:a.method,headers:{...a.headers},body:Ds(a)}),u=Number(l.headers.get("content-length"));if(Number.isFinite(u)&&u>i.maxResponseBytes)return i.limitRejected+=1,await(l.body?.cancel("Instance proxy response limit exceeded.").catch(()=>{})),Ms(s,i.maxResponseBytes);let p;try{p=await async function(e,t){if(!e.body)return Buffer.alloc(0);const n=[];let i=0;const r=e.body.getReader();for(;;){const{done:e,value:s}=await r.read();if(e)break;if(i+=s.byteLength,i>t)throw await r.cancel("Instance proxy response limit exceeded.").catch(()=>{}),Object.assign(new Error("Instance proxy response limit exceeded."),{code:"INSTANCE_PROXY_RESPONSE_TOO_LARGE"});n.push(Buffer.from(s))}return Buffer.concat(n,i)}(l,i.maxResponseBytes)}catch(e){if(!(e instanceof Error)||"INSTANCE_PROXY_RESPONSE_TOO_LARGE"!==e.code)throw e;return i.limitRejected+=1,Ms(s,i.maxResponseBytes)}return r({instanceId:o,action:"proxy.raw",method:a.method,path:d,statusCode:l.status,byteLength:p.length},"node instance raw proxy completed"),{data:{status:l.status,headers:Rs(l.headers),bodyBase64:p.toString("base64")}}}),e.get("/api/node-agent/instances/:id/proxy/ws/*",{websocket:!0},(e,n)=>{const i=n.params.id,s=n.params["*"]||"",o=n.url.indexOf("?"),a=o>=0?n.url.slice(o):"";let c;try{const o=t.instanceBase(i),d=new URL(`/${s}${a}`,`${o}/`);d.protocol="https:"===d.protocol?"wss:":"ws:";const l=function(e){const t=e["sec-websocket-protocol"],n=(Array.isArray(t)?t.join(","):"string"==typeof t?t:"").split(",").map(e=>e.trim()).filter(Boolean);return n.length?n:void 0}(n.headers);r({instanceId:i,action:"proxy.ws",path:`/${s}${a}`,upstreamUrl:d.toString(),protocols:l||[]},"node instance websocket proxy opening"),c=l?new u(d,l):new u(d),c.on("open",()=>{r({instanceId:i,action:"proxy.ws",path:`/${s}${a}`},"node instance websocket proxy opened"),e.on("message",(e,t)=>c?.readyState===u.OPEN&&c.send(function(e,t){return t?e:e.toString()}(e,t))),e.on("close",()=>c?.close()),e.on("error",()=>c?.close())}),c.on("message",(t,n)=>e.readyState===u.OPEN&&e.send(n?t:t.toString())),c.on("close",()=>{r({instanceId:i,action:"proxy.ws",path:`/${s}${a}`},"node instance websocket proxy closed"),e.close()}),c.on("error",t=>{r({instanceId:i,action:"proxy.ws",path:`/${s}${a}`,error:t instanceof Error?t.message:String(t)},"node instance websocket proxy failed"),e.close(1011,"Instance websocket proxy failed.")})}catch(t){r({instanceId:i,action:"proxy.ws",path:`/${s}${a}`,error:t instanceof Error?t.message:String(t)},"node instance websocket endpoint unavailable"),c?.close(),e.close(1011,"Instance websocket endpoint is not reachable.")}})}($,{fetchImpl:C,metrics:F,instanceBase:e=>oa(E.requireInstance(e)),syncModelEnvironment:e=>sa(C,E,e),diagnostic:K}),$}async function da(e){const r=Bi(e.dataDir),s=(o=e.host,a=e.port,Tn.parse({bindScope:"0.0.0.0"===o.trim()?"all-ipv4":"loopback",port:a}));var o,a;const d=t.existsSync(r.settingsPath),l=function(e,t){return new Lr(e.settingsPath,()=>({version:1,externalListener:t}),{schema:Ls,sanitize:Fs})}(r,s),u=l.get().externalListener,m=function(e,i={}){return function(e,i={}){t.mkdirSync(n.dirname(e),{recursive:!0});const r={pid:process.pid,hostname:p.hostname(),component:i.component,command:process.argv.join(" "),acquiredAt:(new Date).toISOString(),token:c.randomUUID(),startIdentity:Xi(process.pid),dataDir:i.dataDir,host:i.host,port:i.port,instanceId:i.instanceId};for(let n=0;n<5;n+=1)try{return t.mkdirSync(e),t.writeFileSync(Ji(e),`${JSON.stringify({token:r.token,pid:r.pid,startIdentity:r.startIdentity,startedAt:(new Date).toISOString()})}\n`,{encoding:"utf8",mode:384,flag:"wx"}),nr(e,r),{lockPath:e,owner:r,release(){const n=Zi(e);n?.token===r.token&&t.rmSync(e,{recursive:!0,force:!0})}}}catch(r){if("EEXIST"!==r.code)throw r;const s=Zi(e);if(tr(s))throw new Ki(e,s,i.error);if(!s&&(rr(e)||ar(e)<(i.incompleteLockStaleMs??2e3))){if(n+1<5){or();continue}throw new Ki(e,void 0,i.error)}const o=c.randomUUID();if(!cr(e,o)){if(n+1<5){or();continue}throw new Ki(e,Zi(e),i.error)}const a=Zi(e);if(tr(a))throw sr(Wi(e)),new Ki(e,a,i.error);if(s?.token&&a?.token!==s.token){sr(Wi(e));continue}if(!lr(e,o))continue;t.rmSync(e,{recursive:!0,force:!0})}const s=Zi(e);throw new Ki(e,s,i.error)}(e,{...i,component:"node-agent",error:{label:"Node agent",code:"NODE_AGENT_ALREADY_RUNNING"}})}(n.join(p.tmpdir(),`task-handoff-node-agent-${process.getuid?.()??"user"}.lock`),{dataDir:r.dataDir,host:$s(u.bindScope),port:u.port});try{const s={...e,port:u.port},o=await ca(s),a=o.nodeAgentState;if(!a)throw new Error("Node agent state was not initialized.");const c=new Io(r).resolveNodeId(e.nodeId||process.env.TASK_HANDOFF_NODE_ID),p=function(e,t,n,i){const r=t.token||process.env.TASK_HANDOFF_NODE_AGENT_TOKEN,s=new Io(n),o=new Map;let a=!1;const c=(t,n)=>{n.status=n.lastDisconnectedAt?"reconnecting":"connecting",n.error=void 0;const s=xo(e,{...n.config,nodeId:i,port:()=>e.nodeAgentState.currentListenerPort,token:r});return n.socket=s,s.on("open",()=>{o.get(t)===n&&n.socket===s&&(n.retry.reset(),n.status="connected",n.lastConnectedAt=(new Date).toISOString(),n.error=void 0,e.log.info({nodeId:i,tunnelUrl:new URL(n.config.tunnelUrl).origin},"node agent reverse tunnel connected"))}),s.on("close",(r,d)=>{o.get(t)===n&&n.socket===s&&(n.socket=void 0,n.lastDisconnectedAt=(new Date).toISOString(),n.error=`WebSocket closed${r?` (${r})`:""}${d?`: ${Buffer.isBuffer(d)?d.toString("utf8"):String(d)}`:""}`,a||(e.log.warn({nodeId:i,tunnelUrl:new URL(n.config.tunnelUrl).origin,code:r,reason:Buffer.isBuffer(d)?d.toString("utf8"):String(d||"")},"node agent reverse tunnel disconnected"),((t,n)=>{if(a||n.retry.pending||o.get(t)!==n)return;const r=n.retry.schedule(()=>{a||o.get(t)!==n||n.socket||c(t,n)});r&&(n.status="reconnecting",e.log.info({nodeId:i,tunnelUrl:new URL(n.config.tunnelUrl).origin,attempt:r.attempt,delay:r.delay},"node agent reverse tunnel reconnect scheduled"))})(t,n)))}),s.on("error",e=>{o.get(t)===n&&n.socket===s&&(n.status="failed",n.error=e instanceof Error?e.message:String(e))}),s},d=(e,t)=>{const n=o.get(e);n?.retry.cancel();const i={config:t,retry:new Ei,status:"connecting"};return o.set(e,i),n?.socket?.close(1e3,"Reverse tunnel reconnecting."),c(e,i)},l=(e,t)=>e.tunnelUrl===t.tunnelUrl&&e.keyId===t.keyId&&e.secret===t.secret;return{connectConfigured:()=>{a=!1;const n=new Map,r=s.resolvedControlPlaneAccess(),c=new Set;for(const{connection:t,pairing:s}of r.connections){if(!t.enabled)continue;if(!s){e.log.warn({nodeId:i,connectionId:t.id,pairingKeyId:t.pairingKeyId},"node agent control-plane connection has no pairing");continue}const r=Oo(t.url);n.set(t.id,{tunnelUrl:r,keyId:s.keyId,secret:s.secret}),c.add(r)}const u=function(e){const t=e.controlPlaneTunnelUrl||process.env.TASK_HANDOFF_CONTROL_PLANE_TUNNEL_URL;return t?new URL(t).toString():void 0}(t);if(u&&!c.has(u)){const e=s.reverseTunnelSecret(process.env.TASK_HANDOFF_CONTROL_PLANE_URL,t.remoteSecret||process.env.TASK_HANDOFF_NODE_AGENT_REMOTE_SECRET,t.remoteKeyId||process.env.TASK_HANDOFF_NODE_AGENT_REMOTE_KEY_ID);n.set(`explicit:${u}`,{tunnelUrl:u,keyId:e?.keyId,secret:e?.secret}),c.add(u)}const p=r.hasPersistedAccess?void 0:function(){const e=process.env.TASK_HANDOFF_CONTROL_PLANE_URL;if(!e)return;const t=new URL(qs,e);return t.protocol="https:"===t.protocol?"wss:":"ws:",t.toString()}();if(p&&!c.has(p)){const e=s.reverseTunnelSecret(process.env.TASK_HANDOFF_CONTROL_PLANE_URL,t.remoteSecret||process.env.TASK_HANDOFF_NODE_AGENT_REMOTE_SECRET,t.remoteKeyId||process.env.TASK_HANDOFF_NODE_AGENT_REMOTE_KEY_ID);n.set(`bootstrap:${p}`,{tunnelUrl:p,keyId:e?.keyId,secret:e?.secret})}(e=>{for(const[t,n]of o)e.has(t)||(n.retry.cancel(),o.delete(t),n.socket?.close(1e3,"Reverse tunnel configuration removed."));for(const[t,n]of e){const e=o.get(t);e&&l(e.config,n)||d(t,n)}})(n)},state:e=>{const t=o.get(e);if(t)return{status:t.status,...t.lastConnectedAt?{lastConnectedAt:t.lastConnectedAt}:{},...t.lastDisconnectedAt?{lastDisconnectedAt:t.lastDisconnectedAt}:{},...t.error?{error:t.error}:{}}},closeAll:()=>{a=!0;for(const e of o.values())e.retry.cancel(),e.socket?.close(1001,"Node agent shutting down.");o.clear()}}}({log:o.log,inject:e=>o.inject(e),nodeAgentEventForwarder:o.nodeAgentEventForwarder,nodeAgentState:a},s,r,c);o.decorate("nodeAgentReverseTunnels",p);const g=new Us({app:o,state:a,settings:l,config:u,source:d?"persisted":"bootstrap"});let h;o.decorate("nodeAgentListenerManager",g),function(e){let t=!1;const n=async n=>{if(!t){t=!0,p.closeAll(),h?.close();try{await e.close()}finally{process.exitCode=n?0:process.exitCode}}},i=()=>{n("SIGINT")},r=()=>{n("SIGTERM")};process.once("SIGINT",i),process.once("SIGTERM",r),e.addHook("onClose",async()=>{process.off("SIGINT",i),process.off("SIGTERM",r)})}(o),o.addHook("onClose",async()=>{h?.close(),m.release()});try{await o.ready();const s=e.ipcPath||process.env.TASK_HANDOFF_NODE_AGENT_IPC_PATH||ur(r.dataDir);h=await async function(e,r){!function(e,i=process.platform){if("win32"!==i){t.mkdirSync(n.dirname(e),{recursive:!0,mode:448});try{t.chmodSync(n.dirname(e),448)}catch{}try{t.unlinkSync(e)}catch(e){if("ENOENT"!==e.code)throw e}}}(r);const s=i.createServer((t,n)=>{e.server.emit("request",t,n)});return s.on("upgrade",(t,n,i)=>{e.server.emit("upgrade",t,n,i)}),await new Promise((e,t)=>{s.once("error",t),s.listen(r,()=>{s.off("error",t),e()})}),s}(o,s),await g.start(),p.connectConfigured(),o.nodeAgentStartRecoverySupervisor?.()}catch(e){throw await o.close(),e}}catch(e){throw m.release(),e}}function la(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 ua(e){if("local-ipc"!==e&&"local-loopback"!==e)throw new Error("Connection mode must be local-ipc or local-loopback.");return e}function pa(e){const t=Number(e);if(!Number.isInteger(t)||t<=0)throw new Error("Expiry must be a positive integer.");return t}(async function(){const t=new e.Command;t.name("task-handoff-node-agent").description("Run a TaskHandoff node agent.").version(E("@task-handoff/cli")).option("--host <host>","Node agent host",process.env.TASK_HANDOFF_NODE_AGENT_HOST||"127.0.0.1").option("-p, --port <port>","Node agent port",la,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",ua).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 da({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",pa).option("--json","Print raw JSON output").action(async e=>{const n=t.opts(),r=e.ipcPath||n.ipcPath||process.env.TASK_HANDOFF_NODE_AGENT_IPC_PATH,s=e.dataDir||n.dataDir||process.env.TASK_HANDOFF_NODE_AGENT_DATA_DIR,o=e.endpoint?void 0:r||ur(s||Hi()),a=await async function(e){const t={"content-type":"application/json",...e.token?{authorization:`Bearer ${e.token}`}:{}},n=JSON.stringify({...e.expiresInMs?{expiresInMs:e.expiresInMs}:{}}),r=e.endpoint?await fetch(`${e.endpoint.replace(/\/$/,"")}/api/node-agent/pairing/invites`,{method:"POST",headers:t,body:n}):await async function(e,t,n={}){const r=n.method||"GET",s="string"==typeof n.body||n.body instanceof Buffer?n.body:void 0===n.body||null===n.body?void 0:String(n.body),o=new Headers(n.headers||{});return void 0===s||o.has("content-length")||o.set("content-length",String(Buffer.byteLength(s))),new Promise((a,c)=>{const d=i.request({socketPath:e,method:r,path:`/api/node-agent${t}`,headers:Object.fromEntries(o.entries())},e=>{const t=e.statusCode||500;a(new Response("HEAD"!==r&&204!==t&&205!==t&&304!==t?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!==s&&d.write(s),d.end()})}(e.ipcPath,"/pairing/invites",{method:"POST",headers:t,body:n}),s=await r.json().catch(()=>({}));if(!r.ok)throw new Error(s.error?.message||`Node agent pairing invite failed with HTTP ${r.status}`);const o="string"==typeof s.data?.joinToken?s.data.joinToken:"";if(!o)throw new Error("Node agent pairing invite response did not include a join token.");return{nodeId:"string"==typeof s.data?.nodeId?s.data.nodeId:"",joinToken:o,expiresAt:"string"==typeof s.data?.expiresAt?s.data.expiresAt:""}}({endpoint:e.endpoint,ipcPath:o,token:e.token,expiresInMs:e.expiresInMs});e.json?console.log(JSON.stringify(a,null,2)):(a.nodeId&&console.log(`Node: ${a.nodeId}`),console.log(`Join token: ${a.joinToken}`),a.expiresAt&&console.log(`Expires: ${a.expiresAt}`))}),await t.parseAsync(process.argv)})().catch(e=>{console.error(e instanceof Error?e.message:String(e)),process.exitCode=1});
|
|
1
|
+
"use strict";var e=require("commander"),t=require("node:fs"),n=require("node:path"),i=require("node:http"),r=require("node:url"),o=require("fastify"),s=require("@fastify/websocket"),a=require("zod"),c=require("node:crypto"),d=require("node:child_process"),l=require("node-pty"),u=require("ws"),m=require("node:os"),p=require("node:net"),g=require("node:stream"),h=require("node:fs/promises"),f=require("node:stream/promises"),y=require("tar"),I=require("write-file-atomic"),A=require("semver"),b="undefined"!=typeof document?document.currentScript:null;function w(e,n){try{const i=JSON.parse(t.readFileSync(e,"utf8"));if(n&&i.name!==n)return;return"string"==typeof i.version&&i.version.trim()?i.version.trim():void 0}catch{return}}function v(e){if(e)try{return n.dirname(t.realpathSync(e))}catch{return}}function E(e,t=process.env,i=e){const r=t.TASK_HANDOFF_VERSION?.trim();if(r)return r;const o=i.split("/").at(-1),s=process.argv[1]?n.resolve(process.argv[1]):void 0,a=s?n.dirname(s):void 0,c=[v(s),a,process.cwd()].filter(e=>Boolean(e));for(const t of new Set(c)){let i=t;for(;;){const t=w(n.join(i,"package.json"),e);if(t)return t;const r=n.dirname(i);if(r===i)break;i=r}}let d;for(const e of new Set(c)){let t=e;for(;;){if(o){const e=w(n.join(t,"packages",o,"package.json"),i);if(e)return e}d||=w(n.join(t,"package.json"));const e=n.dirname(t);if(e===t)break;t=e}}return d||"unknown"}const N=41943040,z="ai.sessions",_=a.z.string().trim().min(1).max(80),S=a.z.enum(["app-session","ai-session"]),T=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 k=a.z.enum(["thinking","tool","editing","approval","responding","unknown"]),C=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(),O=a.z.enum(["pending-init","running","interrupted","completed","errored","shutdown","not-found"]),x=a.z.enum(["started","interacted","interrupted"]),R=a.z.object({threadId:a.z.string().trim().min(1).max(240),path:a.z.string().trim().max(4096).optional(),status:O,activity:x.optional(),message:a.z.string().trim().max(1e3).optional(),updatedAt:a.z.string().datetime()}).strict(),D=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}),P=a.z.object({send:a.z.boolean().optional(),interrupt:a.z.boolean().optional(),approval:a.z.boolean().optional(),openApp:a.z.boolean().optional(),close:a.z.boolean().optional()}).strict(),M=a.z.enum(["image","file"]),j=a.z.object({id:a.z.string().trim().min(1).max(120),kind:M,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)}),L=a.z.union([j.extend({source:a.z.object({type:a.z.literal("inline"),encoding:a.z.literal("base64"),data:a.z.string().min(1).max(31457280)}).strict()}).strict().superRefine((e,t)=>{const n="image"===e.kind?20971520:512e3;(e.size<=0||("file"===e.kind?e.size>=n:e.size>n))&&t.addIssue({code:a.z.ZodIssueCode.custom,path:["size"],message:`Inline ${e.kind} must be between 1 byte and ${n} bytes.`})}),j.extend({source:a.z.object({type:a.z.literal("runtime-path"),path:a.z.string().trim().min(1).max(4096)}).strict()}).strict()]),$=j.extend({sourceType:a.z.enum(["inline","runtime-path"])}).strict(),F=a.z.union([a.z.object({id:a.z.string().trim().min(1).max(120),kind:M.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:M,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()]),U=a.z.enum(["auto","queue","steer","immediate"]),V=a.z.enum(["ask","auto-review","full-access"]),q=a.z.enum(["review","rename","goal","compact"]);a.z.object({command:q,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:q,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 H=a.z.object({name:a.z.string().trim().min(1).max(240),path:a.z.string().trim().min(1).max(4096)}),B=a.z.discriminatedUnion("kind",[H.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(),H.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(),H.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()]),K=a.z.array(B).max(20).default([]),G=a.z.enum(["plugin","skill","file","directory","app"]),J=a.z.object({kind:G,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."})}),W=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(J).max(1e3).default([]),diagnostics:a.z.array(W).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(J.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 Y=a.z.object({message:a.z.string().trim().min(1).max(2e4),mode:U.optional(),permissionMode:V.optional()}),X=Y.extend({attachments:a.z.array(L).max(6).default([]),references:K}).strict().superRefine((e,t)=>{e.attachments.reduce((e,t)=>e+("inline"===t.source.type?t.size:0),0)>N&&t.addIssue({code:a.z.ZodIssueCode.custom,path:["attachments"],message:"Inline attachments must be 41943040 bytes or less in total."})}),Q=Y.extend({attachments:a.z.array(F).max(6).default([]),references:K}).strict(),Z=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();X.extend({agent:_,cwd:Z,clientRequestId:a.z.string().trim().min(1).max(160)}).strict(),Q.extend({agent:_,cwd:Z,clientRequestId:a.z.string().trim().min(1).max(160)}).strict(),a.z.object({disposition:a.z.enum(["created","already-created"]),aiSessionId:a.z.string().trim().min(1).max(120),providerSessionId:a.z.string().trim().min(1).max(240),creationSource:a.z.literal("ai-session")}).strict(),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:S}).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:S}).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 ee=a.z.object({id:a.z.string().trim().min(1).max(120),message:a.z.string().trim().min(1).max(2e4),attachments:a.z.array($).max(6).default([]),references:K,permissionMode:V.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(),te=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(ee).max(100).default([])}).strict().default({revision:0,pendingCount:0,items:[]}),ne=a.z.enum(["control","realtime","adapter-snapshot","transcript-tail","transcript-scan","process-scan","app-session"]),ie=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(),re=a.z.object({id:a.z.string().trim().min(1).max(240),providerTurnId:a.z.string().trim().max(240).optional(),source:ne.optional(),userPrompt:a.z.string().trim().optional(),status:a.z.enum(["queued","running","waiting","completed","failed"]).default("running"),phase:k.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(ie).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(),oe=re.pick({id:!0,providerTurnId:!0,userPrompt:!0,status:!0,phase:!0,summary:!0,lastMessage:!0,contextCompactions:!0,startedAt:!0,updatedAt:!0,completedAt:!0}).strict(),se=a.z.object({id:a.z.string().trim().min(1).max(120),agent:_,creationSource:S.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(),providerMeta:a.z.record(a.z.string(),a.z.unknown()).optional(),appBindingKeys:a.z.array(a.z.string().trim().min(1).max(240)).max(20).optional(),actions:P.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(),userPrompt:a.z.string().trim().optional(),turns:a.z.array(re).max(50).optional(),status:T.default("running"),phase:k.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:C.optional(),toolCallsSinceLastMessage:a.z.number().int().min(0).default(0),subAgents:a.z.array(R).max(50).default([]),transcriptPath:a.z.string().trim().max(4096).optional(),transcriptSize:a.z.number().int().min(0).optional(),startedAt:a.z.string().datetime(),updatedAt:a.z.string().datetime(),completedAt:a.z.string().datetime().optional(),error:a.z.string().trim().max(4e3).optional(),counters:D,queue:te}).strict();a.z.object({session:se,provider:a.z.string().trim().min(1).max(80),action:a.z.enum(["send","queue","steer","interrupt","approval"]),decision:a.z.enum(["allow","deny","skip"]).optional(),turnId:a.z.string().trim().min(1).max(240).optional(),providerTurnId:a.z.string().trim().min(1).max(240).optional(),queueId:a.z.string().trim().min(1).max(120).optional()}).strict();const ae=a.z.object({id:a.z.string().trim().min(1).max(120),agent:a.z.enum(["codex","claude"]),creationSource:S,providerSessionId:a.z.string().trim().min(1).max(240),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),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(ae).max(50).default([])}).strict(),a.z.object({items:a.z.array(ae).max(50).default([])}).strict(),a.z.object({item:ae,turns:a.z.array(oe).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:S}).strict();const ce=se.pick({id:!0,agent:!0,creationSource:!0,appSessionId:!0,appId:!0,providerSessionId:!0,providerMeta:!0,appBindingKeys:!0,actions:!0,activeTurnId:!0,title:!0,cwd:!0,userPrompt:!0,turns:!0,status:!0,phase:!0,summary:!0,lastMessage:!0,lastMessageItemId:!0,currentTool:!0,toolCallsSinceLastMessage:!0,subAgents:!0,queue:!0,startedAt:!0,updatedAt:!0,error:!0}),de=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(ce).default([]),updatedAt:a.z.string().datetime()}).strict();a.z.object({streamId:a.z.string().trim().min(1).max(240),revision:a.z.number().int().min(0),lastEventAt:a.z.string().datetime(),snapshot:de}).strict(),de.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 le=a.z.enum(["provider-event","app-session-created","app-session-updated","app-session-deleted","discovery-scan","control-action","heartbeat-sync","startup"]),ue=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:le}).strict(),me=a.z.object({meta:ue,snapshot:de}).strict(),pe=a.z.object({meta:ue,upserted:a.z.array(ce).default([]),removed:a.z.array(a.z.string().trim().min(1).max(120)).default([])}).strict(),ge=a.z.object({meta:ue,sessionIds:a.z.array(a.z.string().trim().min(1).max(120)).default([]),expiresAt:a.z.string().datetime()}).strict();a.z.object({instanceId:a.z.string().trim().min(1).max(160),nodeId:a.z.string().trim().min(1).max(160).optional(),sessionId:a.z.string().trim().min(1).max(120),providerSessionId:a.z.string().trim().min(1).max(240),turnId:a.z.string().trim().min(1).max(240),itemId:a.z.string().trim().min(1).max(240),delta:a.z.string().min(1),generatedAt:a.z.string().datetime()}).strict(),a.z.object({streamId:a.z.string().trim().min(1).max(240),instanceId:a.z.string().trim().min(1).max(160),sinceRevision:a.z.number().int().min(0),latestRevision:a.z.number().int().min(0),earliestRetainedRevision:a.z.number().int().min(0),syncRequired:a.z.boolean().default(!1),events:a.z.array(a.z.discriminatedUnion("type",[a.z.object({type:a.z.literal("ai-session.snapshot"),payload:me}).strict(),a.z.object({type:a.z.literal("ai-session.patch"),payload:pe}).strict(),a.z.object({type:a.z.literal("ai-session.removed"),payload:ge}).strict()])).default([])}).strict();const he=a.z.object({source:ne,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(),fe=he.extend({type:a.z.literal("snapshot"),agent:a.z.string().trim().min(1).max(80),creationSource:S.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(),providerMeta:a.z.record(a.z.string(),a.z.unknown()).optional(),appBindingKeys:a.z.array(a.z.string().trim().min(1).max(240)).max(20).optional(),actions:P.optional(),title:a.z.string().trim().max(240).optional(),cwd:a.z.string().trim().max(4096).optional(),activeTurnId:a.z.string().trim().max(240).optional(),userPrompt:a.z.string().trim().optional(),turns:a.z.array(re).max(50).optional(),status:T.optional(),phase:k.optional(),summary:a.z.string().trim().max(1e3).optional(),lastMessage:a.z.string().trim().optional(),lastMessageItemId:a.z.string().trim().max(240).optional(),currentTool:C.optional(),toolCallsSinceLastMessage:a.z.number().int().min(0).optional(),subAgents:a.z.array(R).max(50).optional(),transcriptPath:a.z.string().trim().max(4096).optional(),transcriptSize:a.z.number().int().min(0).optional(),replaceActivity:a.z.boolean().optional()}).strict(),ye=he.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","tool-activity","sub-agent-activity","context-compaction"]),activeTurnId:a.z.string().trim().max(240).optional(),providerTurnId:a.z.string().trim().max(240).optional(),userPrompt:a.z.string().trim().optional(),text:a.z.string().optional(),itemId:a.z.string().trim().max(240).optional(),status:T.optional(),phase:k.optional(),summary:a.z.string().trim().max(1e3).optional(),error:a.z.string().trim().max(4e3).optional(),currentTool:C.nullable().optional(),toolCallsSinceLastMessage:a.z.number().int().min(0).optional(),subAgents:a.z.array(R).max(50).optional(),contextCompaction:ie.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("context-compaction"===e.kind?e.contextCompaction||t.addIssue({code:"custom",path:["contextCompaction"],message:"context-compaction events require contextCompaction"}):void 0!==e.contextCompaction&&t.addIssue({code:"custom",path:["contextCompaction"],message:"contextCompaction is only valid for context-compaction events"}),"sub-agent-activity"===e.kind?e.subAgents||t.addIssue({code:"custom",path:["subAgents"],message:"sub-agent-activity events require subAgents"}):void 0!==e.subAgents&&t.addIssue({code:"custom",path:["subAgents"],message:"subAgents is only valid for sub-agent-activity events"}),"tool-activity"!==e.kind)return void 0!==e.currentTool&&t.addIssue({code:"custom",path:["currentTool"],message:"currentTool is only valid for tool-activity events"}),void(void 0!==e.toolCallsSinceLastMessage&&t.addIssue({code:"custom",path:["toolCallsSinceLastMessage"],message:"toolCallsSinceLastMessage is only valid for tool-activity events"}));"currentTool"in e||t.addIssue({code:"custom",path:["currentTool"],message:"tool-activity events require currentTool"}),void 0===e.toolCallsSinceLastMessage&&t.addIssue({code:"custom",path:["toolCallsSinceLastMessage"],message:"tool-activity events require toolCallsSinceLastMessage"})});a.z.discriminatedUnion("type",[fe,ye]);const Ie=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()]),Ae=a.z.union([Ie,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()]),be=a.z.object({promptTemplate:a.z.string().trim().min(1).max(2e4)}).strict(),we=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(),ve=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:Ae,action:be,policy:we.default({maxConcurrentRuns:1,whenBusy:"skip"}),createdAt:a.z.string().datetime(),updatedAt:a.z.string().datetime()}).strict(),Ee=a.z.object({type:a.z.literal("ai-session"),aiSessionId:a.z.string().trim().min(1).max(160)}).strict(),Ne=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:Ee,localName:a.z.string().trim().min(1).max(160).optional(),createdAt:a.z.string().datetime(),updatedAt:a.z.string().datetime()}).strict(),ze=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(),_e=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:Ee,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(ve).default([]),deployments:a.z.array(Ne).default([]),runtime:a.z.array(ze).default([]),recentRuns:a.z.array(_e).default([])}).strict();const Se=a.z.string().regex(/^\d{4}-\d{2}-\d{2}$/,"Proxy protocol version must use YYYY-MM-DD format."),Te=a.z.string().trim().min(1).max(160).regex(/^[a-zA-Z0-9][a-zA-Z0-9_.:-]*$/),ke=a.z.string().datetime(),Ce=a.z.string().trim().min(32).max(4096),Oe=a.z.string().trim().max(2048).transform((e,t)=>{try{return function(e){const t=new URL(e.trim());if("https:"!==t.protocol||t.username||t.password||"/"!==t.pathname||t.search||t.hash)throw new Error("Proxy origin must be an HTTPS origin without credentials, path, query, or fragment.");return t.origin}(e)}catch(e){return t.addIssue({code:"custom",message:e instanceof Error?e.message:String(e)}),a.z.NEVER}});a.z.string().trim().min(1).max(4096).transform((e,t)=>{try{return function(e){const t=e.trim();if(!t.startsWith("/")||t.startsWith("//")||t.includes("\\")||/%25/i.test(t))throw new Error("Proxy route must be a single-encoded node-agent relative route.");const n=t.split("?",1)[0];let i,r;try{i=n.split("/").map(e=>decodeURIComponent(e))}catch{throw new Error("Proxy route contains invalid percent encoding.")}if(i.some(e=>".."===e||"."===e))throw new Error("Proxy route cannot traverse outside the node-agent API.");try{r=new URL(t,"https://node-agent.invalid")}catch{throw new Error("Proxy route is invalid.")}if("https://node-agent.invalid"!==r.origin||r.username||r.password)throw new Error("Proxy route cannot select an absolute upstream URL.");return`${r.pathname}${r.search}`}(e)}catch(e){return t.addIssue({code:"custom",message:e instanceof Error?e.message:String(e)}),a.z.NEVER}});const xe=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"})),Re=a.z.object({code:xe,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(),De=a.z.enum(["active","consumed","revoked","expired"]),Pe=a.z.object({id:Te,targetNodeId:Te,tokenHash:a.z.string().trim().min(32).max(256),status:De,createdBy:Te,expiresAt:ke,consumedByClaimId:Te.optional(),consumedAt:ke.optional(),revokedAt:ke.optional(),createdAt:ke,updatedAt:ke}).strict().omit({tokenHash:!0});a.z.object({targetNodeId:Te,expiresInSeconds:a.z.number().int().min(60).max(3600).default(600)}).strict(),a.z.object({invite:Pe,token:a.z.string().trim().min(24).max(512),proxyOrigin:Oe,protocolVersion:Se}).strict();const Me=a.z.enum(["active","revoked"]),je=a.z.object({id:Te,claimId:Te,sourceControlPlaneId:Te,targetNodeId:Te,bindingKeyId:Te,credentialHash:a.z.string().trim().min(32).max(256),status:Me,revision:a.z.number().int().positive(),lastError:Re.optional(),revokedAt:ke.optional(),createdAt:ke,updatedAt:ke}).strict().omit({credentialHash:!0});a.z.object({protocolVersion:Se,inviteToken:a.z.string().trim().min(24).max(512).optional(),claimId:Te,sourceControlPlaneId:Te,targetNodeId:Te.optional(),bindingKeyId:Te,credential:Ce}).strict(),a.z.object({sourceControlPlaneId:Te,bindingKeyId:Te,credential:Ce}).strict();const Le=a.z.object({id:Te,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:ke.optional(),capabilities:a.z.record(a.z.string(),a.z.unknown()).default({})}).strict(),$e=a.z.object({protocolVersion:Se,binding:je,streamId:Te,revision:a.z.number().int().nonnegative(),observedAt:ke,target:Le}).strict(),Fe=a.z.object({type:a.z.literal("control-plane-proxy.event"),protocolVersion:Se,streamId:Te,bindingId:Te,sourceControlPlaneId:Te,targetNodeId:Te,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:Le,event:a.z.object({type:a.z.string().trim().min(1).max(240),topic:a.z.string().trim().min(1).max(240),createdAt:ke}).strict()}).strict(),Ue=a.z.object({type:a.z.literal("control-plane-proxy.events.ready"),protocolVersion:Se,streamId:Te,bindingId:Te,sourceControlPlaneId:Te,targetNodeId:Te,latestRevision:a.z.number().int().nonnegative(),earliestRetainedRevision:a.z.number().int().nonnegative()}).strict(),Ve=a.z.object({type:a.z.literal("control-plane-proxy.snapshot-required"),protocolVersion:Se,streamId:Te,bindingId:Te,sourceControlPlaneId:Te,targetNodeId:Te,sinceRevision:a.z.number().int().nonnegative(),latestRevision:a.z.number().int().nonnegative(),earliestRetainedRevision:a.z.number().int().nonnegative(),error:Re}).strict();a.z.discriminatedUnion("type",[Fe,Ue,Ve]),a.z.object({protocolVersion:Se,binding:je,target:$e.shape.target}).strict(),a.z.object({id:Te,claimId:Te,proxyOrigin:Oe,requestedName:a.z.string().trim().min(1).max(160).optional(),sourceControlPlaneId:Te,targetNodeId:Te.optional(),bindingKeyId:Te,credential:Ce,status:a.z.enum(["pending","compensation-required"]),createdAt:ke,updatedAt:ke,expiresAt:ke}).strict().omit({credential:!0}),a.z.object({id:Te,nodeId:Te,proxyOrigin:Oe,proxyBindingId:Te,targetNodeId:Te,sourceControlPlaneId:Te,bindingKeyId:Te,credential:Ce,createdAt:ke,updatedAt:ke}).strict();const qe="2026-08-01",He=a.z.string(),Be=a.z.string().trim().min(1).max(120).regex(/^[a-zA-Z0-9][a-zA-Z0-9_.:-]*$/),Ke=a.z.string().datetime(),Ge=a.z.record(a.z.string(),a.z.string()).default({}),Je=a.z.record(a.z.string(),a.z.string()).default({}),We=a.z.string().regex(/^\d{4}-\d{2}-\d{2}$/,"Protocol version must use YYYY-MM-DD format."),Ye=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 Xe(e){if(null==e)return;const t=Ye.parse(e);return"utf8"===t.encoding?t.data:Buffer.from(t.data,"base64")}const Qe=/^[A-Za-z0-9_][A-Za-z0-9_.-]{0,127}$/,Ze=/^sha256:([a-fA-F0-9]{64})$/,et=/^(?:localhost|[a-z0-9](?:[a-z0-9.-]*[a-z0-9])?)(?::[1-9][0-9]{0,4})?$/,tt=/^[a-z0-9]+(?:(?:[._]|__|-+)[a-z0-9]+)*$/;function nt(e){const t=e.trim();if(!t||t.length>512||t.includes("://")||/\s/.test(t))throw new Error("Docker image reference must not contain a URL scheme or whitespace.");const n=t.indexOf("@");if(-1!==n&&n!==t.lastIndexOf("@"))throw new Error("Docker image reference contains more than one digest separator.");const i=-1===n?void 0:t.slice(n+1),r=-1===n?t:t.slice(0,n),o=i?Ze.exec(i):void 0;if(i&&!o)throw new Error("Docker image digest must use sha256 followed by 64 hexadecimal characters.");const s=r.lastIndexOf("/"),a=r.lastIndexOf(":"),c=a>s,d=c?r.slice(a+1):void 0,l=c?r.slice(0,a):r;if(d&&!Qe.test(d))throw new Error("Docker image tag is invalid.");if(!d&&!o)throw new Error("Docker image reference must include an explicit tag or sha256 digest.");const u=l.split("/");if(!u.length||u.some(e=>!e))throw new Error("Docker image repository path is invalid.");const m=u.length>1&&(u[0].includes(".")||u[0].includes(":")||"localhost"===u[0]),p=m?u.slice(1):u;if(m&&!et.test(u[0].toLowerCase()))throw new Error("Docker image registry host or port is invalid.");if(!p.length||p.some(e=>!tt.test(e)))throw new Error("Docker image repository names must be lowercase and use valid separators.");const g=u.map((e,t)=>m&&0===t?e.toLowerCase():e).join("/"),h=o?`sha256:${o[1].toLowerCase()}`:void 0;return`${g}${d?`:${d}`:""}${h?`@${h}`:""}`}function it(e){const t=nt(e),n=t.indexOf("@"),i=-1===n?void 0:t.slice(n+1),r=-1===n?t:t.slice(0,n),o=r.lastIndexOf("/"),s=r.lastIndexOf(":"),a=s>o;return{reference:t,repository:a?r.slice(0,s):r,tag:a?r.slice(s+1):void 0,digest:i}}const rt=a.z.string().trim().min(1).max(512).transform((e,t)=>{try{return nt(e)}catch(e){return t.addIssue({code:"custom",message:e instanceof Error?e.message:String(e)}),a.z.NEVER}}),ot=a.z.string().trim().transform((e,t)=>{const n=Ze.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)}),st=a.z.object({codexModelHash:Be.nullable().optional(),claudeModelHash:Be.nullable().optional()}).strict().default({}),at=a.z.object({imageId:Be,tag:a.z.string().trim().min(1).max(128).regex(Qe).optional()}).strict(),ct=a.z.discriminatedUnion("type",[a.z.object({type:a.z.literal("image"),imageSelection:at}).strict(),a.z.object({type:a.z.literal("template"),environmentTemplateId:Be}).strict()]),dt=a.z.enum(["creating","ready","failed","deleting"]),lt=a.z.enum(["linux","darwin","win32","freebsd","openbsd","aix","sunos","unknown"]),ut=a.z.enum(["x64","arm64","arm","ia32","ppc64","s390x","riscv64","unknown"]),mt=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(),pt=a.z.object({templateId:Be,nodeId:Be,imageId:ot,name:a.z.string().trim().min(1).max(160),platform:lt,architecture:ut}).strict(),gt=a.z.enum(["data","agent-home","workspace"]),ht=a.z.object({role:gt,name:a.z.string().trim().min(1).max(255),mountPath:a.z.string().trim().startsWith("/").max(4096),labels:a.z.record(a.z.string(),a.z.string())}).strict(),ft=a.z.object({deleteVolumes:a.z.boolean()}).strict(),yt=ht.pick({role:!0,name:!0,mountPath:!0}).extend({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(),It=a.z.object({instanceId:Be,containerDeleted:a.z.boolean(),completed:a.z.boolean(),deletedVolumes:a.z.array(yt),retainedVolumes:a.z.array(yt),volumeResults:a.z.array(yt)}).strict(),At={img_default:"market_taskhandoff_browser",img_codex:"market_taskhandoff_codex",img_ai:"market_taskhandoff_ai"};function bt(e,t){if(e&&"object"==typeof e&&!Array.isArray(e)){const t=e;return{imageId:"string"==typeof t.imageId&&At[t.imageId]||t.imageId,..."string"==typeof t.tag?{tag:t.tag}:{}}}if("string"==typeof t)return{imageId:At[t]||t}}function wt(e){if(!e||"object"!=typeof e||Array.isArray(e))return e;const t=e,{defaultImageId:n,...i}=t;return{...i,defaultImageSelection:bt(t.defaultImageSelection,n)}}const vt=a.z.object({id:Be,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(),Et=a.z.object({code:a.z.enum(["APP_CATALOG_INVALID"]),message:a.z.string().trim().min(1).max(500)}).strict(),Nt=a.z.object({items:a.z.array(vt).max(256),observedAt:Ke,issues:a.z.array(Et).max(32).default([])}).strict(),zt=a.z.object({id:Be,name:a.z.string().trim().min(1).max(160),sourceInstanceId:Be,nodeId:Be,imageId:ot.optional(),internalTag:a.z.string().trim().min(1).max(512).optional(),platform:lt.optional(),architecture:ut.optional(),sizeBytes:a.z.number().int().nonnegative().optional(),status:dt,error:mt.optional(),createdAt:Ke,updatedAt:Ke}).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."})}),_t=a.z.enum(["apt","dnf","brew","npm"]),St=a.z.enum(["user","passwordless-sudo","root"]),Tt=a.z.object({platform:lt,arch:ut,installers:a.z.array(_t).max(8),privilege:St,installerAccess:a.z.object({npmGlobalWritable:a.z.boolean().optional()}).strict().optional()}).strict(),kt=a.z.enum(["installed","not-installed","broken","unsupported"]),Ct=a.z.enum(["recipe","bundled","external","none"]),Ot=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(),xt=a.z.object({id:Be,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:kt,managementSource:Ct,version:a.z.string().trim().max(120).optional(),canInstall:a.z.boolean(),canUninstall:a.z.boolean(),installReason:Ot.optional(),uninstallReason:Ot.optional(),activeJobId:Be.optional()}).strict(),Rt=a.z.enum(["install","uninstall"]),Dt=a.z.enum(["queued","running","succeeded","failed","cancelled","interrupted"]),Pt=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"]}),Mt=a.z.object({executable:a.z.string().trim().min(1).max(4096),args:a.z.array(a.z.string().max(4096)).max(128)}).strict(),jt=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(Be).max(64).optional()}).strict(),Lt=a.z.object({id:Be,requestId:Be.optional(),appId:Be,operation:Rt,state:Dt,phase:a.z.string().trim().min(1).max(120).optional(),progress:Pt.optional(),command:Mt.optional(),logTail:a.z.string().max(32768).optional(),logTruncated:a.z.boolean().optional(),error:jt.optional(),requestedAt:Ke,startedAt:Ke.optional(),finishedAt:Ke.optional(),updatedAt:Ke}).strict(),$t=a.z.object({streamId:Be,sequence:a.z.number().int().nonnegative(),capabilities:Tt,apps:a.z.array(xt).max(256),activeJobs:a.z.array(Lt).max(256),recentJobs:a.z.array(Lt).max(256),observedAt:Ke}).strict();a.z.object({requestId:Be.optional()}).strict(),a.z.object({job:Lt}).strict(),a.z.object({type:a.z.literal("app-management"),streamId:Be,sequence:a.z.number().int().nonnegative(),observedAt:Ke,job:Lt.optional(),snapshot:$t.optional()}).strict().refine(e=>void 0!==e.job||void 0!==e.snapshot,{message:"An app management event requires a job or snapshot."});const Ft=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:He.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(),Ut=a.z.enum(["stable","beta","alpha"]),Vt=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(),qt=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(),Ht=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:Ke.optional(),matchedAt:Ke.optional(),error:qt.optional()}).strict(),Bt=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(Be).max(1024).default([]),stoppedInstanceIds:a.z.array(Be).max(1024).default([]),activeInstanceIds:a.z.array(Be).max(1024).default([])}).strict(),Kt=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(Be).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(),Gt=a.z.object({channel:Ut.default("stable")}).strict(),Jt=a.z.object({source:a.z.literal("npm"),channel:Ut,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(Vt).default([]),impact:Bt,updateAvailable:a.z.boolean(),supported:a.z.boolean().default(!0),reason:a.z.string().trim().max(2048).optional(),checkedAt:Ke,preflightToken:a.z.string().trim().min(16).max(240).optional()}).strict(),Wt=a.z.object({id:Be,nodeId:Be,source:a.z.literal("npm"),channel:Ut,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(Vt).default([]),impact:Bt,rollout:Kt,status:a.z.enum(["queued","updating-node","restarting-node","converging-instances","succeeded","degraded","failed"]),error:qt.optional(),startedAt:Ke.optional(),completedAt:Ke.optional(),createdAt:Ke,updatedAt:Ke}).strict(),Yt=a.z.object({channel:Ut,targetVersion:a.z.string().trim().min(1).max(240),preflightToken:a.z.string().trim().min(16).max(240)}).strict(),Xt=a.z.object({type:a.z.enum(["branch","tag","commit"]),name:a.z.string().trim().min(1).max(240).optional(),commit:a.z.string().trim().max(80).optional()}).strict(),Qt=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(),Zt=a.z.object({depth:a.z.number().int().positive().max(1e5).optional(),submodules:a.z.boolean().default(!1),lfs:a.z.boolean().default(!1),subdirectory:a.z.string().trim().max(240).default("")}).strict();a.z.object({id:Be,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:Xt.default({type:"branch",name:"main"}),auth:Qt.default({type:"none"}),clone:Zt.default({submodules:!1,lfs:!1,subdirectory:""}),defaultImageSelection:at.optional(),labels:Ge,createdAt:Ke,updatedAt:Ke}).strict();const en=a.z.object({id:Be,nodeId:Be,name:a.z.string().trim().min(1).max(160),path:a.z.string().trim().min(1).max(4096),defaultImageSelection:at.optional(),labels:Ge,createdAt:Ke,updatedAt:Ke}).strict(),tn=a.z.discriminatedUnion("type",[a.z.object({type:a.z.literal("git-repository"),repositoryId:Be.optional(),url:a.z.string().trim().min(1).max(2048),provider:a.z.string().trim().max(80).optional(),ref:Xt.default({type:"branch",name:"main"}),auth:Qt.default({type:"none"}),clone:Zt.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:Xt.default({type:"branch",name:"main"}),auth:Qt.default({type:"none"}),clone:Zt.default({submodules:!1,lfs:!1,subdirectory:""})}).strict(),a.z.object({type:a.z.literal("local-folder"),localFolderId:Be.optional(),path:a.z.string().trim().min(1).max(4096),ownerNodeId:Be.optional()}).strict()]),nn=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(),rn=a.z.enum(["codex","claude"]),on=a.z.object({id:Be,name:a.z.string().trim().min(1).max(160),source:tn,defaultImageSelection:at.optional(),defaultNodeId:Be.optional(),defaultRuntimeId:Be.optional(),workspacePolicy:nn,labels:Ge,createdAt:Ke,updatedAt:Ke}).strict(),sn=a.z.object({id:Be,name:a.z.string().trim().min(1).max(160),endpoint:a.z.string().trim().min(1).max(2048),key:a.z.string().trim().min(1).max(4096),model:a.z.string().trim().min(1).max(240),app:rn,enabled:a.z.boolean().default(!0),order:a.z.number().int().min(0).max(1e6).default(0),labels:Ge,createdAt:Ke,updatedAt:Ke}).strict(),an=sn,cn=sn.omit({key:!0}).extend({keyPreview:a.z.string().trim().min(1).max(160),keySet:a.z.boolean()}).strict(),dn=cn.extend({referenceCount:a.z.number().int().min(0)}).strict(),ln=a.z.object({instanceId:Be,codexModelHash:Be.optional(),claudeModelHash:Be.optional(),updatedAt:Ke}).strict(),un=a.z.discriminatedUnion("type",[a.z.object({type:a.z.literal("control-plane"),name:sn.shape.name,enabled:sn.shape.enabled,order:sn.shape.order}).strict(),a.z.object({type:a.z.literal("node"),nodeId:Be,name:sn.shape.name,enabled:sn.shape.enabled,order:sn.shape.order,referenceCount:a.z.number().int().min(0)}).strict()]),mn=a.z.object({id:Be,model:cn,locations:a.z.array(un).min(1),referenceCount:a.z.number().int().min(0).default(0)}).strict(),pn=a.z.object({nodeId:Be,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(mn),nodeDiagnostics:a.z.array(pn).default([]),updatedAt:Ke}).strict();const gn=sn.omit({id:!0,createdAt:!0,updatedAt:!0}).strict(),hn=gn.partial().strict(),fn=sn,yn=a.z.object({modelSelection:st,codexModelHash:Be.optional(),claudeModelHash:Be.optional()}).strict();function In(e){const t={app:rn.parse(e.app),endpoint:sn.shape.endpoint.parse(e.endpoint),key:sn.shape.key.parse(e.key),model:sn.shape.model.parse(e.model)};return`mdl_${c.createHash("sha256").update(JSON.stringify(t)).digest("hex")}`}const An=a.z.enum(["market","custom"]),bn=a.z.enum(["active","deprecated","yanked"]),wn=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:ot.optional()}).strict()]),vn=a.z.array(a.z.string().trim().min(1).max(80)).default([]),En=a.z.array(a.z.string().trim().min(1).max(120)).default([]),Nn=a.z.record(a.z.string().trim().min(2).max(35),a.z.string().trim().min(1).max(4096)),zn=a.z.object({os:a.z.string().trim().min(1).max(40),architecture:a.z.string().trim().min(1).max(40),digest:ot.optional(),downloadSizeBytes:a.z.number().int().positive().optional(),unpackedSizeBytes:a.z.number().int().positive().optional()}).strict(),_n=a.z.object({name:a.z.string().trim().min(1).max(128).regex(Qe),version:a.z.string().trim().min(1).max(160).optional(),reference:rt,manifestDigest:ot.optional(),publishedAt:Ke.optional(),platforms:a.z.array(zn).default([]),status:bn.default("active")}).strict(),Sn=a.z.object({id:Be,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:Nn.optional(),cover:wn.optional(),repository:a.z.string().trim().min(1).max(512),defaultTag:a.z.string().trim().min(1).max(128).regex(Qe),tags:a.z.array(_n).min(1),capabilities:vn,optionalApps:En,defaultEnv:Je,labels:Ge,status:bn.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:We,catalogId:Be,revision:a.z.string().trim().min(1).max(240),source:a.z.enum(["embedded","remote","cache"]),generatedAt:Ke,expiresAt:Ke.optional(),items:a.z.array(Sn)}).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:Ke,error:a.z.string().trim().max(4096).optional()}).strict(),a.z.object({id:Be,origin:a.z.literal("custom"),name:a.z.string().trim().min(1).max(160),description:a.z.string().trim().max(4096).optional(),localizedDescriptions:Nn.optional(),cover:wn.optional(),reference:rt,repository:a.z.string().trim().min(1).max(512),tag:a.z.string().trim().min(1).max(128).regex(Qe).optional(),pullPolicy:a.z.literal("if-not-present").default("if-not-present"),capabilities:vn,optionalApps:En,defaultEnv:Je,labels:Ge,createdAt:Ke,updatedAt:Ke}).strict();const Tn=a.z.object({name:a.z.string().trim().min(1).max(128).regex(Qe),version:a.z.string().trim().min(1).max(160).optional(),reference:rt,manifestDigest:ot.optional(),status:bn}).strict(),kn=a.z.object({id:Be,origin:An,name:a.z.string().trim().min(1).max(160),description:a.z.string().trim().max(4096).optional(),localizedDescriptions:Nn.optional(),cover:wn,repository:a.z.string().trim().min(1).max(512),tag:a.z.string().trim().min(1).max(128).regex(Qe).optional(),availableTags:a.z.array(Tn),reference:rt,digest:ot.optional(),downloadSizeBytes:a.z.number().int().positive().optional(),unpackedSizeBytes:a.z.number().int().positive().optional(),capabilities:vn,optionalApps:En,defaultEnv:Je,labels:Ge,readOnly:a.z.boolean(),lifecycleStatus:bn.optional(),market:a.z.object({catalogId:Be,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(),Cn=a.z.object({id:Be,origin:An,name:a.z.string().trim().min(1).max(160),description:a.z.string().trim().max(4096).optional(),localizedDescriptions:Nn.optional(),cover:wn.optional(),repository:a.z.string().trim().min(1).max(512),tag:a.z.string().trim().min(1).max(128).regex(Qe).optional(),requestedReference:rt,resolvedDigest:ot.optional(),resolvedReference:rt.optional(),downloadSizeBytes:a.z.number().int().positive().optional(),pullPolicy:a.z.literal("if-not-present").default("if-not-present"),capabilities:vn,optionalApps:En,defaultEnv:Je,labels:Ge,market:a.z.object({catalogId:Be,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:Ke,updatedAt:Ke}).strict(),On=a.z.object({phase:a.z.enum(["checking-image","pulling-image","resolving-image","ready","failed"]),requestedReference:rt,generation:a.z.number().int().nonnegative().default(0),error:a.z.string().trim().max(4096).optional(),startedAt:Ke,updatedAt:Ke}).strict(),xn="image.pull.terminal.output",Rn="image.pull.terminal.finished",Dn=a.z.object({instanceId:Be,generation:a.z.number().int().nonnegative(),requestedReference:rt,sequence:a.z.number().int().nonnegative(),observedAt:Ke}).strict(),Pn=Dn.extend({data:a.z.string().min(1).max(65536),replay:a.z.boolean().optional()}).strict(),Mn=Dn.extend({outcome:a.z.enum(["succeeded","failed"])}).strict();Dn.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 jn=a.z.discriminatedUnion("kind",[a.z.object({kind:a.z.literal("direct")}).strict(),a.z.object({kind:a.z.literal("control-plane-proxy"),proxyId:Be,proxyBindingId:Be,targetNodeId:Be}).strict()]),Ln=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:Ke.optional(),target:Le.optional(),lastError:Re.optional(),updatedAt:Ke}).strict(),$n=a.z.object({id:Be,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:jn.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:Be.optional(),secret:a.z.string().trim().max(4096).optional(),pairedAt:Ke.optional(),pairing:a.z.object({status:a.z.enum(["pending","paired","expired"]).default("pending"),joinToken:a.z.string().trim().max(4096).optional(),expiresAt:Ke.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:Ln.optional(),appInventory:Nt.optional(),labels:Ge,lastSeenAt:Ke.optional(),createdAt:Ke,updatedAt:Ke}).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."})}),Fn=a.z.object({id:Be,nodeId:Be,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:Ge,createdAt:Ke,updatedAt:Ke}).strict(),Un=a.z.object({instanceId:Be,runtimeKind:a.z.literal("docker"),state:a.z.enum(["pending","available","stopped","unavailable"]),sampledAt:Ke,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();a.z.object({ok:a.z.boolean().optional(),role:a.z.string().optional(),nodeId:Be.optional(),platform:lt.optional()}).passthrough();const Vn=a.z.object({bindScope:a.z.enum(["loopback","all-ipv4"]),port:a.z.number().int().min(1).max(65535)}).strict(),qn=Vn.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(),Hn=Vn;a.z.object({nodeId:Be,joinToken:a.z.string().trim().min(1),expiresAt:Ke}).passthrough(),a.z.object({nodeId:Be,keyId:Be,secret:a.z.string().regex(/^[A-Za-z0-9_-]{32,128}$/),pairedAt:Ke}).strict();const Bn=a.z.object({id:Be,keyId:Be,name:a.z.string().trim().min(1).max(160).optional(),pairedAt:Ke,updatedAt:Ke,current:a.z.boolean()}).passthrough();a.z.object({keyId:Be,revoked:a.z.literal(!0),revokedAt:Ke}).strict(),a.z.object({id:Be,pairingKeyId:Be,url:a.z.string().trim().min(1).max(2048),name:a.z.string().trim().min(1).max(160).optional(),enabled:a.z.boolean(),createdAt:Ke,updatedAt:Ke,status:a.z.enum(["disabled","connecting","connected","reconnecting","failed"]),lastConnectedAt:Ke.optional(),lastDisconnectedAt:Ke.optional(),error:a.z.string().optional()}).passthrough(),a.z.object({pairing:Bn,connection:a.z.object({id:Be,pairingKeyId:Be,url:a.z.string().trim().min(1).max(2048),name:a.z.string().trim().min(1).max(160).optional(),enabled:a.z.boolean(),createdAt:Ke,updatedAt:Ke}).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 Kn=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:kn,status:a.z.enum(["available","pull-required","unknown"]),localImage:Kn.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 Gn=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(Gn)}).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 Jn=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(),Wn=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"}),Yn=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(),Xn=a.z.object({id:Be,name:a.z.string().trim().min(1).max(160),projectId:Be.optional(),source:tn,sourceSnapshot:a.z.record(a.z.string(),a.z.unknown()).default({}),modelSelection:st,nodeId:Be,runtimeId:Be,imageSelection:at.optional(),environmentSource:ct.optional(),environmentTemplateOrigin:pt.optional(),imageSnapshot:Cn.optional(),imageProvisioning:On.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:He.optional(),instanceVersion:a.z.string().trim().max(80).optional(),build:Ft.optional(),runtimeVersion:Ht.optional(),ready:a.z.boolean().default(!1),capabilities:a.z.record(a.z.string(),a.z.unknown()).default({}),appInventory:Nt.optional(),config:a.z.object({autoImportAgentConfigs:a.z.boolean().default(!0),defaultCodexPermissionMode:V.default("ask")}).strict().default({autoImportAgentConfigs:!0,defaultCodexPermissionMode:"ask"}),workspace:Yn.default({status:"unknown"}),target:Jn.default({strategy:"direct-port",status:"unknown"}),access:Wn,apps:a.z.object({runningCount:a.z.number().int().min(0).default(0),problemCount:a.z.number().int().min(0).default(0),updatedAt:Ke.optional(),revision:a.z.number().int().min(0).optional()}).strict().default({runningCount:0,problemCount:0}),aiSessions:de.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:ve,deployments:a.z.array(Ne).default([]),runtime:a.z.array(ze).default([])}).strict()).default([]),recentRuns:a.z.array(_e).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({}),managedVolumes:a.z.array(ht).default([])}).strict().default({labels:{},managedVolumes:[]}),registrationToken:a.z.string().trim().min(1).max(240).optional(),lastHeartbeatAt:Ke.optional(),createdAt:Ke,updatedAt:Ke}).strict(),Qn="instance.lifecycle.snapshot",Zn=a.z.object({instanceId:Xn.shape.id,revision:a.z.number().int().min(0),updatedAt:Ke,status:Xn.shape.status.unwrap(),health:Xn.shape.health.unwrap(),connectionStatus:Xn.shape.connectionStatus.unwrap(),accessStatus:a.z.enum(["reachable","endpoint-unreachable"]),imageProvisioning:On.optional(),workspace:Yn,runtime:Xn.shape.runtime.unwrap(),runtimeVersion:Ht.optional(),ready:a.z.boolean(),lastHeartbeatAt:Ke.optional()}).strict();function ei(e,t){return Xn.safeParse(ti(e,t))}function ti(e,t){if(!e||"object"!=typeof e||Array.isArray(e))return e;const n=e,i=new Set(Object.keys(Xn.shape)),r={};for(const[e,o]of Object.entries(n))i.has(e)?r[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),r.capabilities=e}else r.capabilities={};r.appInventory=function(e,t,n){if(!e||"object"!=typeof e||Array.isArray(e))return;const i=e;Object.keys(i).some(e=>!["observedAt","items","issues"].includes(e))&&t?.({instanceId:n,field:"appInventory"});const r={observedAt:i.observedAt,items:Array.isArray(i.items)?i.items.map(e=>{e&&"object"==typeof e&&!Array.isArray(e)&&Object.keys(e).some(e=>!["id","name","kind","source","availability","capabilities","diagnosticCode"].includes(e))&&t?.({instanceId:n,field:"appInventory.items"});const i=ri(e,["id","name","kind","source","availability","diagnosticCode"]);return!i||"object"!=typeof i||Array.isArray(i)?i:{...i,capabilities:ri(e.capabilities,["automation","supportsCwdSelection"])}}):i.items,issues:Array.isArray(i.issues)?i.issues.map(e=>ri(e,["code","message"])):i.issues},o=Nt.safeParse(r);return o.success?o.data:void 0}(n.appInventory,t,"string"==typeof n.id?n.id:void 0),r.source=function(e,t,n){if(!e||"object"!=typeof e||Array.isArray(e))return e;const i=e,r=i.type,o=tn.options.find(e=>e.shape.type.value===r);if(!o)return e;const s="local-folder"===r?["type","localFolderId","path","ownerNodeId"]:"git-template"===r?["type","url","templateId","ref","auth","clone"]:["type","repositoryId","url","provider","ref","auth","clone"],a=ri(i,s);if("local-folder"!==r){const e=ni(Xt,ri(i.ref,["type","name","commit"]),"source.ref",t,n),r=ni(Qt,ri(i.auth,["type","secretId"]),"source.auth",t,n),o=ni(Zt,ri(i.clone,["depth","submodules","lfs","subdirectory"]),"source.clone",t,n);e?a.ref=e:delete a.ref,r?a.auth=r:delete a.auth,o?a.clone=o:delete a.clone}const c=ni(o,a,"source",t,n);return c?(Object.keys(i).some(e=>!s.includes(e))&&t?.({instanceId:n,field:"source"}),c):a}(n.source,t,"string"==typeof n.id?n.id:void 0),r.sourceSnapshot=n.sourceSnapshot&&"object"==typeof n.sourceSnapshot&&!Array.isArray(n.sourceSnapshot)?n.sourceSnapshot:{},r.build=ni(Ft,n.build,"build",t,"string"==typeof n.id?n.id:void 0),r.aiSessions=function(e,t,n){if(!e||"object"!=typeof e||Array.isArray(e))return;const i=e,r=Array.isArray(i.sessions)?i.sessions.flatMap((e,i)=>{const r=ni(ce,e,`aiSessions.sessions.${i}`,t,n);return r?[r]:[]}):[],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:r,updatedAt:Ke.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"}),de.parse(o)}(n.aiSessions,t,"string"==typeof n.id?n.id:void 0),r.triggers=function(e,t,n){if(!e||"object"!=typeof e||Array.isArray(e))return;const i=e;Object.keys(i).some(e=>!["enabledCount","runningCount","errorCount","configs","recentRuns"].includes(e))&&t?.({instanceId:n,field:"triggers"});const r=(e,i,r)=>Array.isArray(e)?e.flatMap((e,o)=>{const s=ni(i,e,`${r}.${o}`,t,n);return s?[s]:[]}):[],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 s=function(e,t,n,i){if(!e||"object"!=typeof e||Array.isArray(e))return;const r=e,o=ri(r,["configHash","name","description","createdAt","updatedAt"]);if(r.source&&"object"==typeof r.source&&!Array.isArray(r.source)){const e=r.source,t="schedule"===e.type?"interval"===e.scheduleKind?["type","scheduleKind","intervalMs"]:"daily"===e.scheduleKind?["type","scheduleKind","timeOfDay","timezone"]:["type","scheduleKind","weekdays","timeOfDay","timezone"]:"file-change"===e.type?["type","roots","globs","ignore","debounceMs"]:["type","agent","statuses","phases"];o.source=ri(e,t)}return o.action=ri(r.action,["promptTemplate"]),o.policy=ri(r.policy,["cooldownMs","maxConcurrentRuns","whenBusy"]),ni(ve,o,t,n,i)}(o.config,`triggers.configs.${i}.config`,t,n);return"string"==typeof o.configHash&&s?[{configHash:o.configHash,config:s,deployments:r(o.deployments,Ne,`triggers.configs.${i}.deployments`),runtime:r(o.runtime,ze,`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:r(i.recentRuns,_e,"triggers.recentRuns")}}(n.triggers,t,"string"==typeof n.id?n.id:void 0),r.apps=ni(Xn.shape.apps.unwrap(),ri(n.apps,["runningCount","problemCount","updatedAt","revision"]),"apps",t,"string"==typeof n.id?n.id:void 0)||{runningCount:0,problemCount:0},r.config=ni(Xn.shape.config.unwrap(),ri(n.config,["autoImportAgentConfigs","defaultCodexPermissionMode"]),"config",t,"string"==typeof n.id?n.id:void 0)||{autoImportAgentConfigs:!0,defaultCodexPermissionMode:"ask"},r.modelSelection=ni(st.unwrap(),ri(n.modelSelection,["codexModelHash","claudeModelHash"]),"modelSelection",t,"string"==typeof n.id?n.id:void 0)||{},r.imageSnapshot=function(e,t,n,i){if(!e||"object"!=typeof e||Array.isArray(e))return e;const r=e,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 r,o="string"==typeof t.reference?t.reference:i;if(o)try{o=nt(o)}catch{if(!o.includes("@")&&o.lastIndexOf(":")<=o.lastIndexOf("/"))try{o=nt(`${o}:latest`)}catch{}}try{r=o?it(o):void 0}catch{}return{id:t.id,origin:"custom",name:t.name,description:t.description,localizedDescriptions:t.localizedDescriptions,cover:ri(t.cover,["kind","key","url","mediaType","digest"]),reference:r?.reference??o,repository:r?.repository??t.repository,tag:r?.tag??t.tag,pullPolicy:t.pullPolicy??"if-not-present",capabilities:t.capabilities,optionalApps:t.optionalApps,defaultEnv:t.defaultEnv,labels:t.labels,createdAt:t.createdAt,updatedAt:t.updatedAt}}(r),{reference:s,...a}=o,c=r.requestedReference??s;let d;try{d="string"==typeof c?it(c):void 0}catch{}const l={img_default:"market_taskhandoff_browser",img_codex:"market_taskhandoff_codex",img_ai:"market_taskhandoff_ai"},u="string"==typeof r.id?r.id:"string"==typeof t?t:void 0,m="market"===r.origin||u&&l[u]?"market":"custom";return void 0===r.image&&void 0===r.reference||n?.({instanceId:i,field:"imageSnapshot.reference"}),{...a,id:u&&l[u]?l[u]:u,origin:m,repository:d?.repository??r.repository,tag:d?.tag??r.tag,requestedReference:d?.reference??c,resolvedDigest:r.resolvedDigest,resolvedReference:r.resolvedReference,downloadSizeBytes:r.downloadSizeBytes,market:"market"===m?ri(r.market,["catalogId","catalogRevision","publisher","version"])??{catalogId:"task_handoff_embedded",catalogRevision:"legacy",publisher:"task-handoff"}:void 0}}(n.imageSnapshot,n.imageId,t,"string"==typeof n.id?n.id:void 0);const o="string"==typeof n.imageId?{img_default:"market_taskhandoff_browser",img_codex:"market_taskhandoff_codex",img_ai:"market_taskhandoff_ai"}[n.imageId]||n.imageId:void 0,s=ri(n.imageSelection,["imageId","tag"]);r.imageSelection=s||(o?{imageId:o,tag:r.imageSnapshot?.tag}:void 0),r.imageProvisioning=ni(On,ri(n.imageProvisioning,["phase","requestedReference","generation","error","startedAt","updatedAt"]),"imageProvisioning",t,"string"==typeof n.id?n.id:void 0),r.runtimeVersion=function(e,t,n){if(!e||"object"!=typeof e||Array.isArray(e))return;const i=e,r=e=>{if("string"!=typeof e)return;const t=e.trim();return t&&t.length<=80?t:void 0},o=r(i.desiredVersion);if(!o)return void t?.({instanceId:n,field:"runtimeVersion.desiredVersion"});const s=new Set(Ht.shape.phase.options),a="string"==typeof i.phase?i.phase:"pending",c=s.has(a)?a:{idle:"pending",queued:"pending",checking:"pending",downloading:"installing",updating:"installing",completed:"matched",succeeded:"matched",ready:"matched",error:"failed"}[a]||"pending";let d;if(c!==a&&t?.({instanceId:n,field:"runtimeVersion.phase"}),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(qt.shape.code.options),s="string"==typeof e.code&&i.has(e.code)?e.code:"INSTANCE_RUNTIME_INSTALL_FAILED";s!==e.code&&t?.({instanceId:n,field:"runtimeVersion.error.code"});const a=r(e.expectedVersion),c=r(e.actualVersion);d={code:s,message:o,...a?{expectedVersion:a}:{},...c?{actualVersion:c}:{},retryable:!0===e.retryable}}else t?.({instanceId:n,field:"runtimeVersion.error"})}"string"==typeof i.error&&i.error.trim()&&(d={code:"INSTANCE_RUNTIME_INSTALL_FAILED",message:i.error.trim().slice(0,4096),expectedVersion:o,...r(i.actualVersion)?{actualVersion:r(i.actualVersion)}:{},retryable:!1});const l=r(i.actualVersion),u=Ke.safeParse(i.lastAttemptAt),m=Ke.safeParse(i.matchedAt);return void 0===i.lastAttemptAt||u.success||t?.({instanceId:n,field:"runtimeVersion.lastAttemptAt"}),void 0===i.matchedAt||m.success||t?.({instanceId:n,field:"runtimeVersion.matchedAt"}),{desiredVersion: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}:{},...m.success?{matchedAt:m.data}:{},...d?{error:d}:{}}}(n.runtimeVersion,t,"string"==typeof n.id?n.id:void 0),r.workspace=ni(Yn,n.workspace,"workspace",t,"string"==typeof n.id?n.id:void 0)||{status:"unknown"},r.environmentSource=ni(ct,n.environmentSource,"environmentSource",t,"string"==typeof n.id?n.id:void 0),r.environmentTemplateOrigin=ni(pt,n.environmentTemplateOrigin,"environmentTemplateOrigin",t,"string"==typeof n.id?n.id:void 0),r.runtime=ni(Xn.shape.runtime.unwrap(),ri(n.runtime,["kind","containerName","containerId","workspacePath","pid","port","labels","managedVolumes"]),"runtime",t,"string"==typeof n.id?n.id:void 0)||{labels:{},managedVolumes:[]},r.target=ni(Jn,ri(n.target??n.endpoints,["strategy","web","api","vnc","tty","logs","status"]),"target",t,"string"==typeof n.id?n.id:void 0)||{strategy:"direct-port",status:"unknown"},r.access=ni(Wn,ri(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(Xn.shape))Object.prototype.hasOwnProperty.call(r,e)&&!i.safeParse(r[e]).success&&i.safeParse(void 0).success&&(delete r[e],t?.({instanceId:"string"==typeof n.id?n.id:void 0,field:e}));return r}function ni(e,t,n,i,r){if(!t||"object"!=typeof t||Array.isArray(t))return;let o=structuredClone(t),s=!1;for(let t=0;t<20;t+=1){const t=e.safeParse(o);if(t.success)return s&&i?.({instanceId:r,field:n}),t.data;let a=!1;for(const e of t.error.issues){if("unrecognized_keys"!==e.code)continue;const t=ii(o,e.path);if(t&&"object"==typeof t&&!Array.isArray(t))for(const n of e.keys)Object.prototype.hasOwnProperty.call(t,n)&&(delete t[n],a=!0,s=!0)}if(!a){const s=structuredClone(o);let a=!1;for(const e of t.error.issues){if(!e.path.length||"string"!=typeof e.path.at(-1))continue;const t=ii(s,e.path.slice(0,-1)),n=e.path.at(-1);t&&"object"==typeof t&&!Array.isArray(t)&&Object.prototype.hasOwnProperty.call(t,n)&&(delete t[n],a=!0)}if(a){const t=e.safeParse(s);if(t.success)return i?.({instanceId:r,field:n}),t.data}break}}i?.({instanceId:r,field:n})}function ii(e,t){let n=e;for(const e of t){if(!n||"object"!=typeof n)return;n=n[e]}return n}function ri(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 oi=a.z.object({instanceId:Be.optional(),projectId:Be.optional(),source:tn.optional(),nodeId:Be.optional(),runtimeId:Be.optional(),imageSelection:at.optional(),instanceVersion:a.z.string().trim().max(80).optional(),protocolVersion:He,build:Ft.optional(),controlMode:a.z.enum(["standalone","controlled"]).default("controlled"),capabilities:a.z.record(a.z.string(),a.z.unknown()).default({}),appInventory:Nt.optional(),target:Jn.default({strategy:"direct-port",status:"unknown"}),workspace:Yn.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)=>{e.protocolVersion!==qe||e.appInventory||t.addIssue({code:"custom",path:["appInventory"],message:"Current protocol register payload requires appInventory."})}),si=a.z.object({status:Xn.shape.status.optional(),health:Xn.shape.health.optional(),protocolVersion:He,build:Ft.optional(),capabilities:Xn.shape.capabilities.optional(),appInventory:Nt.optional(),apps:Xn.shape.apps.optional(),aiSessions:Xn.shape.aiSessions.optional(),triggers:Xn.shape.triggers.optional(),workspace:Yn.optional(),target:Jn.partial().optional(),processIncarnationId:a.z.string().trim().min(1).max(120).optional()}).strict().superRefine((e,t)=>{e.protocolVersion!==qe||e.appInventory||t.addIssue({code:"custom",path:["appInventory"],message:"Current protocol heartbeat payload requires appInventory."})}),ai=a.z.enum(["web","telegram","wechat","dingding"]);function ci(e,t){let n=mi(t);for(let t=0;t<100;t+=1){const t=e.safeParse(n);if(t.success)return t;const i=di(t.error.issues);let r=!1;for(const e of i){const t=ui(n,e.path);if(t&&"object"==typeof t&&!Array.isArray(t))for(const n of e.keys)Object.prototype.hasOwnProperty.call(t,n)&&(delete t[n],r=!0)}if(!r)return t}return e.safeParse(n)}function di(e,t=[]){const n=[];for(const i of e){if("unrecognized_keys"===i.code){n.push({code:"unrecognized_keys",keys:i.keys,path:[...t,...i.path]});continue}if("invalid_union"!==i.code||!Array.isArray(i.errors))continue;const e=i.errors.filter(e=>Array.isArray(e));if(!e.length)continue;const r=e.reduce((e,t)=>li(t)<li(e)?t:e);n.push(...di(r,[...t,...i.path]))}return n}function li(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(li)):1)},0)}function ui(e,t){let n=e;for(const e of t){if(!n||"object"!=typeof n)return;n=n[e]}return n}function mi(e){return Array.isArray(e)?e.map(mi):e&&"object"==typeof e?Object.getPrototypeOf(e)!==Object.prototype&&null!==Object.getPrototypeOf(e)?e:Object.fromEntries(Object.entries(e).map(([e,t])=>[e,mi(t)])):e}function pi(e,t,n={}){return new Promise((i,r)=>{if(n.signal?.aborted)return void r(Object.assign(new Error(`${e} was aborted.`),{code:"RUNTIME_COMMAND_ABORTED"}));const o=d.spawn(e,t,{stdio:["ignore","pipe","pipe"]}),s=[],a=[];let c=!1;const l=n.timeoutMs?setTimeout(()=>{c=!0,o.kill("SIGKILL")},n.timeoutMs):void 0;let u=!1;const m=()=>{u=!0,o.kill("SIGKILL")},p=()=>{l&&clearTimeout(l),n.signal?.removeEventListener("abort",m)};n.signal?.addEventListener("abort",m,{once:!0}),l?.unref?.(),o.stdout.on("data",e=>s.push(Buffer.from(e))),o.stderr.on("data",e=>a.push(Buffer.from(e))),o.on("error",e=>{p(),r(e)}),o.on("close",t=>{p();const o={stdout:Buffer.concat(s).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 r(t)}if(u)return void r(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}),r(d)})})}a.z.object({id:Be,channel:ai,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:Ke,updatedAt:Ke}).strict(),a.z.object({id:Be,channel:ai,bridgeId:Be.optional(),chatSessionId:a.z.string().trim().min(1).max(240),userId:a.z.string().trim().max(240).optional(),activeProjectId:Be.optional(),activeInstanceId:Be.optional(),activeAiSessionId:a.z.string().trim().min(1).max(120).optional(),lastUsedAt:Ke,createdAt:Ke,updatedAt:Ke}).strict(),a.z.object({source:a.z.object({type:a.z.literal("chat-gateway").default("chat-gateway"),channel:ai,bridgeId:Be.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(L).max(6).default([])}).strict().superRefine((e,t)=>{e.attachments.reduce((e,t)=>e+("inline"===t.source.type?t.size:0),0)>N&&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:Be,aiSessionId:a.z.string().trim().min(1).max(120)}).strict().optional()}).strict(),a.z.object({id:Be,instanceId:Be,projectId:Be.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:Ke}).strict();const gi=(e,t,n={})=>new Promise((i,r)=>{if(n.signal?.aborted)return void r(Object.assign(new Error(`${e} was aborted.`),{code:"RUNTIME_COMMAND_ABORTED"}));const o=[];let s,a=!1,c=!1;try{s=l.spawn(e,t,{name:"xterm-256color",cols:n.cols||120,rows:n.rows||40,cwd:process.cwd(),env:process.env})}catch(e){return void r(e)}const d=n.timeoutMs?setTimeout(()=>{a=!0,s.kill("SIGKILL")},n.timeoutMs):void 0,u=()=>{c=!0;try{s.kill("SIGKILL")}catch{}};n.signal?.addEventListener("abort",u,{once:!0}),d?.unref?.(),s.onData(e=>{o.push(e),n.onData?.(e)}),s.onExit(({exitCode:t})=>{d&&clearTimeout(d),n.signal?.removeEventListener("abort",u);const s={stdout:o.join(""),stderr:""};a?r(Object.assign(new Error(`${e} timed out after ${n.timeoutMs}ms`),{statusCode:504,code:"RUNTIME_COMMAND_TIMEOUT",details:s})):c?r(Object.assign(new Error(`${e} was aborted.`),{code:"RUNTIME_COMMAND_ABORTED",details:s})):0!==t?r(Object.assign(new Error(s.stdout.replace(/\u001b\[[0-?]*[ -/]*[@-~]/g,"").split(/\r?\n/).map(e=>e.trim()).filter(Boolean).at(-1)||`${e} exited with code ${t}`),{statusCode:502,code:"RUNTIME_EXECUTOR_FAILED",details:s})):i(s)})});class hi{inFlight=new Map;runCommand;runTerminalCommand;constructor(e=pi,t){this.runCommand=e,this.runTerminalCommand=t||function(e){return e===pi?gi:async(t,n,i={})=>{const r=await e(t,n,{timeoutMs:i.timeoutMs,signal:i.signal});return r.stdout&&i.onData?.(r.stdout),r.stderr&&i.onData?.(r.stderr),r}}(e)}ensure(e,t,n,i){const r=nt(e),o=this.inFlight.get(r);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 s=new Set,a=new Set;t&&s.add(t),n&&a.add(n);const c={promise:Promise.resolve(void 0),controller:new AbortController,abortDisposers:new Set,phaseListeners:s,terminalListeners:a,terminalSequence:0,terminalTail:""};return this.bindAbort(c,i),c.promise=this.ensureOnce(r,e=>{c.phase=e,s.forEach(t=>t(e))},e=>{c.terminalSequence+=1,c.terminalTail=`${c.terminalTail}${e}`.slice(-262144);const t={sequence:c.terminalSequence,data:e};a.forEach(e=>e(t))},c.controller.signal).finally(()=>{this.inFlight.delete(r);for(const e of c.abortDisposers)e();c.abortDisposers.clear()}),this.inFlight.set(r,c),c.promise}bindAbort(e,t){if(!t)return;if(t.aborted)return void e.controller.abort();const n=()=>e.controller.abort();t.addEventListener("abort",n,{once:!0}),e.abortDisposers.add(()=>t.removeEventListener("abort",n))}async ensureOnce(e,t,n,i){t("checking-image");let r=await this.inspect(e,i).catch(e=>{if(i.aborted)throw e}),o=!1;r||(t("pulling-image"),await this.runTerminalCommand("docker",["pull",e],{cols:120,rows:40,signal:i,onData:n}),o=!0,r=await this.inspect(e,i)),t("resolving-image");const s=(a=r,Array.isArray(a.RepoDigests)?a.RepoDigests.filter(e=>"string"==typeof e):[]).find(e=>/@sha256:[a-fA-F0-9]{64}$/.test(e));var a;const c=s?.split("@").at(-1)?.toLowerCase();return{requestedReference:e,...c?{resolvedDigest:c}:{},resolvedReference:s||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 fi(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 yi=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 Ii(e,t=[]){const n=e&&"object"==typeof e&&!Array.isArray(e)?e:{},i=n.Config&&"object"==typeof n.Config&&!Array.isArray(n.Config)?n.Config:n,r=new Set;for(const e of Array.isArray(i.Env)?i.Env:[]){if("string"!=typeof e)continue;const n=e.indexOf("="),i=-1===n?e:e.slice(0,n),o=-1===n?"":e.slice(n+1);yi.has(i)&&r.add(`Config.Env.${i}`),t.some(e=>e&&o.includes(e))&&r.add(`Config.Env.${i||"unknown"}`)}if(i.Labels&&"object"==typeof i.Labels&&!Array.isArray(i.Labels))for(const[e,n]of Object.entries(i.Labels))(yi.has(e)||"string"==typeof n&&t.some(e=>e&&n.includes(e)))&&r.add(`Config.Labels.${e}`);if(r.size)throw Object.assign(new Error(`Docker configuration contains instance-private values in ${[...r].sort().join(", ")}.`),{statusCode:409,code:"ENVIRONMENT_TEMPLATE_SECRET_IN_DOCKER_CONFIG",findings:[...r].sort()})}class Ai{runCommand;publishHost;images;launcherAssetsDir;portResolutionRetryDelaysMs;constructor(e=pi,i={}){this.runCommand=e,this.images=i.imageService||new hi(e),this.publishHost=i.publishHost||"127.0.0.1",this.launcherAssetsDir=i.launcherAssetsDir||function(){const e=("undefined"==typeof document?require("url").pathToFileURL(__filename).href:b&&"SCRIPT"===b.tagName.toUpperCase()&&b.src||new URL("cli.js",document.baseURI).href)?n.dirname(r.fileURLToPath("undefined"==typeof document?require("url").pathToFileURL(__filename).href:b&&"SCRIPT"===b.tagName.toUpperCase()&&b.src||new URL("cli.js",document.baseURI).href)):__dirname,i=[n.resolve(e,"../../../../../docker"),n.resolve(e,"../docker"),n.resolve(e,"../../docker")];return i.find(e=>t.existsSync(n.join(e,"runtime-installer.mjs")))||i[0]}(),this.portResolutionRetryDelaysMs=i.portResolutionRetryDelaysMs?.length?i.portResolutionRetryDelaysMs:[0,100,250,500,1e3]}async start(e){Ri(e);const t=e.instance.runtime.containerName||Oi(e.instance.id),n=await this.inspectContainerForStart(t);if(n){ki(t,n.id,e.instance.runtime.containerId,"before start","RUNTIME_EXECUTOR_FAILED");const i=n.labels["task-handoff.instance-id"];if(i!==e.instance.id)throw _i("RUNTIME_EXECUTOR_FAILED",`Docker container ${t} belongs to ${i||"an unknown instance"}, not ${e.instance.id}.`);await this.validateManagedVolumes(e,n.mounts);try{await this.runCommand("docker",["start",t])}catch(e){throw _i("RUNTIME_EXECUTOR_FAILED",`Could not start Docker container ${t}.`,e)}return this.runningResult(e,t,n.id)}if(e.instance.environmentTemplateOrigin){const t=await this.inspectEnvironmentTemplateImage(e.instance.environmentTemplateOrigin.imageId);if(t.imageId!==e.instance.environmentTemplateOrigin.imageId||t.platform!==e.instance.environmentTemplateOrigin.platform||t.architecture!==e.instance.environmentTemplateOrigin.architecture)throw Object.assign(new Error(`Environment template image identity or platform changed for instance ${e.instance.id}.`),{statusCode:409,code:"ENVIRONMENT_TEMPLATE_IMAGE_IDENTITY_MISMATCH"})}else await this.images.ensure(e.image.resolvedReference||e.image.requestedReference);let i;await this.createManagedVolumes(e);try{i=await this.runCommand("docker",function(e,t,n={}){const i=n.publishHost||"127.0.0.1",r=e.node?.id||"node_unset",o=e.runtime?.id||"runtime_local_docker",s=["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=${o}`,"--label",`task-handoff.image-id=${e.image.id}`,"--shm-size","1gb","--security-opt","seccomp=unconfined","--network","bridge","--add-host","host.docker.internal:host-gateway","--tmpfs","/tmp:rw,mode=1777","-p",`${i}::8080`];if(!e.privateConfigPath)throw Object.assign(new Error(`Instance ${e.instance.id} private config was not materialized.`),{statusCode:409,code:"INSTANCE_PRIVATE_CONFIG_MISSING"});s.push("--mount",`type=bind,src=${e.privateConfigPath},dst=/run/task-handoff/instance-private-config.json,readonly`);for(const t of e.instance.runtime.managedVolumes)s.push("--mount",`type=volume,src=${t.name},dst=${t.mountPath}`);const a={TASK_HANDOFF_CONTROL_MODE:"controlled",TASK_HANDOFF_NODE_AGENT_URL:e.nodeAgentUrl||e.node?.endpoint||"",TASK_HANDOFF_INSTANCE_ID:e.instance.id,TASK_HANDOFF_INSTANCE_NAME:e.instance.name,TASK_HANDOFF_PROJECT_ID:e.project.id,TASK_HANDOFF_NODE_ID:r,TASK_HANDOFF_RUNTIME_ID:o,TASK_HANDOFF_IMAGE_ID:e.image.id,...e.image.tag?{TASK_HANDOFF_IMAGE_TAG:e.image.tag}:{},TASK_HANDOFF_CHAT_BRIDGES:"none",TASK_HANDOFF_WORKSPACE:e.project.workspacePolicy.path||"/workspace",TASK_HANDOFF_WORKSPACE_MODE:e.project.workspacePolicy.mode};for(const[e,t]of Object.entries(a))xi(s,e,t);"local-folder"===e.project.source.type?s.push("-v",`${e.project.source.path}:${e.project.workspacePolicy.path||"/workspace"}:${e.project.workspacePolicy.readOnly?"ro":"rw"}`):(xi(s,"TASK_HANDOFF_PROJECT_SOURCE",JSON.stringify(e.project.source)),xi(s,"TASK_HANDOFF_WORKSPACE_POLICY",JSON.stringify(e.project.workspacePolicy)),xi(s,"TASK_HANDOFF_GIT_URL",e.project.source.url),e.project.source.ref?.commit?xi(s,"TASK_HANDOFF_GIT_COMMIT",e.project.source.ref.commit):e.project.source.ref?.name&&xi(s,"TASK_HANDOFF_GIT_REF",e.project.source.ref.name),e.project.source.clone?.depth&&xi(s,"TASK_HANDOFF_GIT_DEPTH",String(e.project.source.clone.depth)),xi(s,"TASK_HANDOFF_GIT_SUBMODULES",e.project.source.clone?.submodules?"true":"false"),xi(s,"TASK_HANDOFF_GIT_LFS",e.project.source.clone?.lfs?"true":"false"),e.project.source.clone?.subdirectory&&xi(s,"TASK_HANDOFF_WORKSPACE_SUBDIRECTORY",e.project.source.clone.subdirectory));for(const[t,n]of Object.entries(e.image.defaultEnv))xi(s,t,n);return s.push(e.instance.environmentTemplateOrigin?.imageId||e.image.resolvedReference||e.image.requestedReference),s}(e,t,{publishHost:this.publishHost}))}catch(e){throw _i("RUNTIME_EXECUTOR_FAILED",`Could not create Docker container ${t}.`,e)}return this.runningResult(e,t,i.stdout||void 0)}async inspectContainerConfigSecurity(e,t){Ii(await this.runCommand("docker",["inspect","--format","{{json .}}",e]).then(e=>JSON.parse(e.stdout||"{}")).catch(t=>{throw _i("ENVIRONMENT_TEMPLATE_CONTAINER_INSPECT_FAILED",`Could not inspect Docker container ${e}.`,t)}),t)}async inspectImageConfigSecurity(e,t){Ii(await this.runCommand("docker",["image","inspect","--format","{{json .}}",e]).then(e=>JSON.parse(e.stdout||"{}")).catch(e=>{throw _i("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 _i("ENVIRONMENT_TEMPLATE_CONTAINER_NOT_FOUND",`Docker container ${e} does not exist.`);ki(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 _i("ENVIRONMENT_TEMPLATE_COMMIT_FAILED",`Could not save Docker container ${e} as an environment template.`,t)}}async inspectEnvironmentTemplateImage(e){try{const t=await this.runCommand("docker",["image","inspect","--format","{{json .}}",e]),n=JSON.parse(t.stdout||"{}"),i="string"==typeof n.Id?n.Id:"",r=Ei(n.Os),o=Ni(n.Architecture),s="number"==typeof n.Size?n.Size:Number.NaN;if(!/^sha256:[a-f0-9]{64}$/.test(i)||!r||!o||!Number.isSafeInteger(s)||s<0)throw new Error("Docker image inspection did not return a valid immutable identity.");return{imageId:i,platform:r,architecture:o,sizeBytes:s}}catch(e){throw _i("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,zi(n)]),await this.runCommand("docker",["image","rm",e]),n}catch(e){const t=Si(e)?.toLowerCase()||"";if(t.includes("no such image")||t.includes("no such object"))return;throw _i("ENVIRONMENT_TEMPLATE_UNTAG_FAILED","Could not remove the environment template tag.",e)}}async garbageCollectEnvironmentTemplateImage(e){try{try{await this.runCommand("docker",["image","rm",zi(e)])}catch(e){const t=Si(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=Si(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 _i("ENVIRONMENT_TEMPLATE_GC_FAILED","Could not garbage collect the environment template image.",e)}}async createManagedVolumes(e){this.assertManagedVolumeModel(e);for(const t of e.instance.runtime.managedVolumes){const n=["volume","create"];for(const[e,i]of Object.entries(t.labels).sort(([e],[t])=>e.localeCompare(t)))n.push("--label",`${e}=${i}`);n.push(t.name);try{await this.runCommand("docker",n)}catch(e){throw _i("INSTANCE_VOLUME_CREATE_FAILED",`Could not create managed volume ${t.name}.`,e)}await this.validateManagedVolume(e.instance.id,t)}}assertManagedVolumeModel(e){const t="local-folder"===e.project.source.type?["agent-home","data"]:["agent-home","data","workspace"];if(e.instance.runtime.managedVolumes.map(e=>e.role).sort().join("\0")!==t.join("\0"))throw Object.assign(new Error(`Instance ${e.instance.id} managed volume model does not match its workspace source.`),{statusCode:409,code:"INSTANCE_VOLUME_MODEL_INVALID"})}async validateManagedVolumes(e,t){this.assertManagedVolumeModel(e);for(const n of e.instance.runtime.managedVolumes){await this.validateManagedVolume(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"})}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 validateManagedVolume(e,t){let n;try{n=await this.runCommand("docker",["volume","inspect","--format","{{json .}}",t.name])}catch(e){throw _i("INSTANCE_VOLUME_INSPECT_FAILED",`Could not inspect managed volume ${t.name}.`,e)}try{const i=JSON.parse(n.stdout||"{}"),r=i.Labels&&"object"==typeof i.Labels&&!Array.isArray(i.Labels)?i.Labels:{};if(i.Name!==t.name||"task-handoff"!==r["task-handoff.owner"]||r["task-handoff.instance-id"]!==e||r["task-handoff.volume-role"]!==t.role)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.containerPort(t,"8080/tcp"),r=i?`http://127.0.0.1:${i}`:void 0,o=e.node?.id||"node_unset",s=e.runtime?.id||"runtime_local_docker";return{status:"registering",health:"unknown",connectionStatus:r?"online":"unknown",agentStatus:"unknown",targetStatus:"unknown",uiAccessStatus:"unknown",target:{strategy:"direct-port",status:r?"reachable":"unknown",...r?{web:r,api:`${r}/api`}:{}},workspace:{mode:e.project.workspacePolicy.mode,status:"pending",path:e.project.workspacePolicy.path},runtime:{...e.instance.runtime,kind:"docker",containerName:t,...n?{containerId:n}:{},labels:{...e.instance.runtime.labels,"task-handoff.instance-id":e.instance.id,"task-handoff.project-id":e.project.id,"task-handoff.node-id":o,"task-handoff.runtime-id":s,"task-handoff.image-id":e.image.id}}}}async stop(e){const t=e.instance.runtime.containerName||Oi(e.instance.id);try{await this.runCommand("docker",["stop",t])}catch(e){if(!Ti(e))throw _i("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){Ri(e);const n=e.instance.runtime.containerName||Oi(e.instance.id),i=await this.inspectContainerId(n);if(!i)throw _i("INSTANCE_RUNTIME_RESTART_FAILED",`Docker container ${n} does not exist.`);ki(n,i,t,"before restart","INSTANCE_RUNTIME_RESTART_FAILED"),await this.runCommand("docker",["restart",n]);const r=await this.inspectContainerId(n);if(!r||r!==i)throw _i("INSTANCE_RUNTIME_RESTART_FAILED",`Docker container identity changed while restarting ${n}.`);return ki(n,r,t,"after restart","INSTANCE_RUNTIME_RESTART_FAILED"),this.runningResult(e,n,r)}async delete(e,t){const n=e.instance.runtime.containerName||Oi(e.instance.id);try{await this.runCommand("docker",["rm","-f",n])}catch(e){if(!Ti(e))throw _i("RUNTIME_EXECUTOR_FAILED",`Could not delete Docker container ${n}.`,e)}const i=[];for(const n of e.instance.runtime.managedVolumes)if(t.deleteVolumes)try{const t=await this.inspectVolumeForDelete(n.name);if(!t){i.push({role:n.role,name:n.name,mountPath:n.mountPath,status:"missing"});continue}if(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)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]),i.push({role:n.role,name:n.name,mountPath:n.mountPath,status:"deleted"})}catch(e){i.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 i.push({role:n.role,name:n.name,mountPath:n.mountPath,status:"retained"});return It.parse({instanceId:e.instance.id,containerDeleted:!0,completed:i.every(e=>"failed"!==e.status),deletedVolumes:i.filter(e=>"deleted"===e.status||"missing"===e.status),retainedVolumes:i.filter(e=>"retained"===e.status),volumeResults:i})}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=Si(e)?.toLowerCase()||"";return t.includes("no such volume")||t.includes("no such object")}(t))return;throw _i("INSTANCE_VOLUME_INSPECT_FAILED",`Could not inspect managed volume ${e}.`,t)}}async installRuntime(e){const t=await this.installRuntimeRelease(e);ki(e.containerName,t,e.expectedContainerId,"before runtime restart","INSTANCE_RUNTIME_RESTART_FAILED");try{await this.runCommand("docker",["restart",e.containerName])}catch(t){throw _i("INSTANCE_RUNTIME_RESTART_FAILED",`Could not restart Docker container ${e.containerName}.`,t)}const n=await this.inspectContainerId(e.containerName);if(!n||n!==t)throw _i("INSTANCE_RUNTIME_RESTART_FAILED",`Docker container identity changed while updating ${e.containerName}.`);return ki(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 _i("INSTANCE_RUNTIME_INSTALL_FAILED",`Docker container ${e.containerName} does not exist.`);ki(e.containerName,t,e.expectedContainerId,"before runtime install","INSTANCE_RUNTIME_INSTALL_FAILED");const n=`/opt/task-handoff/instance-runtime/incoming/task-handoff-runtime-${i=e.identity.version,i.replace(/[^0-9A-Za-z.+_-]/g,"-")}-${e.identity.sha256.slice(0,12)}.tar.gz`;var i;await this.runCommand("docker",["exec","--user","0",e.containerName,"install","-d","-o","root","-g","root","-m","0755","/opt/task-handoff/instance-runtime/incoming"]),await this.runCommand("docker",["cp",e.artifactPath,`${e.containerName}:${n}`]);try{await this.runCommand("docker",["exec","--user","0",e.containerName,"task-handoff-runtime","install","--artifact",n,"--version",e.identity.version,"--sha256",e.identity.sha256,"--platform",e.identity.platform,"--arch",e.identity.arch,"--launcher-abi",String(e.identity.launcherAbi)])}catch(t){throw _i("INSTANCE_RUNTIME_INSTALL_FAILED",`Could not install controlled-instance ${e.identity.version} in ${e.containerName}.`,t)}finally{await this.runCommand("docker",["exec","--user","0",e.containerName,"rm","-f",n]).catch(()=>({stdout:"",stderr:""}))}const r=await this.inspectContainerId(e.containerName);if(!r||r!==t)throw _i("INSTANCE_RUNTIME_INSTALL_FAILED",`Docker container identity changed while installing ${e.containerName}.`);return ki(e.containerName,r,e.expectedContainerId,"after runtime install","INSTANCE_RUNTIME_INSTALL_FAILED"),t}async inspectRuntimeVersion(e){const t=await this.inspectContainerId(e);if(!t)return{};const n=await this.runCommand("docker",["exec","--user","agent",e,"task-handoff-runtime","verify-active"]).catch(()=>{});if(!n?.stdout)return{containerId:t};try{const e=ci(Vt,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 _i("INSTANCE_BASE_RUNTIME_INCOMPATIBLE","Could not inspect the Docker runtime target.",e)});t||=e.OSType,n||=e.Architecture}const i=Ei(t),r=Ni(n);if(!i||!r)throw _i("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Docker reported an unsupported runtime target ${String(t||"unknown")}/${String(n||"unknown")}.`);return{platform:i,arch:r,launcherAbi:1}}async installRuntimeLauncher(e){const t=await this.inspectContainerId(e);if(!t)throw _i("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Docker container ${e} does not exist.`);const i=[[n.join(this.launcherAssetsDir,"entrypoint.sh"),"/root/.task-handoff-entrypoint.bootstrap"],[n.join(this.launcherAssetsDir,"instance-launcher.sh"),"/root/.task-handoff-instance-launcher.bootstrap"],[n.join(this.launcherAssetsDir,"runtime-installer.mjs"),"/root/.task-handoff-runtime-installer.bootstrap"]];for(const[t,n]of i)await this.runCommand("docker",["cp",t,`${e}:${n}`]);try{await this.runCommand("docker",["exec","--user","0",e,"bash","-ceu","install -d -o root -g root -m 0755 /opt/task-handoff/instance-runtime /opt/task-handoff/instance-runtime/releases /opt/task-handoff/instance-runtime/staging /opt/task-handoff/instance-runtime/incoming; chown -R root:root /opt/task-handoff/instance-runtime; chmod -R go-w /opt/task-handoff/instance-runtime; install -m 0755 /root/.task-handoff-entrypoint.bootstrap /usr/local/bin/task-handoff-entrypoint; install -m 0755 /root/.task-handoff-instance-launcher.bootstrap /usr/local/bin/task-handoff-instance-launcher; install -d /usr/local/lib/task-handoff; install -m 0755 /root/.task-handoff-runtime-installer.bootstrap /usr/local/lib/task-handoff/runtime-installer.mjs; ln -sfn /usr/local/lib/task-handoff/runtime-installer.mjs /usr/local/bin/task-handoff-runtime; rm -f /root/.task-handoff-entrypoint.bootstrap /root/.task-handoff-instance-launcher.bootstrap /root/.task-handoff-runtime-installer.bootstrap"])}catch(t){throw _i("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Could not install the runtime launcher in ${e}.`,t)}if(await this.inspectContainerId(e)!==t)throw _i("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Docker container identity changed while installing the runtime launcher in ${e}.`)}async inspectContainerId(e){try{return(await this.runCommand("docker",["inspect","--format","{{.Id}}",e])).stdout.trim()||void 0}catch(t){if(Ti(t))return;throw _i("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(Ti(t))return;throw _i("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}]:[]}):[];return{id:e.Id,labels:n,mounts:i}}catch(t){throw _i("RUNTIME_EXECUTOR_FAILED",`Docker returned invalid inspection data for ${e}.`,t)}}async containerPort(e,t){let n,i=!1;for(const r of this.portResolutionRetryDelaysMs){r>0&&await vi(r);try{const n=bi((await this.runCommand("docker",["port",e,t])).stdout);if(n)return n}catch(e){n=e}try{const n=wi((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 _i("RUNTIME_EXECUTOR_FAILED",`Docker container ${e} does not publish ${t}.`);throw _i("RUNTIME_EXECUTOR_FAILED",`Could not resolve the published port for Docker container ${e}.`,n)}}function bi(e){const t=e.split(/\r?\n/).find(Boolean);return t?.match(/:(\d+)$/)?.[1]}function wi(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 vi(e){return new Promise(t=>setTimeout(t,e))}function Ei(e){return"linux"===e||"darwin"===e?e:"windows"===e||"win32"===e?"win32":void 0}function Ni(e){return"amd64"===e||"x86_64"===e||"x64"===e?"x64":"arm64"===e||"aarch64"===e?"arm64":void 0}function zi(e){return`task-handoff/environment-image:${e.replace(/^sha256:/,"")}`}function _i(e,t,n){const i=Si(n),r=new Error(i?`${t} Cause: ${i}`:t,void 0===n?void 0:{cause:n});return Object.assign(r,{statusCode:502,code:e}),r}function Si(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 Ti(e){const t=Si(e)?.toLowerCase()||"";return t.includes("no such container")||t.includes("no such object")}function ki(e,t,n,i,r){if(n&&t!==n)throw _i(r,`Docker container ${e} identity mismatch ${i}: expected ${n}, got ${t}.`)}async function Ci(e=pi){return async function(e=pi){return(await e("docker",["images","--digests","--format","{{json .}}"])).stdout.split(/\r?\n/).map(e=>e.trim()).filter(Boolean).map(e=>{const t=JSON.parse(e),n=t.Repository||"<none>",i=t.Tag||"<none>",r=t.ID||t.IDShort||"",o="<none>"!==n&&"<none>"!==i?`${n}:${i}`:r,s="<none>"!==n&&t.Digest&&"<none>"!==t.Digest?[`${n}@${t.Digest}`]:[];return{repository:n,tag:i,id:r,createdSince:t.CreatedSince,size:t.Size,sizeBytes:fi(t.Size),reference:o,repoDigests:s}}).filter(e=>Boolean(e.reference))}(e)}function Oi(e){return`task-handoff-${e.replace(/[^a-zA-Z0-9_.-]/g,"-")}`}function xi(e,t,n){e.push("-e",`${t}=${n}`)}function Ri(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 Di=a.z.enum(["created","starting","running","stopping","stopped","exited","failed","closed","terminated","unknown"]),Pi=a.z.enum(["tty","vnc","web"]);a.z.object({mode:Pi,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 Mi=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(),ji=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:Di.default("unknown"),bindings:a.z.array(Mi).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()})),Li=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(ji).default([]),updatedAt:a.z.string().datetime()}).strict();a.z.object({streamId:a.z.string().trim().min(1).max(240),revision:a.z.number().int().min(0),lastEventAt:a.z.string().datetime(),snapshot:Li}).strict(),Li.pick({runningCount:!0,problemCount:!0,updatedAt:!0}).extend({revision:a.z.number().int().min(0).optional()});const $i=a.z.enum(["app-session-created","app-session-updated","app-session-deleted","app-session-recovered","control-action","heartbeat-sync","startup"]),Fi=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:$i}).strict(),Ui=a.z.object({meta:Fi,snapshot:Li}).strict(),Vi=a.z.object({meta:Fi,session:ji}).strict(),qi=a.z.object({meta:Fi,sessionId:a.z.string().trim().min(1).max(160),tombstone:ji.optional(),expiresAt:a.z.string().datetime().optional()}).strict();function Hi(e){return e.startsWith("ai-session.")||e.startsWith("ai.session.")?"ai.sessions":e.startsWith("app-session.")?"app.sessions":e.startsWith("app.management")?"apps":e.startsWith("trigger.")?"triggers":e.startsWith("instance.")?"instances":e.startsWith("node.")?"nodes":e.startsWith("project.")?"projects":e.startsWith("model.")?"models":e.startsWith("image.")?"images":e.startsWith("market.")?"market":"system"}a.z.object({streamId:a.z.string().trim().min(1).max(240),instanceId:a.z.string().trim().min(1).max(160),sinceRevision:a.z.number().int().min(0),latestRevision:a.z.number().int().min(0),earliestRetainedRevision:a.z.number().int().min(0),syncRequired:a.z.boolean().default(!1),events:a.z.array(a.z.discriminatedUnion("type",[a.z.object({type:a.z.literal("app-session.snapshot"),payload:Ui}).strict(),a.z.object({type:a.z.literal("app-session.patch"),payload:Vi}).strict(),a.z.object({type:a.z.literal("app-session.removed"),payload:qi}).strict()])).default([])}).strict();const Bi=a.z.enum(["ai.sessions","app.sessions"]),Ki=a.z.object({topic:Bi,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(),Gi=a.z.object({protocolVersion:a.z.literal(1),streams:a.z.array(Ki)}).strict();class Ji{attempt=0;timer;get pending(){return Boolean(this.timer)}get attempts(){return this.attempt}schedule(e,t={}){if(this.timer)return;const n=function(e,t=Math.random){const n=Math.min(3e4,1e3*2**Math.max(0,e));return Math.min(3e4,Math.round(n*(.75+.5*t())))}(this.attempt,t.random);this.attempt+=1;const i=t.setTimeoutFn||setTimeout;return this.timer=i(()=>{this.timer=void 0,e()},n),{attempt:this.attempt,delay:n}}reset(e=clearTimeout){this.timer&&e(this.timer),this.timer=void 0,this.attempt=0}cancel(e=clearTimeout){this.timer&&e(this.timer),this.timer=void 0}}function Wi(e,t=6e4){const n=[];for(let i=0;i<e.length;i+=t)n.push(e.slice(i,i+t));return n}class Yi{sockets=new Map;socketUrls=new Map;retries=new Map;outputs=new Set;imagePullTerminalByInstance=new Map;state;token;logger;safetyIntervalMs;lastAiSessionEventByInstance=new Map;lastAppSessionEventByInstance=new Map;timer;reconnectAttempts=0;safetyReconciliations=0;localSequence=0;createSocket;setIntervalFn;clearIntervalFn;constructor(e,t,n={}){var i;this.state=e,this.token=t,this.logger=n.logger,this.safetyIntervalMs=(i=n.safetyIntervalMs,Math.min(6e4,Math.max(3e4,i??45e3))),this.createSocket=n.createSocket||((e,t)=>new u(e,t)),this.setIntervalFn=n.setIntervalFn||setInterval,this.clearIntervalFn=n.clearIntervalFn||clearInterval}start(){this.sync(),this.timer=this.setIntervalFn(()=>{this.safetyReconciliations+=1,this.sync()},this.safetyIntervalMs)}stop(){this.timer&&(this.clearIntervalFn(this.timer),this.timer=void 0);for(const e of this.sockets.values())e.close();this.sockets.clear(),this.socketUrls.clear();for(const e of this.retries.values())e.timer.cancel();this.retries.clear(),this.outputs.clear()}addOutput(e){this.outputs.add(e),e.on("close",()=>this.outputs.delete(e)),e.on("error",()=>this.outputs.delete(e));for(const t of this.state.listInstances()){const n=Xi(t);n?this.sendForwarded(e,this.createEvent(Qn,n,{instanceId:t.id})):this.logger?.warn?.({instanceId:t.id},"instance.lifecycle.snapshot.invalid")}for(const[t,n]of this.imagePullTerminalByInstance)Wi(n.tail).forEach((i,r)=>this.sendForwarded(e,this.createEvent(xn,{...n.output,sequence:n.output.sequence+r,data:i,...0===r?{replay:!0}:{}},{instanceId:t}))),n.finished&&this.sendForwarded(e,this.createEvent(Rn,n.finished,{instanceId:t}));return this.syncNow(),()=>{this.outputs.delete(e)}}publish(e,t,n={}){this.rememberImagePullTerminal(e,t);const i=this.createEvent(e,t,n);for(const e of this.outputs)this.sendForwarded(e,i)}rememberImagePullTerminal(e,t){if(e===xn){const e=ci(Pn,t);if(!e.success)return;const n=e.data,i=this.imagePullTerminalByInstance.get(n.instanceId);if(i&&n.generation<i.output.generation)return;const r=i?.output.generation===n.generation,o=n.replay||!r?n.data:`${i.tail}${n.data}`.slice(-262144);return void this.imagePullTerminalByInstance.set(n.instanceId,{output:n,tail:o})}if(e===Rn){const e=ci(Mn,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(Qn,function(e){return Zn.parse(Qi(e))}(e),{instanceId:e.id});const t=this.imagePullTerminalByInstance.get(e.id);"ready"===e.imageProvisioning?.phase&&"succeeded"===t?.finished?.outcome&&this.imagePullTerminalByInstance.delete(e.id)}createEvent(e,t,n){const i=++this.localSequence;return{v:1,id:`node_evt_${Date.now().toString(36)}_${i.toString(36)}`,seq:i,type:e,topic:Hi(e),createdAt:(new Date).toISOString(),payload:t,scope:n}}sendForwarded(e,t){const n=JSON.stringify({type:"node-agent.event.forwarded",event:t});e.readyState===u.OPEN&&e.send(n)}syncNow(){this.sync()}diagnostics(){return{reconnectAttempts:this.reconnectAttempts,safetyReconciliations:this.safetyReconciliations,activeConnections:this.sockets.size,pendingRetries:[...this.retries.values()].filter(e=>e.timer.pending).length,safetyIntervalMs:this.safetyIntervalMs}}sync(){const e=new Set(this.state.listInstances().map(e=>e.id));for(const t of this.imagePullTerminalByInstance.keys())e.has(t)||this.imagePullTerminalByInstance.delete(t);if(!this.outputs.size){for(const e of this.sockets.values())e.close();this.sockets.clear(),this.socketUrls.clear();for(const e of this.retries.values())e.timer.cancel();return void this.retries.clear()}const t=new Set;for(const e of this.state.listInstances()){const n=er(e);if(!n)continue;t.add(e.id);const i=this.retries.get(e.id);i?.timer.pending&&i.url!==n&&(i.timer.cancel(),this.retries.delete(e.id)),this.socketUrls.get(e.id)!==n&&this.sockets.has(e.id)&&(this.sockets.get(e.id)?.close(),this.sockets.delete(e.id)),this.sockets.has(e.id)||this.retries.get(e.id)?.timer.pending||this.connect(e.id,n)}for(const[e,n]of this.sockets)if(!t.has(e)){n.close(),this.sockets.delete(e),this.socketUrls.delete(e);const t=this.retries.get(e);t?.timer.cancel(),this.retries.delete(e)}for(const[e,n]of this.retries)t.has(e)||(n.timer.cancel(),this.retries.delete(e),this.socketUrls.delete(e))}connect(e,t){const n=this.token?{authorization:`Bearer ${this.token}`}:void 0,i=this.createSocket(t,{headers:n});this.sockets.set(e,i),this.socketUrls.set(e,t),i.on("open",()=>{const n=this.retries.get(e);n?.timer.reset(),this.retries.set(e,{timer:n?.timer||new Ji,url:t}),i.readyState===u.OPEN&&(i.send(JSON.stringify({v:1,type:"subscribe",topics:[z,"app.sessions","apps","instances"]})),this.logger?.info?.({instanceId:e,url:t},"ai-session.event.forward.connect"),this.logger?.info?.({instanceId:e,url:t},"app-session.event.forward.connect"))}),i.on("message",t=>{const n=function(e,t){try{const n=JSON.parse(String(e));if(!n||"object"!=typeof n||Array.isArray(n))return;const i=n,r="string"==typeof i.type?i.type:"";if(!r||"events.connected"===r)return;const o=i.scope&&"object"==typeof i.scope&&!Array.isArray(i.scope)?i.scope:{};return{v:1,id:"string"==typeof i.id?i.id:`evt_${Date.now().toString(36)}`,seq:Number(i.seq)||0,type:r,topic:"string"==typeof i.topic?i.topic:Hi(r),createdAt:"string"==typeof i.createdAt?i.createdAt:(new Date).toISOString(),payload:"payload"in i?i.payload:{},scope:{...o,instanceId:t}}}catch{return}}(t,e);if(!n)return;if("streams.hello"===n.type){const t=ci(Gi,n.payload);if(!t.success)return this.logger?.warn?.({instanceId:e,issues:t.error.issues},"session-stream.handshake.invalid"),void i.close(1002,"Incompatible session stream handshake.");const r=JSON.stringify({type:"node-agent.streams.hello",instanceId:e,payload:t.data});for(const e of this.outputs)e.readyState===u.OPEN&&e.send(r);return}this.recordAiSessionEvent(e,n),this.recordAppSessionEvent(e,n);const r=JSON.stringify({type:"node-agent.event.forwarded",event:n});for(const e of this.outputs)e.readyState===u.OPEN&&e.send(r)}),i.on("close",()=>{this.sockets.get(e)===i&&(this.sockets.delete(e),this.socketUrls.delete(e),this.scheduleReconnect(e))}),i.on("error",()=>{this.logger?.warn?.({instanceId:e,url:t},"ai-session.event.forward.error"),this.logger?.warn?.({instanceId:e,url:t},"app-session.event.forward.error"),i.close()})}scheduleReconnect(e){const t=this.state.listInstances().find(t=>t.id===e),n=t&&er(t);if(!n||!this.outputs.size)return;const i=this.retries.get(e)??{timer:new Ji};if(i.timer.pending)return;i.url=n;const r=i.timer.schedule(()=>{this.sockets.has(e)||this.connect(e,n)});r&&(this.reconnectAttempts+=1,this.logger?.info?.({instanceId:e,url:n,attempt:r.attempt,delay:r.delay,reconnectAttempts:this.reconnectAttempts},"session-stream.connection.reconnect-scheduled")),this.retries.set(e,i)}recordAiSessionEvent(e,t){if(t.topic!==z)return;if("ai-session.message-delta"===t.type)return;const n=Zi(t.payload),i=this.lastAiSessionEventByInstance.get(e);i?.streamId===n.streamId&&void 0!==i.revision&&void 0!==n.revision&&n.revision>i.revision+1&&this.logger?.warn?.({instanceId:e,traceId:n.traceId,streamId:n.streamId,previousRevision:i.revision,revision:n.revision},"ai-session.event.forward.gap"),this.lastAiSessionEventByInstance.set(e,{streamId:n.streamId??i?.streamId,revision:n.revision??i?.revision}),this.logger?.info?.({instanceId:e,traceId:n.traceId,eventType:t.type,streamId:n.streamId,revision:n.revision},"ai-session.event.forward.message")}recordAppSessionEvent(e,t){if("app.sessions"!==t.topic)return;const n=Zi(t.payload),i=this.lastAppSessionEventByInstance.get(e);i?.streamId===n.streamId&&void 0!==i.revision&&void 0!==n.revision&&n.revision>i.revision+1&&this.logger?.warn?.({instanceId:e,traceId:n.traceId,streamId:n.streamId,previousRevision:i.revision,revision:n.revision},"app-session.event.forward.gap"),this.lastAppSessionEventByInstance.set(e,{streamId:n.streamId??i?.streamId,revision:n.revision??i?.revision}),this.logger?.info?.({instanceId:e,traceId:n.traceId,eventType:t.type,streamId:n.streamId,revision:n.revision},"app-session.event.forward.message")}}function Xi(e){const t=Zn.safeParse(Qi(e));return t.success?t.data:void 0}function Qi(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 Zi(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 er(e){if(!function(e){return!1!==e.ready&&(!e.runtimeVersion||["matched","failed"].includes(e.runtimeVersion.phase))}(e))return;const t=e.target?.api||e.target?.web;if(t)try{const e=new URL("/api/events",t);return e.protocol="https:"===e.protocol?"wss:":"ws:",e.toString()}catch{return}}const tr=new Set(["provisioning","starting","registering","registered","running","unhealthy"]),nr=JSON.stringify({id:"{{.ID}}",name:"{{.Name}}",cpu:"{{.CPUPerc}}",memory:"{{.MemUsage}}",memoryPercent:"{{.MemPerc}}",network:"{{.NetIO}}",blockIo:"{{.BlockIO}}",pids:"{{.PIDs}}"});class ir{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(!tr.has(t.status))return dr(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=rr(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,rr(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=>tr.has(e.status)&&(e.runtime.containerId||e.runtime.containerName));for(const t of e.filter(e=>tr.has(e.status)&&!e.runtime.containerId&&!e.runtime.containerName))this.update(lr(t.id));for(const t of e.filter(e=>!tr.has(e.status)))this.update(dr(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",nr,...n],{timeoutMs:5e3});this.applyDockerOutput(t,e.stdout,i)}catch(e){if(1===t.length)return void this.update(ur(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",nr,t],{timeoutMs:5e3});this.applyDockerOutput([e],n.stdout,i)}catch(t){this.update(ur(e.id,i,t instanceof Error?t.message:String(t)))}}))}}applyDockerOutput(e,t,n){const i=function(e,t=(new Date).toISOString()){const n=new Map;for(const i of e.split(/\r?\n/).filter(Boolean)){let e;try{e=JSON.parse(i)}catch{continue}const r=cr(e.id),o=cr(e.name),s=r||o;if(!s)continue;const a=or(cr(e.memory)),c=or(cr(e.network)),d=or(cr(e.blockIo)),l=Un.parse({instanceId:s,runtimeKind:"docker",state:"available",sampledAt:t,cpu:sr(e.cpu,"usagePercent"),memory:a?{usageBytes:a[0],...void 0!==a[1]?{limitBytes:a[1]}:{},...sr(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:ar(e.pids)});r&&n.set(r,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),r=[...i.entries()].find(([t])=>e.some(e=>e===t||e.startsWith(t)||t.startsWith(e)))?.[1];this.update(r?{...r,instanceId:t.id}:ur(t.id,n,"Container metrics were not returned by Docker."))}}update(e){const t=Un.parse(e);this.snapshots.set(t.instanceId,t),this.publish?.(t)}}function rr(e){return[e.status,e.runtime.containerId||"",e.runtime.containerName||""].join("\0")}function or(e){if(!e)return;const[t,n]=e.split("/").map(e=>function(e){const t=e.trim().match(/^([0-9]+(?:\.[0-9]+)?)\s*([kmgtpe]?i?b)$/i);if(!t)return;const n=Number(t[1]),i=t[2].toLowerCase(),r=i.includes("i"),o="b"===i[0]?"":i[0],s=o?"kmgtpe".indexOf(o)+1:0;return Math.round(n*(r?1024:1e3)**s)}(e||""));return void 0===t?void 0:[t,n]}function sr(e,t){const n=Number(cr(e).replace(/%$/,""));return Number.isFinite(n)&&n>=0?{[t]:n}:void 0}function ar(e){const t=Number(cr(e));return Number.isFinite(t)&&t>=0?t:void 0}function cr(e){return"string"==typeof e||"number"==typeof e?String(e).trim():""}function dr(e){return{instanceId:e,runtimeKind:"docker",state:"stopped",sampledAt:(new Date).toISOString()}}function lr(e){return{instanceId:e,runtimeKind:"docker",state:"pending",sampledAt:(new Date).toISOString()}}function ur(e,t,n){return{instanceId:e,runtimeKind:"docker",state:"unavailable",sampledAt:t,error:n.slice(0,2048)}}function mr(e){try{return t.statSync(e).isDirectory()}catch{return!1}}function pr(e,i){let r;try{r=t.statSync(e)}catch{return}if(!r.isDirectory())return;const o=n.resolve(e),s=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()&&mr(n.join(o,e.name))).sort((e,t)=>e.name.localeCompare(t.name)).slice(0,80).flatMap(e=>{const t=pr(n.join(o,e.name),i-1);return t?[t]:[]}):[];return{name:s,path:o,children:c}}function gr(e){return(e.path?[e.path]:function(){if("win32"!==process.platform)return[n.parse(n.resolve(process.cwd())).root];const e=n.parse(n.resolve(process.cwd())).root,t=Array.from({length:26},(e,t)=>`${String.fromCharCode(65+t)}:\\`);return[...new Set([e,...t])].filter(mr)}()).flatMap(t=>{const n=pr(t,e.depth);return n?[n]:[]})}function hr(){return process.env.TASK_HANDOFF_NODE_AGENT_DATA_DIR||n.join(m.homedir(),".config","task-handoff","node-agent")}function fr(e=hr()){const t=n.resolve(e);return{dataDir:t,identityPath:n.join(t,"identity.json"),settingsPath:n.join(t,"runtime-settings.json"),localFoldersDir:n.join(t,"local-folders"),nodeRuntimesDir:n.join(t,"node-runtimes"),controlledInstancesDir:n.join(t,"controlled-instances"),environmentTemplatesDir:n.join(t,"environment-templates"),instancePrivateConfigsDir:n.join(t,"instance-private-configs"),nodeModelsDir:n.join(t,"models"),modelAssignmentsDir:n.join(t,"model-assignments"),modelEnvironmentsDir:n.join(t,"model-environments"),updatesDir:n.join(t,"updates"),logsDir:n.join(t,"logs")}}class yr 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 Ir(e){return n.join(e,"owner.json")}function Ar(e){return n.join(e,"initializing.json")}function br(e){return n.join(e,"recovering.json")}function wr(e){return Number.isInteger(e)&&Number(e)>0}function vr(e,n=process.platform){if(wr(e)){if("linux"===n)try{const n=t.readFileSync(`/proc/${e}/stat`,"utf8"),i=n.lastIndexOf(")");if(i<0)return;const r=n.slice(i+2).trim().split(/\s+/)[19];return r?`linux:${r}`:void 0}catch{return}if(["darwin","freebsd","openbsd","aix","sunos"].includes(n)){const t=d.spawnSync("ps",["-o","lstart=","-p",String(e)],{encoding:"utf8",timeout:1e3}),i=0===t.status?t.stdout.trim().replace(/\s+/g," "):"";return i?`${n}:${i}`:void 0}if("win32"===n){const t=`(Get-Process -Id ${e} -ErrorAction Stop).StartTime.ToUniversalTime().Ticks`,n=d.spawnSync("powershell.exe",["-NoProfile","-NonInteractive","-Command",t],{encoding:"utf8",timeout:2e3}),i=0===n.status?n.stdout.trim():"";return/^\d+$/.test(i)?`win32:${i}`:void 0}}}function Er(e){try{const n=JSON.parse(t.readFileSync(Ir(e),"utf8"));if(wr(n.pid)&&"string"==typeof n.startTime){const e=n;return{pid:e.pid,hostname:"string"==typeof e.hostname&&e.hostname?e.hostname:m.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(!(wr(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 Nr=Er;function zr(e){if(!wr(e))return!1;try{return process.kill(Number(e),0),!0}catch(e){return"EPERM"===e.code}}function _r(e){if(!e||!zr(e.pid))return!1;if(!e.startIdentity)return!0;const t=vr(e.pid);return void 0===t||t===e.startIdentity}function Sr(e,i){const r=n.join(e,`.owner-${i.token}.tmp`);t.writeFileSync(r,`${JSON.stringify(i,null,2)}\n`,{encoding:"utf8",mode:384,flag:"wx"});const o=Tr(e);if(o?.token!==i.token)throw Cr(r),new Error(`Process lock initialization was superseded: ${e}`);t.renameSync(r,Ir(e)),Cr(Ar(e))}function Tr(e){try{return JSON.parse(t.readFileSync(Ar(e),"utf8"))}catch{return}}function kr(e){const t=Tr(e);return wr(t?.pid)&&_r({pid:t.pid,startIdentity:t.startIdentity})}function Cr(e){try{t.unlinkSync(e)}catch(e){if("ENOENT"!==e.code)throw e}}function Or(){Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,20)}function xr(e){try{const n=Tr(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 Rr(e,i){try{return t.writeFileSync(br(e),`${JSON.stringify({token:i,pid:process.pid,startedAt:(new Date).toISOString()})}\n`,{encoding:"utf8",mode:384,flag:"wx"}),!0}catch(r){if("EEXIST"===r.code)return!!function(e){const i=br(e),r=Dr(i),o=Date.parse(r?.startedAt||"");if(zr(r?.pid)||Number.isFinite(o)&&Date.now()-o<2e3)return!1;const s=n.join(e,`.recovering-${c.randomUUID()}.stale`);try{t.renameSync(i,s)}catch(e){if(["ENOENT","EEXIST"].includes(e.code||""))return!1;throw e}const a=Dr(s);if(a?.token===r?.token)return Cr(s),!0;try{t.linkSync(s,i)}catch(e){if("EEXIST"!==e.code)throw e}finally{Cr(s)}return!1}(e)&&Rr(e,i);if("ENOENT"===r.code)return!1;throw r}}function Dr(e){try{return JSON.parse(t.readFileSync(e,"utf8"))}catch{return}}function Pr(e,t){return Dr(br(e))?.token===t}function Mr(e,t=process.platform){const i=n.resolve(e),r=c.createHash("sha256").update(i).digest("hex").slice(0,16);return"win32"===t?`\\\\.\\pipe\\task-handoff-node-agent-${r}`:n.join("/tmp",`task-handoff-node-agent-${process.getuid?.()??"user"}`,`${r}.sock`)}const jr="runtime-manifest.json";class Lr 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 $r(e,t=""){const i=[],r=await h.readdir(n.join(e,t),{withFileTypes:!0});for(const o of r){const r=t?n.posix.join(t,o.name):o.name;if(!t&&r===jr)continue;const s=n.join(e,...r.split("/"));if(o.isDirectory()){i.push(...await $r(e,r));continue}if(o.isSymbolicLink()){const t=await h.readlink(s);if(n.isAbsolute(t))throw new Lr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload symlink is absolute: ${r}`);const o=n.resolve(n.dirname(s),t),a=n.relative(n.resolve(e),o);if(!a||".."===a||a.startsWith(`..${n.sep}`)||n.isAbsolute(a))throw new Lr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload symlink escapes the artifact: ${r}`);if(!await h.lstat(o).catch(()=>{}))throw new Lr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload symlink is broken: ${r}`);i.push({absolutePath:s,relativePath:r,kind:"symlink",target:t,size:Buffer.byteLength(t)});continue}if(!o.isFile())throw new Lr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload contains unsupported entry: ${r}`);const a=await h.lstat(s);i.push({absolutePath:s,relativePath:r,kind:"file",size:a.size})}return i}async function Fr(e){const n=(await $r(e)).sort((e,t)=>function(e,t){return Buffer.compare(Buffer.from(e,"utf8"),Buffer.from(t,"utf8"))}(e.relativePath,t.relativePath)),i=c.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 Ur(e){for(const[t,n]of[["version",e.version],["platform",e.platform],["arch",e.arch]])if(!/^[0-9A-Za-z._-]+$/.test(n))throw new Lr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Invalid runtime artifact ${t}: ${n}`);return`${e.version}-${e.platform}-${e.arch}`}function Vr(e,t){return`${Ur(e)}-${e.sha256}-${t}`}async function qr(e){const n=c.createHash("sha256");for await(const i of t.createReadStream(e))n.update(i);return n.digest("hex")}class Hr{#e;#t;#n=new Map;constructor(e){this.#e=e.cacheDir,this.#t=e.fetchImpl??fetch}resolve(e,t){const n=Vt.parse(e);if(!/^[a-f0-9]{64}$/.test(t.archiveSha256))throw new Lr("INSTANCE_RUNTIME_ARTIFACT_INVALID","Runtime archive SHA-256 is invalid.");if((t.archiveUrl?1:0)+(t.archivePath?1:0)!=1)throw new Lr("INSTANCE_RUNTIME_ARTIFACT_INVALID","Runtime artifact source must specify exactly one archive location.");const i=Vr(n,t.archiveSha256),r=this.#n.get(i);if(r)return r;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 Lr("INSTANCE_RUNTIME_ARTIFACT_INVALID","Runtime archive SHA-256 is invalid.");const r=Vr(e,i.archiveSha256),o=n.join(this.#e,"archives"),s=n.join(o,`${r}.tar.gz`);if(await h.mkdir(o,{recursive:!0}),await this.#r(s,e,i.archiveSha256))return{identity:e,archivePath:s,cacheHit:!0};await h.rm(s,{force:!0});const a=n.join(o,`.${r}.${c.randomUUID()}.part`);try{const n=await h.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 Lr("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 qr(a)!==i.archiveSha256)throw new Lr("INSTANCE_RUNTIME_ARTIFACT_INVALID","Downloaded runtime archive SHA-256 does not match release metadata.");return await this.#o(a,e),await h.rename(a,s),{identity:e,archivePath:s,cacheHit:!1}}catch(e){if(e instanceof Lr)throw e;throw new Lr("INSTANCE_RUNTIME_ARTIFACT_UNAVAILABLE","Could not download runtime artifact.",{cause:e,retryable:!0})}finally{await h.rm(a,{force:!0})}}async#r(e,t,n){try{return await qr(e)===n&&(await this.#o(e,t),!0)}catch{return!1}}async#o(e,t){const i=n.join(this.#e,"validation",`${Ur(t)}-${c.randomUUID()}`);try{await async function(e,t){await h.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 Lr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime archive entry escapes the artifact root: ${e}`);const r=t.type;if("File"!==r&&"OldFile"!==r&&"Directory"!==r&&"SymbolicLink"!==r)throw new Lr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime archive contains unsupported entry type ${r??"unknown"}: ${e}`);return!0}})}catch(e){throw new Lr("INSTANCE_RUNTIME_ARTIFACT_INVALID","Could not extract runtime artifact safely.",{cause:e})}}(e,i),await async function(e,t,i){const r=await async function(e){let t;try{t=JSON.parse(await h.readFile(n.join(e,jr),"utf8"))}catch(e){throw new Lr("INSTANCE_RUNTIME_ARTIFACT_INVALID","Runtime artifact manifest is missing or invalid JSON.",{cause:e})}const i=ci(Vt,t);if(!i.success)throw new Lr("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 Lr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime artifact ${"sha256"===n?"SHA-256":n} mismatch: expected ${t[n]}, got ${e[n]}.`)}(r,t),1!==r.formatVersion)throw new Lr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Unsupported runtime artifact format ${r.formatVersion}.`);if(i?.platform&&"universal"!==r.platform&&r.platform!==i.platform)throw new Lr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime artifact platform ${r.platform} does not match ${i.platform}.`);if(i?.arch&&"universal"!==r.arch&&r.arch!==i.arch)throw new Lr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime artifact architecture ${r.arch} does not match ${i.arch}.`);if(void 0!==i?.launcherAbi&&r.launcherAbi>i.launcherAbi)throw new Lr("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Runtime requires launcher ABI ${r.launcherAbi}, but the base runtime provides ${i.launcherAbi}.`);const o=function(e,t){if(!e||e.includes("\\")||n.posix.isAbsolute(e))throw new Lr("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 Lr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`${t} escapes the runtime root.`);return i}(r.entrypoint,"Runtime entrypoint"),s=await h.lstat(n.join(e,...o.split("/"))).catch(()=>{});if(!s?.isFile())throw new Lr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime entrypoint is missing: ${o}`);const a=await Fr(e);if(a!==r.sha256)throw new Lr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload SHA-256 mismatch: expected ${r.sha256}, got ${a}.`);return r}(i,t,{platform:t.platform,arch:t.arch})}finally{await h.rm(i,{recursive:!0,force:!0})}}}async function Br(e,t,i,r=fetch){if("linux"!==t||!["x64","arm64"].includes(i))throw new Lr("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[r,o]=await Promise.all([h.readFile(n.join(i,`${t}.manifest.json`),"utf8"),h.readFile(n.join(i,`${t}.tar.gz.sha256`),"utf8")]),s=ci(Vt,JSON.parse(r));if(!s.success||s.data.version!==e||"linux"!==s.data.platform||"universal"!==s.data.arch)throw new Lr("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 Lr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Bundled controlled-instance ${e} has an invalid archive checksum.`);return{identity:s.data,source:{archivePath:n.join(i,`${t}.tar.gz`),archiveSha256:a}}}catch(t){if("ENOENT"===t.code)return;if(t instanceof Lr)throw t;throw new Lr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Could not read bundled controlled-instance ${e}.`,{cause:t})}}(e);if(o)return o;const s=`controlled-instance-runtime-${e}-linux-universal`,a=function(e){const t=process.env.TASK_HANDOFF_RUNTIME_RELEASE_BASE_URL?.trim();return t?t.replaceAll("{version}",e).replace(/\/$/,""):`https://github.com/edgestorage/task-handoff/releases/download/v${e}`}(e),c=`${a}/${s}.manifest.json`,d=`${a}/${s}.tar.gz`,l=`${a}/${s}.tar.gz.sha256`,[u,m]=await Promise.all([r(c),r(l)]).catch(t=>{throw new Lr("INSTANCE_RUNTIME_ARTIFACT_UNAVAILABLE",`Could not read release metadata for controlled-instance ${e}.`,{cause:t,retryable:!0})});if(!u.ok||!m.ok)throw new Lr("INSTANCE_RUNTIME_ARTIFACT_UNAVAILABLE",`Release metadata for controlled-instance ${e} is unavailable (manifest HTTP ${u.status}, checksum HTTP ${m.status}).`,{retryable:u.status>=500||m.status>=500});let p;try{p=await u.json()}catch(t){throw new Lr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Release manifest for controlled-instance ${e} is not valid JSON.`,{cause:t})}const g=ci(Vt,p);if(!g.success)throw new Lr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Release manifest for controlled-instance ${e} is invalid: ${g.error.message}`);if(g.data.version!==e||"linux"!==g.data.platform||"universal"!==g.data.arch)throw new Lr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Release identity mismatch: requested ${e}-linux-universal, received ${g.data.version}-${g.data.platform}-${g.data.arch}.`);const f=(await m.text()).trim().split(/\s+/)[0]?.toLowerCase();if(!f||!/^[a-f0-9]{64}$/.test(f))throw new Lr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Release checksum for controlled-instance ${e} is invalid.`);return{identity:g.data,source:{archiveUrl:d,archiveSha256:f}}}class Kr{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=eo(i.retryBaseDelayMs??1e3,"retryBaseDelayMs"),this.retryMaxDelayMs=eo(i.retryMaxDelayMs??3e4,"retryMaxDelayMs")}schedule(e,t={}){const n=this.requests.get(e)||{startRequested:!1,resumeCancelled:!1};n.startRequested||=!0===t.startRequested,n.resumeCancelled||=!0===t.resumeCancelled||!0===t.startRequested,n.resumeCancelled&&this.cancelled.delete(e),this.requests.set(e,n);const i=this.inFlight.get(e);if(i)return i;const r=Promise.resolve().then(()=>this.reconcile(e,n)).finally(()=>{this.inFlight.delete(e),this.requests.delete(e)});return this.inFlight.set(e,r),r}isRunning(e){return this.inFlight.has(e)}cancel(e){return this.cancelled.add(e),this.inFlight.get(e)}async reconcile(e,t){let n=this.requireInstance(e);const i=this.desiredVersion();if(this.cancelled.has(e)&&!t.resumeCancelled)return this.storePhase(n,"pending");const r=Gr(n),o=r===i&&(await(this.hooks.isInstalled?.(n,i))??!0);if(this.cancelled.has(e))return this.storePhase(this.requireInstance(e),"pending");if(r===i&&o)return this.storeState(n,{desiredVersion:i,actualVersion:r,phase:"matched",attempt:n.runtimeVersion?.attempt||0,matchedAt:this.timestamp()},!Wr(n)&&"failed"!==n.health);const s=n.runtimeVersion?.desiredVersion===i;if(s&&"failed"===n.runtimeVersion?.phase)return n;if(s&&(n.runtimeVersion?.attempt||0)>=this.maxAttempts)return"failed"===n.runtimeVersion?.phase&&n.runtimeVersion.error?n:this.storeBatchFailure(n,i,Zr(i,r,this.maxAttempts,n.runtimeVersion?.error));if(n=this.storeState(n,function(e,t,n,i=!1){const r=e.runtimeVersion,o=r?.desiredVersion===t&&"matched"!==r.phase;return{desiredVersion:t,...n?{actualVersion:n}:{},phase:"pending",attempt:o?r.attempt:0,error:(o?r.error:void 0)||(n!==t||i?Yr(t,n):Xr("INSTANCE_RUNTIME_VERIFICATION_FAILED",`Controlled-instance ${t} is running, but the active runtime artifact does not match the desired release identity.`,t,n,!0))}}(n,i,r,o)),Wr(n)&&!t.startRequested)return n;let a=!1;try{for(;(n.runtimeVersion?.attempt||0)<this.maxAttempts;){if(this.cancelled.has(e))return this.storePhase(this.requireInstance(e),"pending");let r;try{if(n=this.storePhase(n,"draining"),await(this.hooks.beginDrain?.(n)),a=!0,n=this.requireInstance(e),Jr(n)){const t=await this.waitUntil(e,this.drainTimeoutMs,e=>!Jr(e));if(n=this.requireInstance(e),!t){if(this.cancelled.has(e))return this.storePhase(n,"pending");await(this.hooks.onForcedDrain?.(n))}}if(n=this.storePhase(this.requireInstance(e),"installing",!0),await this.hooks.install(n,i),this.cancelled.has(e)||Wr(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=>Gr(e)===i);if(this.cancelled.has(e))return this.storePhase(this.requireInstance(e),"pending");if(!r)throw Xr("INSTANCE_RUNTIME_VERIFICATION_FAILED",`Instance ${e} did not register controlled-instance ${i} after restart.`,i,Gr(this.requireInstance(e)),!0);const o=this.requireInstance(e);if(this.hooks.isInstalled&&!await this.hooks.isInstalled(o,i))throw Xr("INSTANCE_RUNTIME_VERIFICATION_FAILED",`Instance ${e} reported controlled-instance ${i}, but its active runtime release is missing.`,i,Gr(o),!0);return this.storeState(o,{desiredVersion:i,actualVersion:i,phase:"matched",attempt:o.runtimeVersion?.attempt||1,matchedAt:this.timestamp()},!Wr(o)&&"failed"!==o.health)}catch(t){if(this.cancelled.has(e))return this.storePhase(this.requireInstance(e),"pending");r=Qr(t,i,Gr(this.store.get(e)))}n=this.requireInstance(e);const o=n.runtimeVersion?.attempt||1;if(!r.retryable||o>=this.maxAttempts)return this.storeBatchFailure(n,i,o>=this.maxAttempts&&r.retryable?Zr(i,Gr(n),this.maxAttempts,r):r);n=this.storeState(n,{desiredVersion:i,...Gr(n)?{actualVersion:Gr(n)}:{},phase:"pending",attempt:o,lastAttemptAt:this.timestamp(),error:r}),await this.delay(this.retryDelayMs(o))}return this.storeBatchFailure(n,i,Zr(i,Gr(n),this.maxAttempts,n.runtimeVersion?.error))}finally{a&&await(this.hooks.endDrain?.(this.requireInstance(e)))}}storeBatchFailure(e,t,n){const i=Gr(e);return this.storeState(e,{desiredVersion:t,...i?{actualVersion:i}:{},phase:"failed",attempt:e.runtimeVersion?.attempt||0,lastAttemptAt:this.timestamp(),error:n})}retryDelayMs(e){return Math.min(this.retryMaxDelayMs,this.retryBaseDelayMs*2**Math.max(0,e-1))}storePhase(e,t,n=!1){const i=this.desiredVersion(),r=Gr(e),o=e.runtimeVersion?.desiredVersion===i?e.runtimeVersion.error:void 0;return this.storeState(e,{desiredVersion:i,...r?{actualVersion:r}:{},phase:t,attempt:(e.runtimeVersion?.attempt||0)+(n?1:0),lastAttemptAt:this.timestamp(),...o?{error:o}:"pending"===t?{error:Yr(i,r)}:{}},"restarting"!==t&&void 0)}storeState(e,t,n){const i=this.store.get(e.id)||e;return this.store.put(Xn.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 Gr(e){return e?.build?.packageVersion||e?.instanceVersion}function Jr(e){return e.apps.runningCount>0||e.aiSessions.runningCount>0}function Wr(e){return["created","stopped","failed"].includes(e.status)}function Yr(e,t){return Xr("INSTANCE_RUNTIME_VERSION_MISMATCH",`Expected controlled-instance ${e}, received ${t||"an unknown version"}.`,e,t,!0)}function Xr(e,t,n,i,r){return{code:e,message:t,expectedVersion:n,...i?{actualVersion:i}:{},retryable:r}}function Qr(e,t,n){if(e&&"object"==typeof e&&"code"in e&&"message"in e){const i=e,r=qt.shape.code.safeParse(i.code);if(r.success&&"string"==typeof i.message)return Xr(r.data,i.message,t,n,"boolean"!=typeof i.retryable||i.retryable)}return Xr("INSTANCE_RUNTIME_INSTALL_FAILED",e instanceof Error?e.message:String(e),t,n,!0)}function Zr(e,t,n,i){const r=i?.message?` Last error: ${i.message}`:"";return Xr(i?.code||"INSTANCE_RUNTIME_INSTALL_FAILED",`Runtime convergence stopped after ${n} attempts for this instance run.${r}`,e,t,!0)}function eo(e,t){if(!Number.isFinite(e)||e<0)throw new TypeError(`${t} must be a nonnegative finite number.`);return e}function to(e,n=448){t.mkdirSync(e,{recursive:!0,mode:n}),t.chmodSync(e,n)}function no(e,i,r={}){const o=r.directoryMode??448,s=r.fileMode??384;to(n.dirname(e),o),I.sync(e,`${JSON.stringify(i,null,2)}\n`,{encoding:"utf8",mode:s}),t.chmodSync(e,s)}function io(e,t){console.warn(JSON.stringify({message:e,...t}))}function ro(e){return e&&"object"==typeof e&&"issues"in e?{issues:e.issues}:{error:e instanceof Error?e.message:String(e)}}function oo(e,n){const i=n.logger||io;let r;try{r=JSON.parse(t.readFileSync(e,"utf8"))}catch(t){return void i("stored JSON could not be read",{filePath:e,...ro(t)})}if(!n.schema)return r;const o=n.sanitize?n.sanitize(r):r,s=n.schema.safeParse(o);if(s.success)return s.data;const a="strip"in n.schema&&"function"==typeof n.schema.strip?n.schema.strip().safeParse(o):void 0;if(a?.success)return i("unknown stored fields were ignored",{filePath:e,issues:s.error.issues}),a.data;i("stored record failed validation and was isolated",{filePath:e,issues:s.error.issues})}function so(e){return`${e}_${c.randomUUID().replace(/-/g,"").slice(0,20)}`}function ao(){return c.randomBytes(24).toString("base64url")}class co{directory;options;permissionsInitialized=!1;constructor(e,t={}){this.directory=e,this.options=t}init(){if(this.permissionsInitialized&&t.existsSync(this.directory))return;to(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=oo(n.join(this.directory,e),this.options);return t?[t]:[]})}get(e){this.init();const n=this.filePath(e);return t.existsSync(n)?oo(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 no(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 lo{filePathValue;defaults;options;constructor(e,t,n={}){this.filePathValue=e,this.defaults=t,this.options=n}init(){to(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)?oo(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 no(this.filePathValue,n,this.options),n}}const uo=a.z.record(a.z.string(),a.z.string()),mo=new Set(["OPENAI_API_KEY","OPENAI_BASE_URL","CODEX_MODEL","TASK_HANDOFF_CODEX_BASE_URL","TASK_HANDOFF_CODEX_MODEL","TASK_HANDOFF_CODEX_MODEL_ID","ANTHROPIC_API_KEY","ANTHROPIC_BASE_URL","CLAUDE_MODEL","TASK_HANDOFF_CLAUDE_MODEL","TASK_HANDOFF_CLAUDE_MODEL_ID"]);class po{directory;constructor(e){this.directory=e}get(e){try{return uo.parse(JSON.parse(t.readFileSync(this.filePath(e),"utf8")))}catch(t){if(t&&"object"==typeof t&&"code"in t&&"ENOENT"===t.code)return{};throw new Error(`Stored model environment for instance ${e} is invalid: ${t instanceof Error?t.message:String(t)}`)}}has(e){return t.existsSync(this.filePath(e))}listInstanceIds(){return t.existsSync(this.directory)?t.readdirSync(this.directory).filter(e=>e.endsWith(".json")).map(e=>e.slice(0,-5)).sort():[]}put(e,n){const i=uo.parse(n);t.mkdirSync(this.directory,{recursive:!0,mode:448});const r=this.filePath(e);return I.sync(r,`${JSON.stringify(i,null,2)}\n`,{encoding:"utf8",mode:384}),t.chmodSync(r,384),i}delete(e){t.rmSync(this.filePath(e),{force:!0})}filePath(e){return n.join(this.directory,`${e}.json`)}}class go{directory;nodeId;constructor(e,t){this.directory=e,this.nodeId=t}init(){t.mkdirSync(this.directory,{recursive:!0,mode:448}),t.chmodSync(this.directory,448)}list(){return this.init(),t.readdirSync(this.directory).filter(e=>e.endsWith(".json")).sort().flatMap(e=>{const t=this.read(n.join(this.directory,e));return t?[t]:[]})}get(e){const n=this.filePath(e);return t.existsSync(n)?this.read(n):void 0}put(e){const n=an.parse(e);this.init();const i=this.filePath(n.id);return I.sync(i,`${JSON.stringify(n,null,2)}\n`,{encoding:"utf8",mode:384}),t.chmodSync(i,384),n}delete(e){const n=this.filePath(e);return!!t.existsSync(n)&&(t.unlinkSync(n),!0)}read(e){try{const i=JSON.parse(t.readFileSync(e,"utf8")),r=n.basename(e,".json"),o=an.safeParse(i);if(o.success&&o.data.id===r&&In(o.data)===o.data.id)return o.data;const s=an.strip().safeParse(i);return s.success&&s.data.id===r&&In(s.data)===s.data.id?(console.warn(JSON.stringify({message:"unknown stored node model fields were ignored",nodeId:this.nodeId,filePath:e})),s.data):void console.warn(JSON.stringify({message:"stored node model failed validation and was isolated",nodeId:this.nodeId,filePath:e}))}catch(t){return void console.warn(JSON.stringify({message:"stored node model could not be read",nodeId:this.nodeId,filePath:e,error:t instanceof Error?t.message:String(t)}))}}filePath(e){return n.join(this.directory,`${e}.json`)}}class ho{directory;constructor(e){this.directory=e}init(){t.mkdirSync(this.directory,{recursive:!0,mode:448}),t.chmodSync(this.directory,448)}get(e){const n=this.filePath(e);if(t.existsSync(n))try{const i=JSON.parse(t.readFileSync(n,"utf8")),r=ln.safeParse(i);if(r.success)return r.data;const o=ln.strip().safeParse(i);if(o.success)return console.warn(JSON.stringify({message:"unknown stored model assignment fields were ignored",instanceId:e,filePath:n})),o.data;throw r.error}catch(t){throw Object.assign(new Error(`Stored model assignment for instance ${e} is invalid.`),{statusCode:409,code:"NODE_MODEL_ASSIGNMENT_INVALID",cause:t})}}put(e){const n=ln.parse(e);this.init();const i=this.filePath(n.instanceId);return I.sync(i,`${JSON.stringify(n,null,2)}\n`,{encoding:"utf8",mode:384}),t.chmodSync(i,384),n}delete(e){t.rmSync(this.filePath(e),{force:!0})}filePath(e){return n.join(this.directory,`${e}.json`)}}function fo(){return(new Date).toISOString()}class yo{models;assignments;legacyEnvironments;nodeId;instances;constructor(e,t,n){this.nodeId=t,this.instances=n,this.models=new go(e.nodeModelsDir,t),this.assignments=new ho(e.modelAssignmentsDir),this.legacyEnvironments=new po(e.modelEnvironmentsDir)}init(){this.models.init(),this.assignments.init(),this.migrateLegacyEnvironments()}list(){const e=new Map;for(const t of this.instances.list()){const n=this.assignments.get(t.id);for(const t of[n?.codexModelHash,n?.claudeModelHash])t&&e.set(t,(e.get(t)||0)+1)}return this.models.list().map(t=>this.toPublic(t,e.get(t.id)||0))}create(e){const t=fo(),n=In(e),i=this.models.get(n),r=an.parse({...e,id:n,enabled:e.enabled??!0,order:e.order??this.nextOrder(),labels:e.labels||{},createdAt:i?.createdAt||t,updatedAt:t});return this.toPublic(this.models.put(r),this.referenceIds(n).length)}deploy(e){const t=In(e);if(e.id!==t)throw Object.assign(new Error(`Model content hash ${t} does not match ${e.id}.`),{statusCode:400,code:"NODE_MODEL_HASH_MISMATCH"});const n=this.models.get(e.id)||this.models.put(an.parse(e));return this.toPublic(n,this.referenceIds(n.id).length)}update(e,t){const n=this.requireModel(e),i=an.parse({...n,...t,key:t.key?.trim()?t.key:n.key,createdAt:n.createdAt,updatedAt:fo()}),r=In(i),o=this.models.put(an.parse({...i,id:r}));return this.toPublic(o,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)}assign(e,t){const n=this.instances.require(e);if(this.validateRef("codex",t.codexModelHash),this.validateRef("claude",t.claudeModelHash),void 0!==t.modelSelection.codexModelHash&&(t.modelSelection.codexModelHash??void 0)!==t.codexModelHash)throw Object.assign(new Error("Codex model selection does not match its node assignment."),{statusCode:400,code:"NODE_MODEL_SELECTION_MISMATCH"});if(void 0!==t.modelSelection.claudeModelHash&&(t.modelSelection.claudeModelHash??void 0)!==t.claudeModelHash)throw Object.assign(new Error("Claude model selection does not match its node assignment."),{statusCode:400,code:"NODE_MODEL_SELECTION_MISMATCH"});const i=this.assignments.get(e),r=ln.parse({instanceId:e,codexModelHash:t.codexModelHash,claudeModelHash:t.claudeModelHash,updatedAt:fo()});this.assignments.put(r);try{return{assignment:r,instance:this.instances.put(Xn.parse({...n,modelSelection:t.modelSelection,updatedAt:fo()}))}}catch(t){throw i?this.assignments.put(i):this.assignments.delete(e),t}}resolvedEnvironment(e){const t=this.assignments.get(e);if(!t){if(this.legacyEnvironments.has(e))throw Object.assign(new Error(`Legacy model environment for instance ${e} requires manual migration.`),{statusCode:409,code:"NODE_MODEL_MIGRATION_REQUIRED"});return{}}return{...this.environmentForRef("codex",t.codexModelHash),...this.environmentForRef("claude",t.claudeModelHash)}}deleteInstanceMetadata(e){this.assignments.delete(e),this.legacyEnvironments.delete(e)}validateRef(e,t){if(!t)return;const n=this.requireModel(t);if(n.app!==e)throw Object.assign(new Error(`Model ${n.id} belongs to ${n.app}, not ${e}.`),{statusCode:400,code:"NODE_MODEL_APP_MISMATCH"});if(!n.enabled)throw Object.assign(new Error(`Model ${n.id} is disabled.`),{statusCode:409,code:"NODE_MODEL_DISABLED"})}environmentForRef(e,t){if(!t)return{};this.validateRef(e,t);const n=this.requireModel(t);return"codex"===e?{OPENAI_API_KEY:n.key,OPENAI_BASE_URL:n.endpoint,TASK_HANDOFF_CODEX_BASE_URL:n.endpoint,TASK_HANDOFF_CODEX_MODEL:n.model}:{ANTHROPIC_API_KEY:n.key,ANTHROPIC_BASE_URL:n.endpoint,TASK_HANDOFF_CLAUDE_MODEL:n.model}}requireModel(e){const t=this.models.get(e);if(!t)throw Object.assign(new Error(`Model ${e} was not found on node ${this.nodeId}.`),{statusCode:404,code:"NODE_MODEL_NOT_FOUND"});if(In(t)!==t.id)throw Object.assign(new Error(`Stored model ${e} does not match its content hash.`),{statusCode:409,code:"NODE_MODEL_HASH_INVALID"});return t}referenceIds(e){return this.instances.list().filter(t=>{const n=this.assignments.get(t.id);return n?.codexModelHash===e||n?.claudeModelHash===e}).map(e=>e.id)}toPublic(e,t){const{key:n,...i}=e;return dn.parse({...i,keyPreview:n.length<=8?"set":`${n.slice(0,4)}...${n.slice(-4)}`,keySet:!0,referenceCount:t})}nextOrder(){return this.models.list().reduce((e,t)=>Math.max(e,t.order),0)+100}migrateLegacyEnvironments(){for(const e of this.legacyEnvironments.listInstanceIds()){if(!this.instances.has(e)){this.warnMigration(e,"instance-not-found");continue}if(this.assignments.get(e)){try{this.resolvedEnvironment(e),this.legacyEnvironments.delete(e)}catch{this.warnMigration(e,"existing-assignment-invalid")}continue}let t;try{t=this.legacyEnvironments.get(e)}catch{this.warnMigration(e,"sidecar-invalid");continue}if(!Object.keys(t).length){this.legacyEnvironments.delete(e);continue}if(Object.keys(t).some(e=>!mo.has(e))){this.warnMigration(e,"unknown-fields");continue}const n=[];try{const i=this.migrateApp(t,"codex",n),r=this.migrateApp(t,"claude",n);if(!i&&!r)throw new Error("no complete model configuration");const o={...i?{codexModelHash:i}:{},...r?{claudeModelHash:r}:{}};this.assign(e,{modelSelection:o,codexModelHash:i,claudeModelHash:r}),this.resolvedEnvironment(e),this.legacyEnvironments.delete(e)}catch{this.assignments.delete(e);for(const e of n)this.models.delete(e);this.warnMigration(e,"mapping-failed")}}}migrateApp(e,t,n){const i=e["codex"===t?"OPENAI_API_KEY":"ANTHROPIC_API_KEY"],r="codex"===t?e.TASK_HANDOFF_CODEX_BASE_URL||e.OPENAI_BASE_URL:e.ANTHROPIC_BASE_URL,o="codex"===t?e.TASK_HANDOFF_CODEX_MODEL||e.CODEX_MODEL:e.TASK_HANDOFF_CLAUDE_MODEL||e.CLAUDE_MODEL;if(!i&&!r&&!o)return;if(!i||!r||!o)throw new Error("model configuration incomplete");const s=In({app:t,endpoint:r,key:i,model:o}),a=this.models.get(s);if(a){if(a.app!==t||a.key!==i||a.endpoint!==r||a.model!==o||!a.enabled)throw new Error("existing model conflicts with legacy environment");return s}const c=fo();return this.models.put(an.parse({id:s,name:`Migrated ${"codex"===t?"Codex":"Claude"} model`,endpoint:r,key:i,model:o,app:t,enabled:!0,order:this.nextOrder(),labels:{migratedFrom:"instance-model-environment"},createdAt:c,updatedAt:c})),n.push(s),s}warnMigration(e,t){console.warn(JSON.stringify({message:"legacy model environment was preserved because it could not be migrated",nodeId:this.nodeId,instanceId:e,reason:t}))}}function Io(){return(new Date).toISOString()}function Ao(e,t){if(!e)return!0;const n=A.valid(e),i=A.valid(t);return n&&i?A.gt(i,n):e!==t}function bo(){return process.env.TASK_HANDOFF_NPM_COMMAND||"npm"}function wo(e,i){const r=n.join(e,...i.split("/"),"package.json");try{const e=JSON.parse(t.readFileSync(r,"utf8"));if(e.name!==i||"string"!=typeof e.version||!e.version.trim())throw new Error(`Installed package manifest is invalid: ${r}`);return{name:i,version:e.version.trim()}}catch(e){if("ENOENT"===e.code)return;throw e}}async function vo(e){const t=(await e(bo(),["root","--global"])).stdout.trim();if(!t)throw new Error("npm did not return its global module root.");const n=wo(t,"@task-handoff/server"),i=wo(t,"@task-handoff/node-agent");return n?{packageName:"@task-handoff/server",currentVersion:n.version,relatedCurrentVersions:i?[i.version]:[]}:{packageName:"@task-handoff/node-agent",currentVersion:i?.version,relatedCurrentVersions:[]}}function Eo(e){if(!e||"object"!=typeof e||Array.isArray(e))return e;const t=e,n="string"==typeof t.updatedAt?t.updatedAt:Io(),i=t.target&&"object"==typeof t.target&&!Array.isArray(t.target)?t.target:void 0,r="controlled-instance"===i?.component,o={updating:"updating-node",downloading:"updating-node",installing:"updating-node",restarting:"restarting-node",completed:"succeeded",success:"succeeded",error:"failed"},s=new Set(["queued","updating-node","restarting-node","converging-instances","succeeded","degraded","failed"]),a="string"==typeof t.status?t.status:"queued",c=r?"failed":s.has(a)?a:o[a]||"failed",d="string"==typeof t.toVersion&&t.toVersion?t.toVersion:"unknown",l=Bt.strip().safeParse(t.impact).success?Bt.strip().parse(t.impact):{runningInstanceCount:0,stoppedInstanceCount:0,activeInstanceCount:0,restartInstanceCount:0,runningInstanceIds:[],stoppedInstanceIds:[],activeInstanceIds:[]},u=r?{code:"LEGACY_INSTANCE_UPDATE_RETIRED",message:"Independent controlled-instance update jobs were retired in favor of Node reconciliation.",retryable:!1}:"failed"!==c||t.error||s.has(a)||a in o?"string"==typeof t.error?{code:"NODE_UPDATE_FAILED",message:t.error,retryable:!1}:qt.strip().safeParse(t.error).success?qt.strip().parse(t.error):t.error&&"object"==typeof t.error?{code:"NODE_UPDATE_FAILED",message:"string"==typeof t.error.message?t.error.message:"Stored update job contained an unknown error.",retryable:!1}:void 0:{code:"NODE_UPDATE_FAILED",message:`Stored update job used an unknown status: ${a}.`,retryable:!1},{target:m,error:p,...g}=t,h={phase:"succeeded"===c?"succeeded":"failed"===c?"failed":c||"queued",desiredVersion:d,expectedInstanceIds:[],expectedInstanceCount:0,matchedInstanceCount:0,pendingInstanceCount:0,failedInstanceCount:r||"failed"===c?1:0,deferredInstanceCount:0},f=Kt.strip().safeParse(t.rollout);return{...g,source:"npm",status:c,impact:l,runtimeArtifacts:Array.isArray(t.runtimeArtifacts)?t.runtimeArtifacts.flatMap(e=>{const t=Vt.strip().safeParse(e);return t.success?[t.data]:[]}):[],rollout:f.success?f.data:h,...u?{error:u}:{},...r?{completedAt:t.completedAt||n}:{}}}class No{records;constructor(e){this.records=new co(e.updatesDir,{schema:Wt,sanitize:Eo})}init(){this.records.init()}list(){return this.records.list().sort((e,t)=>t.createdAt.localeCompare(e.createdAt))}create(e,t){const n=Io();return this.records.put(Wt.parse({id:so("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(Wt.parse({...n,...t,id:e,createdAt:n.createdAt,updatedAt:Io()}))}reconcileRollouts(e,t,n={}){const i=new Map(e.map(e=>[e.id,e]));for(const e of this.list().filter(e=>["updating-node","restarting-node","converging-instances"].includes(e.status))){if(n.processStarted&&"restarting-node"===e.status&&t!==e.toVersion){this.patch(e.id,{status:"failed",rollout:{...e.rollout,phase:"failed",nodeVersion:t},error:{code:"NODE_UPDATE_FAILED",message:`Node agent restarted with version ${t}, expected ${e.toVersion}.`,retryable:!1},completedAt:Io()});continue}const r="converging-instances"!==e.status&&t===e.toVersion?this.patch(e.id,{status:"converging-instances",rollout:{...e.rollout,phase:"converging-instances",nodeVersion:t}}):e;if("converging-instances"!==r.status)continue;const o=r.rollout.expectedInstanceIds,s=o.map(e=>i.get(e)),a=s.filter(e=>e?.ready&&"matched"===e.runtimeVersion?.phase&&e.runtimeVersion.actualVersion===r.toVersion).length,c=s.filter(e=>e&&["created","stopped","failed"].includes(e.status||"")&&"failed"!==e.runtimeVersion?.phase).length,d=s.filter(e=>!e||"failed"===e.runtimeVersion?.phase).length,l=Math.max(0,o.length-a-d-c),u=d>0?"degraded":0===l?"succeeded":"converging-instances";this.patch(r.id,{status:u,rollout:{...r.rollout,phase:u,nodeVersion:t,expectedInstanceCount:o.length,matchedInstanceCount:a,pendingInstanceCount:l,failedInstanceCount:d,deferredInstanceCount:r.impact.stoppedInstanceCount+c},..."succeeded"===u||"degraded"===u?{completedAt:Io()}:{}})}}run(e,t){(async()=>{this.patch(e.id,{status:"updating-node",rollout:{...e.rollout,phase:"updating-node"},startedAt:Io(),error:void 0});try{await t(e),this.patch(e.id,{status:"succeeded",completedAt:Io()})}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:Io()})}})()}}function zo(){return(new Date).toISOString()}class _o{records;constructor(e){this.records=new co(e.environmentTemplatesDir,{schema:zt,sanitize:e=>function(e,t){if(!e||"object"!=typeof e||Array.isArray(e))return e;const n=e,i=new Set(["id","name","sourceInstanceId","nodeId","imageId","internalTag","platform","architecture","sizeBytes","status","error","createdAt","updatedAt"]),r="string"==typeof n.id?n.id:void 0;for(const e of Object.keys(n))i.has(e)||t?.({templateId:r,field:e});const o=ri(n,[...i]);if(n.error&&"object"==typeof n.error&&!Array.isArray(n.error)){const e=n.error;for(const n of Object.keys(e))["code","message","phase"].includes(n)||t?.({templateId:r,field:`error.${n}`});o.error=ri(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(zt.parse({...e,status:"failed",error:{code:"ENVIRONMENT_TEMPLATE_CREATION_INTERRUPTED",message:"Environment template creation was interrupted by a node-agent restart.",phase:"recovery"},updatedAt:zo()}))}list(){return this.records.list()}get(e){return this.records.get(e)}put(e){return this.records.put(zt.parse(e))}patch(e,t){return this.records.patch(e,t)}delete(e){return this.records.delete(e)}}const So=a.z.record(a.z.string().regex(/^[A-Za-z_][A-Za-z0-9_]*$/),a.z.string()),To=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:So,updatedAt:a.z.string().datetime()}).strict();class ko{directory;constructor(e){this.directory=e.instancePrivateConfigsDir}init(){t.mkdirSync(this.directory,{recursive:!0,mode:448}),t.chmodSync(this.directory,448);for(const e of t.readdirSync(this.directory).filter(e=>e.endsWith(".json")))t.chmodSync(n.join(this.directory,e),384)}filePath(e){return n.join(this.directory,`${e}.json`)}get(e){const n=this.filePath(e);if(!t.existsSync(n))return;const i=JSON.parse(t.readFileSync(n,"utf8")),r=i&&"object"==typeof i&&!Array.isArray(i)?i:{},o=To.parse({version:r.version,instanceId:r.instanceId,instanceCredential:r.instanceCredential??r.registrationToken,environment:r.environment,updatedAt:r.updatedAt});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 void 0===r.instanceCredential&&void 0!==r.registrationToken&&this.put(o),o}put(e){const n=To.parse(e);this.init();const i=this.filePath(n.instanceId);return I.sync(i,`${JSON.stringify(n,null,2)}\n`,{encoding:"utf8",mode:384}),t.chmodSync(i,384),n}materialize(e,t,n){if(!t)throw Object.assign(new Error(`Instance ${e} does not have a long-lived credential.`),{statusCode:409,code:"INSTANCE_PRIVATE_CONFIG_CREDENTIAL_MISSING"});return this.put({version:1,instanceId:e,instanceCredential:t,environment:n,updatedAt:(new Date).toISOString()})}delete(e){t.rmSync(this.filePath(e),{force:!0})}}const Co=function(e,t=process.env,n=e){let i;return()=>{const r=t.TASK_HANDOFF_VERSION?.trim();return r||(i||=E(e,t,n),i)}}("@task-handoff/node-agent",process.env,"@task-handoff/control-plane");function Oo(){return Co()}function xo(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 Ro(e){const t=Oo();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:xo(t,e)}}function Do(e,t,n=!0){if(!n)return Ro(t);const i=Oo(),r=e.runtimeVersion;if(!r||r.desiredVersion!==i)return Ro(t);const o="INSTANCE_RUNTIME_VERSION_MISMATCH"!==r.error?.code?r.error:t===i?void 0:xo(i,t);return Ht.parse({...r,desiredVersion:i,...t?{actualVersion:t}:{actualVersion:void 0},..."pending"===r.phase?{error:o||(t!==i?xo(i,t):void 0)}:{}})}const Po="runtime_local_host",Mo="task-handoff.node-agent.builtin";function jo(){return(new Date).toISOString()}function Lo(e){const t={...e};return delete t[Mo],t}function $o(e){return"local-folder"===e.type?nn.parse({mode:"local-bind",path:"/workspace",readOnly:!1}):nn.parse({mode:"git-clone",path:"/workspace",readOnly:!1})}function Fo(e,t,n){const i=`task-handoff-${e.replace(/[^a-zA-Z0-9_.-]/g,"-")}`;return[{role:"data",suffix:"data",mountPath:"/data"},{role:"agent-home",suffix:"agent-home",mountPath:"/home/agent"},..."local-folder"===n.type?[]:[{role:"workspace",suffix:"workspace",mountPath:"/workspace"}]].map(({role:n,suffix:r,mountPath:o})=>({role:n,name:`${i}-${r}`,mountPath:o,labels:{"task-handoff.owner":"task-handoff","task-handoff.instance-id":e,"task-handoff.node-id":t,"task-handoff.volume-role":n}}))}function Uo(e){const t=tn.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 on.parse({id:n,name:"string"==typeof e.sourceSnapshot.name?e.sourceSnapshot.name:e.name,source:t,defaultImageSelection:e.imageSelection,defaultNodeId:e.nodeId,defaultRuntimeId:e.runtimeId,workspacePolicy:$o(t),labels:{},createdAt:e.createdAt,updatedAt:e.updatedAt})}function Vo(e,t){throw Object.assign(new Error(t),{statusCode:403,code:e})}function qo(e,t){e!==qe&&console.warn(JSON.stringify({message:"protocol version mismatch",peer:t,expectedProtocolVersion:qe,actualProtocolVersion:e||"missing",errorCode:"PROTOCOL_VERSION_MISMATCH"}))}function Ho(e){return"none"!==e.capabilities.artifactKind}function Bo(e={}){return{...e,requiresImage:!1,supportsControlledInstanceApi:!0,supportsContainerLifecycle:!1,supportsAppSessions:!0,supportsHostSessions:!0,artifactKind:"none",isolation:"none"}}class Ko extends co{onStored;privateConfigs;constructor(e,t,n){super(e,t),this.privateConfigs=n}setOnStored(e){this.onStored=e}put(e){const t=super.get(e.id)?.stateRevision||0,n=this.privateConfigs.get(e.id),i=e.registrationToken||n?.instanceCredential;i&&this.privateConfigs.materialize(e.id,i,n?.environment||{});const{registrationToken:r,...o}=e,s=super.put(Xn.parse({...o,stateRevision:Math.max(e.stateRevision||0,t)+1})),a=this.hydrate(s);return this.onStored?.(a),a}get(e){const t=super.get(e);return t?this.hydrate(t):void 0}list(){return super.list().map(e=>this.hydrate(e))}hydrate(e){const t=this.privateConfigs.get(e.id)?.instanceCredential||e.registrationToken;return Xn.parse({...e,registrationToken:t})}}class Go{nodeId;paths;localFolders;nodeRuntimes;controlledInstances;environmentTemplates;instancePrivateConfigs;modelRegistry;updateJobs;node;listenerPort;containerUrlOverride;platform;constructor(e,t,n,i,r,o){this.paths=e,this.nodeId=t,this.localFolders=new co(e.localFoldersDir,{schema:en,sanitize:wt}),this.nodeRuntimes=new co(e.nodeRuntimesDir,{schema:Fn}),this.instancePrivateConfigs=new ko(e),this.controlledInstances=new Ko(e.controlledInstancesDir,{schema:Xn,sanitize:e=>ti(e,e=>{console.warn(JSON.stringify({message:"legacy controlled instance field was ignored",...e}))})},this.instancePrivateConfigs),this.environmentTemplates=new _o(e),this.modelRegistry=new yo(e,t,{has:e=>Boolean(this.controlledInstances.get(e)),list:()=>this.listInstances(),require:e=>this.requireInstance(e),put:e=>this.controlledInstances.put(e)}),this.updateJobs=new No(e),this.listenerPort=r,this.platform=o,this.containerUrlOverride=i;const s=jo();this.node=$n.parse({id:t,name:t,connectionMode:"direct-http",endpoint:n,controlEndpoint:n,containerEndpoint:this.containerUrl,publicWebBase:n?n.replace(/:\d+$/,""):void 0,status:"online",health:"ok",capabilities:{},labels:{},createdAt:s,updatedAt:s})}init(){this.localFolders.init();for(const e of this.localFolders.list())this.localFolders.put(e);if(this.nodeRuntimes.init(),this.instancePrivateConfigs.init(),this.controlledInstances.init(),this.environmentTemplates.init(),this.modelRegistry.init(),this.updateJobs.init(),this.updateJobs.reconcileRollouts(this.controlledInstances.list(),Oo(),{processStarted:!0}),!this.nodeRuntimes.get("runtime_local_docker")){const e=jo();this.nodeRuntimes.put(Fn.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(Po),t=jo();this.nodeRuntimes.put(Fn.parse({id:Po,nodeId:this.nodeId,name:"Local Runtime",type:"local",status:e?.status||"unknown",accessStrategy:"node-proxy",capabilities:Bo(e?.capabilities),labels:{...e?.labels,[Mo]:"true"},createdAt:e?.createdAt||t,updatedAt:e?.updatedAt||t}))}for(const e of this.nodeRuntimes.list())e.nodeId!==this.nodeId&&this.nodeRuntimes.put(Fn.parse({...e,nodeId:this.nodeId,updatedAt:jo()}));for(const e of this.localFolders.list())e.nodeId!==this.nodeId&&this.localFolders.put(en.parse({...e,nodeId:this.nodeId,updatedAt:jo()}));this.normalizeInstanceRuntimeVersions()}normalizeInstanceRuntimeVersions(){for(const e of this.controlledInstances.list()){const t=Ro(e.build?.packageVersion||e.instanceVersion),n=Ho(this.requireRuntime(e.runtimeId)),i=["created","stopped","failed"].includes(e.status),r=n&&e.runtimeVersion?.desiredVersion===t.desiredVersion?e.runtimeVersion:void 0,o=n?"matched"===t.phase?i?t:{...t,phase:"verifying",matchedAt:void 0}:"failed"===r?.phase?{...t,phase:"failed",attempt:r.attempt,lastAttemptAt:r.lastAttemptAt,error:r.error}:{...t,attempt:r?.attempt||0,lastAttemptAt:r?.lastAttemptAt}:t;this.controlledInstances.put(Xn.parse({...e,ready:!1,runtimeVersion:o,updatedAt:jo()}))}}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=jo()}runningInstanceCount(){const e=new Set(["created","stopped","failed"]);return this.listInstances().filter(t=>!e.has(t.status)).length}createLocalFolder(e){const t=jo(),n=en.parse({...e,id:e.id||so("folder"),nodeId:this.nodeId,labels:e.labels||{},createdAt:t,updatedAt:t});return this.localFolders.put(n)}createRuntime(e){if("local"===e.type){const e="win32"===this.platform,t=new Error(e?"Local Runtime is not supported on Windows.":"Local Runtime is built in and cannot be added manually.");throw Object.assign(t,{statusCode:e?400:409,code:e?"LOCAL_RUNTIME_UNSUPPORTED":"LOCAL_RUNTIME_BUILTIN"}),t}const t=jo(),n=Fn.parse({...e,id:e.id||so("runtime"),nodeId:this.nodeId,accessStrategy:e.accessStrategy||(i=e.type,"docker"===i?"direct-port":"node-proxy"),capabilities:e.capabilities||{},labels:Lo(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[Mo]){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=Fn.parse({...n,...t,id:n.id,nodeId:this.nodeId,accessStrategy:t.accessStrategy||n.accessStrategy,capabilities:t.capabilities||n.capabilities,labels:t.labels?Lo(t.labels):n.labels,createdAt:n.createdAt,updatedAt:jo()});return this.nodeRuntimes.put(i)}deleteRuntime(e){if("true"===this.requireRuntime(e).labels[Mo]){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=Fn.parse({...n,...e,id:n.id,nodeId:this.nodeId,createdAt:n.createdAt,updatedAt:jo()});return this.nodeRuntimes.put(t)}):this.nodeRuntimes.put(Fn.parse({...n,status:"unknown",updatedAt:jo()}))}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=ei(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 ${qe}: ${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 Xn.parse({...e,status:"starting",ready:!1,updatedAt:n});case"stop-requested":return Xn.parse({...e,status:"stopping",ready:!1,updatedAt:n});case"stop-failed":return"stopping"!==e.status?e:Xn.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 Xn.parse({...e,build:void 0,instanceVersion:void 0,ready:!1,updatedAt:n});case"runtime-lifecycle-completed":return function(e,t,n,i){if(t.stateRevision>e.stateRevision&&["failed","stopping","stopped","deleting"].includes(t.status))return t;const r=t.stateRevision>e.stateRevision&&t.lastHeartbeatAt!==e.lastHeartbeatAt&&"online"===t.agentStatus;return Xn.parse({...t,...n,...r?{status:t.status,health:t.health,connectionStatus:t.connectionStatus,agentStatus:t.agentStatus,targetStatus:t.targetStatus,uiAccessStatus:t.uiAccessStatus}:{},ready:!!r&&t.ready,target:n.target?r?{...n.target,...t.target}:{...t.target,...n.target}:t.target,workspace:n.workspace?r?{...n.workspace,...t.workspace}:{...t.workspace,...n.workspace}:t.workspace,runtime:n.runtime?{...t.runtime,...n.runtime}:t.runtime,updatedAt:i})}(t.baseline,e,t.observation,n);case"stop-completed":return Xn.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 Xn.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=ei(e);return t.success?[t.data]:[]})}resolvedAssignedModelEnvironment(e){return this.modelRegistry.resolvedEnvironment(e)}createInstance(e){const t=this.requireRuntime(e.runtimeId),i=jo(),r=e.id||so("inst"),o=tn.parse(e.source),s=e.environmentSource||(e.imageSelection?{type:"image",imageSelection:e.imageSelection}:void 0);if("template"===s?.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"===s?.type?this.environmentTemplates.get(s.environmentTemplateId):void 0;if("template"===s?.type&&(!a||"ready"!==a.status)){const e=new Error(`Environment template ${s.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)&&(!s||"image"===s.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?Cn.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?Cn.parse(e.image):void 0,d="local"===t.type&&"local-folder"===o.type?n.resolve(o.path):void 0,l=Xn.parse({id:r,name:e.name||`instance-${r.replace(/^inst_?/,"").slice(0,6)}`,source:o,sourceSnapshot:e.sourceSnapshot||{},modelSelection:e.modelSelection,projectId:e.projectId,nodeId:this.nodeId,runtimeId:t.id,imageSelection:"image"===s?.type?s.imageSelection:void 0,environmentSource:s,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"!==s?.type?{phase:"checking-image",requestedReference:c.requestedReference,generation:0,startedAt:i,updatedAt:i}:void 0,status:c&&"docker"===t.type&&"template"!==s?.type?"provisioning":"created",health:"unknown",connectionStatus:"unknown",agentStatus:"unknown",targetStatus:"unknown",uiAccessStatus:"unknown",controlMode:"controlled",ready:!1,runtimeVersion:Ro(),capabilities:{},config:{autoImportAgentConfigs:e.config?.autoImportAgentConfigs??!0,defaultCodexPermissionMode:e.config?.defaultCodexPermissionMode??("docker"===t.type?"full-access":"ask")},workspace:"local"===t.type?{mode:"local-bind",status:"unknown",path:d}:{status:"unknown"},target:{strategy:"node-proxy",status:"unknown"},runtime:"local"===t.type?{kind:"local",workspacePath:d,labels:{"task-handoff.runtime-kind":"local"},managedVolumes:[]}:{labels:{},managedVolumes:Fo(r,this.nodeId,o)},registrationToken:ao(),createdAt:i,updatedAt:i}),u=this.controlledInstances.put(l);return this.instancePrivateConfigs.materialize(u.id,u.registrationToken,this.resolvedAssignedModelEnvironment(u.id)),u}registerInstance(e,t,n){const i=oi.parse(t),r=jo(),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;qo(i.protocolVersion,`Instance ${e}`);const s=i.build?.packageVersion||i.instanceVersion,a=Ho(this.requireRuntime(o.runtimeId)),c=Do(o,s,a),d=Xn.parse({...o,status:"registered",health:s===Oo()?"ok":"degraded",ready:!a&&s===Oo(),connectionStatus:"online",agentStatus:"online",targetStatus:"endpoint-unreachable"===i.target.status?"endpoint-unreachable":"reachable"===i.target.status?"reachable":o.targetStatus,uiAccessStatus:"endpoint-unreachable"===i.target.status?"endpoint-unreachable":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,...i.target},registrationToken:o.registrationToken||i.registrationToken,lastHeartbeatAt:r,updatedAt:r});return this.controlledInstances.put(d)}heartbeatInstance(e,t,n){const i=this.requireInstance(e);this.validateInstanceToken(i,n);const r=si.parse(t);i.processIncarnationId&&r.processIncarnationId&&r.processIncarnationId!==i.processIncarnationId&&function(e,t){throw Object.assign(new Error(t),{statusCode:409,code:"INSTANCE_PROCESS_INCARNATION_MISMATCH"})}(0,`Instance ${e} report belongs to an obsolete controlled-instance process.`),qo(r.protocolVersion,`Instance ${e}`);const o=jo(),s=r.target?{...i.target,...r.target}:i.target,a={...s,status:"unknown"===s.status&&(s.web||s.api)?"reachable":s.status},c="endpoint-unreachable"===a.status?"endpoint-unreachable":"reachable"===a.status?"reachable":i.targetStatus,d=Do(i,r.build?.packageVersion||i.build?.packageVersion||i.instanceVersion,Ho(this.requireRuntime(i.runtimeId))),l=r.health||i.health,u="running"===(r.status||i.status)&&"failed"!==l,m=Xn.parse({...i,...r,target:a,ready:u,health:l,runtimeVersion:d,processIncarnationId:r.processIncarnationId||i.processIncarnationId,agentStatus:"online",targetStatus:c,uiAccessStatus:c,connectionStatus:"online",build:r.build||i.build,lastHeartbeatAt:o,updatedAt:o});return this.controlledInstances.put(m)}validateInstanceReport(e,t,n){this.validateInstanceToken(e,n||t.registrationToken),t.instanceId&&t.instanceId!==e.id&&Vo("INSTANCE_ID_MISMATCH",`Instance ${t.instanceId} cannot register as ${e.id}.`),t.nodeId&&t.nodeId!==this.nodeId&&Vo("INSTANCE_NODE_MISMATCH",`Instance ${e.id} belongs to node ${this.nodeId}.`),t.runtimeId&&t.runtimeId!==e.runtimeId&&Vo("INSTANCE_RUNTIME_MISMATCH",`Instance ${e.id} belongs to runtime ${e.runtimeId}.`),t.imageSelection&&t.imageSelection.imageId!==e.imageSelection?.imageId&&Vo("INSTANCE_IMAGE_MISMATCH",`Instance ${e.id} belongs to image ${e.imageSelection?.imageId}.`)}validateInstanceToken(e,t){e.registrationToken&&t===e.registrationToken||Vo("INSTANCE_REGISTRATION_TOKEN_INVALID",`Invalid registration token for instance ${e.id}.`)}context(e,t=this.resolvedAssignedModelEnvironment(e.id)){const n=e.imageSnapshot||Cn.parse({id:"img_localhost",origin:"custom",name:"Localhost",repository:"localhost",tag:"local",requestedReference:"localhost:local",pullPolicy:"if-not-present",capabilities:[],optionalApps:[],defaultEnv:{},labels:{},createdAt:e.createdAt,updatedAt:e.updatedAt}),i=this.instancePrivateConfigs.materialize(e.id,e.registrationToken,t);return{project:Uo(e),image:n,node:this.node,runtime:this.requireRuntime(e.runtimeId),instance:e,nodeAgentUrl:this.containerUrl,modelEnv:t,privateConfigPath:this.instancePrivateConfigs.filePath(i.instanceId)}}}const Jo=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(),Wo=a.z.object({id:a.z.string().trim().min(1).max(120).optional(),name:a.z.string().trim().min(1).max(160),path:a.z.string().trim().min(1).max(4096),defaultImageSelection:at.optional(),labels:a.z.record(a.z.string(),a.z.string()).default({})}).strict(),Yo=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(),Xo=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:at.optional(),environmentSource:ct.optional(),projectId:a.z.string().trim().min(1).max(120).optional(),image:Cn.optional(),source:tn,sourceSnapshot:a.z.record(a.z.string(),a.z.unknown()).default({}),config:a.z.object({autoImportAgentConfigs:a.z.boolean().optional(),defaultCodexPermissionMode:V.optional()}).strict().optional(),modelSelection:Xn.shape.modelSelection}).strict().superRefine((e,t)=>{e.environmentSource&&e.imageSelection&&t.addIssue({code:"custom",path:["environmentSource"],message:"environmentSource and imageSelection are mutually exclusive."}),"template"===e.environmentSource?.type&&e.image&&t.addIssue({code:"custom",path:["image"],message:"Template environment source is resolved by the node-agent and cannot include an image snapshot."})}),Qo=a.z.object({name:a.z.string().trim().min(1).max(160).optional(),config:a.z.object({autoImportAgentConfigs:a.z.boolean().optional(),defaultCodexPermissionMode:V.optional()}).strict().optional(),modelSelection:Xn.shape.modelSelection.optional()}).strict(),Zo=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(),es=Zo.omit({id:!0}).partial().strict();function ts(e){const t=e.authorization;return"string"==typeof t&&t.startsWith("Bearer ")?t.slice(7).trim():void 0}class ns{operations=new Map;intents=new Map;intent(e){const t=this.intents.get(e);if(t)return t;const n={};return this.intents.set(e,n),n}invalidate(e){const t={};return this.intents.set(e,t),t}isIntentCurrent(e,t){return this.intents.get(e)===t}clearIntent(e){this.intents.delete(e)}async run(e,t){const n=this.operations.get(e)||Promise.resolve();let i;const r=new Promise(e=>{i=e});this.operations.set(e,r),await n;try{return await t()}finally{i(),this.operations.get(e)===r&&this.operations.delete(e)}}}const is=a.z.object({}).strict().default({});function rs(){return(new Date).toISOString()}function os(){return(new Date).toISOString()}class ss{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=os();return this.state.controlledInstances.put(Xn.parse({...t,status:"provisioning",health:"unknown",imageProvisioning:{phase:"checking-image",requestedReference:t.imageSnapshot.requestedReference,generation:(t.imageProvisioning?.generation||0)+1,startedAt:n,updatedAt:n},updatedAt:n}))}provision(e,t){if(this.stopped)return Promise.resolve();const n=e.imageProvisioning?.generation;if(void 0===n)return Promise.resolve();const i=`${e.id}:${n}`,r=this.inFlight.get(i);if(r)return r;const 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 r,o=0,s=!1,a=Promise.resolve();try{const c=await this.images.ensure(i.imageSnapshot.requestedReference,n=>{a=a.then(async()=>{if(!r)try{await this.updatePhase(e.id,t,n,e.createdAt)}catch(e){r={error:e}}})},n=>{this.stopped||(s=!0,o=n.sequence,this.publishTerminalOutput(e,t,n))},this.abortController.signal);if(await a,r)throw r.error;if(this.stopped)return;s&&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 r=this.state.controlledInstances.put(Xn.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:os()},updatedAt:os()}));this.options.sync(),this.options.diagnostic({instanceId:e.id,action:"image.provision",reference:c.requestedReference,digest:c.resolvedDigest,pulled:c.pulled},"node instance image provisioning completed"),"starting"===r.status&&await(n?.())};await(this.options.runInstanceOperation?.(e.id,d)??d())}catch(n){if(await a,r&&(n=r.error),this.stopped)return;s&&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(Xn.parse({...n,status:"failed",health:"failed",imageProvisioning:{...n.imageProvisioning,phase:"failed",error:i,updatedAt:os()},updatedAt:os()})),this.options.sync(),this.options.warn({instanceId:e.id,action:"image.provision",reference:n.imageProvisioning.requestedReference,error:i},"node instance image provisioning failed"))};await(this.options.runInstanceOperation?.(e.id,c)??c())}}currentGeneration(e,t,n=!0,i){const r=this.state.controlledInstances.get(e);if(!(!r||i&&r.createdAt!==i||r.imageProvisioning?.generation!==t||n&&!r.imageSnapshot))return r}async updatePhase(e,t,n,i){if(this.stopped)return;const r=async()=>{if(this.stopped)return;const r=this.currentGeneration(e,t,!0,i);r&&["provisioning","starting"].includes(r.status)&&(this.state.controlledInstances.put(Xn.parse({...r,status:"starting"===r.status?"starting":"provisioning",imageProvisioning:{...r.imageProvisioning,phase:n,error:void 0,updatedAt:os()},updatedAt:os()})),this.options.sync())};await(this.options.runInstanceOperation?.(e,r)??r())}eventBase(e,t){return{instanceId:e.id,generation:t,requestedReference:e.imageProvisioning.requestedReference,observedAt:os()}}publishTerminalOutput(e,t,n){for(const[i,r]of function(e,t=6e4){const n=[];for(let i=0;i<e.length;i+=t)n.push(e.slice(i,i+t));return n}(n.data).entries())this.options.publish(xn,{...this.eventBase(e,t),sequence:1e3*n.sequence+i,data:r,...n.replay?{replay:!0}:{}},e.id)}publishFinished(e,t,n,i){this.options.publish(Rn,{...this.eventBase(e,t),sequence:1e3*n,outcome:i},e.id)}}const as=a.z.object({name:a.z.string().trim().min(1).max(160)}).strict();function cs(){return(new Date).toISOString()}function ds(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 ls{templateOperations=new ns;store;privateConfigs;docker;requireInstanceValue;requireRuntimeValue;runInstanceOperationValue;isImageReferencedValue;constructor(e,t,n,i,r,o,s=()=>!1){this.store=e,this.privateConfigs=t,this.docker=n,this.requireInstanceValue=i,this.requireRuntimeValue=r,this.runInstanceOperationValue=o,this.isImageReferencedValue=s}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=as.parse(t),i=this.requireInstanceValue(e),r=this.requireRuntimeValue(i.runtimeId);if("docker"!==r.type)throw Object.assign(new Error(`Runtime ${r.name} does not support environment templates.`),{statusCode:409,code:"ENVIRONMENT_TEMPLATE_RUNTIME_UNSUPPORTED"});if(!i.runtime.containerName)throw Object.assign(new Error(`Instance ${i.id} does not have a Docker container.`),{statusCode:409,code:"ENVIRONMENT_TEMPLATE_CONTAINER_NOT_FOUND"});const o=cs(),s=so("envtpl"),a=`task-handoff/environment-template:${s.toLowerCase().replace(/[^a-z0-9_.-]/g,"-")}`;return this.store.put(zt.parse({id:s,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 r=this.privateConfigs.get(i.id);if(!r)throw Object.assign(new Error(`Instance ${i.id} private configuration is missing.`),{code:"INSTANCE_PRIVATE_CONFIG_MISSING"});const o=[r.instanceCredential,...Object.values(r.environment)];await this.docker.inspectContainerConfigSecurity(n.runtime.containerName,o),e=await this.docker.commitEnvironmentTemplate(n.runtime.containerName,n.runtime.containerId,a),t=!0;const c=await this.docker.inspectEnvironmentTemplateImage(a);return await this.docker.inspectImageConfigSecurity(a,o),this.store.put(zt.parse({...this.require(s),...c,status:"ready",error:void 0,updatedAt:cs()}))}catch(n){return t&&(await this.docker.untagEnvironmentTemplate(a,e).catch(()=>!1),e&&await this.docker.garbageCollectEnvironmentTemplateImage(e).catch(()=>!1)),this.store.put(zt.parse({...this.require(s),status:"failed",error:ds(n,"ENVIRONMENT_TEMPLATE_CREATE_FAILED","commit"),updatedAt:cs()}))}})}async delete(e){return this.runTemplateOperation(e,async()=>{const t=this.require(e);this.store.put(zt.parse({...t,status:"deleting",error:void 0,updatedAt:cs()}));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(zt.parse({...t,status:"failed",error:ds(e,"ENVIRONMENT_TEMPLATE_DELETE_FAILED","delete"),updatedAt:cs()})),e}})}async releaseUnusedImage(e){return!this.store.list().some(t=>t.imageId===e)&&!this.isImageReferencedValue(e)&&this.docker.garbageCollectEnvironmentTemplateImage(e)}}const us=new Set(["DELETE","GET","HEAD","PATCH","POST","PUT","OPTIONS"]);function ms(e){return"string"==typeof e&&us.has(e.toUpperCase())?e.toUpperCase():"GET"}const ps=new Set(["content-encoding","content-length","transfer-encoding"]),gs=67108864;function hs(e){return Object.fromEntries([...e.entries()].filter(([e])=>!ps.has(e.toLowerCase())))}function fs(e){return e.bodyBase64?Buffer.from(e.bodyBase64,"base64"):e.body}function ys(){const e=Number(process.env.TASK_HANDOFF_INSTANCE_PROXY_MAX_RESPONSE_BYTES);return Number.isSafeInteger(e)&&e>0?e:67108864}function Is(e){return e.startsWith("/")?e:`/${e}`}function As(e,t){return e.code(502).send({error:{code:"INSTANCE_PROXY_RESPONSE_TOO_LARGE",message:`Instance response exceeds ${t} bytes.`}})}const bs=a.z.object({version:a.z.literal(1),externalListener:Vn}).strict();function ws(e){return"all-ipv4"===e?"0.0.0.0":"127.0.0.1"}function vs(e){if(!e||"object"!=typeof e||Array.isArray(e))return e;const t=e,n=t.externalListener&&"object"==typeof t.externalListener&&!Array.isArray(t.externalListener)?t.externalListener:{},i=Object.keys(t).filter(e=>"version"!==e&&"externalListener"!==e),r=Object.keys(n).filter(e=>"bindScope"!==e&&"port"!==e);return(i.length||r.length)&&console.warn(JSON.stringify({message:"unknown stored node agent runtime setting fields were ignored",filePath:"runtime-settings.json",fields:[...i,...r.map(e=>`externalListener.${e}`)]})),{version:t.version,externalListener:{bindScope:n.bindScope,port:n.port}}}async function Es(e){const t=ws(e.bindScope);return!await new Promise(t=>{const n=p.createConnection({host:"127.0.0.1",port:e.port}),i=e=>{n.removeAllListeners(),n.destroy(),t(e)};n.once("connect",()=>i(!0)),n.once("error",()=>i(!1)),n.setTimeout(250,()=>i(!1))})&&new Promise(n=>{const i=p.createServer();i.once("error",()=>n(!1)),i.listen({host:t,port:e.port,exclusive:!0},()=>i.close(()=>n(!0)))})}class Ns{app;state;settings;sockets=new Set;config;source;status="error";error;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.app.server.on("connection",e=>{this.sockets.add(e),e.once("close",()=>this.sockets.delete(e))})}current(){return qn.parse({...this.config,host:ws(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:ws(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 ${ws(this.config.bindScope)}:${this.config.port}: ${this.error}`),{statusCode:409,code:"NODE_AGENT_LISTENER_BIND_FAILED"})}return this.current()}update(e){const t=this.updateQueue.then(()=>this.updateOnce(e));return this.updateQueue=t.then(()=>{},()=>{}),t}async updateOnce(e){const t=Hn.parse(e);if(t.bindScope===this.config.bindScope&&t.port===this.config.port)return this.current();if(t.port!==this.config.port){const e=this.state.runningInstanceCount();if(e>0)throw Object.assign(new Error(`Cannot change the node agent port while ${e} controlled instance(s) are running.`),{statusCode:409,code:"NODE_AGENT_LISTENER_PORT_IN_USE_BY_INSTANCES",blockingInstanceCount:e})}const n=this.snapshot();await this.stop();try{await this.listen(t)}catch(e){throw await this.restore(n),Object.assign(new Error(`Failed to bind node agent TCP listener at ${ws(t.bindScope)}:${t.port}: ${e instanceof Error?e.message:String(e)}`),{statusCode:409,code:"NODE_AGENT_LISTENER_BIND_FAILED"})}try{this.settings.put({version:1,externalListener:t})}catch(e){throw await this.stop(),await this.restore(n),Object.assign(new Error(`Failed to persist node agent TCP listener: ${e instanceof Error?e.message:String(e)}`),{statusCode:500,code:"NODE_AGENT_LISTENER_PERSIST_FAILED"})}return this.config=t,this.source="persisted",this.status="listening",this.error=void 0,this.state.setListenerPort(t.port),this.current()}async shutdown(){await this.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)}async listen(e){await new Promise((t,n)=>{const i=e=>{this.app.server.off("listening",r),n(e)},r=()=>{this.app.server.off("error",i),t()};this.app.server.once("error",i),this.app.server.once("listening",r),this.app.server.listen({host:ws(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 zs="TASK_HANDOFF_NODE_AGENT_V1",_s="/api/node-tunnel";function Ss(e=""){return c.createHash("sha256").update(e).digest("hex")}function Ts(e,t){return c.createHmac("sha256",e).update(function(e){return[zs,e.keyId,e.method.toUpperCase(),e.pathWithQuery,e.timestamp,e.nonce,e.bodySha256].join("\n")}(t)).digest("hex")}function ks(e){const t=e.timestamp||(new Date).toISOString(),n=e.nonce||c.randomBytes(18).toString("base64url"),i=Ss(e.body||""),r=Ts(e.secret,{keyId:e.keyId,method:e.method,pathWithQuery:e.pathWithQuery,timestamp:t,nonce:n,bodySha256:i});return{"x-taskhandoff-node-id":e.nodeId,"x-taskhandoff-key-id":e.keyId,"x-taskhandoff-timestamp":t,"x-taskhandoff-nonce":n,"x-taskhandoff-body-sha256":i,"x-taskhandoff-signature":r}}class Cs{usedNonces=new Map;identity;nodeId;overrideSecret;overrideKeyId;nowMs;constructor(e,t,n,i,r=Date.now){this.identity=e,this.nodeId=t,this.overrideSecret=n,this.overrideKeyId=i,this.nowMs=r}hasRemoteSecrets(){return this.identity.remoteSecrets(this.overrideSecret,this.overrideKeyId).length>0}verify(e){const t=function(e){const t=new Map;for(const[n,i]of Object.entries(e)){const e=Array.isArray(i)?i.join(","):"string"==typeof i?i:void 0===i?"":String(i);t.set(n.toLowerCase(),e)}return{nodeId:t.get("x-taskhandoff-node-id")||"",keyId:t.get("x-taskhandoff-key-id")||"",timestamp:t.get("x-taskhandoff-timestamp")||"",nonce:t.get("x-taskhandoff-nonce")||"",bodySha256:t.get("x-taskhandoff-body-sha256")||"",signature:t.get("x-taskhandoff-signature")||""}}(e.headers);if(!t.nodeId&&!t.signature)return!1;const n="DELETE"===e.method&&"/api/node-agent/pairing/current"===e.url.split("?")[0],i=this.identity.remoteSecrets(this.overrideSecret,this.overrideKeyId,n);if(!i.length)return!1;if(t.nodeId!==this.nodeId)throw Object.assign(new Error("Invalid node agent HMAC node id."),{statusCode:401,code:"NODE_AGENT_HMAC_NODE_MISMATCH"});if(!t.keyId)throw Object.assign(new Error("Node agent HMAC key id is missing."),{statusCode:401,code:"NODE_AGENT_HMAC_KEY_MISSING"});const r=i.filter(e=>t.keyId===e.keyId);if(!r.length)throw Object.assign(new Error("Invalid node agent HMAC key id."),{statusCode:401,code:"NODE_AGENT_HMAC_KEY_INVALID"});const o=Date.parse(t.timestamp);if(!Number.isFinite(o)||Math.abs(this.nowMs()-o)>6e4)throw Object.assign(new Error("Node agent HMAC timestamp is outside the allowed window."),{statusCode:401,code:"NODE_AGENT_HMAC_TIMESTAMP_INVALID"});if(!t.nonce)throw Object.assign(new Error("Node agent HMAC nonce is missing."),{statusCode:401,code:"NODE_AGENT_HMAC_NONCE_MISSING"});this.pruneNonces();const s=`${t.nodeId}:${t.keyId}:${t.nonce}`;if(this.usedNonces.has(s))throw Object.assign(new Error("Node agent HMAC nonce was already used."),{statusCode:401,code:"NODE_AGENT_HMAC_NONCE_REPLAY"});const a=Ss(null==(d=e.body)?"":"string"==typeof d||Buffer.isBuffer(d)?d:JSON.stringify(d));var d;if(t.bodySha256!==a)throw Object.assign(new Error("Node agent HMAC body hash mismatch."),{statusCode:401,code:"NODE_AGENT_HMAC_BODY_HASH_INVALID"});if(!r.some(n=>function(e,t){const n=Buffer.from(e,"hex"),i=Buffer.from(t,"hex");return n.length===i.length&&c.timingSafeEqual(n,i)}(t.signature,Ts(n.secret,{keyId:t.keyId,method:e.method,pathWithQuery:e.url,timestamp:t.timestamp,nonce:t.nonce,bodySha256:a}))))throw Object.assign(new Error("Invalid node agent HMAC signature."),{statusCode:401,code:"NODE_AGENT_HMAC_SIGNATURE_INVALID"});return this.usedNonces.set(s,o+6e4+1),t.keyId}pruneNonces(){const e=this.nowMs();for(const[t,n]of this.usedNonces)n<=e&&this.usedNonces.delete(t)}}const Os=a.z.string().trim().min(1).max(160),xs=a.z.string().datetime(),Rs=a.z.string().min(1).max(4096),Ds=a.z.string().trim().url().max(2048),Ps=a.z.object({tokenHash:a.z.string().trim().min(1).max(256),expiresAt:xs,createdAt:xs,controlPlaneName:a.z.string().trim().min(1).max(160).optional()}).strip(),Ms=a.z.object({id:Os,keyId:Os,name:a.z.string().trim().min(1).max(160).optional(),secret:Rs,pairedAt:xs,revokedAt:xs.optional(),updatedAt:xs}).strip(),js=a.z.object({id:Os,pairingKeyId:Os,name:a.z.string().trim().min(1).max(160).optional(),url:Ds,enabled:a.z.boolean().default(!0),createdAt:xs,updatedAt:xs}).strip(),Ls=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(),$s=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(),Fs=a.z.object({controlPlaneUrl:a.z.string().trim().url().max(2048),joinToken:a.z.string().trim().min(1).max(4096),controlPlaneName:a.z.string().trim().min(1).max(160).optional(),activate:a.z.boolean().optional()}).strict();function Us(){return(new Date).toISOString()}const Vs=new Set(["nodeId","createdAt","updatedAt","pairingInvites","controlPlanePairings","controlPlaneConnections","remoteControlPlanes"]),qs=new Set(["tokenHash","expiresAt","createdAt","controlPlaneName"]),Hs=new Set(["id","keyId","name","secret","pairedAt","revokedAt","updatedAt"]),Bs=new Set(["id","pairingKeyId","name","url","enabled","createdAt","updatedAt"]),Ks=new Set(["id","keyId","name","url","secret","pairedAt","updatedAt","active"]);function Gs(e,t){console.warn(JSON.stringify({message:e,...t}))}function Js(e,t){return Object.assign(new Error(e,void 0===t?void 0:{cause:t}),{code:"NODE_AGENT_IDENTITY_INVALID"})}function Ws(e,t){return Object.keys(e).filter(e=>!t.has(e))}function Ys(e,t,n){const i=xs.safeParse(e);return i.success?i.data:(n("invalid node agent identity timestamp was replaced",{field:t}),Us())}function Xs(e,t){if(!e||"object"!=typeof e||Array.isArray(e))throw Js("Node agent identity must be a JSON object.");const n=e,i=Os.safeParse(n.nodeId);if(!i.success)throw Js("Node agent identity has an invalid nodeId.",i.error);const r=i.data,o=Ws(n,Vs);o.length&&t("unknown node agent identity fields were ignored",{fields:o});const s=Array.isArray(n.remoteControlPlanes)?n.remoteControlPlanes.flatMap(e=>{if(!e||"object"!=typeof e||Array.isArray(e))return[];const n=e,i=Ws(n,Ks);i.length&&t("unknown legacy node agent remote control-plane fields were ignored",{fields:i});const r=Ms.safeParse(n);if(!r.success)return t("invalid legacy node agent control-plane pairing was ignored",{issues:r.error.issues}),[];const o=n.url?js.safeParse({id:`connection_${r.data.keyId}`,pairingKeyId:r.data.keyId,name:n.name,url:n.url,enabled:!1!==n.active,createdAt:r.data.pairedAt,updatedAt:r.data.updatedAt}):void 0;return[{pairing:r.data,...o?.success?{connection:o.data}:{}}]}):[],a=(e,n,i,r)=>Array.isArray(e)?e.flatMap(e=>{if(!e||"object"!=typeof e||Array.isArray(e))return t(`invalid node agent ${r} was ignored`,{}),[];const o=Ws(e,n);o.length&&t(`unknown node agent ${r} fields were ignored`,{fields:o});const s=i.safeParse(e);return s.success?[s.data]:(t(`invalid node agent ${r} was ignored`,{issues:s.error.issues}),[])}):[];return{nodeId:r,createdAt:Ys(n.createdAt,"createdAt",t),updatedAt:Ys(n.updatedAt,"updatedAt",t),pairingInvites:Array.isArray(n.pairingInvites)?n.pairingInvites.flatMap(e=>{if(!e||"object"!=typeof e||Array.isArray(e))return t("invalid node agent pairing invite was ignored",{}),[];const n=Ws(e,qs);n.length&&t("unknown node agent pairing invite fields were ignored",{fields:n});const i=Ps.safeParse(e);return i.success?[i.data]:(t("invalid node agent pairing invite was ignored",{issues:i.error.issues}),[])}):[],controlPlanePairings:n.controlPlanePairings?a(n.controlPlanePairings,Hs,Ms,"control-plane pairing"):s.map(e=>e.pairing),controlPlaneConnections:n.controlPlaneConnections?a(n.controlPlaneConnections,Bs,js,"control-plane connection"):s.flatMap(e=>e.connection?[e.connection]:[])}}class Qs{paths;logger;constructor(e,t={}){this.paths=e,this.logger=t.logger||Gs}read(){let e,n;try{e=t.readFileSync(this.paths.identityPath,"utf8")}catch(e){if("ENOENT"===e.code)return;throw Object.assign(new Error(`Node agent identity could not be read: ${this.paths.identityPath}`,{cause:e}),{code:"NODE_AGENT_IDENTITY_READ_FAILED"})}try{n=JSON.parse(e)}catch(e){throw Js(`Node agent identity contains invalid JSON: ${this.paths.identityPath}`,e)}return Xs(n,this.logger)}write(e){t.mkdirSync(n.dirname(this.paths.identityPath),{recursive:!0});const i=Xs({...e,updatedAt:Us()},this.logger);I.sync(this.paths.identityPath,`${JSON.stringify(i,null,2)}\n`,{encoding:"utf8",mode:384})}}function Zs(){return(new Date).toISOString()}class ea{store;controlPlaneConnectionOperations=new Map;constructor(e){this.store=new Qs(e)}async runControlPlaneConnectionOperation(e,t){const n=e.replace(/\/$/,""),i=this.controlPlaneConnectionOperations.get(n)||Promise.resolve();let r;const o=new Promise(e=>{r=e});this.controlPlaneConnectionOperations.set(n,o),await i;try{return await t()}finally{r(),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=so("node");return this.writeNodeId(n),n}createPairingInvite(e){const t=this.prunePairingInvites(this.store.read()||this.newIdentity()),n=Zs(),i=new Date(Date.now()+(e.expiresInMs||6e5)).toISOString(),r=ao(),o={tokenHash:Ss(r),createdAt:n,expiresAt:i,...e.controlPlaneName?{controlPlaneName:e.controlPlaneName}:{}};return this.store.write({...t,pairingInvites:[...t.pairingInvites||[],o]}),{...o,token:r}}completePairingInvite(e){const t=this.prunePairingInvites(this.store.read()||this.newIdentity()),n=Ss(e.joinToken),i=(t.pairingInvites||[]).find(e=>e.tokenHash===n);if(!i){const e=new Error("Node agent pairing invite is invalid or expired.");throw Object.assign(e,{statusCode:401,code:"NODE_AGENT_PAIRING_INVITE_INVALID"}),e}const r=Zs(),o={id:e.controlPlaneId||so("cp"),keyId:so("key"),...e.controlPlaneName||i.controlPlaneName?{name:e.controlPlaneName||i.controlPlaneName}:{},secret:ao(),pairedAt:r,updatedAt:r};return this.store.write({...t,pairingInvites:(t.pairingInvites||[]).filter(e=>e.tokenHash!==n),controlPlanePairings:[...(t.controlPlanePairings||[]).filter(e=>e.id!==o.id),o]}),o}stageControlPlaneConnection(e){const{pairing:t,connection:n}=this.createControlPlaneConnection(e),i=this.store.read()||this.newIdentity(),r=n.url.replace(/\/$/,""),o=(i.controlPlaneConnections||[]).filter(e=>e.id===n.id||e.url.replace(/\/$/,"")===r);return this.store.write({...i,controlPlanePairings:[...(i.controlPlanePairings||[]).filter(e=>e.keyId!==t.keyId),t],controlPlaneConnections:[...(i.controlPlaneConnections||[]).filter(e=>e.id!==n.id&&e.url.replace(/\/$/,"")!==r),n]}),{pairing:t,connection:n,replacedConnections:o}}commitControlPlaneConnection(e,t={}){const n=this.store.read()||this.newIdentity(),i={...e.pairing,...t.name?{name:t.name}:{}},r={...e.connection,...t.name?{name:t.name}:{}},o=new Set((n.controlPlaneConnections||[]).map(e=>e.pairingKeyId)),s=new Set(e.replacedConnections.map(e=>e.pairingKeyId));return this.store.write({...n,controlPlanePairings:[...(n.controlPlanePairings||[]).filter(e=>e.keyId!==i.keyId&&(!s.has(e.keyId)||o.has(e.keyId))),i],controlPlaneConnections:[...(n.controlPlaneConnections||[]).filter(e=>e.id!==r.id),r]}),{pairing:i,connection:r}}rollbackControlPlaneConnection(e){const t=this.store.read();if(!t)return;const n=new Set(e.replacedConnections.map(e=>e.id));this.store.write({...t,controlPlanePairings:(t.controlPlanePairings||[]).filter(t=>t.keyId!==e.pairing.keyId),controlPlaneConnections:[...(t.controlPlaneConnections||[]).filter(t=>t.id!==e.connection.id&&!n.has(t.id)),...e.replacedConnections]})}createControlPlaneConnection(e){const t=Zs(),n={id:so("cp"),keyId:so("key"),...e.name?{name:e.name}:{},secret:ao(),pairedAt:t,updatedAt:t};return{pairing:n,connection:{id:so("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=Zs();return this.store.write({...t,controlPlanePairings:t.controlPlanePairings.map(t=>t.keyId===e?{...t,revokedAt:i,updatedAt:i}:t)}),{keyId:e,revoked:!0,revokedAt:i}}deleteControlPlaneConnection(e){const t=this.store.read();if(!t)return!1;const n=(t.controlPlaneConnections||[]).filter(t=>t.id!==e);return n.length!==(t.controlPlaneConnections||[]).length&&(this.store.write({...t,controlPlaneConnections:n}),!0)}remoteSecrets(e,t,n=!1){return[...(this.store.read()?.controlPlanePairings||[]).filter(e=>n||!e.revokedAt).map(e=>({keyId:e.keyId,secret:e.secret})),...e&&t?[{keyId:t,secret:e}]:[]]}isRevokedPairing(e){return Boolean(this.store.read()?.controlPlanePairings?.some(t=>t.keyId===e&&t.revokedAt))}reverseTunnelSecret(e,t,n){if(t&&n)return{keyId:n,secret:t};const i=this.store.read(),r=(i?.controlPlanePairings||[]).filter(e=>!e.revokedAt);if(!r.length)return;if(e){const t=e.replace(/\/$/,""),n=(i?.controlPlaneConnections||[]).find(e=>e.url.replace(/\/$/,"")===t),o=n&&r.find(e=>e.keyId===n.pairingKeyId);if(o)return{keyId:o.keyId,secret:o.secret}}const o=[...r].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:Zs(),updatedAt:Zs(),pairingInvites:[],controlPlanePairings:[],controlPlaneConnections:[]}}writeNodeId(e){const t=this.store.read();this.store.write({...t||{createdAt:Zs()},nodeId:e,updatedAt:Zs(),pairingInvites:t?.pairingInvites||[],controlPlanePairings:t?.controlPlanePairings||[],controlPlaneConnections:t?.controlPlaneConnections||[]})}prunePairingInvites(e){const t=Date.now();return{...e,pairingInvites:(e.pairingInvites||[]).filter(e=>Date.parse(e.expiresAt)>t)}}}const ta=a.z.string().trim().min(1).max(160);const na=Yt.strict();function ia(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 ra{preflights=new Map;options;constructor(e){this.options=e}async check(e){const t=Gt.parse(e),n=ia(this.options.listInstances()),i=await vo(this.options.runCommand),r=this.options.currentRuntimeVersion(),o="@task-handoff/server"===i.packageName?[...new Set([...i.relatedCurrentVersions,r])]:i.relatedCurrentVersions,s=await async function(e){const t=e.packageName||"@task-handoff/node-agent",n=await async function(e,t,n){const i=function(e){return"stable"===e?"latest":e}(n),r=await e(bo(),["view",`${t}@${i}`,"version","--json"]).catch(e=>{if(!function(e){if(!e||"object"!=typeof e)return!1;const t=e,n=[t.message,t.details?.stdout,t.details?.stderr].filter(e=>"string"==typeof e).join("\n");return/\bE404\b/i.test(n)}(e))throw e});if(!r)return;const o=JSON.parse(r.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 Jt.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:Io()})}({channel:e.channel,currentVersion:e.currentVersion,impact:e.impact});const i=Ao(e.currentVersion,n)||(e.relatedCurrentVersions||[]).some(e=>Ao(e,n)),r=i?await async function(e,t,n){const i=await e(bo(),["view",`${t}@${n}`,"dist.integrity","--json"]),r=JSON.parse(i.stdout);if("string"!=typeof r||!/^sha(?:256|384|512)-[A-Za-z0-9+/=]+$/.test(r))throw Object.assign(new Error(`npm did not return immutable integrity metadata for ${t}@${n}.`),{statusCode:502,code:"NODE_UPDATE_PREFLIGHT_FAILED",retryable:!0});return r}(e.runCommand,t,n):void 0;return Jt.parse({source:"npm",channel:e.channel,currentVersion:e.currentVersion,availableVersion:n,...r?{artifactRef:`npm:${t}@${n}#${r}`}:{},runtimeArtifacts:e.runtimeArtifacts||[],impact:e.impact||{runningInstanceCount:0,stoppedInstanceCount:0,activeInstanceCount:0,restartInstanceCount:0,runningInstanceIds:[],stoppedInstanceIds:[],activeInstanceIds:[]},updateAvailable:i,checkedAt:Io()})}({channel:t.channel,currentVersion:i.currentVersion||r,runCommand:this.options.runCommand,packageName:i.packageName,relatedCurrentVersions:o,impact:n});if(!s.updateAvailable)return s;const a={...s,runtimeArtifacts:await this.options.resolveRuntimeArtifacts(s.availableVersion),preflightToken:ao()};return this.preflights.set(a.preflightToken,{result:a,expiresAt:Date.now()+6e5}),a}async apply(e){const i=na.parse(e),r=await this.consumePreflight(i);if(!r.supported)throw Object.assign(new Error(r.reason||"The requested update is not supported."),{statusCode:400,code:"UPDATE_UNSUPPORTED"});if(!r.updateAvailable)throw Object.assign(new Error(r.reason||"No update is available for the selected channel."),{statusCode:409,code:"UPDATE_NOT_AVAILABLE"});const o=this.options.jobs.create(this.options.nodeId,r),{worker:s,packaged:a,expectedWorker:c}=function(e,i=t.existsSync){const r=[n.resolve(e,"..","bin","task-handoff-node-update-worker"),n.resolve(e,"..","..","bin","task-handoff-node-update-worker")],o=r.find(i),s=n.resolve(e,"..","..","..","..","scripts","node-update-worker.cjs");return o?{worker:o,packaged:!0,expectedWorker:r[0]}:i(s)?{worker:s,packaged:!1,expectedWorker:r[0]}:{worker:void 0,packaged:!1,expectedWorker:r[0]}}(this.options.moduleDir);if(!s)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?[s]:[process.execPath,s],"--job-file",this.options.jobs.records.filePath(o.id),"--target-version",o.toVersion,"--npm-command",bo(),...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 o}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 vo(this.options.runCommand);n.channel===e.channel&&n.availableVersion===e.targetVersion&&n.currentVersion===(i.currentVersion||this.options.currentRuntimeVersion())&&!0===n.artifactRef?.startsWith(`npm:${i.packageName}@`)&&JSON.stringify(n.impact)===JSON.stringify(ia(this.options.listInstances()))||this.throwStale();const r=await this.options.resolveRuntimeArtifacts(n.availableVersion);return JSON.stringify(n.runtimeArtifacts)!==JSON.stringify(r)&&this.throwStale(),n}throwStale(){throw Object.assign(new Error("The update target or affected instances changed after preflight. Check for updates again."),{statusCode:409,code:"UPDATE_PREFLIGHT_STALE"})}}const oa=new Set(["provisioning","starting","registering","registered","running"]);function sa(e){return Xn.parse({...e,health:"unknown",connectionStatus:"offline",agentStatus:"offline",targetStatus:"unknown",uiAccessStatus:"unknown",target:{...e.target,status:"unknown"},updatedAt:(new Date).toISOString()})}class aa{options;restoredInstances=new Set;restoreErrors=new Map;unexpectedExitRetries=new Map;suppressedInstances=new Set;pendingUnexpectedExits=new Map;activeRestores=new Map;timer;activeCycle;cycleRequested=!1;cycleRequestDelayMs;started=!1;stopped=!1;constructor(e){this.options=e}markRestored(e){const t=this.options.state.requireInstance(e).status;return!["failed","stopping","stopped"].includes(t)&&(this.restoredInstances.add(e),this.restoreErrors.delete(e),!0)}allowRecovery(e){this.suppressedInstances.delete(e);const t=this.pendingUnexpectedExits.get(e);void 0!==t&&(this.pendingUnexpectedExits.delete(e),this.applyUnexpectedLocalExit(e,t))}completeSuppressedOperation(e){this.pendingUnexpectedExits.delete(e),this.restoredInstances.delete(e),this.restoreErrors.delete(e),this.unexpectedExitRetries.delete(e)}forgetInstance(e){this.restoredInstances.delete(e),this.restoreErrors.delete(e),this.unexpectedExitRetries.delete(e),this.suppressedInstances.delete(e),this.activeRestores.delete(e),this.pendingUnexpectedExits.delete(e)}async suppressRecovery(e){this.suppressedInstances.add(e),await(this.activeRestores.get(e)?.catch(()=>{}))}handleUnexpectedLocalExit(e,t){this.stopped||(this.suppressedInstances.has(e)?this.pendingUnexpectedExits.set(e,t):this.applyUnexpectedLocalExit(e,t))}applyUnexpectedLocalExit(e,t){const n=this.options.state.requireInstance(e);if("local"!==this.options.state.requireRuntime(n.runtimeId).type)return;this.restoredInstances.delete(e);const i=this.options.nowMs?.()??Date.now(),r=this.unexpectedExitRetries.get(e),o=this.options.crashStableWindowMs??3e4,s=r&&i-r.lastExitAt<o?r.attempt+1:1;this.unexpectedExitRetries.set(e,{attempt:s,lastExitAt:i});const a=this.options.retryBaseDelayMs??1e3,c=1===s?0:Math.min(this.options.retryMaxDelayMs??3e4,a*2**Math.min(s-2,10)),d=t instanceof Error?t.message:String(t);this.restoreErrors.set(e,{message:d,attempt:s,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(oa.has(t.status)||"failed"===t.status)&&(!e||e.nextAttemptAt<=(this.options.nowMs?.()??Date.now()))}return"docker"===n.type&&(oa.has(t.status)||"provisioning"===t.status&&"ready"===t.imageProvisioning?.phase)});await Promise.all(t.map(async t=>{if(this.stopped)return;const n=async()=>{if(this.stopped)return;const n=e.listInstances().find(e=>e.id===t.id);if(!n)return;if(!this.isRestoreCandidate(n))return;const i=this.restoreErrors.get(n.id);try{const t=this.options.restoreInstance(n.id);this.activeRestores.set(n.id,t);try{await t}finally{this.activeRestores.get(n.id)===t&&this.activeRestores.delete(n.id)}if(this.stopped||this.suppressedInstances.has(n.id))return;if(await this.options.autoImport(e.requireInstance(n.id)),this.stopped||this.suppressedInstances.has(n.id))return;if(this.restoreErrors.get(n.id)!==i)return;if(!this.markRestored(n.id))throw new Error(`Restored instance ${n.id} did not reach a recoverable running state.`)}catch(t){if(this.stopped||this.suppressedInstances.has(n.id))return;"local"===e.requireRuntime(n.runtimeId).type&&e.applyInstanceLifecycle(n.id,{type:"start-failed",error:t});const i=t instanceof Error?t.message:String(t),r=this.restoreErrors.get(n.id),o=(r?.attempt??0)+1,s=this.options.retryBaseDelayMs??1e3,a=Math.min(this.options.retryMaxDelayMs??3e4,s*2**Math.min(o-1,10)),c=(this.options.nowMs?.()??Date.now())+a;this.restoreErrors.set(n.id,{message:i,attempt:o,nextAttemptAt:c}),r?.message===i&&r.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(oa.has(e.status)||"failed"===e.status)&&(!t||t.nextAttemptAt<=(this.options.nowMs?.()??Date.now()))}return"docker"===t.type&&(oa.has(e.status)||"provisioning"===e.status&&"ready"===e.imageProvisioning?.phase)}async recoverManagedInstances(){if(this.stopped)return;const{state:e,convergence:t}=this.options,n=e.listInstances().filter(e=>this.options.usesManagedArtifact(e)&&!t.isRunning(e.id)&&(this.restoredInstances.has(e.id)||"unknown"!==e.target.status)&&(!e.ready||"matched"!==e.runtimeVersion?.phase)&&!["created","stopped","failed","provisioning","stopping"].includes(e.status));await Promise.all(n.map(async e=>{if(!this.stopped)try{await t.schedule(e.id)}catch(t){this.options.error({instanceId:e.id,error:t},"runtime convergence recovery failed")}}))}start(){this.started||this.stopped||(this.started=!0,this.runAndContinue())}async stop(){this.stopped=!0,this.timer&&clearTimeout(this.timer),this.timer=void 0;const e=this.options.stopImageProvisioning(),t=this.options.state.listInstances().map(e=>this.options.convergence.cancel(e.id));await Promise.all(t),await this.activeCycle,await e,await this.options.runtimeAdapters.stopAll();for(const e of this.options.state.listInstances())"local"===this.options.state.requireRuntime(e.runtimeId).type&&this.options.state.controlledInstances.put(sa(e))}async runCycle(){await this.restoreManagedInstances(),this.stopped||await this.recoverManagedInstances()}runAndContinue(){if(this.stopped)return;const e=this.runCycle().catch(e=>this.options.error({error:e},"node agent startup recovery cycle failed"));this.activeCycle=e,e.finally(()=>{this.activeCycle===e&&(this.activeCycle=void 0),this.cycleRequested?(this.cycleRequested=!1,this.cycleRequestDelayMs=void 0,this.scheduleNext()):this.scheduleNext()})}scheduleNext(){if(this.stopped)return;const e=this.options.nowMs?.()??Date.now(),t=new Map(this.options.state.listInstances().map(e=>[e.id,e])),n=[...this.restoreErrors.entries()].reduce((e,[n,i])=>{const r=t.get(n);return!r||this.restoredInstances.has(n)||this.suppressedInstances.has(n)||"local"!==this.options.state.requireRuntime(r.runtimeId).type?e:oa.has(r.status)||"failed"===r.status?Math.min(e,i.nextAttemptAt):e},Number.POSITIVE_INFINITY),i=Math.min(this.options.intervalMs??1e4,Math.max(0,n-e));this.timer=setTimeout(()=>{this.timer=void 0,this.runAndContinue()},i),this.timer.unref?.()}requestCycle(e=0){if(this.started&&!this.stopped){if(this.activeCycle)return this.cycleRequested=!0,void(this.cycleRequestDelayMs=void 0===this.cycleRequestDelayMs?e:Math.min(this.cycleRequestDelayMs,e));this.timer&&clearTimeout(this.timer),this.timer=setTimeout(()=>{this.timer=void 0,this.runAndContinue()},e),this.timer.unref?.()}}}function ca(e){return e.readyState===(e.OPEN??1)}function da(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 la(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 ua(e,t,n){e.close(la(t),da(n)||void 0)}function ma(e,t,n,i){if(ca(e))for(const e of t.splice(0))if(i(e),!n(e))return}function pa(e,t){const n=new URL(t.tunnelUrl);n.searchParams.set("nodeId",t.nodeId);const i=t.secret?ks({nodeId:t.nodeId,keyId:t.keyId,secret:t.secret,method:"GET",pathWithQuery:`${n.pathname}${n.search}`}):{},r=new u(n,{headers:i}),o=new Map,s=new Map,a=new Map;let c,d,l=!0;r.on("error",i=>{e.log.warn({nodeId:t.nodeId,tunnelUrl:`${n.origin}${n.pathname}`,error:i instanceof Error?i.message:String(i)},"node agent reverse tunnel connection failed")});const m=e=>{const n=e.startsWith("/")?e:`/${e}`,i="function"==typeof t.port?t.port():t.port,r=new URL(`/api/node-agent${n}`,`http://127.0.0.1:${i}`);return r.protocol="ws:",r},p=(e,n,i,r={})=>{const o=e.startsWith("/")?e:`/${e}`;return{...r,...t.secret&&t.keyId?ks({nodeId:t.nodeId,keyId:t.keyId,secret:t.secret,method:n,pathWithQuery:`/api/node-agent${o}`,body:i}):t.token?{authorization:`Bearer ${t.token}`}:{}}},g=e=>t.secret?ks({nodeId:t.nodeId,keyId:t.keyId,secret:t.secret,method:"GET",pathWithQuery:`${e.pathname}${e.search}`}):{},h=(e,t,n)=>{const i=o.get(e);o.delete(e),i?.upstream&&ua(i.upstream,t,n),i?.tunnel&&ua(i.tunnel,t,n)},f=(e,t,n=!1)=>new Promise((i,r)=>{e.send(t,{binary:n},e=>e?r(e):i())});r.on("open",()=>{r.send(JSON.stringify({type:"node-agent.identify",nodeId:t.nodeId,serverTime:(new Date).toISOString()})),c=e.nodeAgentEventForwarder?.addOutput(r),d=setInterval(()=>{l?(l=!1,r.ping()):r.terminate()},25e3),d.unref?.()}),r.on("pong",()=>{l=!0}),r.on("close",()=>{d&&clearInterval(d),d=void 0;for(const e of o.keys())h(e,1001,"Reverse tunnel disconnected.");for(const[e,t]of s)s.delete(e),t.controller.abort(),ua(t.tunnel,1001,"Reverse tunnel disconnected.");for(const[e,t]of a)a.delete(e),t.abort();c?.(),c=void 0});return r.on("message",i=>{(async i=>{let c;try{c=JSON.parse(String(i))}catch{return void r.send(JSON.stringify({type:"node-agent.error",code:"INVALID_JSON"}))}const d=c&&"object"==typeof c?c:{};if("control-plane.http.open"===d.type){const i="string"==typeof d.streamId?d.streamId:"",o="string"==typeof d.route&&d.route.startsWith("/")?d.route:"/health",a=d.init&&"object"==typeof d.init?d.init:{},c=a.headers&&"object"==typeof a.headers?a.headers:{},l=ms(a.method);let m;try{m=Xe(a.body)}catch(n){return e.log.warn({nodeId:t.nodeId,messageType:d.type,streamId:i,error:n instanceof Error?n.message:String(n)},"node agent reverse tunnel request body rejected"),void r.send(JSON.stringify({type:"node-agent.error",code:"NODE_TUNNEL_REQUEST_BODY_INVALID",streamId:i}))}const h=new AbortController,y=(e=>{const t=new URL(n);return t.pathname=`${t.pathname.replace(/\/$/,"")}/http-streams/${encodeURIComponent(e)}`,t})(i),I=new u(y,{headers:g(y)});return s.set(i,{tunnel:I,controller:h}),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:l,headers:p(o,l,m,c),body:Buffer.isBuffer(m)?new Uint8Array(m):m,signal:h.signal});if(await f(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 f(I,Buffer.from(n),!0)}}await f(I,JSON.stringify({type:"node-agent.http.end",streamId:i})),I.close(1e3,"HTTP stream completed.")}catch(e){I.readyState===u.OPEN&&(await f(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{s.delete(i)}}),I.on("close",()=>{h.abort(),s.delete(i)}),void I.on("error",()=>h.abort())}if("control-plane.http.cancel"===d.type){const e="string"==typeof d.streamId?d.streamId:"",t=s.get(e);if(!t)return;return s.delete(e),t.controller.abort(),void ua(t.tunnel,1e3,"string"==typeof d.reason?d.reason:"HTTP stream canceled.")}if("control-plane.websocket.open"===d.type){const e="string"==typeof d.streamId?d.streamId:"",t="string"==typeof d.route?d.route:"",i=Array.isArray(d.protocols)?d.protocols.filter(e=>"string"==typeof e):void 0;try{const s=p(t,"GET",void 0),a=i?.length?new u(m(t),i,{headers:s}):new u(m(t),{headers:s}),c=(e=>{const t=new URL(n);return t.pathname=`${t.pathname.replace(/\/$/,"")}/streams/${encodeURIComponent(e)}`,t})(e),d=new u(c,{headers:g(c)});o.set(e,{upstream:a,tunnel:d,close:(e=1e3,t="")=>{ua(a,e,t),ua(d,e,t)}}),a.on("open",()=>{r.send(JSON.stringify({type:"node-agent.websocket.open",streamId:e,protocol:a.protocol}))}),function(e,t,n={}){const i=n.pendingFrameLimit??256,r=n.maxFrameBytes??8388608,o=n.maxTotalBytes??1073741824,s=n.maxBufferedBytes??16777216;let a=!1,c=ca(t);const d=[],l=[];let u,m=0,p=0,g=0;const h=e=>Buffer.isBuffer(e)||e instanceof ArrayBuffer||ArrayBuffer.isView(e)?e.byteLength:Buffer.byteLength("string"==typeof e?e:String(e),"utf8"),f=(i,s)=>{const a=h(s);return g+=a,n.onFrame?.(i,a),!(a>r||g>o)||(ua(e,1009,"WebSocket bridge traffic limit exceeded."),ua(t,1009,"WebSocket bridge traffic limit exceeded."),!1)},y=()=>{u&&(clearTimeout(u),u=void 0)},I=(n,i)=>{const r=i.bytes;if((n.bufferedAmount??0)+r>s)return ua(e,1013,"WebSocket bridge consumer is too slow."),ua(t,1013,"WebSocket bridge consumer is too slow."),!1;try{return function(e,t){e.send(t.data,{binary:t.isBinary})}(n,i),!0}catch{return ua(e,1011,"WebSocket bridge send failed."),ua(t,1011,"WebSocket bridge send failed."),!1}},A=(n,r,o)=>{if(r.length>=i)return ua(e,1011,"WebSocket bridge pending frame limit exceeded."),void ua(t,1011,"WebSocket bridge pending frame limit exceeded.");const a="upstream"===n?m:p;if((("upstream"===n?t:e).bufferedAmount??0)+a+o.bytes>s)return ua(e,1013,"WebSocket bridge consumer is too slow."),void ua(t,1013,"WebSocket bridge consumer is too slow.");r.push(o),"upstream"===n?m+=o.bytes:p+=o.bytes};n.upstreamOpenTimeoutMs&&!c&&(u=setTimeout(()=>{c||a||(ua(e,1011,"Upstream websocket did not open."),ua(t))},n.upstreamOpenTimeoutMs)),e.on("open",()=>ma(e,l,t=>I(e,t),e=>{p-=e.bytes})),t.on("open",()=>{y(),c=!0,n.onUpstreamOpen?.(),ma(t,d,e=>I(t,e),e=>{m-=e.bytes})}),e.on("message",(e,n=!1)=>{if(!f("client-to-upstream",e))return;const i={data:e,isBinary:Boolean(n),bytes:h(e)};ca(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:h(t)};ca(e)?I(e,i):A("client",l,i)}),t.on("close",(t,i)=>{y(),n.onUpstreamClose?.(t,i),(c||a||!n.onUpstreamCloseBeforeOpen?.())&&ua(e,t,i)}),t.on("error",t=>{n.onUpstreamError?.(t),(c||a||!n.onUpstreamErrorBeforeOpen?.(t))&&ua(e)}),e.on("close",(e,i)=>{y(),a=!0,n.onClientClose?.(e,i),ua(t,e,i)}),e.on("error",e=>{y(),a=!0,n.onClientError?.(e),ua(t,1011,"WebSocket bridge client failed.")})}(d,a,{pendingFrameLimit:256,upstreamOpenTimeoutMs:1e4,onClientClose:()=>{o.delete(e)},onClientError:t=>{o.delete(e),r.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=la(t),s=da(n);r.send(JSON.stringify({type:"node-agent.websocket.close",streamId:e,...void 0===i?{}:{code:i},...s?{reason:s}:{}}))},onUpstreamError:t=>{o.delete(e),r.send(JSON.stringify({type:"node-agent.websocket.error",streamId:e,message:t instanceof Error?t.message:String(t)}))}})}catch(t){r.send(JSON.stringify({type:"node-agent.websocket.error",streamId:e,message:t instanceof Error?t.message:String(t)}))}return}if("control-plane.websocket.close"===d.type){const e="string"==typeof d.streamId?d.streamId:"";return void h(e,"number"==typeof d.code?d.code:1e3,"string"==typeof d.reason?d.reason:"")}if("control-plane.request.cancel"===d.type){const e="string"==typeof d.requestId?d.requestId:"";return a.get(e)?.abort(),void a.delete(e)}if("control-plane.request"===d.type){const n="string"==typeof d.requestId?d.requestId:"",i=d.init&&"object"==typeof d.init?d.init:{},o="string"==typeof d.route&&d.route.startsWith("/")?d.route:"/health",s=i.headers&&"object"==typeof i.headers?i.headers:{},c=ms(i.method);let l;try{l=Xe(i.body)}catch(i){return e.log.warn({nodeId:t.nodeId,messageType:d.type,requestId:n,error:i instanceof Error?i.message:String(i)},"node agent reverse tunnel request body rejected"),void r.send(JSON.stringify({type:"node-agent.response",requestId:n,status:400,error:{code:"NODE_TUNNEL_REQUEST_BODY_INVALID",message:"Reverse tunnel request body does not match the negotiated protocol."}}))}const u=new AbortController;a.set(n,u);try{const t=await e.inject({method:c,url:`/api/node-agent${o}`,headers:p(o,c,l,s),payload:l,signal:u.signal});if(u.signal.aborted)return;r.send(JSON.stringify({type:"node-agent.response",requestId:n,status:t.statusCode,headers:t.headers,body:t.body}))}catch(e){if(u.signal.aborted)return;r.send(JSON.stringify({type:"node-agent.response",requestId:n,status:502,error:{code:"NODE_AGENT_REVERSE_INJECT_FAILED",message:e instanceof Error?e.message:String(e)}}))}finally{a.delete(n)}}})(i).catch(n=>{e.log.warn({nodeId:t.nodeId,error:n instanceof Error?n.message:String(n)},"node agent reverse tunnel message rejected");try{r.send(JSON.stringify({type:"node-agent.error",code:"INVALID_TUNNEL_MESSAGE"}))}catch{}})}),r}function ga(e){const t=new URL(_s,e);return t.protocol="https:"===t.protocol?"wss:":"ws:",t.toString()}const ha=new Set(["linux","darwin","win32","freebsd","openbsd","aix","sunos"]);function fa(e){return ha.has(e)?e:"unknown"}function ya(e){return!0===e.managedArtifacts}class Ia{managedArtifacts=!0;executor;runCommand;platform;arch;constructor(e,t,n,i){this.executor=e,this.runCommand=t,this.platform=n,this.arch=i}artifactTarget(e){return this.executor.inspectRuntimeTarget(e?.instance.runtime.containerName)}async installRuntime(e,t){const n=e.instance.runtime.containerName;if(!n)throw Object.assign(new Error(`Instance ${e.instance.id} does not have a Docker container.`),{code:"INSTANCE_RUNTIME_INSTALL_FAILED"});await this.executor.installRuntimeLauncher(n),await this.executor.installRuntimeRelease({containerName:n,expectedContainerId:e.instance.runtime.containerId,artifactPath:t.archivePath,identity:t.identity})}async inspectRuntime(e,t){const n=e.instance.runtime.containerName;return!!n&&function(e,t){return e.packageName===t.packageName&&e.version===t.version&&e.platform===t.platform&&e.arch===t.arch&&e.formatVersion===t.formatVersion&&e.launcherAbi===t.launcherAbi&&e.entrypoint===t.entrypoint&&e.sha256===t.sha256}(await this.executor.inspectRuntimeVersion(n),t)}start(e){return this.executor.start(e)}stop(e){return this.executor.stop(e)}restart(e){return this.executor.restart(e,e.instance.runtime.containerId)}delete(e,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:fa(this.platform),...t?{serverVersion:t}:{}}}}}catch(t){return{status:"offline",capabilities:{...e.capabilities,daemon:{status:"offline",hostPlatform:fa(this.platform),error:t instanceof Error?t.message:String(t)}}}}}}class Aa{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(ya)}async stopAll(){await(this.local.stopAll?.())}}const ba="task-handoff.local-process-nonce",wa=1e3;function va(e){return e.runtime.port?`http://127.0.0.1:${e.runtime.port}`:e.target.web}async function Ea(e,t){try{const n=await fetch(`${e}/api/internal/node-agent/process-identity`,{headers:{authorization:`Bearer ${t}`},signal:AbortSignal.timeout(wa)});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 Na(e,t){if(vr(e)!==t)return!1;try{process.kill(e,"SIGTERM")}catch{return!0}const n=Date.now()+3e3;for(;Date.now()<n;){try{process.kill(e,0)}catch{return!0}await new Promise(e=>setTimeout(e,50))}try{process.kill(e,"SIGKILL")}catch{}const i=Date.now()+1e3;for(;Date.now()<i;){try{process.kill(e,0)}catch{return!0}await new Promise(e=>setTimeout(e,50))}return!1}function za(e,t){return Object.assign(new Error(t),{statusCode:503,code:"LOCAL_INSTANCE_STOP_UNCONFIRMED",instanceId:e.id})}async function _a(e){return!await function(e){return new Promise(t=>{const n=p.createConnection({host:"127.0.0.1",port:e}),i=e=>{n.removeAllListeners(),n.destroy(),t(e)};n.once("connect",()=>i(!0)),n.once("error",()=>i(!1)),n.setTimeout(250,()=>i(!1))})}(e)&&new Promise(t=>{const n=p.createServer();n.once("error",()=>t(!1)),n.listen({host:"127.0.0.1",port:e,exclusive:!0},()=>n.close(()=>t(!0)))})}const Sa=_a;function Ta(e,t=3e3){return null!==e.exitCode||null!==e.signalCode?Promise.resolve():new Promise(n=>{const i=setTimeout(()=>{null===e.exitCode&&null===e.signalCode&&e.kill("SIGKILL"),n()},t);i.unref(),e.once("exit",()=>{clearTimeout(i),n()})})}class ka{children=new Map;readyChildren=new WeakSet;expectedExits=new WeakSet;lockPath;onUnexpectedExit;onUnexpectedExitError;constructor(e,t,n){this.lockPath=e,this.onUnexpectedExit=t,this.onUnexpectedExitError=n}track(e,t){this.children.set(e,t),t.once("exit",(n,i)=>{if(this.release(e,t),this.readyChildren.has(t)&&!this.expectedExits.has(t)){const r={instanceId:e,pid:t.pid,code:n,signal:i},o=e=>{try{this.onUnexpectedExitError?.(e,r)}catch{}};try{Promise.resolve(this.onUnexpectedExit?.(r)).catch(o)}catch(e){o(e)}}})}markReady(e,t){return this.children.get(e)===t&&null===t.exitCode&&null===t.signalCode&&(this.readyChildren.add(t),!0)}release(e,t){this.children.get(e)===t&&this.children.delete(e)}async stop(e){const t=this.children.get(e.id);if(t)return this.expectedExits.add(t),t.killed||t.kill("SIGTERM"),this.children.delete(e.id),void await Ta(t);const i=await async function(e){const t=va(e),n=e.runtime.labels?.[ba];if(!t||!n||!e.registrationToken)return;const i=await Ea(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(wa)})).ok?i:void 0}catch{return}}(e);if(i){const t=va(e),n=Date.now()+3e3;for(;t&&Date.now()<n;){if(!await Ea(t,e.registrationToken))return;await new Promise(e=>setTimeout(e,50))}const r=t?await Ea(t,e.registrationToken):void 0;if(r&&r.instanceId===i.instanceId&&r.pid===i.pid&&r.processNonce===i.processNonce&&r.startIdentity===i.startIdentity&&r.startIdentity&&await Na(r.pid,r.startIdentity))return;throw za(e,`Controlled instance ${e.id} accepted shutdown but its exit could not be confirmed.`)}const r=function(e=function(){const e="win32"===process.platform?m.tmpdir():"/tmp";return n.join(e,`task-handoff-local-controlled-instance-${function(){const e=process.getuid?.();return void 0!==e?String(e):m.userInfo().username.replace(/[^a-zA-Z0-9_.-]/g,"_")}()}.lock`)}()){return Er(e)}(this.lockPath),o=await async function(e){const t=va(e);if(t)try{const[n,i]=await Promise.all([fetch(`${t}/api/instance/status`,{signal:AbortSignal.timeout(wa)}),fetch(`${t}/api/diagnostics`,{signal:AbortSignal.timeout(wa)})]);if(!n.ok||!i.ok)return;const r=await n.json(),o=await i.json(),s=o.data?.runtime?.pid;if(r.data?.id!==e.id||"controlled"!==r.data.controlMode||"number"!=typeof s||!Number.isInteger(s)||s<=0)return;const a=vr(s);return a?{pid:s,startIdentity:a}:void 0}catch{return}}(e);if(o){if(await Na(o.pid,o.startIdentity))return;throw za(e,`Legacy controlled instance ${e.id} did not exit after termination.`)}if(r?.instanceId===e.id&&_r(r))throw za(e,`Local controlled instance ${e.id} is still owned by pid ${r.pid}, but its process identity could not be verified.`)}async waitUntilHealthy(e,t,n,i,r=3e3){const o=Date.now()+r;for(;Date.now()<o;){if(null!==n.exitCode||null!==n.signalCode)return!1;const r=await Ea(e,i);if(r&&r.instanceId===t.instanceId&&r.pid===t.pid&&r.processNonce===t.processNonce&&r.startIdentity===t.startIdentity)return!0;await new Promise(e=>setTimeout(e,100))}return!1}async stopAll(){const e=Array.from(this.children.values());for(const t of e)this.expectedExits.add(t),t.killed||t.kill("SIGTERM");this.children.clear(),await Promise.all(e.map(e=>Ta(e)))}}async function Ca(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 Oa{runCommand;paths;nodeAgentUrl;processSupervisor;commandOverride;lockPath;constructor(e,t,n,i,r,o,s){this.runCommand=e,this.paths=t,this.nodeAgentUrl=n,this.commandOverride=i,this.lockPath=r,this.processSupervisor=new ka(r,o,s)}async start(e){await this.processSupervisor.stop(e.instance);const i=function(e){if("local-folder"!==e.source.type){const e=new Error("Localhost runtime currently supports local folder sources only.");throw Object.assign(e,{statusCode:400,code:"LOCAL_RUNTIME_REQUIRES_LOCAL_FOLDER"}),e}return n.resolve(e.source.path)}(e.instance),r=e.instance.runtime.port,o=!!r&&await _a(r),s="allocate"===process.env.TASK_HANDOFF_LOCAL_INSTANCE_PORT_CONFLICT;if(r&&!o&&!s)throw Object.assign(new Error(`Local controlled instance port 127.0.0.1:${r} is already in use.`),{statusCode:409,code:"LOCAL_INSTANCE_PORT_IN_USE"});const a=r&&o?r:await async function(){const e=Number(process.env.TASK_HANDOFF_LOCAL_INSTANCE_PORT_START||19e3),t=Number.isInteger(e)&&e>0?e:19e3;for(let e=t;e<t+1e3&&e<=65535;e+=1)if(await Sa(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"})}(),l=n.join(this.paths.dataDir,"local-instances",e.instance.id),u=n.join(l,"logs");t.mkdirSync(u,{recursive:!0});const[m,...p]=function(e){if(e)return e;const i=n.resolve(process.cwd(),"bin","task-handoff.js");if(t.existsSync(i))return[process.execPath,i,"web"];throw Object.assign(new Error("The bundled controlled-instance command is unavailable."),{statusCode:500,code:"LOCAL_CONTROLLED_COMMAND_MISSING"})}(this.commandOverride),g=[...p,"--host","127.0.0.1","--port",String(a)],h=c.randomUUID(),f=t.openSync(n.join(u,"controlled-instance.out.log"),"a"),y=t.openSync(n.join(u,"controlled-instance.err.log"),"a"),I=d.spawn(m,g,{cwd:i,detached:!1,stdio:["ignore",f,y],env:{...process.env,TASK_HANDOFF_CONTROL_MODE:"controlled",TASK_HANDOFF_RUNTIME_KIND:"local",TASK_HANDOFF_CONTROLLED_INSTANCE_VERSION:Oo(),...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:h,TASK_HANDOFF_WORKSPACE:i,TASK_HANDOFF_WORKSPACE_MODE:"local-bind",TASK_HANDOFF_DATA_DIR:l,TASK_HANDOFF_LOG_DIR:u,TASK_HANDOFF_APP_SESSION_PERSIST:"1",TASK_HANDOFF_CODEX_APP_SERVER:process.env.TASK_HANDOFF_CODEX_APP_SERVER||"1",TASK_HANDOFF_WEB_PORT:String(a),TASK_HANDOFF_WEB_HOST:"127.0.0.1",...e.modelEnv||{}}});t.closeSync(f),t.closeSync(y);try{await function(e){return new Promise((t,n)=>{const i=()=>{e.off("error",r),t()},r=t=>{e.off("spawn",i),n(t)};e.once("spawn",i),e.once("error",r)})}(I)}catch(e){const r=e instanceof Error?e.message:String(e);try{t.appendFileSync(n.join(u,"controlled-instance.lifecycle.log"),`[${(new Date).toISOString()}] spawn failed command=${m} cwd=${i} error=${r}\n`)}catch{}throw Object.assign(new Error(`Controlled instance process could not start with command ${m} in ${i}: ${r}`),{statusCode:500,code:"LOCAL_INSTANCE_PROCESS_SPAWN_FAILED"})}this.processSupervisor.track(e.instance.id,I),I.on("error",e=>{try{t.appendFileSync(n.join(u,"controlled-instance.lifecycle.log"),`[${(new Date).toISOString()}] process error pid=${I.pid??""} error=${e.message}\n`)}catch{}}),I.once("exit",(e,i)=>{try{t.appendFileSync(n.join(u,"controlled-instance.lifecycle.log"),`[${(new Date).toISOString()}] exited pid=${I.pid??""} code=${e??""} signal=${i??""}\n`)}catch{}});const A=`http://127.0.0.1:${a}`,b=I.pid?vr(I.pid):void 0;if(!(I.pid&&e.instance.registrationToken&&await this.processSupervisor.waitUntilHealthy(A,{instanceId:e.instance.id,pid:I.pid,processNonce:h,startIdentity:b},I,e.instance.registrationToken)&&this.processSupervisor.markReady(e.instance.id,I)))throw this.processSupervisor.release(e.instance.id,I),null===I.exitCode&&null===I.signalCode&&I.kill("SIGTERM"),await Ta(I),Object.assign(new Error(`Controlled instance process did not become ready for instance ${e.instance.id} on ${A}.`),{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:A,api:`${A}/api`},workspace:{mode:"local-bind",status:"pending",path:i},runtime:{kind:"local",workspacePath:i,pid:I.pid,port:a,labels:{...e.instance.runtime.labels,"task-handoff.runtime-kind":"local",[ba]:h}}}}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 await this.processSupervisor.stop(e.instance),this.start(e)}async delete(e,t){return await this.stop(e),It.parse({instanceId:e.instance.id,containerDeleted:!0,completed:!0,deletedVolumes:[],retainedVolumes:[],volumeResults:[]})}async check(e){const[t,n]=await Promise.all([Ca(this.runCommand,"codex"),Ca(this.runCommand,"claude")]);return{status:"online",capabilities:Bo({...e.capabilities,apps:{terminal:!0,codex:t,claude:n}})}}async stopAll(){await this.processSupervisor.stopAll()}}const xa=["codex","claude"],Ra=5e3;function Da(e){const t=process.env[e]?.trim();return t||void 0}function Pa(e){const t=e.authorization;return"string"==typeof t&&t.startsWith("Bearer ")?t.slice(7).trim():void 0}function Ma(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 ja(e){return!e.ip&&!e.socket.remoteAddress&&!e.socket.remoteFamily}function La(){return(new Date).toISOString()}async function $a(e,t){if(!t.target.web)return"unknown";const n=new AbortController,i=setTimeout(()=>n.abort(),2e3);try{return(await e(`${qa(t)}/api/health`,{signal:n.signal})).ok?"reachable":"endpoint-unreachable"}catch{return"endpoint-unreachable"}finally{clearTimeout(i)}}async function Fa(e,t,n,i){const r=new AbortController,o=setTimeout(()=>r.abort(),i);try{return await e(t,{...n,signal:r.signal})}finally{clearTimeout(o)}}async function Ua(e,t,n,i){if(!t.config.autoImportAgentConfigs)return void i.diagnostic({instanceId:t.id,action:n},"node instance config auto-import skipped");if("reachable"!==t.targetStatus)return;const r=qa(t),o=Number(process.env.TASK_HANDOFF_CONFIG_AUTO_IMPORT_TIMEOUT_MS||Ra);for(const s of xa)try{const a=await Fa(e,`${r}/api/config-sync/import/${encodeURIComponent(s)}`,{method:"POST"},Number.isFinite(o)&&o>0?o:Ra);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 Va(e,t,n){const i=t.requireInstance(n);if(t.instancePrivateConfigs.materialize(i.id,i.registrationToken,t.resolvedAssignedModelEnvironment(n)),"reachable"!==i.targetStatus||!i.target.web)return!1;const r=await Fa(e,`${qa(i)}/api/internal/model-environment`,{method:"PUT",headers:{"content-type":"application/json",authorization:`Bearer ${i.registrationToken}`},body:JSON.stringify(t.resolvedAssignedModelEnvironment(n))},Ra);if(!r.ok)throw Object.assign(new Error(`Instance ${n} rejected its managed model environment with HTTP ${r.status}.`),{statusCode:502,code:"INSTANCE_MODEL_ENVIRONMENT_APPLY_FAILED"});return!0}function qa(e){const t=e.target.web;if(!t){const t=new Error(`Instance ${e.id} does not have a web endpoint.`);throw Object.assign(t,{statusCode:409,code:"NODE_INSTANCE_WEB_ENDPOINT_MISSING"}),t}if("direct-port"!==e.target.strategy)return t.replace(/\/$/,"");try{const e=new URL(t);return e.port?(e.hostname=process.env.TASK_HANDOFF_NODE_AGENT_PROXY_HOST||"127.0.0.1",e.toString().replace(/\/$/,"")):t.replace(/\/$/,"")}catch{return t.replace(/\/$/,"")}}async function Ha(e,t,n,i,r,o="request"){const s=e.requireInstance(i);if(s.imageProvisioning&&"ready"!==s.imageProvisioning.phase&&"docker"===e.requireRuntime(s.runtimeId).type)return r.diagnostic({instanceId:i,action:"start",reason:o,runtimeId:s.runtimeId,imageId:s.imageSelection?.imageId,imagePhase:s.imageProvisioning.phase},"node instance start queued until image provisioning completes"),e.controlledInstances.put(Xn.parse({...s,status:"starting",updatedAt:La()}));r.diagnostic({instanceId:i,action:"start",reason:o,runtimeId:s.runtimeId,imageId:s.imageSelection?.imageId},"node instance start requested");const a=e.applyInstanceLifecycle(i,{type:"start-requested"}),c=t.forRuntime(e.requireRuntime(a.runtimeId)),d=await c.start(e.context(a)),l=await $a(n,Xn.parse({...a,...d,target:d.target?{...a.target,...d.target}:a.target,workspace:d.workspace?{...a.workspace,error:void 0,...d.workspace}:a.workspace,runtime:d.runtime?{...a.runtime,...d.runtime}:a.runtime,updatedAt:La()})),u=e.applyInstanceLifecycle(i,{type:"runtime-lifecycle-completed",baseline:a,observation:{...d,target:d.target?{...d.target,status:l}:void 0,workspace:d.workspace?{error:void 0,...d.workspace}:void 0,targetStatus:l,uiAccessStatus:l}});return r.diagnostic({instanceId:i,action:"start",reason:o,status:u.status,connectionStatus:u.connectionStatus,targetStatus:u.targetStatus,targetWeb:u.target.web,containerName:u.runtime.containerName},"node instance start completed"),u}async function Ba(e={}){const t=e.token||process.env.TASK_HANDOFF_NODE_AGENT_TOKEN,i=Number(e.port||process.env.TASK_HANDOFF_NODE_AGENT_PORT||"8091"),c=`http://127.0.0.1:${i}`,d=e.containerUrl||process.env.TASK_HANDOFF_NODE_AGENT_CONTAINER_URL,l=fr(e.dataDir),m=e.remoteSecret||process.env.TASK_HANDOFF_NODE_AGENT_REMOTE_SECRET,p=e.remoteKeyId||process.env.TASK_HANDOFF_NODE_AGENT_REMOTE_KEY_ID,h=new ea(l),f=h.resolveNodeId(e.nodeId||process.env.TASK_HANDOFF_NODE_ID),y=e.connectionMode||("local-ipc"===process.env.TASK_HANDOFF_NODE_AGENT_CONNECTION_MODE?"local-ipc":"local-loopback"),I=e.ipcPath||process.env.TASK_HANDOFF_NODE_AGENT_IPC_PATH||Mr(l.dataDir),A="local-ipc"===y?`ipc://${encodeURIComponent(I)}`:c,w=e.platform||process.platform,v=e.arch||process.arch,E=new Go(l,f,c,d,i,w);E.node.connectionMode=y,E.node.controlEndpoint=A,E.node.endpoint=A,E.init();const N=e.dockerCommandRunner||pi,z=new hi(N,e.dockerTerminalCommandRunner),_=new Ai(N,{publishHost:"127.0.0.1",imageService:z});let S;const T=new Aa(new Ia(_,N,w,v),new Oa(e.dockerCommandRunner||pi,l,()=>E.localNodeAgentUrl,function(){const e=process.env.TASK_HANDOFF_LOCAL_CONTROLLED_COMMAND_ARGV?.trim();if(!e){const e=process.env.TASK_HANDOFF_LOCAL_CONTROLLED_COMMAND?.trim();return e?e.split(/\s+/):void 0}let t;try{t=JSON.parse(e)}catch{throw Object.assign(new Error("TASK_HANDOFF_LOCAL_CONTROLLED_COMMAND_ARGV must be valid JSON."),{code:"LOCAL_CONTROLLED_COMMAND_INVALID"})}if(!Array.isArray(t)||!t.length||t.some(e=>"string"!=typeof e||!e))throw Object.assign(new Error("TASK_HANDOFF_LOCAL_CONTROLLED_COMMAND_ARGV must be a non-empty string array."),{code:"LOCAL_CONTROLLED_COMMAND_INVALID"});return t}(),e.localControlledInstanceLockPath,e=>S.handleUnexpectedLocalExit(e.instanceId,new Error(`Local controlled instance exited unexpectedly (pid=${e.pid??"unknown"}, code=${e.code??"none"}, signal=${e.signal??"none"}).`)),(e,t)=>$.log.error({error:e,instanceId:t.instanceId,pid:t.pid},"local controlled instance exit recovery failed"))),k=e.updateCommandRunner||e.dockerCommandRunner||pi,C=e.fetchImpl||fetch,O=new Hr({cacheDir:n.join(l.dataDir,"runtime-artifacts"),fetchImpl:C}),x=e.resolveRuntimeArtifactRelease||((e,t,n)=>Br(e,t,n,C)),R=async(t,n,i)=>{const r=await n.artifactTarget(i);if(e.resolveRuntimeArtifact)return e.resolveRuntimeArtifact(t,r.platform,r.arch);const o=await x(t,r.platform,r.arch);if(o.identity.launcherAbi>r.launcherAbi)throw Object.assign(new Error(`Runtime requires launcher ABI ${o.identity.launcherAbi}, but ${r.platform}-${r.arch} provides ABI ${r.launcherAbi}.`),{code:"INSTANCE_BASE_RUNTIME_INCOMPATIBLE",retryable:!1});return O.resolve(o.identity,o.source)},D=e=>T.forRuntime(E.requireRuntime(e.runtimeId)),P=e=>{const t=D(e);return ya(t)?t:void 0},M=e=>{const t=P(e);if(t)return t;throw Object.assign(new Error(`Runtime for instance ${e.id} does not use managed artifacts.`),{code:"INSTANCE_RUNTIME_ARTIFACT_UNMANAGED",retryable:!1})},j=e=>Boolean(P(e)),L=(e,t)=>{const n=E.context(e);return R(t,M(e),n)},$=o({logger:e.logger??!0}),F={requests:0,active:0,completed:0,aborted:0,limitRejected:0,responseBytes:0,totalDurationMs:0,maxResponseBytes:ys()};$.decorate("nodeAgentState",E),await $.register(s);const U=new Yi(E,t,{logger:$.log,safetyIntervalMs:Number(process.env.TASK_HANDOFF_EVENT_CONNECTION_SAFETY_INTERVAL_MS)||void 0}),V=new Kr(E.controlledInstances,Oo,{isInstalled:async(e,t)=>{const n=await L(e,t);return M(e).inspectRuntime(E.context(e),n.identity)},beginDrain:async e=>{try{const t=await async function(e,t){const n=qa(t);if(t.registrationToken&&(await Fa(e,`${n}/api/internal/node-agent/drain`,{method:"POST",headers:{authorization:`Bearer ${t.registrationToken}`}},1e4)).ok)return{requested:t.apps.runningCount,failures:[]};const i=await Fa(e,`${n}/api/apps/sessions`,{method:"GET",headers:{"cache-control":"no-cache"}},5e3);if(!i.ok)throw new Error(`Could not list app sessions for runtime drain (HTTP ${i.status}).`);const r=function(e){if(!e||"object"!=typeof e||Array.isArray(e))return[];const t=e.data;if(Array.isArray(t))return t;if(!t||"object"!=typeof t||Array.isArray(t))return[];const n=t.snapshot,i=(n&&"object"==typeof n&&!Array.isArray(n)?n:t).sessions;return Array.isArray(i)?i:[]}(await i.json()).flatMap(e=>{if(!e||"object"!=typeof e||Array.isArray(e))return[];const t=e;return"running"===t.status&&"string"==typeof t.id&&t.id?[t.id]:[]}),o=await Promise.all(r.map(async t=>{try{const i=await Fa(e,`${n}/api/apps/sessions/${encodeURIComponent(t)}/stop`,{method:"POST"},5e3);return i.ok?void 0:{sessionId:t,error:`HTTP ${i.status}`}}catch(e){return{sessionId:t,error:e instanceof Error?e.message:String(e)}}}));return{requested:r.length,failures:o.filter(e=>Boolean(e))}}(C,e);t.failures.length?$.log.warn({instanceId:e.id,requested:t.requested,failures:t.failures},"runtime convergence could not stop every app session"):$.log.info({instanceId:e.id,requested:t.requested},"runtime convergence requested app session drain")}catch(t){$.log.warn({instanceId:e.id,error:t instanceof Error?t.message:String(t)},"runtime convergence could not request app session drain")}},endDrain:async e=>{try{await async function(e,t){return!!t.registrationToken&&(await Fa(e,`${qa(t)}/api/internal/node-agent/resume`,{method:"POST",headers:{authorization:`Bearer ${t.registrationToken}`}},5e3)).ok}(C,e)&&$.log.info({instanceId:e.id},"runtime convergence released app session drain")}catch(t){$.log.warn({instanceId:e.id,error:t instanceof Error?t.message:String(t)},"runtime convergence could not release app session drain")}},install:async(e,t)=>{const n=M(e);await n.installRuntime(E.context(e),await L(e,t))},restart:async e=>{const t=D(e),n=E.applyInstanceLifecycle(e.id,{type:"convergence-restart-requested"}),i=await t.restart(E.context(n));E.applyInstanceLifecycle(e.id,{type:"runtime-lifecycle-completed",baseline:n,observation:i})},onForcedDrain:e=>$.log.warn({instanceId:e.id},"runtime convergence drain deadline reached; restarting instance")},{drainTimeoutMs:Number(process.env.TASK_HANDOFF_RUNTIME_DRAIN_TIMEOUT_MS)||void 0,verificationTimeoutMs:Number(process.env.TASK_HANDOFF_RUNTIME_VERIFY_TIMEOUT_MS)||void 0,maxAttempts:Number(process.env.TASK_HANDOFF_RUNTIME_MAX_ATTEMPTS)||void 0});E.controlledInstances.setOnStored(e=>{U.publishInstanceLifecycle(e),E.updateJobs.reconcileRollouts(E.listInstances(),Oo())}),U.start(),$.decorate("nodeAgentEventForwarder",U);const q=new ir(N,()=>E.listInstances().filter(e=>"docker"===E.requireRuntime(e.runtimeId).type),e=>U.publish("instance.metrics.snapshot",e,{instanceId:e.instanceId}));q.start(),$.decorate("nodeAgentRuntimeMetrics",q);const H=(Z=process.env.TASK_HANDOFF_DIAGNOSTIC_LOGS,["1","true","yes","on"].includes(String(Z||"").trim().toLowerCase())),B=new Cs(h,f,m,p),K=(e,t)=>{H&&$.log.info(e,t)},G={diagnostic:K,warn:(e,t)=>$.log.warn(e,t)},J=new ns,W=new ls(E.environmentTemplates,E.instancePrivateConfigs,_,e=>E.requireInstance(e),e=>E.requireRuntime(e),(e,t)=>J.run(e,t),e=>E.listInstances().some(t=>t.environmentTemplateOrigin?.imageId===e)),Y=async(e,t,n=()=>!0)=>{try{if(!n())return E.requireInstance(e);let i=E.requireInstance(e);"failed"===i.runtimeVersion?.phase&&j(i)&&(i=E.controlledInstances.put(Xn.parse({...i,ready:!1,runtimeVersion:Ro(Gr(i)),updatedAt:La()})));const r=E.requireRuntime(i.runtimeId);await Ha(E,T,C,e,G);const o=E.requireInstance(e);if("docker"===r.type&&o.imageProvisioning&&"ready"!==o.imageProvisioning.phase)return U.syncNow(),o;if(!n())return E.requireInstance(e);S.markRestored(e);let s=E.requireInstance(e);if(j(s)){try{s=await V.schedule(e,{startRequested:!0})}catch(n){s=E.requireInstance(e),G.warn({instanceId:e,action:"runtime.converge",reason:t,error:n instanceof Error?n.message:String(n)},"node instance runtime convergence failed after start")}"failed"===s.runtimeVersion?.phase&&G.warn({instanceId:e,action:"runtime.converge",reason:t,error:s.runtimeVersion.error},"node instance started with failed runtime convergence")}return n()?(await Ua(C,s,"start",G),U.syncNow(),s):E.requireInstance(e)}catch(n){throw E.applyInstanceLifecycle(e,{type:"start-failed",error:n}),U.syncNow(),G.warn({instanceId:e,action:"start",reason:t,error:n instanceof Error?n.message:String(n)},"node instance start failed"),n}},X=new ss(E,z,{sync:()=>U.syncNow(),diagnostic:G.diagnostic,warn:G.warn,publish:(e,t,n)=>U.publish(e,t,{instanceId:n}),runInstanceOperation:(e,t)=>J.run(e,t)}),Q=e=>{const t=J.intent(e.id);X.provision(e,async()=>{await Y(e.id,"image-ready",()=>J.isIntentCurrent(e.id,t)).catch(()=>{})})};var Z;S=new aa({state:E,runtimeAdapters:T,convergence:V,restoreInstance:e=>Ha(E,T,C,e,G,"restore"),autoImport:e=>Ua(C,e,"start",G),provisionImage:Q,stopImageProvisioning:()=>X.stop(),usesManagedArtifact:j,warn:G.warn,error:(e,t)=>$.log.error(e,t),runInstanceOperation:(e,t)=>J.run(e,t)});const ee=new ra({nodeId:f,jobs:E.updateJobs,runCommand:k,currentRuntimeVersion:Oo,listInstances:()=>E.listInstances(),resolveRuntimeArtifacts:async e=>(await(async e=>{const t=new Map;for(const e of T.managedAdapters()){const n=await e.artifactTarget();t.set(`${n.platform}-${n.arch}`,{adapter:e})}for(const e of E.listInstances()){const n=P(e);if(!n)continue;const i=E.context(e),r=await n.artifactTarget(i);t.set(`${r.platform}-${r.arch}`,{adapter:n,context:i})}return(await Promise.all([...t.values()].map(({adapter:t,context:n})=>R(e,t,n)))).sort((e,t)=>`${e.identity.platform}/${e.identity.arch}`.localeCompare(`${t.identity.platform}/${t.identity.arch}`))})(e)).map(e=>e.identity),moduleDir:("undefined"==typeof document?require("url").pathToFileURL(__filename).href:b&&"SCRIPT"===b.tagName.toUpperCase()&&b.src||new URL("cli.js",document.baseURI).href)?n.dirname(r.fileURLToPath("undefined"==typeof document?require("url").pathToFileURL(__filename).href:b&&"SCRIPT"===b.tagName.toUpperCase()&&b.src||new URL("cli.js",document.baseURI).href)):__dirname});return $.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);(H||i.statusCode>=500)&&(i.statusCode>=500?$.log.error.bind($.log):$.log.warn.bind($.log))({method:t.method,url:t.url,statusCode:i.statusCode,errorCode:i.code,error:i.message},"node agent request failed"),n.code(i.statusCode).send({error:{code:i.code,message:i.message,...e&&"object"==typeof e&&"string"==typeof e.expectedVersion?{expectedVersion:e.expectedVersion}:{},...e&&"object"==typeof e&&"string"==typeof e.actualVersion?{actualVersion:e.actualVersion}:{},...e&&"object"==typeof e&&"string"==typeof e.phase?{phase:e.phase}:{},...e&&"object"==typeof e&&"boolean"==typeof e.retryable?{retryable:e.retryable}:{},...e&&"object"==typeof e&&"number"==typeof e.blockingInstanceCount?{blockingInstanceCount:e.blockingInstanceCount}:{}}})}),$.addHook("preHandler",async e=>{const n=B.verify(e);if(n){if(h.isRevokedPairing(n)&&"/api/node-agent/pairing/current"!==e.url.split("?")[0]){const e=new Error("The node agent pairing used for this request has been revoked.");throw Object.assign(e,{statusCode:401,code:"NODE_AGENT_HMAC_KEY_REVOKED"}),e}e.nodeAgentAuthKeyId=n}else if(ja(e)){if(t&&Pa(e.headers)!==t){const e=new Error("Invalid node agent token.");throw Object.assign(e,{statusCode:401,code:"NODE_AGENT_UNAUTHORIZED"}),e}}else if("/api/node-agent/pairing/complete"!==e.url.split("?")[0]&&!function(e){const t=e.split("?")[0];return/^\/api\/node-agent\/instances\/[^/]+\/(register|heartbeat)$/.test(t)}(e.url)){if(B.hasRemoteSecrets()){const e=new Error("Node agent HMAC signature is required.");throw Object.assign(e,{statusCode:401,code:"NODE_AGENT_HMAC_SIGNATURE_REQUIRED"}),e}if(!function(e){return Ma(e.ip)||Ma(e.socket.remoteAddress)||!e.ip&&!e.socket.remoteAddress&&!e.socket.remoteFamily}(e)){const e=new Error("Local node agent access is only accepted from loopback or local IPC connections.");throw Object.assign(e,{statusCode:401,code:"NODE_AGENT_LOCAL_TOKEN_REQUIRES_LOOPBACK"}),e}if(t&&Pa(e.headers)!==t){const e=new Error("Invalid node agent token.");throw Object.assign(e,{statusCode:401,code:"NODE_AGENT_UNAUTHORIZED"}),e}}}),$.addHook("onClose",async()=>{q.stop(),U.stop(),await S.stop()}),$.decorate("nodeAgentRestoreManagedInstances",()=>S.restoreManagedInstances()),$.decorate("nodeAgentRecoverManagedInstances",()=>S.recoverManagedInstances()),$.decorate("nodeAgentStartRecoverySupervisor",()=>S.start()),$.get("/api/node-agent/health",async()=>{return{data:{ok:!0,role:"node-agent",listener:{host:"127.0.0.1",port:E.currentListenerPort},nodeId:f,platform:fa(w),arch:process.arch,protocolVersion:qe,build:(e="node-agent",{component:e,packageName:"@task-handoff/node-agent",packageVersion:Oo(),protocolVersion:qe,buildId:Da("TASK_HANDOFF_BUILD_ID"),builtAt:Da("TASK_HANDOFF_BUILT_AT"),gitCommit:Da("TASK_HANDOFF_GIT_COMMIT"),imageRef:Da("TASK_HANDOFF_IMAGE_REF"),imageDigest:Da("TASK_HANDOFF_IMAGE_DIGEST")}),instanceProxy:{...F},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)}))}($,e=>{if(!ja(e)){const e=new Error("Node agent TCP listener settings are available only over local Unix IPC.");throw Object.assign(e,{statusCode:403,code:"NODE_AGENT_LISTENER_LOCAL_IPC_ONLY"}),e}if(!$.nodeAgentListenerManager){const e=new Error("Node agent TCP listener manager is not initialized.");throw Object.assign(e,{statusCode:503,code:"NODE_AGENT_LISTENER_UNAVAILABLE"}),e}return $.nodeAgentListenerManager}),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)}))}($,ee,E.updateJobs),function(e,t){const{identity:n,nodeId:i,fetchImpl:r}=t;e.post("/api/node-agent/pairing/invites",async(e,t)=>{const r=n.createPairingInvite(Ls.parse(e.body||{}));return t.code(201).send({data:{nodeId:i,joinToken:r.token,expiresAt:r.expiresAt}})}),e.post("/api/node-agent/pairing/complete",async(e,t)=>{const r=n.completePairingInvite($s.parse(e.body));return t.code(201).send({data:{nodeId:i,keyId:r.keyId,secret:r.secret,pairedAt:r.pairedAt}})}),e.get("/api/node-agent/control-plane-pairings",async e=>({data:n.listControlPlanePairings(e.nodeAgentAuthKeyId)})),e.delete("/api/node-agent/control-plane-pairings/:keyId",async e=>{const t=ta.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=ta.parse(e.params.connectionId),r=n.deleteControlPlaneConnection(i);return r&&t.reverseTunnels()?.connectConfigured(),{data:{deleted:r}}}),e.post("/api/node-agent/control-plane-connections",async(e,o)=>{const s=Fs.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(/\/$/,"")}(s.controlPlaneUrl);return n.runControlPlaneConnectionOperation(a,async()=>{const e=n.stageControlPlaneConnection({url:a,...s.controlPlaneName?{name:s.controlPlaneName}:{},enabled:!1!==s.activate});let c;try{c=await async function(e,t,n){const i=await e(new URL("/api/node-join/complete",t).toString(),{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(n)}),r=await i.json().catch(()=>({}));if(!i.ok){const e=new Error(r.error?.message||`Control-plane node join failed with HTTP ${i.status}.`);throw Object.assign(e,{statusCode:i.status,code:r.error?.code||"NODE_AGENT_REMOTE_JOIN_FAILED"}),e}return r.data||{}}(r,a,{joinToken:s.joinToken,nodeId:i,nodeName:t.nodeName(),keyId:e.pairing.keyId,secret:e.pairing.secret,pairedAt:e.pairing.pairedAt})}catch(t){throw n.rollbackControlPlaneConnection(e),t}const d=n.commitControlPlaneConnection(e,{name:s.controlPlaneName||("string"==typeof c.name&&c.name?c.name:void 0)});let l,u=d.connection.enabled?"saved":"disabled";const m=t.reverseTunnels();if(m)try{m.connectConfigured(),d.connection.enabled&&(u="connecting")}catch(e){u="failed",l=e instanceof Error?e.message:String(e)}return o.code(201).send({data:{pairing:n.listControlPlanePairings().find(e=>e.keyId===d.pairing.keyId),connection:d.connection,tunnel:{status:u,...l?{error:l}:{}}}})})})}($,{identity:h,nodeId:f,nodeName:()=>E.node.name,fetchImpl:C,reverseTunnels:()=>$.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(Zo.parse(e.body))})),e.patch("/api/node-agent/runtimes/:id",async e=>({data:t.updateRuntime(e.params.id,es.parse(e.body))})),e.delete("/api/node-agent/runtimes/:id",async e=>({data:{deleted:t.deleteRuntime(e.params.id)}})),e.post("/api/node-agent/runtimes/:id/check",async e=>({data:await t.checkRuntime(e.params.id)})),e.get("/api/node-agent/local-folders",async()=>({data:t.listLocalFolders()})),e.get("/api/node-agent/folders/tree",async e=>({data:t.listFolderTree(Yo.parse(e.query))})),e.post("/api/node-agent/local-folders",async(e,n)=>n.code(201).send({data:t.createLocalFolder(Wo.parse(e.body))})),e.delete("/api/node-agent/local-folders/:id",async e=>({data:{deleted:t.deleteLocalFolder(e.params.id)}}))}($,{listRuntimes:()=>E.nodeRuntimes.list(),createRuntime:e=>E.createRuntime(e),updateRuntime:(e,t)=>E.updateRuntime(e,t),deleteRuntime:e=>E.deleteRuntime(e),checkRuntime:async e=>{const t=E.requireRuntime(e);return E.checkRuntime(e,T.forRuntime(t))},listLocalFolders:()=>E.localFolders.list(),listFolderTree:gr,createLocalFolder:e=>E.createLocalFolder(e),deleteLocalFolder:e=>E.localFolders.delete(e)}),function(e,t){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(gn.parse(e.body))})),e.put("/api/node-agent/models/:id/deploy",async e=>{const n=e.params.id,i=fn.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,hn.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 n=e.params.id,i=t.assign(n,yn.parse(e.body));return await(e=>Va(C,E,e))(n),{data:i}})}($,E.modelRegistry),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:zt.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)}))}($,W),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(Xo.parse(e.body));return t.afterCreate(i),n.code(201).send({data:i})}),e.post("/api/node-agent/instances/:id/image-provisioning/retry",async e=>{const n=t.retryImageProvisioning(e.params.id);return t.afterImageRetry(n),{data:n}}),e.patch("/api/node-agent/instances/:id",async e=>{const n=t.update(e.params.id,Qo.parse(e.body));return t.afterUpdate(n),{data:n}}),e.post("/api/node-agent/instances/:id/register",async(e,n)=>{const i=e.params.id,r=t.sanitizeReport(i,"register",e.body),o=t.register(i,oi.parse(r),ts(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),r=t.heartbeat(n,si.parse(i),ts(e.headers));return t.afterReport(r,"heartbeat"),{data:r}})}($,{list:()=>E.listInstances(),create:e=>"template"===e.environmentSource?.type?W.runTemplateOperation(e.environmentSource.environmentTemplateId,()=>E.createInstance(e)):E.createInstance(e),retryImageProvisioning:e=>X.retry(e),update:(e,t)=>{const n=E.requireInstance(e);return E.controlledInstances.put(Xn.parse({...n,...t,...t.config?{config:{...n.config,...t.config}}:{},updatedAt:La()}))},register:(e,t,n)=>E.registerInstance(e,t,n),heartbeat:(e,t,n)=>E.heartbeatInstance(e,t,n),sanitizeReport:(e,t,n)=>{const i=n&&"object"==typeof n&&!Array.isArray(n)?n.protocolVersion:void 0;if("string"!=typeof i||i===qe)return n;const r=({field:n,action:r})=>$.log.warn({instanceId:e,report:t,protocolVersion:i,expectedProtocolVersion:qe,field:n,action:r},"cross-version controlled instance report sanitized");return"register"===t?function(e,t){if(!e||"object"!=typeof e||Array.isArray(e))return e;const n=e,i=["instanceId","projectId","source","nodeId","runtimeId","imageSelection","instanceVersion","protocolVersion","build","controlMode","capabilities","appInventory","target","workspace","registrationToken","processIncarnationId"],r=new Set([...i,"imageId"]);for(const e of Object.keys(n))r.has(e)||t?.({field:e,action:"ignored"});return Object.prototype.hasOwnProperty.call(n,"imageId")&&t?.({field:"imageId",action:"migrated"}),{...ri(n,i),imageSelection:bt(n.imageSelection,n.imageId)}}(n,r):function(e,t){if(!e||"object"!=typeof e||Array.isArray(e))return e;const n=["status","health","protocolVersion","build","capabilities","appInventory","apps","aiSessions","triggers","workspace","target","processIncarnationId"],i=new Set(n);for(const n of Object.keys(e))i.has(n)||t?.({field:n,action:"ignored"});return ri(e,n)}(n,r)},afterCreate:e=>{U.syncNow(),e.imageProvisioning&&Q(e)},afterImageRetry:e=>{U.syncNow(),Q(e)},afterUpdate:()=>U.syncNow(),afterReport:(e,t)=>{U.syncNow(),"register"===t?K({instanceId:e.id,action:t,protocolVersion:e.protocolVersion,build:e.build,targetStatus:e.targetStatus,targetStrategy:e.target.strategy},"node instance registered"):K({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"),!j(e)||e.ready&&"matched"===e.runtimeVersion?.phase||V.schedule(e.id).catch(n=>$.log.error({instanceId:e.id,error:n},`runtime convergence after ${t} failed`))}}),$.get("/api/node-agent/events",{websocket:!0},e=>{const t=e;t.send(JSON.stringify({type:"node-agent.events.connected",nodeId:f,serverTime:(new Date).toISOString()}));const n=U.addOutput(t);t.on("close",n),t.on("error",n)}),$.get("/api/node-agent/docker/images",async()=>({data:await Ci(e.dockerCommandRunner)})),$.get("/api/node-agent/instances/:id/metrics",async e=>{const t=e.params.id,n=E.requireInstance(t);if("docker"!==E.requireRuntime(n.runtimeId).type){const e=new Error(`Runtime type ${E.requireRuntime(n.runtimeId).type} does not provide resource metrics.`);throw Object.assign(e,{statusCode:409,code:"INSTANCE_METRICS_UNSUPPORTED"}),e}return{data:await q.snapshot(t)}}),function(e,t,n,i,r,o=new ns){const s=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"})};e.post("/api/node-agent/instances/:id/start",async e=>{is.parse(e.body);const t=e.params.id,n=s(t);return o.run(t,async()=>(c(t,n),r.allowRecovery(t),{data:await r.start(t,()=>o.isIntentCurrent(t,n))}))}),e.post("/api/node-agent/instances/:id/runtime/reconcile",async e=>{const n=e.params.id;is.parse(e.body);const a=s(n);return o.run(n,async()=>{c(n,a);const e=t.requireInstance(n);t.putInstance(Xn.parse({...e,ready:!1,runtimeVersion:Ro(Gr(e)),updatedAt:rs()})),c(n,a);const o=await i.schedule(n,{startRequested:!["created","stopped"].includes(e.status),resumeCancelled:!0});return c(n,a),r.sync(),{data:o}})}),e.post("/api/node-agent/instances/:id/stop",async e=>{const i=e.params.id;t.requireInstance(i),o.invalidate(i);const s=a(i);return o.run(i,async()=>{const e=t.requireInstance(i);t.applyLifecycle(i,{type:"stop-requested"});try{await r.suppressRecovery(i);const e=await s;if("error"in e)throw e.error;const o=t.requireInstance(i);r.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}),r.sync()}finally{r.allowRecovery(i)}throw n}const o=t.applyLifecycle(i,{type:"stop-completed"});return r.completeSuppressedRecovery(i),r.sync(),r.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;is.parse(e.body);const d=s(a);return o.run(a,async()=>{c(a,d),r.allowRecovery(a);let e=t.requireInstance(a);if(r.isManaged(e)&&(!e.ready||"matched"!==e.runtimeVersion?.phase)){"failed"===e.runtimeVersion?.phase&&(e=t.putInstance(Xn.parse({...e,runtimeVersion:Ro(Gr(e)),updatedAt:rs()}))),c(a,d);const n=await i.schedule(a,{startRequested:!0});return c(a,d),r.sync(),{data:n}}r.diagnostic({instanceId:a,action:"restart",runtimeId:e.runtimeId,imageId:e.imageSelection?.imageId,containerName:e.runtime.containerName},"node instance restart requested");const o=await n.forRuntime(t.requireRuntime(e.runtimeId)).restart(t.context(e));let s=t.applyLifecycle(a,{type:"runtime-lifecycle-completed",baseline:e,observation:{...o,target:o.target?{...e.target,...o.target}:void 0}});r.markRestarted(a),c(a,d);const l=Xn.parse({...s,updatedAt:rs()}),u=await r.probe(l);return c(a,d),s=t.applyLifecycle(a,{type:"runtime-lifecycle-completed",baseline:s,observation:{target:{...s.target,status:u},targetStatus:u,uiAccessStatus:u}}),await r.autoImport(s),r.sync(),r.diagnostic({instanceId:a,action:"restart",status:s.status,connectionStatus:s.connectionStatus,targetStatus:s.targetStatus,targetWeb:s.target.web,containerName:s.runtime.containerName},"node instance restart completed"),{data:s}})}),e.post("/api/node-agent/instances/:id/delete",async e=>{const i=e.params.id,s=ft.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 r.suppressRecovery(i);const e=await c;if("error"in e)throw e.error;const a=t.requireInstance(i);t.putInstance(Xn.parse({...a,status:"deleting",ready:!1,updatedAt:rs()})),r.diagnostic({instanceId:i,action:"delete",runtimeId:a.runtimeId,containerName:a.runtime.containerName},"node instance delete requested");const d=await n.forRuntime(t.requireRuntime(a.runtimeId)).delete(t.context(a,{}),s);if(!d.completed)return r.diagnostic({instanceId:i,action:"delete",volumeResults:d.volumeResults},"node instance delete requires retry"),r.sync(),{data:d};r.diagnostic({instanceId:i,action:"delete"},"node instance delete completed");const l=t.deleteInstance(i);return l&&(r.forgetRecovery(i),o.clearIntent(i)),r.deleteMetadata(i),l&&a.environmentTemplateOrigin?.imageId&&r.releaseEnvironmentImage&&await r.releaseEnvironmentImage(a.environmentTemplateOrigin.imageId).catch(e=>{r.diagnostic({instanceId:i,action:"release-environment-image",error:e instanceof Error?e.message:String(e)},"environment image cleanup deferred after instance deletion")}),r.sync(),{data:d}}catch(n){try{t.putInstance(Xn.parse({...e,updatedAt:rs()})),r.sync()}finally{r.allowRecovery(i)}throw n}})})}($,{requireInstance:e=>E.requireInstance(e),requireRuntime:e=>E.requireRuntime(e),putInstance:e=>E.controlledInstances.put(e),deleteInstance:e=>E.controlledInstances.delete(e),applyLifecycle:(e,t)=>E.applyInstanceLifecycle(e,t),context:(e,t)=>E.context(e,t)},T,V,{start:(e,t)=>Y(e,"request",t),sync:()=>U.syncNow(),isManaged:j,probe:e=>$a(C,e),autoImport:e=>Ua(C,e,"restart",G),markRestarted:e=>S.markRestored(e),allowRecovery:e=>S.allowRecovery(e),suppressRecovery:e=>S.suppressRecovery(e),forgetRecovery:e=>S.forgetInstance(e),completeSuppressedRecovery:e=>S.completeSuppressedOperation(e),deleteMetadata:e=>{E.modelRegistry.deleteInstanceMetadata(e),E.instancePrivateConfigs.delete(e)},releaseEnvironmentImage:e=>W.releaseUnusedImage(e),diagnostic:K},J),function(e,t){const{fetchImpl:n,metrics:i,diagnostic:r}=t;e.post("/api/node-agent/instances/:id/proxy",async(e,i)=>{const o=e.params.id,s=Jo.parse(e.body),a=t.instanceBase(o),c=Is(s.path);"POST"===s.method&&"/api/apps/sessions"===c&&await t.syncModelEnvironment(o),r({instanceId:o,action:"proxy",method:s.method,path:c,instanceBase:a},"node instance proxy requested");const d=await n(`${a}${c}`,{method:s.method,headers:{...s.headers},body:fs(s)}),l=d.headers.get("content-type")||"application/octet-stream",u=await d.text();r({instanceId:o,action:"proxy",method:s.method,path:c,statusCode:d.status,contentType:l},"node instance proxy completed"),i.code(d.status).type(l).send(u)}),e.post("/api/node-agent/instances/:id/proxy/stream",{bodyLimit:gs},async(e,o)=>{const s=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()-s,i.responseBytes+=c,i[e]+=1)},m=()=>{a.abort(),d&&u("aborted")};e.raw.once("aborted",m),o.raw.once("close",m);try{const s=e.params.id,l=Jo.parse(e.body),m=t.instanceBase(s),p=Is(l.path);r({instanceId:s,action:"proxy.stream",method:l.method,path:p,instanceBase:m},"node instance streaming proxy requested");const h=await n(`${m}${p}`,{method:l.method,headers:{...l.headers},body:fs(l),signal:a.signal}),f=Number(h.headers.get("content-length"));if(Number.isFinite(f)&&f>i.maxResponseBytes)return i.limitRejected+=1,a.abort(),As(o,i.maxResponseBytes);o.code(h.status);for(const[e,t]of Object.entries(hs(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",m),d||u("completed")}}),e.post("/api/node-agent/instances/:id/proxy/raw",{bodyLimit:gs},async(e,o)=>{const s=e.params.id,a=Jo.parse(e.body),c=t.instanceBase(s),d=Is(a.path);r({instanceId:s,action:"proxy.raw",method:a.method,path:d,instanceBase:c},"node instance raw proxy requested");const l=await n(`${c}${d}`,{method:a.method,headers:{...a.headers},body:fs(a)}),u=Number(l.headers.get("content-length"));if(Number.isFinite(u)&&u>i.maxResponseBytes)return i.limitRejected+=1,await(l.body?.cancel("Instance proxy response limit exceeded.").catch(()=>{})),As(o,i.maxResponseBytes);let m;try{m=await async function(e,t){if(!e.body)return Buffer.alloc(0);const n=[];let i=0;const r=e.body.getReader();for(;;){const{done:e,value:o}=await r.read();if(e)break;if(i+=o.byteLength,i>t)throw await r.cancel("Instance proxy response limit exceeded.").catch(()=>{}),Object.assign(new Error("Instance proxy response limit exceeded."),{code:"INSTANCE_PROXY_RESPONSE_TOO_LARGE"});n.push(Buffer.from(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,As(o,i.maxResponseBytes)}return r({instanceId:s,action:"proxy.raw",method:a.method,path:d,statusCode:l.status,byteLength:m.length},"node instance raw proxy completed"),{data:{status:l.status,headers:hs(l.headers),bodyBase64:m.toString("base64")}}}),e.get("/api/node-agent/instances/:id/proxy/ws/*",{websocket:!0},(e,n)=>{const i=n.params.id,o=n.params["*"]||"",s=n.url.indexOf("?"),a=s>=0?n.url.slice(s):"";let c;try{const s=t.instanceBase(i),d=new URL(`/${o}${a}`,`${s}/`);d.protocol="https:"===d.protocol?"wss:":"ws:";const l=function(e){const t=e["sec-websocket-protocol"],n=(Array.isArray(t)?t.join(","):"string"==typeof t?t:"").split(",").map(e=>e.trim()).filter(Boolean);return n.length?n:void 0}(n.headers);r({instanceId:i,action:"proxy.ws",path:`/${o}${a}`,upstreamUrl:d.toString(),protocols:l||[]},"node instance websocket proxy opening"),c=l?new u(d,l):new u(d),c.on("open",()=>{r({instanceId:i,action:"proxy.ws",path:`/${o}${a}`},"node instance websocket proxy opened"),e.on("message",(e,t)=>c?.readyState===u.OPEN&&c.send(function(e,t){return t?e:e.toString()}(e,t))),e.on("close",()=>c?.close()),e.on("error",()=>c?.close())}),c.on("message",(t,n)=>e.readyState===u.OPEN&&e.send(n?t:t.toString())),c.on("close",()=>{r({instanceId:i,action:"proxy.ws",path:`/${o}${a}`},"node instance websocket proxy closed"),e.close()}),c.on("error",t=>{r({instanceId:i,action:"proxy.ws",path:`/${o}${a}`,error:t instanceof Error?t.message:String(t)},"node instance websocket proxy failed"),e.close(1011,"Instance websocket proxy failed.")})}catch(t){r({instanceId:i,action:"proxy.ws",path:`/${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.")}})}($,{fetchImpl:C,metrics:F,instanceBase:e=>qa(E.requireInstance(e)),syncModelEnvironment:e=>Va(C,E,e),diagnostic:K}),$}async function Ka(e){const r=fr(e.dataDir),o=(s=e.host,a=e.port,Vn.parse({bindScope:"0.0.0.0"===s.trim()?"all-ipv4":"loopback",port:a}));var s,a;const d=t.existsSync(r.settingsPath),l=function(e,t){return new lo(e.settingsPath,()=>({version:1,externalListener:t}),{schema:bs,sanitize:vs})}(r,o);let u=l.get().externalListener;if("allocate"===process.env.TASK_HANDOFF_NODE_AGENT_PORT_CONFLICT){const e=await async function(e,t=20){for(let n=0;n<t&&e.port+n<=65535;n+=1){const t={...e,port:e.port+n};if(await Es(t))return t}throw Object.assign(new Error(`No available node-agent port found starting at ${e.port}.`),{statusCode:503,code:"NODE_AGENT_LISTENER_PORT_UNAVAILABLE"})}(u);e.port!==u.port&&(l.put({version:1,externalListener:e}),u=e)}const p=function(e,i={}){return function(e,i={}){t.mkdirSync(n.dirname(e),{recursive:!0});const r={pid:process.pid,hostname:m.hostname(),component:i.component,command:process.argv.join(" "),acquiredAt:(new Date).toISOString(),token:c.randomUUID(),startIdentity:vr(process.pid),dataDir:i.dataDir,host:i.host,port:i.port,instanceId:i.instanceId};for(let n=0;n<5;n+=1)try{return t.mkdirSync(e),t.writeFileSync(Ar(e),`${JSON.stringify({token:r.token,pid:r.pid,startIdentity:r.startIdentity,startedAt:(new Date).toISOString()})}\n`,{encoding:"utf8",mode:384,flag:"wx"}),Sr(e,r),{lockPath:e,owner:r,release(){const n=Nr(e);n?.token===r.token&&t.rmSync(e,{recursive:!0,force:!0})}}}catch(r){if("EEXIST"!==r.code)throw r;const o=Nr(e);if(_r(o))throw new yr(e,o,i.error);if(!o&&(kr(e)||xr(e)<(i.incompleteLockStaleMs??2e3))){if(n+1<5){Or();continue}throw new yr(e,void 0,i.error)}const s=c.randomUUID();if(!Rr(e,s)){if(n+1<5){Or();continue}throw new yr(e,Nr(e),i.error)}const a=Nr(e);if(_r(a))throw Cr(br(e)),new yr(e,a,i.error);if(o?.token&&a?.token!==o.token){Cr(br(e));continue}if(!Pr(e,s))continue;t.rmSync(e,{recursive:!0,force:!0})}const o=Nr(e);throw new yr(e,o,i.error)}(e,{...i,component:"node-agent",error:{label:"Node agent",code:"NODE_AGENT_ALREADY_RUNNING"}})}(n.join(m.tmpdir(),`task-handoff-node-agent-${process.getuid?.()??"user"}.lock`),{dataDir:r.dataDir,host:ws(u.bindScope),port:u.port});try{const o={...e,port:u.port},s=await Ba(o),a=s.nodeAgentState;if(!a)throw new Error("Node agent state was not initialized.");const c=new ea(r).resolveNodeId(e.nodeId||process.env.TASK_HANDOFF_NODE_ID),m=function(e,t,n,i){const r=t.token||process.env.TASK_HANDOFF_NODE_AGENT_TOKEN,o=new ea(n),s=new Map;let a=!1;const c=(t,n)=>{n.status=n.lastDisconnectedAt?"reconnecting":"connecting",n.error=void 0;const o=pa(e,{...n.config,nodeId:i,port:()=>e.nodeAgentState.currentListenerPort,token:r});return n.socket=o,o.on("open",()=>{s.get(t)===n&&n.socket===o&&(n.status="connecting",n.handshakeTimer=setTimeout(()=>{s.get(t)===n&&n.socket===o&&"connected"!==n.status&&(n.error="Reverse tunnel did not receive a control-plane handshake.",o.close(1008,"Reverse tunnel handshake timed out."))},1e4),n.handshakeTimer.unref?.())}),o.on("message",r=>{if(s.get(t)!==n||n.socket!==o||"connected"===n.status)return;let a;try{a=JSON.parse(String(r))}catch{return}const c=a&&"object"==typeof a?a.type:void 0;"control-plane.hello"!==c&&"control-plane.identified"!==c||(n.handshakeTimer&&clearTimeout(n.handshakeTimer),n.handshakeTimer=void 0,n.retry.reset(),n.status="connected",n.lastConnectedAt=(new Date).toISOString(),n.error=void 0,e.log.info({nodeId:i,tunnelUrl:new URL(n.config.tunnelUrl).origin},"node agent reverse tunnel connected"))}),o.on("close",(r,d)=>{s.get(t)===n&&n.socket===o&&(n.handshakeTimer&&clearTimeout(n.handshakeTimer),n.handshakeTimer=void 0,n.socket=void 0,n.lastDisconnectedAt=(new Date).toISOString(),n.error=`WebSocket closed${r?` (${r})`:""}${d?`: ${Buffer.isBuffer(d)?d.toString("utf8"):String(d)}`:""}`,a||(e.log.warn({nodeId:i,tunnelUrl:new URL(n.config.tunnelUrl).origin,code:r,reason:Buffer.isBuffer(d)?d.toString("utf8"):String(d||"")},"node agent reverse tunnel disconnected"),((t,n)=>{if(a||n.retry.pending||s.get(t)!==n)return;const r=n.retry.schedule(()=>{a||s.get(t)!==n||n.socket||c(t,n)});r&&(n.status="reconnecting",e.log.info({nodeId:i,tunnelUrl:new URL(n.config.tunnelUrl).origin,attempt:r.attempt,delay:r.delay},"node agent reverse tunnel reconnect scheduled"))})(t,n)))}),o.on("error",e=>{s.get(t)===n&&n.socket===o&&(n.status="failed",n.error=e instanceof Error?e.message:String(e))}),o},d=(e,t)=>{const n=s.get(e);n?.retry.cancel(),n?.handshakeTimer&&clearTimeout(n.handshakeTimer);const i={config:t,retry:new Ji,status:"connecting"};return s.set(e,i),n?.socket?.close(1e3,"Reverse tunnel reconnecting."),c(e,i)},l=(e,t)=>e.tunnelUrl===t.tunnelUrl&&e.keyId===t.keyId&&e.secret===t.secret;return{connectConfigured:()=>{a=!1;const n=new Map,r=o.resolvedControlPlaneAccess(),c=new Set;for(const{connection:t,pairing:o}of r.connections){if(!t.enabled)continue;if(!o){e.log.warn({nodeId:i,connectionId:t.id,pairingKeyId:t.pairingKeyId},"node agent control-plane connection has no pairing");continue}const r=ga(t.url);n.set(t.id,{tunnelUrl:r,keyId:o.keyId,secret:o.secret}),c.add(r)}const u=function(e){const t=e.controlPlaneTunnelUrl||process.env.TASK_HANDOFF_CONTROL_PLANE_TUNNEL_URL;return t?new URL(t).toString():void 0}(t);if(u&&!c.has(u)){const e=o.reverseTunnelSecret(process.env.TASK_HANDOFF_CONTROL_PLANE_URL,t.remoteSecret||process.env.TASK_HANDOFF_NODE_AGENT_REMOTE_SECRET,t.remoteKeyId||process.env.TASK_HANDOFF_NODE_AGENT_REMOTE_KEY_ID);n.set(`explicit:${u}`,{tunnelUrl:u,keyId:e?.keyId,secret:e?.secret}),c.add(u)}const m=r.hasPersistedAccess?void 0:function(){const e=process.env.TASK_HANDOFF_CONTROL_PLANE_URL;if(!e)return;const t=new URL(_s,e);return t.protocol="https:"===t.protocol?"wss:":"ws:",t.toString()}();if(m&&!c.has(m)){const e=o.reverseTunnelSecret(process.env.TASK_HANDOFF_CONTROL_PLANE_URL,t.remoteSecret||process.env.TASK_HANDOFF_NODE_AGENT_REMOTE_SECRET,t.remoteKeyId||process.env.TASK_HANDOFF_NODE_AGENT_REMOTE_KEY_ID);n.set(`bootstrap:${m}`,{tunnelUrl:m,keyId:e?.keyId,secret:e?.secret})}(e=>{for(const[t,n]of s)e.has(t)||(n.retry.cancel(),n.handshakeTimer&&clearTimeout(n.handshakeTimer),s.delete(t),n.socket?.close(1e3,"Reverse tunnel configuration removed."));for(const[t,n]of e){const e=s.get(t);e&&l(e.config,n)||d(t,n)}})(n)},state:e=>{const t=s.get(e);if(t)return{status:t.status,...t.lastConnectedAt?{lastConnectedAt:t.lastConnectedAt}:{},...t.lastDisconnectedAt?{lastDisconnectedAt:t.lastDisconnectedAt}:{},...t.error?{error:t.error}:{}}},closeAll:()=>{a=!0;for(const e of s.values())e.retry.cancel(),e.handshakeTimer&&clearTimeout(e.handshakeTimer),e.socket?.close(1001,"Node agent shutting down.");s.clear()}}}({log:s.log,inject:e=>s.inject(e),nodeAgentEventForwarder:s.nodeAgentEventForwarder,nodeAgentState:a},o,r,c);s.decorate("nodeAgentReverseTunnels",m);const g=new Ns({app:s,state:a,settings:l,config:u,source:d?"persisted":"bootstrap"});let h;s.decorate("nodeAgentListenerManager",g),function(e){let t=!1;const n=async n=>{if(!t){t=!0,m.closeAll(),h?.close();try{await e.close()}finally{process.exitCode=n?0:process.exitCode}}},i=()=>{n("SIGINT")},r=()=>{n("SIGTERM")};process.once("SIGINT",i),process.once("SIGTERM",r),e.addHook("onClose",async()=>{process.off("SIGINT",i),process.off("SIGTERM",r)})}(s),s.addHook("onClose",async()=>{h?.close(),p.release()});try{await s.ready();const o=e.ipcPath||process.env.TASK_HANDOFF_NODE_AGENT_IPC_PATH||Mr(r.dataDir);h=await async function(e,r){!function(e,i=process.platform){if("win32"!==i){t.mkdirSync(n.dirname(e),{recursive:!0,mode:448});try{t.chmodSync(n.dirname(e),448)}catch{}try{t.unlinkSync(e)}catch(e){if("ENOENT"!==e.code)throw e}}}(r);const 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(r,()=>{o.off("error",t),e()})}),o}(s,o),await g.start(),m.connectConfigured(),s.nodeAgentStartRecoverySupervisor?.()}catch(e){throw await s.close(),e}}catch(e){throw p.release(),e}}function Ga(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 Ja(e){if("local-ipc"!==e&&"local-loopback"!==e)throw new Error("Connection mode must be local-ipc or local-loopback.");return e}function Wa(e){const t=Number(e);if(!Number.isInteger(t)||t<=0)throw new Error("Expiry must be a positive integer.");return t}(async function(){const t=new e.Command;t.name("task-handoff-node-agent").description("Run a TaskHandoff node agent.").version(E("@task-handoff/cli")).option("--host <host>","Node agent host",process.env.TASK_HANDOFF_NODE_AGENT_HOST||"127.0.0.1").option("-p, --port <port>","Node agent port",Ga,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",Ja).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 Ka({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",Wa).option("--json","Print raw JSON output").action(async e=>{const n=t.opts(),r=e.ipcPath||n.ipcPath||process.env.TASK_HANDOFF_NODE_AGENT_IPC_PATH,o=e.dataDir||n.dataDir||process.env.TASK_HANDOFF_NODE_AGENT_DATA_DIR,s=e.endpoint?void 0:r||Mr(o||hr()),a=await async function(e){const t={"content-type":"application/json",...e.token?{authorization:`Bearer ${e.token}`}:{}},n=JSON.stringify({...e.expiresInMs?{expiresInMs:e.expiresInMs}:{}}),r=e.endpoint?await fetch(`${e.endpoint.replace(/\/$/,"")}/api/node-agent/pairing/invites`,{method:"POST",headers:t,body:n}):await async function(e,t,n={}){const r=n.method||"GET",o="string"==typeof n.body||n.body instanceof Buffer?n.body:void 0===n.body||null===n.body?void 0:String(n.body),s=new Headers(n.headers||{});return void 0===o||s.has("content-length")||s.set("content-length",String(Buffer.byteLength(o))),new Promise((a,c)=>{const d=i.request({socketPath:e,method:r,path:`/api/node-agent${t}`,headers:Object.fromEntries(s.entries())},e=>{const t=e.statusCode||500;a(new Response("HEAD"!==r&&204!==t&&205!==t&&304!==t?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()})}(e.ipcPath,"/pairing/invites",{method:"POST",headers:t,body:n}),o=await r.json().catch(()=>({}));if(!r.ok)throw new Error(o.error?.message||`Node agent pairing invite failed with HTTP ${r.status}`);const s="string"==typeof o.data?.joinToken?o.data.joinToken:"";if(!s)throw new Error("Node agent pairing invite response did not include a join token.");return{nodeId:"string"==typeof o.data?.nodeId?o.data.nodeId:"",joinToken:s,expiresAt:"string"==typeof o.data?.expiresAt?o.data.expiresAt:""}}({endpoint:e.endpoint,ipcPath:s,token:e.token,expiresInMs:e.expiresInMs});e.json?console.log(JSON.stringify(a,null,2)):(a.nodeId&&console.log(`Node: ${a.nodeId}`),console.log(`Join token: ${a.joinToken}`),a.expiresAt&&console.log(`Expires: ${a.expiresAt}`))}),await t.parseAsync(process.argv)})().catch(e=>{console.error(e instanceof Error?e.message:String(e)),process.exitCode=1});
|